diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp')
-rw-r--r-- | src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp | 1679 |
1 files changed, 0 insertions, 1679 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp deleted file mode 100644 index 28ec5e083..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/7z/7zIn.cpp +++ /dev/null @@ -1,1679 +0,0 @@ -// 7zIn.cpp - -#include "StdAfx.h" - -#ifdef _WIN32 -#include <wchar.h> -#else -#include <ctype.h> -#endif - -#include "../../../../C/7zCrc.h" -#include "../../../../C/CpuArch.h" - -#include "../../Common/StreamObjects.h" -#include "../../Common/StreamUtils.h" - -#include "7zDecode.h" -#include "7zIn.h" - -#define Get16(p) GetUi16(p) -#define Get32(p) GetUi32(p) -#define Get64(p) GetUi64(p) - -// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader -#ifndef _SFX -#define FORMAT_7Z_RECOVERY -#endif - -using namespace NWindows; -using namespace NCOM; - -namespace NArchive { -namespace N7z { - -static const UInt32 k_LZMA2 = 0x21; -static const UInt32 k_LZMA = 0x030101; - -static void BoolVector_Fill_False(CBoolVector &v, unsigned size) -{ - v.ClearAndSetSize(size); - bool *p = &v[0]; - for (unsigned i = 0; i < size; i++) - p[i] = false; -} - -static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) -{ - if (index >= (UInt32)v.Size()) - return true; - bool res = v[index]; - v[index] = true; - return res; -} - -bool CFolder::CheckStructure(unsigned numUnpackSizes) const -{ - const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it - const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax - const unsigned kNumBindsMax = 32; - - if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) - return false; - - { - CBoolVector v; - BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); - - unsigned i; - for (i = 0; i < BindPairs.Size(); i++) - if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) - return false; - for (i = 0; i < PackStreams.Size(); i++) - if (BoolVector_GetAndSet(v, PackStreams[i])) - return false; - - BoolVector_Fill_False(v, numUnpackSizes); - for (i = 0; i < BindPairs.Size(); i++) - if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) - return false; - } - - UInt32 mask[kMaskSize]; - unsigned i; - for (i = 0; i < kMaskSize; i++) - mask[i] = 0; - - { - CUIntVector inStreamToCoder, outStreamToCoder; - for (i = 0; i < Coders.Size(); i++) - { - CNum j; - const CCoderInfo &coder = Coders[i]; - for (j = 0; j < coder.NumInStreams; j++) - inStreamToCoder.Add(i); - for (j = 0; j < coder.NumOutStreams; j++) - outStreamToCoder.Add(i); - } - - for (i = 0; i < BindPairs.Size(); i++) - { - const CBindPair &bp = BindPairs[i]; - mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); - } - } - - for (i = 0; i < kMaskSize; i++) - for (unsigned j = 0; j < kMaskSize; j++) - if (((1 << j) & mask[i]) != 0) - mask[i] |= mask[j]; - - for (i = 0; i < kMaskSize; i++) - if (((1 << i) & mask[i]) != 0) - return false; - - return true; -} - -class CInArchiveException {}; -class CUnsupportedFeatureException: public CInArchiveException {}; - -static void ThrowException() { throw CInArchiveException(); } -static inline void ThrowEndOfData() { ThrowException(); } -static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } -static inline void ThrowIncorrect() { ThrowException(); } - -class CStreamSwitch -{ - CInArchive *_archive; - bool _needRemove; - bool _needUpdatePos; -public: - CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} - ~CStreamSwitch() { Remove(); } - void Remove(); - void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); - void Set(CInArchive *archive, const CByteBuffer &byteBuffer); - void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); -}; - -void CStreamSwitch::Remove() -{ - if (_needRemove) - { - if (_archive->_inByteBack->GetRem() != 0) - _archive->ThereIsHeaderError = true; - _archive->DeleteByteStream(_needUpdatePos); - _needRemove = false; - } -} - -void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) -{ - Remove(); - _archive = archive; - _archive->AddByteStream(data, size); - _needRemove = true; - _needUpdatePos = needUpdatePos; -} - -void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) -{ - Set(archive, byteBuffer, byteBuffer.Size(), false); -} - -void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) -{ - Remove(); - Byte external = archive->ReadByte(); - if (external != 0) - { - CNum dataIndex = archive->ReadNum(); - if (dataIndex >= dataVector->Size()) - ThrowIncorrect(); - Set(archive, (*dataVector)[dataIndex]); - } -} - -void CInArchive::AddByteStream(const Byte *buf, size_t size) -{ - if (_numInByteBufs == kNumBufLevelsMax) - ThrowIncorrect(); - _inByteBack = &_inByteVector[_numInByteBufs++]; - _inByteBack->Init(buf, size); -} - - -Byte CInByte2::ReadByte() -{ - if (_pos >= _size) - ThrowEndOfData(); - return _buffer[_pos++]; -} - -void CInByte2::ReadBytes(Byte *data, size_t size) -{ - if (size > _size - _pos) - ThrowEndOfData(); - memcpy(data, _buffer + _pos, size); - _pos += size; -} - -void CInByte2::SkipData(UInt64 size) -{ - if (size > _size - _pos) - ThrowEndOfData(); - _pos += (size_t)size; -} - -void CInByte2::SkipData() -{ - SkipData(ReadNumber()); -} - -static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) -{ - if (size == 0) - { - processed = 0; - return 0; - } - Byte firstByte = *p++; - size--; - if ((firstByte & 0x80) == 0) - { - processed = 1; - return firstByte; - } - Byte mask = 0x40; - if (size == 0) - { - processed = 0; - return 0; - } - UInt64 value = (UInt64)*p; - p++; - size--; - for (unsigned i = 1; i < 8; i++) - { - if ((firstByte & mask) == 0) - { - UInt64 highPart = firstByte & (mask - 1); - value += (highPart << (i * 8)); - processed = i + 1; - return value; - } - if (size == 0) - { - processed = 0; - return 0; - } - value |= ((UInt64)*p << (i * 8)); - p++; - size--; - mask >>= 1; - } - processed = 9; - return value; -} - -UInt64 CInByte2::ReadNumber() -{ - size_t processed; - UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); - if (processed == 0) - ThrowEndOfData(); - _pos += processed; - return res; -} - -CNum CInByte2::ReadNum() -{ - /* - if (_pos < _size) - { - Byte val = _buffer[_pos]; - if ((unsigned)val < 0x80) - { - _pos++; - return (unsigned)val; - } - } - */ - UInt64 value = ReadNumber(); - if (value > kNumMax) - ThrowUnsupported(); - return (CNum)value; -} - -UInt32 CInByte2::ReadUInt32() -{ - if (_pos + 4 > _size) - ThrowEndOfData(); - UInt32 res = Get32(_buffer + _pos); - _pos += 4; - return res; -} - -UInt64 CInByte2::ReadUInt64() -{ - if (_pos + 8 > _size) - ThrowEndOfData(); - UInt64 res = Get64(_buffer + _pos); - _pos += 8; - return res; -} - -#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false; - -static inline bool TestSignature(const Byte *p) -{ - CHECK_SIGNATURE - return CrcCalc(p + 12, 20) == Get32(p + 8); -} - -#ifdef FORMAT_7Z_RECOVERY -static inline bool TestSignature2(const Byte *p) -{ - CHECK_SIGNATURE; - if (CrcCalc(p + 12, 20) == Get32(p + 8)) - return true; - for (unsigned i = 8; i < kHeaderSize; i++) - if (p[i] != 0) - return false; - return (p[6] != 0 || p[7] != 0); -} -#else -#define TestSignature2(p) TestSignature(p) -#endif - -HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) -{ - RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); - - if (TestSignature2(_header)) - return S_OK; - if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) - return S_FALSE; - - const UInt32 kBufSize = 1 << 15; - CByteArr buf(kBufSize); - memcpy(buf, _header, kHeaderSize); - UInt64 offset = 0; - - for (;;) - { - UInt32 readSize = kBufSize - kHeaderSize; - { - UInt64 rem = *searchHeaderSizeLimit - offset; - if (readSize > rem) - readSize = (UInt32)rem; - if (readSize == 0) - return S_FALSE; - } - UInt32 processed = 0; - RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); - if (processed == 0) - return S_FALSE; - for (UInt32 pos = 0;;) - { - const Byte *p = buf + pos + 1; - const Byte *lim = buf + processed; - for (; p <= lim; p += 4) - { - if (p[0] == '7') break; - if (p[1] == '7') { p += 1; break; } - if (p[2] == '7') { p += 2; break; } - if (p[3] == '7') { p += 3; break; } - }; - if (p > lim) - break; - pos = (UInt32)(p - buf); - if (TestSignature(p)) - { - memcpy(_header, p, kHeaderSize); - _arhiveBeginStreamPosition += offset + pos; - return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); - } - } - offset += processed; - memmove(buf, buf + processed, kHeaderSize); - } -} - -// S_FALSE means that file is not archive -HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) -{ - HeadersSize = 0; - Close(); - RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) - RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) - RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) - RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); - _stream = stream; - return S_OK; -} - -void CInArchive::Close() -{ - _numInByteBufs = 0; - _stream.Release(); - ThereIsHeaderError = false; -} - -void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) -{ - for (;;) - { - if (ReadID() == NID::kEnd) - break; - SkipData(); - } -} - -// CFolder &folder can be non empty. So we must set all fields - -void CInByte2::ParseFolder(CFolder &folder) -{ - CNum numCoders = ReadNum(); - - folder.Coders.SetSize(numCoders); - - CNum numInStreams = 0; - CNum numOutStreams = 0; - CNum i; - for (i = 0; i < numCoders; i++) - { - CCoderInfo &coder = folder.Coders[i]; - { - Byte mainByte = ReadByte(); - if ((mainByte & 0xC0) != 0) - ThrowUnsupported(); - unsigned idSize = (mainByte & 0xF); - if (idSize > 8 || idSize > GetRem()) - ThrowUnsupported(); - const Byte *longID = GetPtr(); - UInt64 id = 0; - for (unsigned j = 0; j < idSize; j++) - id = ((id << 8) | longID[j]); - SkipDataNoCheck(idSize); - coder.MethodID = id; - - if ((mainByte & 0x10) != 0) - { - coder.NumInStreams = ReadNum(); - coder.NumOutStreams = ReadNum(); - } - else - { - coder.NumInStreams = 1; - coder.NumOutStreams = 1; - } - if ((mainByte & 0x20) != 0) - { - CNum propsSize = ReadNum(); - coder.Props.Alloc((size_t)propsSize); - ReadBytes((Byte *)coder.Props, (size_t)propsSize); - } - else - coder.Props.Free(); - } - numInStreams += coder.NumInStreams; - numOutStreams += coder.NumOutStreams; - } - - CNum numBindPairs = numOutStreams - 1; - folder.BindPairs.SetSize(numBindPairs); - for (i = 0; i < numBindPairs; i++) - { - CBindPair &bp = folder.BindPairs[i]; - bp.InIndex = ReadNum(); - bp.OutIndex = ReadNum(); - } - - if (numInStreams < numBindPairs) - ThrowUnsupported(); - CNum numPackStreams = numInStreams - numBindPairs; - folder.PackStreams.SetSize(numPackStreams); - if (numPackStreams == 1) - { - for (i = 0; i < numInStreams; i++) - if (folder.FindBindPairForInStream(i) < 0) - { - folder.PackStreams[0] = i; - break; - } - if (i == numInStreams) - ThrowUnsupported(); - } - else - for (i = 0; i < numPackStreams; i++) - folder.PackStreams[i] = ReadNum(); -} - -void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const -{ - size_t startPos = FoCodersDataOffset[folderIndex]; - CInByte2 inByte; - inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); - inByte.ParseFolder(folder); - if (inByte.GetRem() != 0) - throw 20120424; -} - - -void CDatabase::GetPath(unsigned index, UString &path) const -{ - path.Empty(); - if (!NameOffsets || !NamesBuf) - return; - - size_t offset = NameOffsets[index]; - size_t size = NameOffsets[index + 1] - offset - 1; - - if (size >= (1 << 20)) - return; - - wchar_t *s = path.GetBuffer((unsigned)size); - - const Byte *p = ((const Byte *)NamesBuf + offset * 2); - - #if defined(_WIN32) && defined(MY_CPU_LE) - - wmemcpy(s, (const wchar_t *)p, size); - - #else - - for (size_t i = 0; i < size; i++) - { - *s = Get16(p); - p += 2; - s++; - } - - #endif - - path.ReleaseBuffer((unsigned)size); -} - -HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() -{ - PropVariant_Clear(path); - if (!NameOffsets || !NamesBuf) - return S_OK; - - size_t offset = NameOffsets[index]; - size_t size = NameOffsets[index + 1] - offset; - - if (size >= (1 << 14)) - return S_OK; - - RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); - wchar_t *s = path->bstrVal; - - const Byte *p = ((const Byte *)NamesBuf + offset * 2); - - for (size_t i = 0; i < size; i++) - { - wchar_t c = Get16(p); - p += 2; - #if WCHAR_PATH_SEPARATOR != L'/' - if (c == L'/') - c = WCHAR_PATH_SEPARATOR; - #endif - *s++ = c; - } - - return S_OK; - - /* - unsigned cur = index; - unsigned size = 0; - - for (int i = 0;; i++) - { - size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; - size += (unsigned)len; - if (i > 256 || len > (1 << 14) || size > (1 << 14)) - return PropVarEm_Set_Str(path, "[TOO-LONG]"); - cur = Files[cur].Parent; - if (cur < 0) - break; - } - size--; - - RINOK(PropVarEm_Alloc_Bstr(path, size)); - wchar_t *s = path->bstrVal; - s += size; - *s = 0; - cur = index; - - for (;;) - { - unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); - const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; - do - { - p -= 2; - --s; - wchar_t c = Get16(p); - if (c == '/') - c = WCHAR_PATH_SEPARATOR; - *s = c; - } - while (--len); - const CFileItem &file = Files[cur]; - cur = file.Parent; - if (cur < 0) - return S_OK; - *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); - } - */ -} - -void CInArchive::WaitId(UInt64 id) -{ - for (;;) - { - UInt64 type = ReadID(); - if (type == id) - return; - if (type == NID::kEnd) - ThrowIncorrect(); - SkipData(); - } -} - -void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) -{ - ReadBoolVector2(numItems, crcs.Defs); - crcs.Vals.ClearAndSetSize(numItems); - UInt32 *p = &crcs.Vals[0]; - const bool *defs = &crcs.Defs[0]; - for (unsigned i = 0; i < numItems; i++) - { - UInt32 crc = 0; - if (defs[i]) - crc = ReadUInt32(); - p[i] = crc; - } -} - -void CInArchive::ReadPackInfo(CFolders &f) -{ - CNum numPackStreams = ReadNum(); - - WaitId(NID::kSize); - f.PackPositions.Alloc(numPackStreams + 1); - f.NumPackStreams = numPackStreams; - UInt64 sum = 0; - for (CNum i = 0; i < numPackStreams; i++) - { - f.PackPositions[i] = sum; - UInt64 packSize = ReadNumber(); - sum += packSize; - if (sum < packSize) - ThrowIncorrect(); - } - f.PackPositions[numPackStreams] = sum; - - UInt64 type; - for (;;) - { - type = ReadID(); - if (type == NID::kEnd) - return; - if (type == NID::kCRC) - { - CUInt32DefVector PackCRCs; - ReadHashDigests(numPackStreams, PackCRCs); - continue; - } - SkipData(); - } -} - -void CInArchive::ReadUnpackInfo( - const CObjectVector<CByteBuffer> *dataVector, - CFolders &folders) -{ - WaitId(NID::kFolder); - CNum numFolders = ReadNum(); - - CNum numCodersOutStreams = 0; - { - CStreamSwitch streamSwitch; - streamSwitch.Set(this, dataVector); - const Byte *startBufPtr = _inByteBack->GetPtr(); - folders.NumFolders = numFolders; - - folders.FoStartPackStreamIndex.Alloc(numFolders + 1); - folders.FoToMainUnpackSizeIndex.Alloc(numFolders); - folders.FoCodersDataOffset.Alloc(numFolders + 1); - folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); - - CRecordVector<bool> InStreamUsed; - CRecordVector<bool> OutStreamUsed; - - CNum packStreamIndex = 0; - CNum fo; - CInByte2 *inByte = _inByteBack; - for (fo = 0; fo < numFolders; fo++) - { - UInt32 numOutStreams = 0; - UInt32 indexOfMainStream = 0; - UInt32 numPackStreams = 0; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; - - numOutStreams = 0; - CNum numInStreams = 0; - CNum numCoders = inByte->ReadNum(); - for (CNum ci = 0; ci < numCoders; ci++) - { - Byte mainByte = inByte->ReadByte(); - if ((mainByte & 0xC0) != 0) - ThrowUnsupported(); - unsigned idSize = (mainByte & 0xF); - if (idSize > 8) - ThrowUnsupported(); - if (idSize > inByte->GetRem()) - ThrowEndOfData(); - const Byte *longID = inByte->GetPtr(); - UInt64 id = 0; - for (unsigned j = 0; j < idSize; j++) - id = ((id << 8) | longID[j]); - inByte->SkipDataNoCheck(idSize); - if (folders.ParsedMethods.IDs.Size() < 128) - folders.ParsedMethods.IDs.AddToUniqueSorted(id); - CNum coderInStreams = 1; - CNum coderOutStreams = 1; - if ((mainByte & 0x10) != 0) - { - coderInStreams = inByte->ReadNum(); - coderOutStreams = inByte->ReadNum(); - } - numInStreams += coderInStreams; - if (numInStreams < coderInStreams) - ThrowUnsupported(); - numOutStreams += coderOutStreams; - if (numOutStreams < coderOutStreams) - ThrowUnsupported(); - if ((mainByte & 0x20) != 0) - { - CNum propsSize = inByte->ReadNum(); - if (propsSize > inByte->GetRem()) - ThrowEndOfData(); - if (id == k_LZMA2 && propsSize == 1) - { - Byte v = *_inByteBack->GetPtr(); - if (folders.ParsedMethods.Lzma2Prop < v) - folders.ParsedMethods.Lzma2Prop = v; - } - else if (id == k_LZMA && propsSize == 5) - { - UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); - if (folders.ParsedMethods.LzmaDic < dicSize) - folders.ParsedMethods.LzmaDic = dicSize; - } - inByte->SkipDataNoCheck((size_t)propsSize); - } - } - - if (numOutStreams == 1 && numInStreams == 1) - { - indexOfMainStream = 0; - numPackStreams = 1; - } - else - { - UInt32 i; - if (numOutStreams == 0) - ThrowUnsupported(); - CNum numBindPairs = numOutStreams - 1; - if (numInStreams < numBindPairs) - ThrowUnsupported(); - if (numInStreams >= 256 || numOutStreams >= 256) - ThrowUnsupported(); - - InStreamUsed.ClearAndSetSize(numInStreams); - for (i = 0; i < numInStreams; i++) - InStreamUsed[i] = false; - - OutStreamUsed.ClearAndSetSize(numOutStreams); - for (i = 0; i < numOutStreams; i++) - OutStreamUsed[i] = false; - - for (i = 0; i < numBindPairs; i++) - { - CNum index = ReadNum(); - if (index >= numInStreams || InStreamUsed[index]) - ThrowUnsupported(); - InStreamUsed[index] = true; - index = ReadNum(); - if (index >= numOutStreams || OutStreamUsed[index]) - ThrowUnsupported(); - OutStreamUsed[index] = true; - } - - numPackStreams = numInStreams - numBindPairs; - - if (numPackStreams != 1) - for (i = 0; i < numPackStreams; i++) - inByte->ReadNum(); // PackStreams - - for (i = 0; i < numOutStreams; i++) - if (!OutStreamUsed[i]) - { - indexOfMainStream = i; - break; - } - if (i == numOutStreams) - ThrowUnsupported(); - } - folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; - numCodersOutStreams += numOutStreams; - folders.FoStartPackStreamIndex[fo] = packStreamIndex; - packStreamIndex += numPackStreams; - folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; - } - size_t dataSize = _inByteBack->GetPtr() - startBufPtr; - folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; - folders.FoStartPackStreamIndex[fo] = packStreamIndex; - folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; - folders.CodersData.CopyFrom(startBufPtr, dataSize); - } - - WaitId(NID::kCodersUnpackSize); - folders.CoderUnpackSizes.Alloc(numCodersOutStreams); - for (CNum i = 0; i < numCodersOutStreams; i++) - folders.CoderUnpackSizes[i] = ReadNumber(); - - for (;;) - { - UInt64 type = ReadID(); - if (type == NID::kEnd) - return; - if (type == NID::kCRC) - { - ReadHashDigests(numFolders, folders.FolderCRCs); - continue; - } - SkipData(); - } -} - -void CInArchive::ReadSubStreamsInfo( - CFolders &folders, - CRecordVector<UInt64> &unpackSizes, - CUInt32DefVector &digests) -{ - folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); - CNum i; - for (i = 0; i < folders.NumFolders; i++) - folders.NumUnpackStreamsVector[i] = 1; - - UInt64 type; - - for (;;) - { - type = ReadID(); - if (type == NID::kNumUnpackStream) - { - for (i = 0; i < folders.NumFolders; i++) - folders.NumUnpackStreamsVector[i] = ReadNum(); - continue; - } - if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) - break; - SkipData(); - } - - if (type == NID::kSize) - { - for (i = 0; i < folders.NumFolders; i++) - { - // v3.13 incorrectly worked with empty folders - // v4.07: we check that folder is empty - CNum numSubstreams = folders.NumUnpackStreamsVector[i]; - if (numSubstreams == 0) - continue; - UInt64 sum = 0; - for (CNum j = 1; j < numSubstreams; j++) - { - UInt64 size = ReadNumber(); - unpackSizes.Add(size); - sum += size; - if (sum < size) - ThrowIncorrect(); - } - UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); - if (folderUnpackSize < sum) - ThrowIncorrect(); - unpackSizes.Add(folderUnpackSize - sum); - } - type = ReadID(); - } - else - { - for (i = 0; i < folders.NumFolders; i++) - { - /* v9.26 - v9.29 incorrectly worked: - if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ - CNum val = folders.NumUnpackStreamsVector[i]; - if (val > 1) - ThrowIncorrect(); - if (val == 1) - unpackSizes.Add(folders.GetFolderUnpackSize(i)); - } - } - - unsigned numDigests = 0; - for (i = 0; i < folders.NumFolders; i++) - { - CNum numSubstreams = folders.NumUnpackStreamsVector[i]; - if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) - numDigests += numSubstreams; - } - - for (;;) - { - if (type == NID::kEnd) - break; - if (type == NID::kCRC) - { - // CUInt32DefVector digests2; - // ReadHashDigests(numDigests, digests2); - CBoolVector digests2; - ReadBoolVector2(numDigests, digests2); - - digests.ClearAndSetSize(unpackSizes.Size()); - - unsigned k = 0; - unsigned k2 = 0; - - for (i = 0; i < folders.NumFolders; i++) - { - CNum numSubstreams = folders.NumUnpackStreamsVector[i]; - if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) - { - digests.Defs[k] = true; - digests.Vals[k] = folders.FolderCRCs.Vals[i]; - k++; - } - else for (CNum j = 0; j < numSubstreams; j++) - { - bool defined = digests2[k2++]; - digests.Defs[k] = defined; - UInt32 crc = 0; - if (defined) - crc = ReadUInt32(); - digests.Vals[k] = crc; - k++; - } - } - // if (k != unpackSizes.Size()) throw 1234567; - } - else - SkipData(); - - type = ReadID(); - } - - if (digests.Defs.Size() != unpackSizes.Size()) - { - digests.ClearAndSetSize(unpackSizes.Size()); - unsigned k = 0; - for (i = 0; i < folders.NumFolders; i++) - { - CNum numSubstreams = folders.NumUnpackStreamsVector[i]; - if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) - { - digests.Defs[k] = true; - digests.Vals[k] = folders.FolderCRCs.Vals[i]; - k++; - } - else for (CNum j = 0; j < numSubstreams; j++) - { - digests.Defs[k] = false; - digests.Vals[k] = 0; - k++; - } - } - } -} - -void CInArchive::ReadStreamsInfo( - const CObjectVector<CByteBuffer> *dataVector, - UInt64 &dataOffset, - CFolders &folders, - CRecordVector<UInt64> &unpackSizes, - CUInt32DefVector &digests) -{ - UInt64 type = ReadID(); - - if (type == NID::kPackInfo) - { - dataOffset = ReadNumber(); - ReadPackInfo(folders); - type = ReadID(); - } - - if (type == NID::kUnpackInfo) - { - ReadUnpackInfo(dataVector, folders); - type = ReadID(); - } - - if (folders.NumFolders != 0 && !folders.PackPositions) - { - // if there are folders, we need PackPositions also - folders.PackPositions.Alloc(1); - folders.PackPositions[0] = 0; - } - - if (type == NID::kSubStreamsInfo) - { - ReadSubStreamsInfo(folders, unpackSizes, digests); - type = ReadID(); - } - else - { - folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); - /* If digests.Defs.Size() == 0, it means that there are no crcs. - So we don't need to fill digests with values. */ - // digests.Vals.ClearAndSetSize(folders.NumFolders); - // BoolVector_Fill_False(digests.Defs, folders.NumFolders); - for (CNum i = 0; i < folders.NumFolders; i++) - { - folders.NumUnpackStreamsVector[i] = 1; - unpackSizes.Add(folders.GetFolderUnpackSize(i)); - // digests.Vals[i] = 0; - } - } - - if (type != NID::kEnd) - ThrowIncorrect(); -} - -void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) -{ - v.ClearAndSetSize(numItems); - Byte b = 0; - Byte mask = 0; - bool *p = &v[0]; - for (unsigned i = 0; i < numItems; i++) - { - if (mask == 0) - { - b = ReadByte(); - mask = 0x80; - } - p[i] = ((b & mask) != 0); - mask >>= 1; - } -} - -void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) -{ - Byte allAreDefined = ReadByte(); - if (allAreDefined == 0) - { - ReadBoolVector(numItems, v); - return; - } - v.ClearAndSetSize(numItems); - bool *p = &v[0]; - for (unsigned i = 0; i < numItems; i++) - p[i] = true; -} - -void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, - CUInt64DefVector &v, unsigned numItems) -{ - ReadBoolVector2(numItems, v.Defs); - - CStreamSwitch streamSwitch; - streamSwitch.Set(this, &dataVector); - - v.Vals.ClearAndSetSize(numItems); - UInt64 *p = &v.Vals[0]; - const bool *defs = &v.Defs[0]; - - for (unsigned i = 0; i < numItems; i++) - { - UInt64 t = 0; - if (defs[i]) - t = ReadUInt64(); - p[i] = t; - } -} - -HRESULT CInArchive::ReadAndDecodePackedStreams( - DECL_EXTERNAL_CODECS_LOC_VARS - UInt64 baseOffset, - UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector - _7Z_DECODER_CRYPRO_VARS_DECL - ) -{ - CFolders folders; - CRecordVector<UInt64> unpackSizes; - CUInt32DefVector digests; - - ReadStreamsInfo(NULL, - dataOffset, - folders, - unpackSizes, - digests); - - CDecoder decoder( - #ifdef _ST_MODE - false - #else - true - #endif - ); - - for (CNum i = 0; i < folders.NumFolders; i++) - { - CByteBuffer &data = dataVector.AddNew(); - UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); - size_t unpackSize = (size_t)unpackSize64; - if (unpackSize != unpackSize64) - ThrowUnsupported(); - data.Alloc(unpackSize); - - CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; - CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; - outStreamSpec->Init(data, unpackSize); - - HRESULT result = decoder.Decode( - EXTERNAL_CODECS_LOC_VARS - _stream, baseOffset + dataOffset, - folders, i, - outStream, NULL - _7Z_DECODER_CRYPRO_VARS - #if !defined(_7ZIP_ST) && !defined(_SFX) - , false, 1 - #endif - ); - RINOK(result); - - if (folders.FolderCRCs.ValidAndDefined(i)) - if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) - ThrowIncorrect(); - } - HeadersSize += folders.PackPositions[folders.NumPackStreams]; - return S_OK; -} - -HRESULT CInArchive::ReadHeader( - DECL_EXTERNAL_CODECS_LOC_VARS - CDbEx &db - _7Z_DECODER_CRYPRO_VARS_DECL - ) -{ - UInt64 type = ReadID(); - - if (type == NID::kArchiveProperties) - { - ReadArchiveProperties(db.ArcInfo); - type = ReadID(); - } - - CObjectVector<CByteBuffer> dataVector; - - if (type == NID::kAdditionalStreamsInfo) - { - HRESULT result = ReadAndDecodePackedStreams( - EXTERNAL_CODECS_LOC_VARS - db.ArcInfo.StartPositionAfterHeader, - db.ArcInfo.DataStartPosition2, - dataVector - _7Z_DECODER_CRYPRO_VARS - ); - RINOK(result); - db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; - type = ReadID(); - } - - CRecordVector<UInt64> unpackSizes; - CUInt32DefVector digests; - - if (type == NID::kMainStreamsInfo) - { - ReadStreamsInfo(&dataVector, - db.ArcInfo.DataStartPosition, - (CFolders &)db, - unpackSizes, - digests); - db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader; - type = ReadID(); - } - - db.Files.Clear(); - - if (type == NID::kFilesInfo) - { - - CNum numFiles = ReadNum(); - db.Files.ClearAndSetSize(numFiles); - CNum i; - /* - db.Files.Reserve(numFiles); - CNum i; - for (i = 0; i < numFiles; i++) - db.Files.Add(CFileItem()); - */ - - db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); - // if (!db.PackSizes.IsEmpty()) - db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); - if (numFiles > 0 && !digests.Defs.IsEmpty()) - db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); - - CBoolVector emptyStreamVector; - BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles); - CBoolVector emptyFileVector; - CBoolVector antiFileVector; - CNum numEmptyStreams = 0; - - for (;;) - { - UInt64 type = ReadID(); - if (type == NID::kEnd) - break; - UInt64 size = ReadNumber(); - if (size > _inByteBack->GetRem()) - ThrowIncorrect(); - CStreamSwitch switchProp; - switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); - bool addPropIdToList = true; - bool isKnownType = true; - if (type > ((UInt32)1 << 30)) - isKnownType = false; - else switch((UInt32)type) - { - case NID::kName: - { - CStreamSwitch streamSwitch; - streamSwitch.Set(this, &dataVector); - size_t rem = _inByteBack->GetRem(); - db.NamesBuf.Alloc(rem); - ReadBytes(db.NamesBuf, rem); - db.NameOffsets.Alloc(db.Files.Size() + 1); - size_t pos = 0; - unsigned i; - for (i = 0; i < db.Files.Size(); i++) - { - size_t curRem = (rem - pos) / 2; - const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); - size_t j; - for (j = 0; j < curRem && buf[j] != 0; j++); - if (j == curRem) - ThrowEndOfData(); - db.NameOffsets[i] = pos / 2; - pos += j * 2 + 2; - } - db.NameOffsets[i] = pos / 2; - if (pos != rem) - ThereIsHeaderError = true; - break; - } - case NID::kWinAttrib: - { - CBoolVector boolVector; - ReadBoolVector2(db.Files.Size(), boolVector); - CStreamSwitch streamSwitch; - streamSwitch.Set(this, &dataVector); - for (i = 0; i < numFiles; i++) - { - CFileItem &file = db.Files[i]; - file.AttribDefined = boolVector[i]; - if (file.AttribDefined) - file.Attrib = ReadUInt32(); - } - break; - } - /* - case NID::kIsAux: - { - ReadBoolVector(db.Files.Size(), db.IsAux); - break; - } - case NID::kParent: - { - db.IsTree = true; - // CBoolVector boolVector; - // ReadBoolVector2(db.Files.Size(), boolVector); - // CStreamSwitch streamSwitch; - // streamSwitch.Set(this, &dataVector); - CBoolVector boolVector; - ReadBoolVector2(db.Files.Size(), boolVector); - - db.ThereAreAltStreams = false; - for (i = 0; i < numFiles; i++) - { - CFileItem &file = db.Files[i]; - // file.Parent = -1; - // if (boolVector[i]) - file.Parent = (int)ReadUInt32(); - file.IsAltStream = !boolVector[i]; - if (file.IsAltStream) - db.ThereAreAltStreams = true; - } - break; - } - */ - case NID::kEmptyStream: - { - ReadBoolVector(numFiles, emptyStreamVector); - numEmptyStreams = 0; - for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) - if (emptyStreamVector[i]) - numEmptyStreams++; - - BoolVector_Fill_False(emptyFileVector, numEmptyStreams); - BoolVector_Fill_False(antiFileVector, numEmptyStreams); - - break; - } - case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; - case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; - case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; - case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; - case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; - case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; - case NID::kDummy: - { - for (UInt64 j = 0; j < size; j++) - if (ReadByte() != 0) - ThereIsHeaderError = true; - addPropIdToList = false; - break; - } - /* - case NID::kNtSecure: - { - try - { - { - CStreamSwitch streamSwitch; - streamSwitch.Set(this, &dataVector); - UInt32 numDescriptors = ReadUInt32(); - size_t offset = 0; - db.SecureOffsets.Clear(); - for (i = 0; i < numDescriptors; i++) - { - UInt32 size = ReadUInt32(); - db.SecureOffsets.Add(offset); - offset += size; - } - // ThrowIncorrect();; - db.SecureOffsets.Add(offset); - db.SecureBuf.SetCapacity(offset); - for (i = 0; i < numDescriptors; i++) - { - offset = db.SecureOffsets[i]; - ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); - } - db.SecureIDs.Clear(); - for (unsigned i = 0; i < db.Files.Size(); i++) - { - db.SecureIDs.Add(ReadNum()); - // db.SecureIDs.Add(ReadUInt32()); - } - // ReadUInt32(); - if (_inByteBack->GetRem() != 0) - ThrowIncorrect();; - } - } - catch(CInArchiveException &) - { - ThereIsHeaderError = true; - addPropIdToList = isKnownType = false; - db.ClearSecure(); - } - break; - } - */ - default: - addPropIdToList = isKnownType = false; - } - if (isKnownType) - { - if (addPropIdToList) - db.ArcInfo.FileInfoPopIDs.Add(type); - } - else - { - db.UnsupportedFeatureWarning = true; - _inByteBack->SkipRem(); - } - // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) - if (_inByteBack->GetRem() != 0) - ThrowIncorrect(); - } - - type = ReadID(); // Read (NID::kEnd) end of headers - - CNum emptyFileIndex = 0; - CNum sizeIndex = 0; - - CNum numAntiItems = 0; - for (i = 0; i < numEmptyStreams; i++) - if (antiFileVector[i]) - numAntiItems++; - - for (i = 0; i < numFiles; i++) - { - CFileItem &file = db.Files[i]; - bool isAnti; - file.HasStream = !emptyStreamVector[i]; - file.Crc = 0; - if (file.HasStream) - { - file.IsDir = false; - isAnti = false; - file.Size = unpackSizes[sizeIndex]; - file.CrcDefined = digests.ValidAndDefined(sizeIndex); - if (file.CrcDefined) - file.Crc = digests.Vals[sizeIndex]; - sizeIndex++; - } - else - { - file.IsDir = !emptyFileVector[emptyFileIndex]; - isAnti = antiFileVector[emptyFileIndex]; - emptyFileIndex++; - file.Size = 0; - file.CrcDefined = false; - } - if (numAntiItems != 0) - db.IsAnti.Add(isAnti); - } - } - db.FillLinks(); - /* - if (type != NID::kEnd) - ThrowIncorrect(); - if (_inByteBack->GetRem() != 0) - ThrowIncorrect(); - */ - return S_OK; -} - -void CDbEx::FillLinks() -{ - FolderStartFileIndex.ClearAndSetSize(NumFolders); - - FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size()); - - CNum folderIndex = 0; - CNum indexInFolder = 0; - unsigned i; - for (i = 0; i < Files.Size(); i++) - { - bool emptyStream = !Files[i].HasStream; - if (indexInFolder == 0) - { - if (emptyStream) - { - FileIndexToFolderIndexMap[i] = kNumNoIndex; - continue; - } - // v3.13 incorrectly worked with empty folders - // v4.07: we skip empty folders - for (;;) - { - if (folderIndex >= NumFolders) - ThrowIncorrect(); - FolderStartFileIndex[folderIndex] = i; - if (NumUnpackStreamsVector[folderIndex] != 0) - break; - folderIndex++; - } - } - FileIndexToFolderIndexMap[i] = folderIndex; - if (emptyStream) - continue; - if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) - { - folderIndex++; - indexInFolder = 0; - } - } - - if (indexInFolder != 0) - folderIndex++; - /* - if (indexInFolder != 0) - ThrowIncorrect(); - */ - for (;;) - { - if (folderIndex >= NumFolders) - return; - FolderStartFileIndex[folderIndex] = i; - /* - if (NumUnpackStreamsVector[folderIndex] != 0) - ThrowIncorrect();; - */ - folderIndex++; - } -} - -HRESULT CInArchive::ReadDatabase2( - DECL_EXTERNAL_CODECS_LOC_VARS - CDbEx &db - _7Z_DECODER_CRYPRO_VARS_DECL - ) -{ - db.Clear(); - db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; - - db.ArcInfo.Version.Major = _header[6]; - db.ArcInfo.Version.Minor = _header[7]; - - if (db.ArcInfo.Version.Major != kMajorVersion) - { - // db.UnsupportedVersion = true; - return S_FALSE; - } - - UInt64 nextHeaderOffset = Get64(_header + 12); - UInt64 nextHeaderSize = Get64(_header + 20); - UInt32 nextHeaderCRC = Get32(_header + 28); - - #ifdef FORMAT_7Z_RECOVERY - UInt32 crcFromArc = Get32(_header + 8); - if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) - { - UInt64 cur, fileSize; - RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); - const unsigned kCheckSize = 512; - Byte buf[kCheckSize]; - RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); - UInt64 rem = fileSize - cur; - unsigned checkSize = kCheckSize; - if (rem < kCheckSize) - checkSize = (unsigned)(rem); - if (checkSize < 3) - return S_FALSE; - RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); - - if (buf[checkSize - 1] != 0) - return S_FALSE; - - unsigned i; - for (i = checkSize - 2;; i--) - { - if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || - buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) - break; - if (i == 0) - return S_FALSE; - } - nextHeaderSize = checkSize - i; - nextHeaderOffset = rem - nextHeaderSize; - nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); - RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); - db.StartHeaderWasRecovered = true; - } - else - #endif - { - // Crc was tested already at signature check - // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); - } - - db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; - db.PhySize = kHeaderSize; - - db.IsArc = false; - if ((Int64)nextHeaderOffset < 0 || - nextHeaderSize > ((UInt64)1 << 62)) - return S_FALSE; - if (nextHeaderSize == 0) - { - if (nextHeaderOffset != 0) - return S_FALSE; - db.IsArc = true; - return S_OK; - } - - if (!db.StartHeaderWasRecovered) - db.IsArc = true; - - HeadersSize += kHeaderSize + nextHeaderSize; - db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; - if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) - { - db.UnexpectedEnd = true; - return S_FALSE; - } - RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); - - size_t nextHeaderSize_t = (size_t)nextHeaderSize; - if (nextHeaderSize_t != nextHeaderSize) - return E_OUTOFMEMORY; - CByteBuffer buffer2(nextHeaderSize_t); - - RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)); - - if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) - ThrowIncorrect(); - - if (!db.StartHeaderWasRecovered) - db.PhySizeWasConfirmed = true; - - CStreamSwitch streamSwitch; - streamSwitch.Set(this, buffer2); - - CObjectVector<CByteBuffer> dataVector; - - UInt64 type = ReadID(); - if (type != NID::kHeader) - { - if (type != NID::kEncodedHeader) - ThrowIncorrect(); - HRESULT result = ReadAndDecodePackedStreams( - EXTERNAL_CODECS_LOC_VARS - db.ArcInfo.StartPositionAfterHeader, - db.ArcInfo.DataStartPosition2, - dataVector - _7Z_DECODER_CRYPRO_VARS - ); - RINOK(result); - if (dataVector.Size() == 0) - return S_OK; - if (dataVector.Size() > 1) - ThrowIncorrect(); - streamSwitch.Remove(); - streamSwitch.Set(this, dataVector.Front()); - if (ReadID() != NID::kHeader) - ThrowIncorrect(); - } - - db.IsArc = true; - - db.HeadersSize = HeadersSize; - - return ReadHeader( - EXTERNAL_CODECS_LOC_VARS - db - _7Z_DECODER_CRYPRO_VARS - ); -} - -HRESULT CInArchive::ReadDatabase( - DECL_EXTERNAL_CODECS_LOC_VARS - CDbEx &db - _7Z_DECODER_CRYPRO_VARS_DECL - ) -{ - try - { - HRESULT res = ReadDatabase2( - EXTERNAL_CODECS_LOC_VARS db - _7Z_DECODER_CRYPRO_VARS - ); - if (ThereIsHeaderError) - db.ThereIsHeaderError = true; - if (res == E_NOTIMPL) - ThrowUnsupported(); - return res; - } - catch(CUnsupportedFeatureException &) - { - db.UnsupportedFeatureError = true; - return S_FALSE; - } - catch(CInArchiveException &) - { - db.ThereIsHeaderError = true; - return S_FALSE; - } -} - -}} |