| // 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 | |
| _numThreads = NSystem::GetNumberOfProcessors(); | |
| #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) | |
| { | |
| UString methodName; | |
| FindMethod(EXTERNAL_CODECS_VARS id, methodName); | |
| if (methodName.IsEmpty()) | |
| { | |
| for (unsigned i = 0; i < methodName.Len(); i++) | |
| if (methodName[i] >= 0x80) | |
| { | |
| methodName.Empty(); | |
| break; | |
| } | |
| } | |
| if (methodName.IsEmpty()) | |
| ConvertMethodIdToString(s, id); | |
| else | |
| for (unsigned i = 0; i < methodName.Len(); i++) | |
| s += (char)methodName[i]; | |
| } | |
| #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]; | |
| if (!s.IsEmpty()) | |
| s += ' '; | |
| 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; | |
| } | |
| } | |
| 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 p = props[0]; | |
| if ((p & 1) == 0) | |
| ConvertUInt32ToString((UInt32)((p >> 1) + 12), s); | |
| else | |
| GetStringForSizeValue(s, 3 << ((p >> 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 | |
| { | |
| UString methodName; | |
| FindMethod(EXTERNAL_CODECS_VARS id64, methodName); | |
| if (methodName.IsEmpty()) | |
| { | |
| for (unsigned j = 0; j < methodName.Len(); j++) | |
| if (methodName[j] >= 0x80) | |
| { | |
| methodName.Empty(); | |
| break; | |
| } | |
| } | |
| 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] = (char)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]; | |
| 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 (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); 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) | |
| { | |
| const CFolder &folderInfo = _db.Folders[folderIndex]; | |
| if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && | |
| folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) | |
| { | |
| prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); | |
| } | |
| else | |
| prop = (UInt64)0; | |
| } | |
| else | |
| prop = (UInt64)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; | |
| _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 | |
| #endif | |
| ); | |
| RINOK(result); | |
| _inStream = stream; | |
| } | |
| catch(...) | |
| { | |
| Close(); | |
| // return E_INVALIDARG; | |
| // we must return out_of_memory here | |
| return S_FALSE; | |
| } | |
| // _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; | |
| #endif | |
| return S_OK; | |
| COM_TRY_END | |
| } | |
| #ifdef __7Z_SET_PROPERTIES | |
| #ifdef EXTRACT_ONLY | |
| STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) | |
| { | |
| COM_TRY_BEGIN | |
| const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); | |
| _numThreads = numProcessors; | |
| 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; | |
| int index = ParseStringToUInt32(name, number); | |
| if (index == 0) | |
| { | |
| if (name.IsPrefixedBy(L"mt")) | |
| { | |
| RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); | |
| continue; | |
| } | |
| else | |
| return E_INVALIDARG; | |
| } | |
| } | |
| return S_OK; | |
| COM_TRY_END | |
| } | |
| #endif | |
| #endif | |
| IMPL_ISetCompressCodecsInfo | |
| }} |