diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp | 153 |
1 files changed, 95 insertions, 58 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp b/3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp index 05fd80de3fd..5498c590cee 100644 --- a/3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/3rdparty/lzma/CPP/7zip/Archive/7z/7zExtract.cpp @@ -16,10 +16,11 @@ namespace NArchive { namespace N7z { -class CFolderOutStream: - public ISequentialOutStream, - public CMyUnknownImp -{ +Z7_CLASS_IMP_COM_1( + CFolderOutStream + , ISequentialOutStream + /* , ICompressGetSubStreamSize */ +) CMyComPtr<ISequentialOutStream> _stream; public: bool TestMode; @@ -31,6 +32,7 @@ private: UInt64 _rem; const UInt32 *_indexes; + // unsigned _startIndex; unsigned _numFiles; unsigned _fileIndex; @@ -40,8 +42,6 @@ private: HRESULT ProcessEmptyFiles(); public: - MY_UNKNOWN_IMP1(ISequentialOutStream) - const CDbEx *_db; CMyComPtr<IArchiveExtractCallback> ExtractCallback; @@ -52,8 +52,6 @@ public: CheckCrc(true) {} - STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); - HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles); HRESULT FlushCorrupted(Int32 callbackOperationResult); @@ -63,6 +61,7 @@ public: HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles) { + // _startIndex = startIndex; _fileIndex = startIndex; _indexes = indexes; _numFiles = numFiles; @@ -76,11 +75,10 @@ HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsig HRESULT CFolderOutStream::OpenFile(bool isCorrupted) { const CFileItem &fi = _db->Files[_fileIndex]; - UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); - Int32 askMode = (_fileIndex == nextFileIndex) ? - (TestMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract) : + const UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); + Int32 askMode = (_fileIndex == nextFileIndex) ? TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract : NExtract::NAskMode::kSkip; if (isCorrupted @@ -90,7 +88,7 @@ HRESULT CFolderOutStream::OpenFile(bool isCorrupted) askMode = NExtract::NAskMode::kTest; CMyComPtr<ISequentialOutStream> realOutStream; - RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)); + RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)) _stream = realOutStream; _crc = CRC_INIT_VAL; @@ -136,13 +134,13 @@ HRESULT CFolderOutStream::ProcessEmptyFiles() { while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0) { - RINOK(OpenFile()); - RINOK(CloseFile()); + RINOK(OpenFile()) + RINOK(CloseFile()) } return S_OK; } -STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +Z7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; @@ -152,6 +150,12 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc if (_fileIsOpen) { UInt32 cur = (size < _rem ? size : (UInt32)_rem); + if (_calcCrc) + { + const UInt32 k_Step = (UInt32)1 << 20; + if (cur > k_Step) + cur = k_Step; + } HRESULT result = S_OK; if (_stream) result = _stream->Write(data, cur, &cur); @@ -164,16 +168,16 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc _rem -= cur; if (_rem == 0) { - RINOK(CloseFile()); - RINOK(ProcessEmptyFiles()); + RINOK(CloseFile()) + RINOK(ProcessEmptyFiles()) } - RINOK(result); + RINOK(result) if (cur == 0) break; continue; } - RINOK(ProcessEmptyFiles()); + RINOK(ProcessEmptyFiles()) if (_numFiles == 0) { // we support partial extracting @@ -186,7 +190,7 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc // return S_FALSE; return k_My_HRESULT_WritingWasCut; } - RINOK(OpenFile()); + RINOK(OpenFile()) } return S_OK; @@ -198,19 +202,37 @@ HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) { if (_fileIsOpen) { - RINOK(CloseFile_and_SetResult(callbackOperationResult)); + RINOK(CloseFile_and_SetResult(callbackOperationResult)) } else { - RINOK(OpenFile(true)); + RINOK(OpenFile(true)) } } return S_OK; } -STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, - Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) +/* +Z7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) +{ + *value = 0; + // const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex; + const unsigned numFiles_Original = _numFiles; + if (subStream >= numFiles_Original) + return S_FALSE; // E_FAIL; + *value = _db->Files[_startIndex + (unsigned)subStream].Size; + return S_OK; +} +*/ + + +Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)) { + // for GCC + // CFolderOutStream *folderOutStream = new CFolderOutStream; + // CMyComPtr<ISequentialOutStream> outStream(folderOutStream); + COM_TRY_BEGIN CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; @@ -219,7 +241,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, // numItems = (UInt32)(Int32)-1; - bool allFilesMode = (numItems == (UInt32)(Int32)-1); + const bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _db.Files.Size(); @@ -234,8 +256,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (i = 0; i < numItems; i++) { - UInt32 fileIndex = allFilesMode ? i : indices[i]; - CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; + const UInt32 fileIndex = allFilesMode ? i : indices[i]; + const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) continue; if (folderIndex != prevFolder || fileIndex < nextFile) @@ -247,7 +269,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } } - RINOK(extractCallback->SetTotal(importantTotalUnpacked)); + RINOK(extractCallback->SetTotal(importantTotalUnpacked)) CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; @@ -258,8 +280,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, false #elif !defined(USE_MIXER_ST) true - #elif !defined(__7Z_SET_PROPERTIES) - #ifdef _7ZIP_ST + #elif !defined(Z7_7Z_SET_PROPERTIES) + #ifdef Z7_ST false #else true @@ -271,8 +293,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 curPacked, curUnpacked; - CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage; - extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage); + CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage; + extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage); CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); @@ -284,7 +306,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked) { - RINOK(lps->SetCur()); + RINOK(lps->SetCur()) if (i >= numItems) break; @@ -293,7 +315,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, curPacked = 0; UInt32 fileIndex = allFilesMode ? i : indices[i]; - CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; + const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; UInt32 numSolidFiles = 1; @@ -306,7 +328,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, for (k = i + 1; k < numItems; k++) { - UInt32 fileIndex2 = allFilesMode ? k : indices[k]; + const UInt32 fileIndex2 = allFilesMode ? k : indices[k]; if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex || fileIndex2 < nextFile) break; @@ -320,20 +342,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } { - HRESULT result = folderOutStream->Init(fileIndex, + const HRESULT result = folderOutStream->Init(fileIndex, allFilesMode ? NULL : indices + i, numSolidFiles); i += numSolidFiles; - RINOK(result); + RINOK(result) } - // to test solid block with zero unpacked size we disable that code if (folderOutStream->WasWritingFinished()) + { + // for debug: to test zero size stream unpacking + // if (folderIndex == kNumNoIndex) // enable this check for debug continue; + } + + if (folderIndex == kNumNoIndex) + return E_FAIL; - #ifndef _NO_CRYPTO + #ifndef Z7_NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); @@ -341,14 +369,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, try { - #ifndef _NO_CRYPTO + #ifndef Z7_NO_CRYPTO bool isEncrypted = false; bool passwordIsDefined = false; - UString password; + UString_Wipe password; #endif + bool dataAfterEnd_Error = false; - HRESULT result = decoder.Decode( + const HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS _inStream, _db.ArcInfo.DataStartPosition, @@ -358,29 +387,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, outStream, progress, NULL // *inStreamMainRes + , dataAfterEnd_Error - _7Z_DECODER_CRYPRO_VARS - #if !defined(_7ZIP_ST) && !defined(_SFX) - , true, _numThreads + Z7_7Z_DECODER_CRYPRO_VARS + #if !defined(Z7_ST) + , true, _numThreads, _memUsage_Decompress #endif ); - if (result == S_FALSE || result == E_NOTIMPL) + if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error) { - bool wasFinished = folderOutStream->WasWritingFinished(); - - int resOp = (result == S_FALSE ? - NExtract::NOperationResult::kDataError : - NExtract::NOperationResult::kUnsupportedMethod); + const bool wasFinished = folderOutStream->WasWritingFinished(); - RINOK(folderOutStream->FlushCorrupted(resOp)); + int resOp = NExtract::NOperationResult::kDataError; + + if (result != S_FALSE) + { + if (result == E_NOTIMPL) + resOp = NExtract::NOperationResult::kUnsupportedMethod; + else if (wasFinished && dataAfterEnd_Error) + resOp = NExtract::NOperationResult::kDataAfterEnd; + } + + RINOK(folderOutStream->FlushCorrupted(resOp)) if (wasFinished) { // we don't show error, if it's after required files if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage) { - RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)); + RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)) } } continue; @@ -389,14 +425,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (result != S_OK) return result; - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) continue; } catch(...) { - RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) // continue; - return E_FAIL; + // return E_FAIL; + throw; } } |