| OLD | NEW |
| (Empty) |
| 1 // 7zExtract.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 #include "7zHandler.h" | |
| 6 #include "7zFolderOutStream.h" | |
| 7 #include "7zDecode.h" | |
| 8 // #include "7z1Decode.h" | |
| 9 | |
| 10 #include "../../../Common/ComTry.h" | |
| 11 #include "../../Common/StreamObjects.h" | |
| 12 #include "../../Common/ProgressUtils.h" | |
| 13 #include "../../Common/LimitedStreams.h" | |
| 14 | |
| 15 namespace NArchive { | |
| 16 namespace N7z { | |
| 17 | |
| 18 struct CExtractFolderInfo | |
| 19 { | |
| 20 #ifdef _7Z_VOL | |
| 21 int VolumeIndex; | |
| 22 #endif | |
| 23 CNum FileIndex; | |
| 24 CNum FolderIndex; | |
| 25 CBoolVector ExtractStatuses; | |
| 26 UInt64 UnpackSize; | |
| 27 CExtractFolderInfo( | |
| 28 #ifdef _7Z_VOL | |
| 29 int volumeIndex, | |
| 30 #endif | |
| 31 CNum fileIndex, CNum folderIndex): | |
| 32 #ifdef _7Z_VOL | |
| 33 VolumeIndex(volumeIndex), | |
| 34 #endif | |
| 35 FileIndex(fileIndex), | |
| 36 FolderIndex(folderIndex), | |
| 37 UnpackSize(0) | |
| 38 { | |
| 39 if (fileIndex != kNumNoIndex) | |
| 40 { | |
| 41 ExtractStatuses.Reserve(1); | |
| 42 ExtractStatuses.Add(true); | |
| 43 } | |
| 44 }; | |
| 45 }; | |
| 46 | |
| 47 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
| 48 Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) | |
| 49 { | |
| 50 COM_TRY_BEGIN | |
| 51 bool testMode = (testModeSpec != 0); | |
| 52 CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; | |
| 53 UInt64 importantTotalUnpacked = 0; | |
| 54 | |
| 55 bool allFilesMode = (numItems == UInt32(-1)); | |
| 56 if (allFilesMode) | |
| 57 numItems = | |
| 58 #ifdef _7Z_VOL | |
| 59 _refs.Size(); | |
| 60 #else | |
| 61 _db.Files.Size(); | |
| 62 #endif | |
| 63 | |
| 64 if(numItems == 0) | |
| 65 return S_OK; | |
| 66 | |
| 67 /* | |
| 68 if(_volumes.Size() != 1) | |
| 69 return E_FAIL; | |
| 70 const CVolume &volume = _volumes.Front(); | |
| 71 const CArchiveDatabaseEx &_db = volume.Database; | |
| 72 IInStream *_inStream = volume.Stream; | |
| 73 */ | |
| 74 | |
| 75 CObjectVector<CExtractFolderInfo> extractFolderInfoVector; | |
| 76 for(UInt32 ii = 0; ii < numItems; ii++) | |
| 77 { | |
| 78 // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; | |
| 79 UInt32 ref2Index = allFilesMode ? ii : indices[ii]; | |
| 80 // const CRef2 &ref2 = _refs[ref2Index]; | |
| 81 | |
| 82 // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) | |
| 83 { | |
| 84 #ifdef _7Z_VOL | |
| 85 // const CRef &ref = ref2.Refs[ri]; | |
| 86 const CRef &ref = _refs[ref2Index]; | |
| 87 | |
| 88 int volumeIndex = ref.VolumeIndex; | |
| 89 const CVolume &volume = _volumes[volumeIndex]; | |
| 90 const CArchiveDatabaseEx &db = volume.Database; | |
| 91 UInt32 fileIndex = ref.ItemIndex; | |
| 92 #else | |
| 93 const CArchiveDatabaseEx &db = _db; | |
| 94 UInt32 fileIndex = ref2Index; | |
| 95 #endif | |
| 96 | |
| 97 CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; | |
| 98 if (folderIndex == kNumNoIndex) | |
| 99 { | |
| 100 extractFolderInfoVector.Add(CExtractFolderInfo( | |
| 101 #ifdef _7Z_VOL | |
| 102 volumeIndex, | |
| 103 #endif | |
| 104 fileIndex, kNumNoIndex)); | |
| 105 continue; | |
| 106 } | |
| 107 if (extractFolderInfoVector.IsEmpty() || | |
| 108 folderIndex != extractFolderInfoVector.Back().FolderIndex | |
| 109 #ifdef _7Z_VOL | |
| 110 || volumeIndex != extractFolderInfoVector.Back().VolumeIndex | |
| 111 #endif | |
| 112 ) | |
| 113 { | |
| 114 extractFolderInfoVector.Add(CExtractFolderInfo( | |
| 115 #ifdef _7Z_VOL | |
| 116 volumeIndex, | |
| 117 #endif | |
| 118 kNumNoIndex, folderIndex)); | |
| 119 const CFolder &folderInfo = db.Folders[folderIndex]; | |
| 120 UInt64 unpackSize = folderInfo.GetUnpackSize(); | |
| 121 importantTotalUnpacked += unpackSize; | |
| 122 extractFolderInfoVector.Back().UnpackSize = unpackSize; | |
| 123 } | |
| 124 | |
| 125 CExtractFolderInfo &efi = extractFolderInfoVector.Back(); | |
| 126 | |
| 127 // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; | |
| 128 CNum startIndex = db.FolderStartFileIndex[folderIndex]; | |
| 129 for (CNum index = efi.ExtractStatuses.Size(); | |
| 130 index <= fileIndex - startIndex; index++) | |
| 131 { | |
| 132 // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; | |
| 133 // Count partial_folder_size | |
| 134 // efi.UnpackSize += unpackSize; | |
| 135 // importantTotalUnpacked += unpackSize; | |
| 136 efi.ExtractStatuses.Add(index == fileIndex - startIndex); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 extractCallback->SetTotal(importantTotalUnpacked); | |
| 142 | |
| 143 CDecoder decoder( | |
| 144 #ifdef _ST_MODE | |
| 145 false | |
| 146 #else | |
| 147 true | |
| 148 #endif | |
| 149 ); | |
| 150 // CDecoder1 decoder; | |
| 151 | |
| 152 UInt64 currentTotalPacked = 0; | |
| 153 UInt64 currentTotalUnpacked = 0; | |
| 154 UInt64 totalFolderUnpacked; | |
| 155 UInt64 totalFolderPacked; | |
| 156 | |
| 157 CLocalProgress *lps = new CLocalProgress; | |
| 158 CMyComPtr<ICompressProgressInfo> progress = lps; | |
| 159 lps->Init(extractCallback, false); | |
| 160 | |
| 161 for(int i = 0; i < extractFolderInfoVector.Size(); i++, | |
| 162 currentTotalUnpacked += totalFolderUnpacked, | |
| 163 currentTotalPacked += totalFolderPacked) | |
| 164 { | |
| 165 lps->OutSize = currentTotalUnpacked; | |
| 166 lps->InSize = currentTotalPacked; | |
| 167 RINOK(lps->SetCur()); | |
| 168 | |
| 169 const CExtractFolderInfo &efi = extractFolderInfoVector[i]; | |
| 170 totalFolderUnpacked = efi.UnpackSize; | |
| 171 | |
| 172 totalFolderPacked = 0; | |
| 173 | |
| 174 CFolderOutStream *folderOutStream = new CFolderOutStream; | |
| 175 CMyComPtr<ISequentialOutStream> outStream(folderOutStream); | |
| 176 | |
| 177 #ifdef _7Z_VOL | |
| 178 const CVolume &volume = _volumes[efi.VolumeIndex]; | |
| 179 const CArchiveDatabaseEx &db = volume.Database; | |
| 180 #else | |
| 181 const CArchiveDatabaseEx &db = _db; | |
| 182 #endif | |
| 183 | |
| 184 CNum startIndex; | |
| 185 if (efi.FileIndex != kNumNoIndex) | |
| 186 startIndex = efi.FileIndex; | |
| 187 else | |
| 188 startIndex = db.FolderStartFileIndex[efi.FolderIndex]; | |
| 189 | |
| 190 | |
| 191 HRESULT result = folderOutStream->Init(&db, | |
| 192 #ifdef _7Z_VOL | |
| 193 volume.StartRef2Index, | |
| 194 #else | |
| 195 0, | |
| 196 #endif | |
| 197 startIndex, | |
| 198 &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); | |
| 199 | |
| 200 RINOK(result); | |
| 201 | |
| 202 if (efi.FileIndex != kNumNoIndex) | |
| 203 continue; | |
| 204 | |
| 205 CNum folderIndex = efi.FolderIndex; | |
| 206 const CFolder &folderInfo = db.Folders[folderIndex]; | |
| 207 | |
| 208 totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); | |
| 209 | |
| 210 CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; | |
| 211 UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); | |
| 212 | |
| 213 #ifndef _NO_CRYPTO | |
| 214 CMyComPtr<ICryptoGetTextPassword> getTextPassword; | |
| 215 if (extractCallback) | |
| 216 extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPasswor
d); | |
| 217 #endif | |
| 218 | |
| 219 try | |
| 220 { | |
| 221 #ifndef _NO_CRYPTO | |
| 222 bool passwordIsDefined; | |
| 223 #endif | |
| 224 | |
| 225 HRESULT result = decoder.Decode( | |
| 226 EXTERNAL_CODECS_VARS | |
| 227 #ifdef _7Z_VOL | |
| 228 volume.Stream, | |
| 229 #else | |
| 230 _inStream, | |
| 231 #endif | |
| 232 folderStartPackPos, | |
| 233 &db.PackSizes[packStreamIndex], | |
| 234 folderInfo, | |
| 235 outStream, | |
| 236 progress | |
| 237 #ifndef _NO_CRYPTO | |
| 238 , getTextPassword, passwordIsDefined | |
| 239 #endif | |
| 240 #ifdef COMPRESS_MT | |
| 241 , true, _numThreads | |
| 242 #endif | |
| 243 ); | |
| 244 | |
| 245 if (result == S_FALSE) | |
| 246 { | |
| 247 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResu
lt::kDataError)); | |
| 248 continue; | |
| 249 } | |
| 250 if (result == E_NOTIMPL) | |
| 251 { | |
| 252 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResu
lt::kUnSupportedMethod)); | |
| 253 continue; | |
| 254 } | |
| 255 if (result != S_OK) | |
| 256 return result; | |
| 257 if (folderOutStream->WasWritingFinished() != S_OK) | |
| 258 { | |
| 259 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResu
lt::kDataError)); | |
| 260 continue; | |
| 261 } | |
| 262 } | |
| 263 catch(...) | |
| 264 { | |
| 265 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult
::kDataError)); | |
| 266 continue; | |
| 267 } | |
| 268 } | |
| 269 return S_OK; | |
| 270 COM_TRY_END | |
| 271 } | |
| 272 | |
| 273 }} | |
| OLD | NEW |