1*f6dc9357SAndroid Build Coastguard Worker // 7zExtract.cpp 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h" 4*f6dc9357SAndroid Build Coastguard Worker 5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h" 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h" 10*f6dc9357SAndroid Build Coastguard Worker 11*f6dc9357SAndroid Build Coastguard Worker #include "7zDecode.h" 12*f6dc9357SAndroid Build Coastguard Worker #include "7zHandler.h" 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker // EXTERN_g_ExternalCodecs 15*f6dc9357SAndroid Build Coastguard Worker 16*f6dc9357SAndroid Build Coastguard Worker namespace NArchive { 17*f6dc9357SAndroid Build Coastguard Worker namespace N7z { 18*f6dc9357SAndroid Build Coastguard Worker 19*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1( 20*f6dc9357SAndroid Build Coastguard Worker CFolderOutStream 21*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream 22*f6dc9357SAndroid Build Coastguard Worker /* , ICompressGetSubStreamSize */ 23*f6dc9357SAndroid Build Coastguard Worker ) 24*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> _stream; 25*f6dc9357SAndroid Build Coastguard Worker public: 26*f6dc9357SAndroid Build Coastguard Worker bool TestMode; 27*f6dc9357SAndroid Build Coastguard Worker bool CheckCrc; 28*f6dc9357SAndroid Build Coastguard Worker private: 29*f6dc9357SAndroid Build Coastguard Worker bool _fileIsOpen; 30*f6dc9357SAndroid Build Coastguard Worker bool _calcCrc; 31*f6dc9357SAndroid Build Coastguard Worker UInt32 _crc; 32*f6dc9357SAndroid Build Coastguard Worker UInt64 _rem; 33*f6dc9357SAndroid Build Coastguard Worker 34*f6dc9357SAndroid Build Coastguard Worker const UInt32 *_indexes; 35*f6dc9357SAndroid Build Coastguard Worker // unsigned _startIndex; 36*f6dc9357SAndroid Build Coastguard Worker unsigned _numFiles; 37*f6dc9357SAndroid Build Coastguard Worker unsigned _fileIndex; 38*f6dc9357SAndroid Build Coastguard Worker 39*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenFile(bool isCorrupted = false); 40*f6dc9357SAndroid Build Coastguard Worker HRESULT CloseFile_and_SetResult(Int32 res); 41*f6dc9357SAndroid Build Coastguard Worker HRESULT CloseFile(); 42*f6dc9357SAndroid Build Coastguard Worker HRESULT ProcessEmptyFiles(); 43*f6dc9357SAndroid Build Coastguard Worker 44*f6dc9357SAndroid Build Coastguard Worker public: 45*f6dc9357SAndroid Build Coastguard Worker const CDbEx *_db; 46*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveExtractCallback> ExtractCallback; 47*f6dc9357SAndroid Build Coastguard Worker 48*f6dc9357SAndroid Build Coastguard Worker bool ExtraWriteWasCut; 49*f6dc9357SAndroid Build Coastguard Worker 50*f6dc9357SAndroid Build Coastguard Worker CFolderOutStream(): 51*f6dc9357SAndroid Build Coastguard Worker TestMode(false), 52*f6dc9357SAndroid Build Coastguard Worker CheckCrc(true) 53*f6dc9357SAndroid Build Coastguard Worker {} 54*f6dc9357SAndroid Build Coastguard Worker 55*f6dc9357SAndroid Build Coastguard Worker HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles); 56*f6dc9357SAndroid Build Coastguard Worker HRESULT FlushCorrupted(Int32 callbackOperationResult); 57*f6dc9357SAndroid Build Coastguard Worker 58*f6dc9357SAndroid Build Coastguard Worker bool WasWritingFinished() const { return _numFiles == 0; } 59*f6dc9357SAndroid Build Coastguard Worker }; 60*f6dc9357SAndroid Build Coastguard Worker 61*f6dc9357SAndroid Build Coastguard Worker 62*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles) 63*f6dc9357SAndroid Build Coastguard Worker { 64*f6dc9357SAndroid Build Coastguard Worker // _startIndex = startIndex; 65*f6dc9357SAndroid Build Coastguard Worker _fileIndex = startIndex; 66*f6dc9357SAndroid Build Coastguard Worker _indexes = indexes; 67*f6dc9357SAndroid Build Coastguard Worker _numFiles = numFiles; 68*f6dc9357SAndroid Build Coastguard Worker 69*f6dc9357SAndroid Build Coastguard Worker _fileIsOpen = false; 70*f6dc9357SAndroid Build Coastguard Worker ExtraWriteWasCut = false; 71*f6dc9357SAndroid Build Coastguard Worker 72*f6dc9357SAndroid Build Coastguard Worker return ProcessEmptyFiles(); 73*f6dc9357SAndroid Build Coastguard Worker } 74*f6dc9357SAndroid Build Coastguard Worker 75*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::OpenFile(bool isCorrupted) 76*f6dc9357SAndroid Build Coastguard Worker { 77*f6dc9357SAndroid Build Coastguard Worker const CFileItem &fi = _db->Files[_fileIndex]; 78*f6dc9357SAndroid Build Coastguard Worker const UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); 79*f6dc9357SAndroid Build Coastguard Worker Int32 askMode = (_fileIndex == nextFileIndex) ? TestMode ? 80*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest : 81*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract : 82*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kSkip; 83*f6dc9357SAndroid Build Coastguard Worker 84*f6dc9357SAndroid Build Coastguard Worker if (isCorrupted 85*f6dc9357SAndroid Build Coastguard Worker && askMode == NExtract::NAskMode::kExtract 86*f6dc9357SAndroid Build Coastguard Worker && !_db->IsItemAnti(_fileIndex) 87*f6dc9357SAndroid Build Coastguard Worker && !fi.IsDir) 88*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kTest; 89*f6dc9357SAndroid Build Coastguard Worker 90*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream; 91*f6dc9357SAndroid Build Coastguard Worker RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)) 92*f6dc9357SAndroid Build Coastguard Worker 93*f6dc9357SAndroid Build Coastguard Worker _stream = realOutStream; 94*f6dc9357SAndroid Build Coastguard Worker _crc = CRC_INIT_VAL; 95*f6dc9357SAndroid Build Coastguard Worker _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir); 96*f6dc9357SAndroid Build Coastguard Worker 97*f6dc9357SAndroid Build Coastguard Worker _fileIsOpen = true; 98*f6dc9357SAndroid Build Coastguard Worker _rem = fi.Size; 99*f6dc9357SAndroid Build Coastguard Worker 100*f6dc9357SAndroid Build Coastguard Worker if (askMode == NExtract::NAskMode::kExtract 101*f6dc9357SAndroid Build Coastguard Worker && !realOutStream 102*f6dc9357SAndroid Build Coastguard Worker && !_db->IsItemAnti(_fileIndex) 103*f6dc9357SAndroid Build Coastguard Worker && !fi.IsDir) 104*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip; 105*f6dc9357SAndroid Build Coastguard Worker return ExtractCallback->PrepareOperation(askMode); 106*f6dc9357SAndroid Build Coastguard Worker } 107*f6dc9357SAndroid Build Coastguard Worker 108*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res) 109*f6dc9357SAndroid Build Coastguard Worker { 110*f6dc9357SAndroid Build Coastguard Worker _stream.Release(); 111*f6dc9357SAndroid Build Coastguard Worker _fileIsOpen = false; 112*f6dc9357SAndroid Build Coastguard Worker 113*f6dc9357SAndroid Build Coastguard Worker if (!_indexes) 114*f6dc9357SAndroid Build Coastguard Worker _numFiles--; 115*f6dc9357SAndroid Build Coastguard Worker else if (*_indexes == _fileIndex) 116*f6dc9357SAndroid Build Coastguard Worker { 117*f6dc9357SAndroid Build Coastguard Worker _indexes++; 118*f6dc9357SAndroid Build Coastguard Worker _numFiles--; 119*f6dc9357SAndroid Build Coastguard Worker } 120*f6dc9357SAndroid Build Coastguard Worker 121*f6dc9357SAndroid Build Coastguard Worker _fileIndex++; 122*f6dc9357SAndroid Build Coastguard Worker return ExtractCallback->SetOperationResult(res); 123*f6dc9357SAndroid Build Coastguard Worker } 124*f6dc9357SAndroid Build Coastguard Worker 125*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::CloseFile() 126*f6dc9357SAndroid Build Coastguard Worker { 127*f6dc9357SAndroid Build Coastguard Worker const CFileItem &fi = _db->Files[_fileIndex]; 128*f6dc9357SAndroid Build Coastguard Worker return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ? 129*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK : 130*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kCRCError); 131*f6dc9357SAndroid Build Coastguard Worker } 132*f6dc9357SAndroid Build Coastguard Worker 133*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::ProcessEmptyFiles() 134*f6dc9357SAndroid Build Coastguard Worker { 135*f6dc9357SAndroid Build Coastguard Worker while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0) 136*f6dc9357SAndroid Build Coastguard Worker { 137*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenFile()) 138*f6dc9357SAndroid Build Coastguard Worker RINOK(CloseFile()) 139*f6dc9357SAndroid Build Coastguard Worker } 140*f6dc9357SAndroid Build Coastguard Worker return S_OK; 141*f6dc9357SAndroid Build Coastguard Worker } 142*f6dc9357SAndroid Build Coastguard Worker 143*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)) 144*f6dc9357SAndroid Build Coastguard Worker { 145*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 146*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0; 147*f6dc9357SAndroid Build Coastguard Worker 148*f6dc9357SAndroid Build Coastguard Worker while (size != 0) 149*f6dc9357SAndroid Build Coastguard Worker { 150*f6dc9357SAndroid Build Coastguard Worker if (_fileIsOpen) 151*f6dc9357SAndroid Build Coastguard Worker { 152*f6dc9357SAndroid Build Coastguard Worker UInt32 cur = (size < _rem ? size : (UInt32)_rem); 153*f6dc9357SAndroid Build Coastguard Worker if (_calcCrc) 154*f6dc9357SAndroid Build Coastguard Worker { 155*f6dc9357SAndroid Build Coastguard Worker const UInt32 k_Step = (UInt32)1 << 20; 156*f6dc9357SAndroid Build Coastguard Worker if (cur > k_Step) 157*f6dc9357SAndroid Build Coastguard Worker cur = k_Step; 158*f6dc9357SAndroid Build Coastguard Worker } 159*f6dc9357SAndroid Build Coastguard Worker HRESULT result = S_OK; 160*f6dc9357SAndroid Build Coastguard Worker if (_stream) 161*f6dc9357SAndroid Build Coastguard Worker result = _stream->Write(data, cur, &cur); 162*f6dc9357SAndroid Build Coastguard Worker if (_calcCrc) 163*f6dc9357SAndroid Build Coastguard Worker _crc = CrcUpdate(_crc, data, cur); 164*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 165*f6dc9357SAndroid Build Coastguard Worker *processedSize += cur; 166*f6dc9357SAndroid Build Coastguard Worker data = (const Byte *)data + cur; 167*f6dc9357SAndroid Build Coastguard Worker size -= cur; 168*f6dc9357SAndroid Build Coastguard Worker _rem -= cur; 169*f6dc9357SAndroid Build Coastguard Worker if (_rem == 0) 170*f6dc9357SAndroid Build Coastguard Worker { 171*f6dc9357SAndroid Build Coastguard Worker RINOK(CloseFile()) 172*f6dc9357SAndroid Build Coastguard Worker RINOK(ProcessEmptyFiles()) 173*f6dc9357SAndroid Build Coastguard Worker } 174*f6dc9357SAndroid Build Coastguard Worker RINOK(result) 175*f6dc9357SAndroid Build Coastguard Worker if (cur == 0) 176*f6dc9357SAndroid Build Coastguard Worker break; 177*f6dc9357SAndroid Build Coastguard Worker continue; 178*f6dc9357SAndroid Build Coastguard Worker } 179*f6dc9357SAndroid Build Coastguard Worker 180*f6dc9357SAndroid Build Coastguard Worker RINOK(ProcessEmptyFiles()) 181*f6dc9357SAndroid Build Coastguard Worker if (_numFiles == 0) 182*f6dc9357SAndroid Build Coastguard Worker { 183*f6dc9357SAndroid Build Coastguard Worker // we support partial extracting 184*f6dc9357SAndroid Build Coastguard Worker /* 185*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 186*f6dc9357SAndroid Build Coastguard Worker *processedSize += size; 187*f6dc9357SAndroid Build Coastguard Worker break; 188*f6dc9357SAndroid Build Coastguard Worker */ 189*f6dc9357SAndroid Build Coastguard Worker ExtraWriteWasCut = true; 190*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE; 191*f6dc9357SAndroid Build Coastguard Worker return k_My_HRESULT_WritingWasCut; 192*f6dc9357SAndroid Build Coastguard Worker } 193*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenFile()) 194*f6dc9357SAndroid Build Coastguard Worker } 195*f6dc9357SAndroid Build Coastguard Worker 196*f6dc9357SAndroid Build Coastguard Worker return S_OK; 197*f6dc9357SAndroid Build Coastguard Worker } 198*f6dc9357SAndroid Build Coastguard Worker 199*f6dc9357SAndroid Build Coastguard Worker HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) 200*f6dc9357SAndroid Build Coastguard Worker { 201*f6dc9357SAndroid Build Coastguard Worker while (_numFiles != 0) 202*f6dc9357SAndroid Build Coastguard Worker { 203*f6dc9357SAndroid Build Coastguard Worker if (_fileIsOpen) 204*f6dc9357SAndroid Build Coastguard Worker { 205*f6dc9357SAndroid Build Coastguard Worker RINOK(CloseFile_and_SetResult(callbackOperationResult)) 206*f6dc9357SAndroid Build Coastguard Worker } 207*f6dc9357SAndroid Build Coastguard Worker else 208*f6dc9357SAndroid Build Coastguard Worker { 209*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenFile(true)) 210*f6dc9357SAndroid Build Coastguard Worker } 211*f6dc9357SAndroid Build Coastguard Worker } 212*f6dc9357SAndroid Build Coastguard Worker return S_OK; 213*f6dc9357SAndroid Build Coastguard Worker } 214*f6dc9357SAndroid Build Coastguard Worker 215*f6dc9357SAndroid Build Coastguard Worker /* 216*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) 217*f6dc9357SAndroid Build Coastguard Worker { 218*f6dc9357SAndroid Build Coastguard Worker *value = 0; 219*f6dc9357SAndroid Build Coastguard Worker // const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex; 220*f6dc9357SAndroid Build Coastguard Worker const unsigned numFiles_Original = _numFiles; 221*f6dc9357SAndroid Build Coastguard Worker if (subStream >= numFiles_Original) 222*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; // E_FAIL; 223*f6dc9357SAndroid Build Coastguard Worker *value = _db->Files[_startIndex + (unsigned)subStream].Size; 224*f6dc9357SAndroid Build Coastguard Worker return S_OK; 225*f6dc9357SAndroid Build Coastguard Worker } 226*f6dc9357SAndroid Build Coastguard Worker */ 227*f6dc9357SAndroid Build Coastguard Worker 228*f6dc9357SAndroid Build Coastguard Worker 229*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 230*f6dc9357SAndroid Build Coastguard Worker Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)) 231*f6dc9357SAndroid Build Coastguard Worker { 232*f6dc9357SAndroid Build Coastguard Worker // for GCC 233*f6dc9357SAndroid Build Coastguard Worker // CFolderOutStream *folderOutStream = new CFolderOutStream; 234*f6dc9357SAndroid Build Coastguard Worker // CMyComPtr<ISequentialOutStream> outStream(folderOutStream); 235*f6dc9357SAndroid Build Coastguard Worker 236*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 237*f6dc9357SAndroid Build Coastguard Worker 238*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; 239*f6dc9357SAndroid Build Coastguard Worker 240*f6dc9357SAndroid Build Coastguard Worker UInt64 importantTotalUnpacked = 0; 241*f6dc9357SAndroid Build Coastguard Worker 242*f6dc9357SAndroid Build Coastguard Worker // numItems = (UInt32)(Int32)-1; 243*f6dc9357SAndroid Build Coastguard Worker 244*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 245*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode) 246*f6dc9357SAndroid Build Coastguard Worker numItems = _db.Files.Size(); 247*f6dc9357SAndroid Build Coastguard Worker 248*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0) 249*f6dc9357SAndroid Build Coastguard Worker return S_OK; 250*f6dc9357SAndroid Build Coastguard Worker 251*f6dc9357SAndroid Build Coastguard Worker { 252*f6dc9357SAndroid Build Coastguard Worker CNum prevFolder = kNumNoIndex; 253*f6dc9357SAndroid Build Coastguard Worker UInt32 nextFile = 0; 254*f6dc9357SAndroid Build Coastguard Worker 255*f6dc9357SAndroid Build Coastguard Worker UInt32 i; 256*f6dc9357SAndroid Build Coastguard Worker 257*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++) 258*f6dc9357SAndroid Build Coastguard Worker { 259*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileIndex = allFilesMode ? i : indices[i]; 260*f6dc9357SAndroid Build Coastguard Worker const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; 261*f6dc9357SAndroid Build Coastguard Worker if (folderIndex == kNumNoIndex) 262*f6dc9357SAndroid Build Coastguard Worker continue; 263*f6dc9357SAndroid Build Coastguard Worker if (folderIndex != prevFolder || fileIndex < nextFile) 264*f6dc9357SAndroid Build Coastguard Worker nextFile = _db.FolderStartFileIndex[folderIndex]; 265*f6dc9357SAndroid Build Coastguard Worker for (CNum index = nextFile; index <= fileIndex; index++) 266*f6dc9357SAndroid Build Coastguard Worker importantTotalUnpacked += _db.Files[index].Size; 267*f6dc9357SAndroid Build Coastguard Worker nextFile = fileIndex + 1; 268*f6dc9357SAndroid Build Coastguard Worker prevFolder = folderIndex; 269*f6dc9357SAndroid Build Coastguard Worker } 270*f6dc9357SAndroid Build Coastguard Worker } 271*f6dc9357SAndroid Build Coastguard Worker 272*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(importantTotalUnpacked)) 273*f6dc9357SAndroid Build Coastguard Worker 274*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; 275*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false); 276*f6dc9357SAndroid Build Coastguard Worker 277*f6dc9357SAndroid Build Coastguard Worker CDecoder decoder( 278*f6dc9357SAndroid Build Coastguard Worker #if !defined(USE_MIXER_MT) 279*f6dc9357SAndroid Build Coastguard Worker false 280*f6dc9357SAndroid Build Coastguard Worker #elif !defined(USE_MIXER_ST) 281*f6dc9357SAndroid Build Coastguard Worker true 282*f6dc9357SAndroid Build Coastguard Worker #elif !defined(Z7_7Z_SET_PROPERTIES) 283*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ST 284*f6dc9357SAndroid Build Coastguard Worker false 285*f6dc9357SAndroid Build Coastguard Worker #else 286*f6dc9357SAndroid Build Coastguard Worker true 287*f6dc9357SAndroid Build Coastguard Worker #endif 288*f6dc9357SAndroid Build Coastguard Worker #else 289*f6dc9357SAndroid Build Coastguard Worker _useMultiThreadMixer 290*f6dc9357SAndroid Build Coastguard Worker #endif 291*f6dc9357SAndroid Build Coastguard Worker ); 292*f6dc9357SAndroid Build Coastguard Worker 293*f6dc9357SAndroid Build Coastguard Worker UInt64 curPacked, curUnpacked; 294*f6dc9357SAndroid Build Coastguard Worker 295*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage; 296*f6dc9357SAndroid Build Coastguard Worker extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage); 297*f6dc9357SAndroid Build Coastguard Worker 298*f6dc9357SAndroid Build Coastguard Worker CFolderOutStream *folderOutStream = new CFolderOutStream; 299*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream(folderOutStream); 300*f6dc9357SAndroid Build Coastguard Worker 301*f6dc9357SAndroid Build Coastguard Worker folderOutStream->_db = &_db; 302*f6dc9357SAndroid Build Coastguard Worker folderOutStream->ExtractCallback = extractCallback; 303*f6dc9357SAndroid Build Coastguard Worker folderOutStream->TestMode = (testModeSpec != 0); 304*f6dc9357SAndroid Build Coastguard Worker folderOutStream->CheckCrc = (_crcSize != 0); 305*f6dc9357SAndroid Build Coastguard Worker 306*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked) 307*f6dc9357SAndroid Build Coastguard Worker { 308*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur()) 309*f6dc9357SAndroid Build Coastguard Worker 310*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems) 311*f6dc9357SAndroid Build Coastguard Worker break; 312*f6dc9357SAndroid Build Coastguard Worker 313*f6dc9357SAndroid Build Coastguard Worker curUnpacked = 0; 314*f6dc9357SAndroid Build Coastguard Worker curPacked = 0; 315*f6dc9357SAndroid Build Coastguard Worker 316*f6dc9357SAndroid Build Coastguard Worker UInt32 fileIndex = allFilesMode ? i : indices[i]; 317*f6dc9357SAndroid Build Coastguard Worker const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; 318*f6dc9357SAndroid Build Coastguard Worker 319*f6dc9357SAndroid Build Coastguard Worker UInt32 numSolidFiles = 1; 320*f6dc9357SAndroid Build Coastguard Worker 321*f6dc9357SAndroid Build Coastguard Worker if (folderIndex != kNumNoIndex) 322*f6dc9357SAndroid Build Coastguard Worker { 323*f6dc9357SAndroid Build Coastguard Worker curPacked = _db.GetFolderFullPackSize(folderIndex); 324*f6dc9357SAndroid Build Coastguard Worker UInt32 nextFile = fileIndex + 1; 325*f6dc9357SAndroid Build Coastguard Worker fileIndex = _db.FolderStartFileIndex[folderIndex]; 326*f6dc9357SAndroid Build Coastguard Worker UInt32 k; 327*f6dc9357SAndroid Build Coastguard Worker 328*f6dc9357SAndroid Build Coastguard Worker for (k = i + 1; k < numItems; k++) 329*f6dc9357SAndroid Build Coastguard Worker { 330*f6dc9357SAndroid Build Coastguard Worker const UInt32 fileIndex2 = allFilesMode ? k : indices[k]; 331*f6dc9357SAndroid Build Coastguard Worker if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex 332*f6dc9357SAndroid Build Coastguard Worker || fileIndex2 < nextFile) 333*f6dc9357SAndroid Build Coastguard Worker break; 334*f6dc9357SAndroid Build Coastguard Worker nextFile = fileIndex2 + 1; 335*f6dc9357SAndroid Build Coastguard Worker } 336*f6dc9357SAndroid Build Coastguard Worker 337*f6dc9357SAndroid Build Coastguard Worker numSolidFiles = k - i; 338*f6dc9357SAndroid Build Coastguard Worker 339*f6dc9357SAndroid Build Coastguard Worker for (k = fileIndex; k < nextFile; k++) 340*f6dc9357SAndroid Build Coastguard Worker curUnpacked += _db.Files[k].Size; 341*f6dc9357SAndroid Build Coastguard Worker } 342*f6dc9357SAndroid Build Coastguard Worker 343*f6dc9357SAndroid Build Coastguard Worker { 344*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = folderOutStream->Init(fileIndex, 345*f6dc9357SAndroid Build Coastguard Worker allFilesMode ? NULL : indices + i, 346*f6dc9357SAndroid Build Coastguard Worker numSolidFiles); 347*f6dc9357SAndroid Build Coastguard Worker 348*f6dc9357SAndroid Build Coastguard Worker i += numSolidFiles; 349*f6dc9357SAndroid Build Coastguard Worker 350*f6dc9357SAndroid Build Coastguard Worker RINOK(result) 351*f6dc9357SAndroid Build Coastguard Worker } 352*f6dc9357SAndroid Build Coastguard Worker 353*f6dc9357SAndroid Build Coastguard Worker if (folderOutStream->WasWritingFinished()) 354*f6dc9357SAndroid Build Coastguard Worker { 355*f6dc9357SAndroid Build Coastguard Worker // for debug: to test zero size stream unpacking 356*f6dc9357SAndroid Build Coastguard Worker // if (folderIndex == kNumNoIndex) // enable this check for debug 357*f6dc9357SAndroid Build Coastguard Worker continue; 358*f6dc9357SAndroid Build Coastguard Worker } 359*f6dc9357SAndroid Build Coastguard Worker 360*f6dc9357SAndroid Build Coastguard Worker if (folderIndex == kNumNoIndex) 361*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 362*f6dc9357SAndroid Build Coastguard Worker 363*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_CRYPTO 364*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICryptoGetTextPassword> getTextPassword; 365*f6dc9357SAndroid Build Coastguard Worker if (extractCallback) 366*f6dc9357SAndroid Build Coastguard Worker extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); 367*f6dc9357SAndroid Build Coastguard Worker #endif 368*f6dc9357SAndroid Build Coastguard Worker 369*f6dc9357SAndroid Build Coastguard Worker try 370*f6dc9357SAndroid Build Coastguard Worker { 371*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_CRYPTO 372*f6dc9357SAndroid Build Coastguard Worker bool isEncrypted = false; 373*f6dc9357SAndroid Build Coastguard Worker bool passwordIsDefined = false; 374*f6dc9357SAndroid Build Coastguard Worker UString_Wipe password; 375*f6dc9357SAndroid Build Coastguard Worker #endif 376*f6dc9357SAndroid Build Coastguard Worker 377*f6dc9357SAndroid Build Coastguard Worker bool dataAfterEnd_Error = false; 378*f6dc9357SAndroid Build Coastguard Worker 379*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = decoder.Decode( 380*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_VARS 381*f6dc9357SAndroid Build Coastguard Worker _inStream, 382*f6dc9357SAndroid Build Coastguard Worker _db.ArcInfo.DataStartPosition, 383*f6dc9357SAndroid Build Coastguard Worker _db, folderIndex, 384*f6dc9357SAndroid Build Coastguard Worker &curUnpacked, 385*f6dc9357SAndroid Build Coastguard Worker 386*f6dc9357SAndroid Build Coastguard Worker outStream, 387*f6dc9357SAndroid Build Coastguard Worker lps, 388*f6dc9357SAndroid Build Coastguard Worker NULL // *inStreamMainRes 389*f6dc9357SAndroid Build Coastguard Worker , dataAfterEnd_Error 390*f6dc9357SAndroid Build Coastguard Worker 391*f6dc9357SAndroid Build Coastguard Worker Z7_7Z_DECODER_CRYPRO_VARS 392*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ST) 393*f6dc9357SAndroid Build Coastguard Worker , true, _numThreads, _memUsage_Decompress 394*f6dc9357SAndroid Build Coastguard Worker #endif 395*f6dc9357SAndroid Build Coastguard Worker ); 396*f6dc9357SAndroid Build Coastguard Worker 397*f6dc9357SAndroid Build Coastguard Worker if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error) 398*f6dc9357SAndroid Build Coastguard Worker { 399*f6dc9357SAndroid Build Coastguard Worker const bool wasFinished = folderOutStream->WasWritingFinished(); 400*f6dc9357SAndroid Build Coastguard Worker 401*f6dc9357SAndroid Build Coastguard Worker int resOp = NExtract::NOperationResult::kDataError; 402*f6dc9357SAndroid Build Coastguard Worker 403*f6dc9357SAndroid Build Coastguard Worker if (result != S_FALSE) 404*f6dc9357SAndroid Build Coastguard Worker { 405*f6dc9357SAndroid Build Coastguard Worker if (result == E_NOTIMPL) 406*f6dc9357SAndroid Build Coastguard Worker resOp = NExtract::NOperationResult::kUnsupportedMethod; 407*f6dc9357SAndroid Build Coastguard Worker else if (wasFinished && dataAfterEnd_Error) 408*f6dc9357SAndroid Build Coastguard Worker resOp = NExtract::NOperationResult::kDataAfterEnd; 409*f6dc9357SAndroid Build Coastguard Worker } 410*f6dc9357SAndroid Build Coastguard Worker 411*f6dc9357SAndroid Build Coastguard Worker RINOK(folderOutStream->FlushCorrupted(resOp)) 412*f6dc9357SAndroid Build Coastguard Worker 413*f6dc9357SAndroid Build Coastguard Worker if (wasFinished) 414*f6dc9357SAndroid Build Coastguard Worker { 415*f6dc9357SAndroid Build Coastguard Worker // we don't show error, if it's after required files 416*f6dc9357SAndroid Build Coastguard Worker if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage) 417*f6dc9357SAndroid Build Coastguard Worker { 418*f6dc9357SAndroid Build Coastguard Worker RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)) 419*f6dc9357SAndroid Build Coastguard Worker } 420*f6dc9357SAndroid Build Coastguard Worker } 421*f6dc9357SAndroid Build Coastguard Worker continue; 422*f6dc9357SAndroid Build Coastguard Worker } 423*f6dc9357SAndroid Build Coastguard Worker 424*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK) 425*f6dc9357SAndroid Build Coastguard Worker return result; 426*f6dc9357SAndroid Build Coastguard Worker 427*f6dc9357SAndroid Build Coastguard Worker RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) 428*f6dc9357SAndroid Build Coastguard Worker continue; 429*f6dc9357SAndroid Build Coastguard Worker } 430*f6dc9357SAndroid Build Coastguard Worker catch(...) 431*f6dc9357SAndroid Build Coastguard Worker { 432*f6dc9357SAndroid Build Coastguard Worker RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)) 433*f6dc9357SAndroid Build Coastguard Worker // continue; 434*f6dc9357SAndroid Build Coastguard Worker // return E_FAIL; 435*f6dc9357SAndroid Build Coastguard Worker throw; 436*f6dc9357SAndroid Build Coastguard Worker } 437*f6dc9357SAndroid Build Coastguard Worker } 438*f6dc9357SAndroid Build Coastguard Worker 439*f6dc9357SAndroid Build Coastguard Worker return S_OK; 440*f6dc9357SAndroid Build Coastguard Worker 441*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 442*f6dc9357SAndroid Build Coastguard Worker } 443*f6dc9357SAndroid Build Coastguard Worker 444*f6dc9357SAndroid Build Coastguard Worker }} 445