You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
764 lines
19 KiB
764 lines
19 KiB
// 7zHandler.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../../../../C/CpuArch.h"
|
|
|
|
#include "../../../Common/ComTry.h"
|
|
#include "../../../Common/IntToString.h"
|
|
|
|
#ifndef __7Z_SET_PROPERTIES
|
|
#include "../../../Windows/System.h"
|
|
#endif
|
|
|
|
#include "../Common/ItemNameUtils.h"
|
|
|
|
#include "7zHandler.h"
|
|
#include "7zProperties.h"
|
|
|
|
#ifdef __7Z_SET_PROPERTIES
|
|
#ifdef EXTRACT_ONLY
|
|
#include "../Common/ParseProperties.h"
|
|
#endif
|
|
#endif
|
|
|
|
using namespace NWindows;
|
|
using namespace NCOM;
|
|
|
|
namespace NArchive {
|
|
namespace N7z {
|
|
|
|
CHandler::CHandler()
|
|
{
|
|
#ifndef _NO_CRYPTO
|
|
_isEncrypted = false;
|
|
_passwordIsDefined = false;
|
|
#endif
|
|
|
|
#ifdef EXTRACT_ONLY
|
|
|
|
_crcSize = 4;
|
|
|
|
#ifdef __7Z_SET_PROPERTIES
|
|
_useMultiThreadMixer = true;
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
|
{
|
|
*numItems = _db.Files.Size();
|
|
return S_OK;
|
|
}
|
|
|
|
#ifdef _SFX
|
|
|
|
IMP_IInArchive_ArcProps_NO_Table
|
|
|
|
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
|
{
|
|
*numProps = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
|
|
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
#else
|
|
|
|
static const Byte kArcProps[] =
|
|
{
|
|
kpidHeadersSize,
|
|
kpidMethod,
|
|
kpidSolid,
|
|
kpidNumBlocks
|
|
// , kpidIsTree
|
|
};
|
|
|
|
IMP_IInArchive_ArcProps
|
|
|
|
static inline char GetHex(unsigned value)
|
|
{
|
|
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
|
}
|
|
|
|
static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
|
|
{
|
|
int len = 0;
|
|
do
|
|
{
|
|
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
|
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
|
}
|
|
while (id != 0);
|
|
return (unsigned)-len;
|
|
}
|
|
|
|
static void ConvertMethodIdToString(AString &res, UInt64 id)
|
|
{
|
|
const unsigned kLen = 32;
|
|
char s[kLen];
|
|
unsigned len = kLen - 1;
|
|
s[len] = 0;
|
|
res += s + len - ConvertMethodIdToString_Back(s + len, id);
|
|
}
|
|
|
|
static unsigned GetStringForSizeValue(char *s, UInt32 val)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i <= 31; i++)
|
|
if (((UInt32)1 << i) == val)
|
|
{
|
|
if (i < 10)
|
|
{
|
|
s[0] = (char)('0' + i);
|
|
s[1] = 0;
|
|
return 1;
|
|
}
|
|
if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
|
|
else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
|
|
else { s[0] = '3'; s[1] = (char)('0' + i - 30); }
|
|
s[2] = 0;
|
|
return 2;
|
|
}
|
|
char c = 'b';
|
|
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
|
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
|
::ConvertUInt32ToString(val, s);
|
|
unsigned pos = MyStringLen(s);
|
|
s[pos++] = c;
|
|
s[pos] = 0;
|
|
return pos;
|
|
}
|
|
|
|
/*
|
|
static inline void AddHexToString(UString &res, Byte value)
|
|
{
|
|
res += GetHex((Byte)(value >> 4));
|
|
res += GetHex((Byte)(value & 0xF));
|
|
}
|
|
*/
|
|
|
|
static char *AddProp32(char *s, const char *name, UInt32 v)
|
|
{
|
|
*s++ = ':';
|
|
s = MyStpCpy(s, name);
|
|
::ConvertUInt32ToString(v, s);
|
|
return s + MyStringLen(s);
|
|
}
|
|
|
|
void CHandler::AddMethodName(AString &s, UInt64 id)
|
|
{
|
|
AString name;
|
|
FindMethod(EXTERNAL_CODECS_VARS id, name);
|
|
if (name.IsEmpty())
|
|
ConvertMethodIdToString(s, id);
|
|
else
|
|
s += name;
|
|
}
|
|
|
|
#endif
|
|
|
|
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
|
{
|
|
#ifndef _SFX
|
|
COM_TRY_BEGIN
|
|
#endif
|
|
NCOM::CPropVariant prop;
|
|
switch (propID)
|
|
{
|
|
#ifndef _SFX
|
|
case kpidMethod:
|
|
{
|
|
AString s;
|
|
const CParsedMethods &pm = _db.ParsedMethods;
|
|
FOR_VECTOR (i, pm.IDs)
|
|
{
|
|
UInt64 id = pm.IDs[i];
|
|
s.Add_Space_if_NotEmpty();
|
|
char temp[16];
|
|
if (id == k_LZMA2)
|
|
{
|
|
s += "LZMA2:";
|
|
if ((pm.Lzma2Prop & 1) == 0)
|
|
ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
|
|
else
|
|
GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
|
|
s += temp;
|
|
}
|
|
else if (id == k_LZMA)
|
|
{
|
|
s += "LZMA:";
|
|
GetStringForSizeValue(temp, pm.LzmaDic);
|
|
s += temp;
|
|
}
|
|
else
|
|
AddMethodName(s, id);
|
|
}
|
|
prop = s;
|
|
break;
|
|
}
|
|
case kpidSolid: prop = _db.IsSolid(); break;
|
|
case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
|
|
case kpidHeadersSize: prop = _db.HeadersSize; break;
|
|
case kpidPhySize: prop = _db.PhySize; break;
|
|
case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
|
|
/*
|
|
case kpidIsTree: if (_db.IsTree) prop = true; break;
|
|
case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
|
|
case kpidIsAux: if (_db.IsTree) prop = true; break;
|
|
*/
|
|
// case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
|
|
#endif
|
|
|
|
case kpidWarningFlags:
|
|
{
|
|
UInt32 v = 0;
|
|
if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
|
|
if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
|
|
if (v != 0)
|
|
prop = v;
|
|
break;
|
|
}
|
|
|
|
case kpidErrorFlags:
|
|
{
|
|
UInt32 v = 0;
|
|
if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
|
|
if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
|
|
if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
|
// if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
|
|
if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
|
|
prop = v;
|
|
break;
|
|
}
|
|
|
|
case kpidReadOnly:
|
|
{
|
|
if (!_db.CanUpdate())
|
|
prop = true;
|
|
break;
|
|
}
|
|
}
|
|
prop.Detach(value);
|
|
return S_OK;
|
|
#ifndef _SFX
|
|
COM_TRY_END
|
|
#endif
|
|
}
|
|
|
|
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
|
|
{
|
|
UInt64 value;
|
|
if (v.GetItem(index, value))
|
|
PropVarEm_Set_FileTime64(prop, value);
|
|
}
|
|
|
|
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
|
|
{
|
|
if (folderIndex == kNumNoIndex)
|
|
return false;
|
|
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
|
const Byte *p = _db.CodersData + startPos;
|
|
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
|
CInByte2 inByte;
|
|
inByte.Init(p, size);
|
|
|
|
CNum numCoders = inByte.ReadNum();
|
|
for (; numCoders != 0; numCoders--)
|
|
{
|
|
Byte mainByte = inByte.ReadByte();
|
|
unsigned idSize = (mainByte & 0xF);
|
|
const Byte *longID = inByte.GetPtr();
|
|
UInt64 id64 = 0;
|
|
for (unsigned j = 0; j < idSize; j++)
|
|
id64 = ((id64 << 8) | longID[j]);
|
|
inByte.SkipDataNoCheck(idSize);
|
|
if (id64 == k_AES)
|
|
return true;
|
|
if ((mainByte & 0x20) != 0)
|
|
inByte.SkipDataNoCheck(inByte.ReadNum());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
|
|
{
|
|
*numProps = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
|
|
{
|
|
*name = NULL;
|
|
*propID = kpidNtSecure;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
|
|
{
|
|
/*
|
|
const CFileItem &file = _db.Files[index];
|
|
*parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
|
|
*parent = (UInt32)(Int32)file.Parent;
|
|
*/
|
|
*parentType = NParentType::kDir;
|
|
*parent = (UInt32)(Int32)-1;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
|
|
{
|
|
*data = NULL;
|
|
*dataSize = 0;
|
|
*propType = 0;
|
|
|
|
if (/* _db.IsTree && propID == kpidName ||
|
|
!_db.IsTree && */ propID == kpidPath)
|
|
{
|
|
if (_db.NameOffsets && _db.NamesBuf)
|
|
{
|
|
size_t offset = _db.NameOffsets[index];
|
|
size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
|
|
if (size < ((UInt32)1 << 31))
|
|
{
|
|
*data = (const void *)(_db.NamesBuf + offset * 2);
|
|
*dataSize = (UInt32)size;
|
|
*propType = NPropDataType::kUtf16z;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
/*
|
|
if (propID == kpidNtSecure)
|
|
{
|
|
if (index < (UInt32)_db.SecureIDs.Size())
|
|
{
|
|
int id = _db.SecureIDs[index];
|
|
size_t offs = _db.SecureOffsets[id];
|
|
size_t size = _db.SecureOffsets[id + 1] - offs;
|
|
if (size >= 0)
|
|
{
|
|
*data = _db.SecureBuf + offs;
|
|
*dataSize = (UInt32)size;
|
|
*propType = NPropDataType::kRaw;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
return S_OK;
|
|
}
|
|
|
|
#ifndef _SFX
|
|
|
|
HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
|
{
|
|
PropVariant_Clear(prop);
|
|
if (folderIndex == kNumNoIndex)
|
|
return S_OK;
|
|
// for (int ttt = 0; ttt < 1; ttt++) {
|
|
const unsigned kTempSize = 256;
|
|
char temp[kTempSize];
|
|
unsigned pos = kTempSize;
|
|
temp[--pos] = 0;
|
|
|
|
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
|
const Byte *p = _db.CodersData + startPos;
|
|
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
|
CInByte2 inByte;
|
|
inByte.Init(p, size);
|
|
|
|
// numCoders == 0 ???
|
|
CNum numCoders = inByte.ReadNum();
|
|
bool needSpace = false;
|
|
|
|
for (; numCoders != 0; numCoders--, needSpace = true)
|
|
{
|
|
if (pos < 32) // max size of property
|
|
break;
|
|
Byte mainByte = inByte.ReadByte();
|
|
unsigned idSize = (mainByte & 0xF);
|
|
const Byte *longID = inByte.GetPtr();
|
|
UInt64 id64 = 0;
|
|
for (unsigned j = 0; j < idSize; j++)
|
|
id64 = ((id64 << 8) | longID[j]);
|
|
inByte.SkipDataNoCheck(idSize);
|
|
|
|
if ((mainByte & 0x10) != 0)
|
|
{
|
|
inByte.ReadNum(); // NumInStreams
|
|
inByte.ReadNum(); // NumOutStreams
|
|
}
|
|
|
|
CNum propsSize = 0;
|
|
const Byte *props = NULL;
|
|
if ((mainByte & 0x20) != 0)
|
|
{
|
|
propsSize = inByte.ReadNum();
|
|
props = inByte.GetPtr();
|
|
inByte.SkipDataNoCheck(propsSize);
|
|
}
|
|
|
|
const char *name = NULL;
|
|
char s[32];
|
|
s[0] = 0;
|
|
|
|
if (id64 <= (UInt32)0xFFFFFFFF)
|
|
{
|
|
UInt32 id = (UInt32)id64;
|
|
if (id == k_LZMA)
|
|
{
|
|
name = "LZMA";
|
|
if (propsSize == 5)
|
|
{
|
|
UInt32 dicSize = GetUi32((const Byte *)props + 1);
|
|
char *dest = s + GetStringForSizeValue(s, dicSize);
|
|
UInt32 d = props[0];
|
|
if (d != 0x5D)
|
|
{
|
|
UInt32 lc = d % 9;
|
|
d /= 9;
|
|
UInt32 pb = d / 5;
|
|
UInt32 lp = d % 5;
|
|
if (lc != 3) dest = AddProp32(dest, "lc", lc);
|
|
if (lp != 0) dest = AddProp32(dest, "lp", lp);
|
|
if (pb != 2) dest = AddProp32(dest, "pb", pb);
|
|
}
|
|
}
|
|
}
|
|
else if (id == k_LZMA2)
|
|
{
|
|
name = "LZMA2";
|
|
if (propsSize == 1)
|
|
{
|
|
Byte d = props[0];
|
|
if ((d & 1) == 0)
|
|
ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
|
|
else
|
|
GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
|
|
}
|
|
}
|
|
else if (id == k_PPMD)
|
|
{
|
|
name = "PPMD";
|
|
if (propsSize == 5)
|
|
{
|
|
Byte order = *props;
|
|
char *dest = s;
|
|
*dest++ = 'o';
|
|
ConvertUInt32ToString(order, dest);
|
|
dest += MyStringLen(dest);
|
|
dest = MyStpCpy(dest, ":mem");
|
|
GetStringForSizeValue(dest, GetUi32(props + 1));
|
|
}
|
|
}
|
|
else if (id == k_Delta)
|
|
{
|
|
name = "Delta";
|
|
if (propsSize == 1)
|
|
ConvertUInt32ToString((UInt32)props[0] + 1, s);
|
|
}
|
|
else if (id == k_BCJ2) name = "BCJ2";
|
|
else if (id == k_BCJ) name = "BCJ";
|
|
else if (id == k_AES)
|
|
{
|
|
name = "7zAES";
|
|
if (propsSize >= 1)
|
|
{
|
|
Byte firstByte = props[0];
|
|
UInt32 numCyclesPower = firstByte & 0x3F;
|
|
ConvertUInt32ToString(numCyclesPower, s);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (name)
|
|
{
|
|
unsigned nameLen = MyStringLen(name);
|
|
unsigned propsLen = MyStringLen(s);
|
|
unsigned totalLen = nameLen + propsLen;
|
|
if (propsLen != 0)
|
|
totalLen++;
|
|
if (needSpace)
|
|
totalLen++;
|
|
if (totalLen + 5 >= pos)
|
|
break;
|
|
pos -= totalLen;
|
|
MyStringCopy(temp + pos, name);
|
|
if (propsLen != 0)
|
|
{
|
|
char *dest = temp + pos + nameLen;
|
|
*dest++ = ':';
|
|
MyStringCopy(dest, s);
|
|
}
|
|
if (needSpace)
|
|
temp[pos + totalLen - 1] = ' ';
|
|
}
|
|
else
|
|
{
|
|
AString methodName;
|
|
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
|
|
if (needSpace)
|
|
temp[--pos] = ' ';
|
|
if (methodName.IsEmpty())
|
|
pos -= ConvertMethodIdToString_Back(temp + pos, id64);
|
|
else
|
|
{
|
|
unsigned len = methodName.Len();
|
|
if (len + 5 > pos)
|
|
break;
|
|
pos -= len;
|
|
for (unsigned i = 0; i < len; i++)
|
|
temp[pos + i] = methodName[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (numCoders != 0 && pos >= 4)
|
|
{
|
|
temp[--pos] = ' ';
|
|
temp[--pos] = '.';
|
|
temp[--pos] = '.';
|
|
temp[--pos] = '.';
|
|
}
|
|
|
|
return PropVarEm_Set_Str(prop, temp + pos);
|
|
// }
|
|
}
|
|
|
|
#endif
|
|
|
|
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
|
{
|
|
PropVariant_Clear(value);
|
|
// COM_TRY_BEGIN
|
|
// NCOM::CPropVariant prop;
|
|
|
|
/*
|
|
const CRef2 &ref2 = _refs[index];
|
|
if (ref2.Refs.IsEmpty())
|
|
return E_FAIL;
|
|
const CRef &ref = ref2.Refs.Front();
|
|
*/
|
|
|
|
const CFileItem &item = _db.Files[index];
|
|
const UInt32 index2 = index;
|
|
|
|
switch (propID)
|
|
{
|
|
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
|
|
case kpidSize:
|
|
{
|
|
PropVarEm_Set_UInt64(value, item.Size);
|
|
// prop = ref2.Size;
|
|
break;
|
|
}
|
|
case kpidPackSize:
|
|
{
|
|
// prop = ref2.PackSize;
|
|
{
|
|
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
|
if (folderIndex != kNumNoIndex)
|
|
{
|
|
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
|
|
PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
|
|
/*
|
|
else
|
|
PropVarEm_Set_UInt64(value, 0);
|
|
*/
|
|
}
|
|
else
|
|
PropVarEm_Set_UInt64(value, 0);
|
|
}
|
|
break;
|
|
}
|
|
// case kpidIsAux: prop = _db.IsItemAux(index2); break;
|
|
case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
|
|
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
|
|
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
|
|
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
|
|
case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
|
|
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
|
|
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
|
|
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
|
|
/*
|
|
case kpidIsAltStream: prop = item.IsAltStream; break;
|
|
case kpidNtSecure:
|
|
{
|
|
int id = _db.SecureIDs[index];
|
|
size_t offs = _db.SecureOffsets[id];
|
|
size_t size = _db.SecureOffsets[id + 1] - offs;
|
|
if (size >= 0)
|
|
{
|
|
prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
|
|
}
|
|
break;
|
|
}
|
|
*/
|
|
|
|
case kpidPath: return _db.GetPath_Prop(index, value);
|
|
|
|
#ifndef _SFX
|
|
|
|
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
|
|
case kpidBlock:
|
|
{
|
|
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
|
if (folderIndex != kNumNoIndex)
|
|
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
|
|
}
|
|
break;
|
|
/*
|
|
case kpidPackedSize0:
|
|
case kpidPackedSize1:
|
|
case kpidPackedSize2:
|
|
case kpidPackedSize3:
|
|
case kpidPackedSize4:
|
|
{
|
|
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
|
if (folderIndex != kNumNoIndex)
|
|
{
|
|
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
|
|
_db.FoStartPackStreamIndex[folderIndex + 1] -
|
|
_db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
|
|
{
|
|
PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
|
|
}
|
|
}
|
|
else
|
|
PropVarEm_Set_UInt64(value, 0);
|
|
}
|
|
break;
|
|
*/
|
|
|
|
#endif
|
|
}
|
|
// prop.Detach(value);
|
|
return S_OK;
|
|
// COM_TRY_END
|
|
}
|
|
|
|
STDMETHODIMP CHandler::Open(IInStream *stream,
|
|
const UInt64 *maxCheckStartPosition,
|
|
IArchiveOpenCallback *openArchiveCallback)
|
|
{
|
|
COM_TRY_BEGIN
|
|
Close();
|
|
#ifndef _SFX
|
|
_fileInfoPopIDs.Clear();
|
|
#endif
|
|
|
|
try
|
|
{
|
|
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
|
|
|
|
#ifndef _NO_CRYPTO
|
|
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
|
if (openArchiveCallback)
|
|
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
|
#endif
|
|
|
|
CInArchive archive(
|
|
#ifdef __7Z_SET_PROPERTIES
|
|
_useMultiThreadMixer
|
|
#else
|
|
true
|
|
#endif
|
|
);
|
|
_db.IsArc = false;
|
|
RINOK(archive.Open(stream, maxCheckStartPosition));
|
|
_db.IsArc = true;
|
|
|
|
HRESULT result = archive.ReadDatabase(
|
|
EXTERNAL_CODECS_VARS
|
|
_db
|
|
#ifndef _NO_CRYPTO
|
|
, getTextPassword, _isEncrypted, _passwordIsDefined, _password
|
|
#endif
|
|
);
|
|
RINOK(result);
|
|
|
|
_inStream = stream;
|
|
}
|
|
catch(...)
|
|
{
|
|
Close();
|
|
// return E_INVALIDARG;
|
|
// return S_FALSE;
|
|
// we must return out_of_memory here
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
// _inStream = stream;
|
|
#ifndef _SFX
|
|
FillPopIDs();
|
|
#endif
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
|
|
STDMETHODIMP CHandler::Close()
|
|
{
|
|
COM_TRY_BEGIN
|
|
_inStream.Release();
|
|
_db.Clear();
|
|
#ifndef _NO_CRYPTO
|
|
_isEncrypted = false;
|
|
_passwordIsDefined = false;
|
|
_password.Empty();
|
|
#endif
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
|
|
#ifdef __7Z_SET_PROPERTIES
|
|
#ifdef EXTRACT_ONLY
|
|
|
|
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
|
{
|
|
COM_TRY_BEGIN
|
|
|
|
InitCommon();
|
|
_useMultiThreadMixer = true;
|
|
|
|
for (UInt32 i = 0; i < numProps; i++)
|
|
{
|
|
UString name = names[i];
|
|
name.MakeLower_Ascii();
|
|
if (name.IsEmpty())
|
|
return E_INVALIDARG;
|
|
const PROPVARIANT &value = values[i];
|
|
UInt32 number;
|
|
unsigned index = ParseStringToUInt32(name, number);
|
|
if (index == 0)
|
|
{
|
|
if (name.IsEqualTo("mtf"))
|
|
{
|
|
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
|
|
continue;
|
|
}
|
|
{
|
|
HRESULT hres;
|
|
if (SetCommonProperty(name, value, hres))
|
|
{
|
|
RINOK(hres);
|
|
continue;
|
|
}
|
|
}
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
return S_OK;
|
|
COM_TRY_END
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
IMPL_ISetCompressCodecsInfo
|
|
|
|
}}
|