Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Archive/Zip/ZipHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // ZipHandler.cpp3 #include "StdAfx.h"5 #include "Common/ComTry.h"6 #include "Common/Defs.h"7 #include "Common/IntToString.h"8 #include "Common/StringConvert.h"10 #include "Windows/PropVariant.h"11 #include "Windows/Time.h"13 #include "../../IPassword.h"15 #include "../../Common/CreateCoder.h"16 #include "../../Common/FilterCoder.h"17 #include "../../Common/ProgressUtils.h"18 #include "../../Common/StreamObjects.h"19 #include "../../Common/StreamUtils.h"21 #include "../../Compress/CopyCoder.h"22 #include "../../Compress/LzmaDecoder.h"23 #include "../../Compress/ImplodeDecoder.h"24 #include "../../Compress/ShrinkDecoder.h"26 #include "../../Crypto/WzAes.h"27 #include "../../Crypto/ZipCrypto.h"28 #include "../../Crypto/ZipStrong.h"30 #include "../Common/ItemNameUtils.h"31 #include "../Common/OutStreamWithCRC.h"33 #include "ZipHandler.h"35 using namespace NWindows;37 namespace NArchive {38 namespace NZip {40 // static const CMethodId kMethodId_Store = 0;41 static const CMethodId kMethodId_ZipBase = 0x040100;42 static const CMethodId kMethodId_BZip2 = 0x040202;44 const wchar_t *kHostOS[] =45 {46 L"FAT",47 L"AMIGA",48 L"VMS",49 L"Unix",50 L"VM/CMS",51 L"Atari",52 L"HPFS",53 L"Macintosh",54 L"Z-System",55 L"CP/M",56 L"TOPS-20",57 L"NTFS",58 L"SMS/QDOS",59 L"Acorn",60 L"VFAT",61 L"MVS",62 L"BeOS",63 L"Tandem",64 L"OS/400",65 L"OS/X"66 };69 static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);71 static const wchar_t *kUnknownOS = L"Unknown";73 STATPROPSTG kProps[] =74 {75 { NULL, kpidPath, VT_BSTR},76 { NULL, kpidIsDir, VT_BOOL},77 { NULL, kpidSize, VT_UI8},78 { NULL, kpidPackSize, VT_UI8},79 { NULL, kpidMTime, VT_FILETIME},80 { NULL, kpidCTime, VT_FILETIME},81 { NULL, kpidATime, VT_FILETIME},83 { NULL, kpidAttrib, VT_UI4},85 { NULL, kpidEncrypted, VT_BOOL},86 { NULL, kpidComment, VT_BSTR},88 { NULL, kpidCRC, VT_UI4},90 { NULL, kpidMethod, VT_BSTR},91 { NULL, kpidHostOS, VT_BSTR}93 // { NULL, kpidUnpackVer, VT_UI1},94 };96 const wchar_t *kMethods[] =97 {98 L"Store",99 L"Shrink",100 L"Reduced1",101 L"Reduced2",102 L"Reduced2",103 L"Reduced3",104 L"Implode",105 L"Tokenizing",106 L"Deflate",107 L"Deflate64",108 L"PKImploding"109 };111 const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);112 const wchar_t *kBZip2Method = L"BZip2";113 const wchar_t *kLZMAMethod = L"LZMA";114 const wchar_t *kJpegMethod = L"Jpeg";115 const wchar_t *kWavPackMethod = L"WavPack";116 const wchar_t *kPPMdMethod = L"PPMd";117 const wchar_t *kAESMethod = L"AES";118 const wchar_t *kZipCryptoMethod = L"ZipCrypto";119 const wchar_t *kStrongCryptoMethod = L"StrongCrypto";121 struct CStrongCryptoPair122 {123 UInt16 Id;124 const wchar_t *Name;125 };127 CStrongCryptoPair g_StrongCryptoPairs[] =128 {129 { NStrongCryptoFlags::kDES, L"DES" },130 { NStrongCryptoFlags::kRC2old, L"RC2a" },131 { NStrongCryptoFlags::k3DES168, L"3DES-168" },132 { NStrongCryptoFlags::k3DES112, L"3DES-112" },133 { NStrongCryptoFlags::kAES128, L"pkAES-128" },134 { NStrongCryptoFlags::kAES192, L"pkAES-192" },135 { NStrongCryptoFlags::kAES256, L"pkAES-256" },136 { NStrongCryptoFlags::kRC2, L"RC2" },137 { NStrongCryptoFlags::kBlowfish, L"Blowfish" },138 { NStrongCryptoFlags::kTwofish, L"Twofish" },139 { NStrongCryptoFlags::kRC4, L"RC4" }140 };142 STATPROPSTG kArcProps[] =143 {144 { NULL, kpidBit64, VT_BOOL},145 { NULL, kpidComment, VT_BSTR}146 };148 CHandler::CHandler()149 {150 InitMethodProperties();151 }153 static AString BytesToString(const CByteBuffer &data)154 {155 AString s;156 int size = (int)data.GetCapacity();157 if (size > 0)158 {159 char *p = s.GetBuffer(size + 1);160 memcpy(p, (const Byte *)data, size);161 p[size] = '\0';162 s.ReleaseBuffer();163 }164 return s;165 }167 IMP_IInArchive_Props168 IMP_IInArchive_ArcProps170 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)171 {172 COM_TRY_BEGIN173 NWindows::NCOM::CPropVariant prop;174 switch(propID)175 {176 case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;177 case kpidComment:178 prop = MultiByteToUnicodeString(BytesToString(m_Archive.m_ArchiveInfo.Comment), CP_ACP);179 break;180 }181 prop.Detach(value);182 COM_TRY_END183 return S_OK;184 }186 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)187 {188 *numItems = m_Items.Size();189 return S_OK;190 }192 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)193 {194 COM_TRY_BEGIN195 NWindows::NCOM::CPropVariant prop;196 const CItemEx &item = m_Items[index];197 switch(propID)198 {199 case kpidPath: prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break;200 case kpidIsDir: prop = item.IsDir(); break;201 case kpidSize: prop = item.UnPackSize; break;202 case kpidPackSize: prop = item.PackSize; break;203 case kpidTimeType:204 {205 FILETIME utcFileTime;206 if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kTagTime, utcFileTime))207 prop = (UInt32)NFileTimeType::kWindows;208 break;209 }210 case kpidCTime:211 {212 FILETIME ft;213 if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))214 prop = ft;215 break;216 }217 case kpidATime:218 {219 FILETIME ft;220 if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))221 prop = ft;222 break;223 }224 case kpidMTime:225 {226 FILETIME utcFileTime;227 if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utcFileTime))228 {229 FILETIME localFileTime;230 if (NTime::DosTimeToFileTime(item.Time, localFileTime))231 {232 if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))233 utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;234 }235 else236 utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;237 }238 prop = utcFileTime;239 break;240 }241 case kpidAttrib: prop = item.GetWinAttributes(); break;242 case kpidEncrypted: prop = item.IsEncrypted(); break;243 case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break;244 case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break;245 case kpidMethod:246 {247 UInt16 methodId = item.CompressionMethod;248 UString method;249 if (item.IsEncrypted())250 {251 if (methodId == NFileHeader::NCompressionMethod::kWzAES)252 {253 method = kAESMethod;254 CWzAesExtraField aesField;255 if (item.CentralExtra.GetWzAesField(aesField))256 {257 method += L"-";258 wchar_t s[32];259 ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);260 method += s;261 method += L" ";262 methodId = aesField.Method;263 }264 }265 else266 {267 if (item.IsStrongEncrypted())268 {269 CStrongCryptoField f;270 bool finded = false;271 if (item.CentralExtra.GetStrongCryptoField(f))272 {273 for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++)274 {275 const CStrongCryptoPair &pair = g_StrongCryptoPairs[i];276 if (f.AlgId == pair.Id)277 {278 method += pair.Name;279 finded = true;280 break;281 }282 }283 }284 if (!finded)285 method += kStrongCryptoMethod;286 }287 else288 method += kZipCryptoMethod;289 method += L" ";290 }291 }292 if (methodId < kNumMethods)293 method += kMethods[methodId];294 else switch (methodId)295 {296 case NFileHeader::NCompressionMethod::kLZMA:297 method += kLZMAMethod;298 if (item.IsLzmaEOS())299 method += L":EOS";300 break;301 case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;302 case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;303 case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;304 case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;305 default:306 {307 wchar_t s[32];308 ConvertUInt64ToString(methodId, s);309 method += s;310 }311 }312 prop = method;313 break;314 }315 case kpidHostOS:316 prop = (item.MadeByVersion.HostOS < kNumHostOSes) ?317 (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS;318 break;319 }320 prop.Detach(value);321 return S_OK;322 COM_TRY_END323 }325 class CProgressImp: public CProgressVirt326 {327 CMyComPtr<IArchiveOpenCallback> _callback;328 public:329 STDMETHOD(SetTotal)(UInt64 numFiles);330 STDMETHOD(SetCompleted)(UInt64 numFiles);331 CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}332 };334 STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles)335 {336 if (_callback)337 return _callback->SetTotal(&numFiles, NULL);338 return S_OK;339 }341 STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles)342 {343 if (_callback)344 return _callback->SetCompleted(&numFiles, NULL);345 return S_OK;346 }348 STDMETHODIMP CHandler::Open(IInStream *inStream,349 const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)350 {351 COM_TRY_BEGIN352 try353 {354 Close();355 RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));356 RINOK(m_Archive.Open(inStream, maxCheckStartPosition));357 CProgressImp progressImp(callback);358 return m_Archive.ReadHeaders(m_Items, &progressImp);359 }360 catch(const CInArchiveException &) { Close(); return S_FALSE; }361 catch(...) { Close(); throw; }362 COM_TRY_END363 }365 STDMETHODIMP CHandler::Close()366 {367 m_Items.Clear();368 m_Archive.Close();369 return S_OK;370 }372 //////////////////////////////////////373 // CHandler::DecompressItems375 class CLzmaDecoder:376 public ICompressCoder,377 public CMyUnknownImp378 {379 NCompress::NLzma::CDecoder *DecoderSpec;380 CMyComPtr<ICompressCoder> Decoder;381 public:382 CLzmaDecoder();383 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,384 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);386 MY_UNKNOWN_IMP387 };389 CLzmaDecoder::CLzmaDecoder()390 {391 DecoderSpec = new NCompress::NLzma::CDecoder;392 Decoder = DecoderSpec;393 }395 HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,396 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)397 {398 Byte buf[9];399 RINOK(ReadStream_FALSE(inStream, buf, 9));400 if (buf[2] != 5 || buf[3] != 0)401 return E_NOTIMPL;402 RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));403 return Decoder->Code(inStream, outStream, NULL, outSize, progress);404 }406 struct CMethodItem407 {408 UInt16 ZipMethod;409 CMyComPtr<ICompressCoder> Coder;410 };412 class CZipDecoder413 {414 NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;415 NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec;416 NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec;418 CMyComPtr<ICompressFilter> _zipCryptoDecoder;419 CMyComPtr<ICompressFilter> _pkAesDecoder;420 CMyComPtr<ICompressFilter> _wzAesDecoder;422 CFilterCoder *filterStreamSpec;423 CMyComPtr<ISequentialInStream> filterStream;424 CMyComPtr<ICryptoGetTextPassword> getTextPassword;425 CObjectVector<CMethodItem> methodItems;427 public:428 CZipDecoder():429 _zipCryptoDecoderSpec(0),430 _pkAesDecoderSpec(0),431 _wzAesDecoderSpec(0),432 filterStreamSpec(0) {}434 HRESULT Decode(435 DECL_EXTERNAL_CODECS_LOC_VARS436 CInArchive &archive, const CItemEx &item,437 ISequentialOutStream *realOutStream,438 IArchiveExtractCallback *extractCallback,439 ICompressProgressInfo *compressProgress,440 UInt32 numThreads, Int32 &res);441 };443 HRESULT CZipDecoder::Decode(444 DECL_EXTERNAL_CODECS_LOC_VARS445 CInArchive &archive, const CItemEx &item,446 ISequentialOutStream *realOutStream,447 IArchiveExtractCallback *extractCallback,448 ICompressProgressInfo *compressProgress,449 UInt32 numThreads, Int32 &res)450 {451 res = NArchive::NExtract::NOperationResult::kDataError;452 CInStreamReleaser inStreamReleaser;454 bool needCRC = true;455 bool wzAesMode = false;456 bool pkAesMode = false;457 UInt16 methodId = item.CompressionMethod;458 if (item.IsEncrypted())459 {460 if (item.IsStrongEncrypted())461 {462 CStrongCryptoField f;463 if (item.CentralExtra.GetStrongCryptoField(f))464 {465 pkAesMode = true;466 }467 if (!pkAesMode)468 {469 res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;470 return S_OK;471 }472 }473 if (methodId == NFileHeader::NCompressionMethod::kWzAES)474 {475 CWzAesExtraField aesField;476 if (item.CentralExtra.GetWzAesField(aesField))477 {478 wzAesMode = true;479 needCRC = aesField.NeedCrc();480 }481 }482 }484 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;485 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;486 outStreamSpec->SetStream(realOutStream);487 outStreamSpec->Init(needCRC);489 UInt64 authenticationPos;491 CMyComPtr<ISequentialInStream> inStream;492 {493 UInt64 packSize = item.PackSize;494 if (wzAesMode)495 {496 if (packSize < NCrypto::NWzAes::kMacSize)497 return S_OK;498 packSize -= NCrypto::NWzAes::kMacSize;499 }500 UInt64 dataPos = item.GetDataPosition();501 inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));502 authenticationPos = dataPos + packSize;503 }505 CMyComPtr<ICompressFilter> cryptoFilter;506 if (item.IsEncrypted())507 {508 if (wzAesMode)509 {510 CWzAesExtraField aesField;511 if (!item.CentralExtra.GetWzAesField(aesField))512 return S_OK;513 methodId = aesField.Method;514 if (!_wzAesDecoder)515 {516 _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;517 _wzAesDecoder = _wzAesDecoderSpec;518 }519 cryptoFilter = _wzAesDecoder;520 Byte properties = aesField.Strength;521 RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));522 }523 else if (pkAesMode)524 {525 if (!_pkAesDecoder)526 {527 _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder;528 _pkAesDecoder = _pkAesDecoderSpec;529 }530 cryptoFilter = _pkAesDecoder;531 }532 else533 {534 if (!_zipCryptoDecoder)535 {536 _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;537 _zipCryptoDecoder = _zipCryptoDecoderSpec;538 }539 cryptoFilter = _zipCryptoDecoder;540 }541 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;542 RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));544 if (!getTextPassword)545 extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);547 if (getTextPassword)548 {549 CMyComBSTR password;550 RINOK(getTextPassword->CryptoGetTextPassword(&password));551 AString charPassword;552 if (wzAesMode || pkAesMode)553 {554 charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);555 /*556 for (int i = 0;; i++)557 {558 wchar_t c = password[i];559 if (c == 0)560 break;561 if (c >= 0x80)562 {563 res = NArchive::NExtract::NOperationResult::kDataError;564 return S_OK;565 }566 charPassword += (char)c;567 }568 */569 }570 else571 {572 // we use OEM. WinZip/Windows probably use ANSI for some files573 charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);574 }575 HRESULT result = cryptoSetPassword->CryptoSetPassword(576 (const Byte *)(const char *)charPassword, charPassword.Length());577 if (result != S_OK)578 return S_OK;579 }580 else581 {582 RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));583 }584 }586 int m;587 for (m = 0; m < methodItems.Size(); m++)588 if (methodItems[m].ZipMethod == methodId)589 break;591 if (m == methodItems.Size())592 {593 CMethodItem mi;594 mi.ZipMethod = methodId;595 if (methodId == NFileHeader::NCompressionMethod::kStored)596 mi.Coder = new NCompress::CCopyCoder;597 else if (methodId == NFileHeader::NCompressionMethod::kShrunk)598 mi.Coder = new NCompress::NShrink::CDecoder;599 else if (methodId == NFileHeader::NCompressionMethod::kImploded)600 mi.Coder = new NCompress::NImplode::NDecoder::CCoder;601 else if (methodId == NFileHeader::NCompressionMethod::kLZMA)602 mi.Coder = new CLzmaDecoder;603 else604 {605 CMethodId szMethodID;606 if (methodId == NFileHeader::NCompressionMethod::kBZip2)607 szMethodID = kMethodId_BZip2;608 else609 {610 if (methodId > 0xFF)611 {612 res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;613 return S_OK;614 }615 szMethodID = kMethodId_ZipBase + (Byte)methodId;616 }618 RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false));620 if (mi.Coder == 0)621 {622 res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;623 return S_OK;624 }625 }626 m = methodItems.Add(mi);627 }628 ICompressCoder *coder = methodItems[m].Coder;630 {631 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;632 coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);633 if (setDecoderProperties)634 {635 Byte properties = (Byte)item.Flags;636 RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));637 }638 }640 #ifdef COMPRESS_MT641 {642 CMyComPtr<ICompressSetCoderMt> setCoderMt;643 coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);644 if (setCoderMt)645 {646 RINOK(setCoderMt->SetNumberOfThreads(numThreads));647 }648 }649 #endif651 {652 HRESULT result = S_OK;653 CMyComPtr<ISequentialInStream> inStreamNew;654 if (item.IsEncrypted())655 {656 if (!filterStream)657 {658 filterStreamSpec = new CFilterCoder;659 filterStream = filterStreamSpec;660 }661 filterStreamSpec->Filter = cryptoFilter;662 if (wzAesMode)663 {664 result = _wzAesDecoderSpec->ReadHeader(inStream);665 }666 else if (pkAesMode)667 {668 result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize);669 if (result == S_OK)670 {671 bool passwOK;672 result = _pkAesDecoderSpec->CheckPassword(passwOK);673 if (result == S_OK && !passwOK)674 result = S_FALSE;675 }676 }677 else678 {679 result = _zipCryptoDecoderSpec->ReadHeader(inStream);680 }682 if (result == S_OK)683 {684 RINOK(filterStreamSpec->SetInStream(inStream));685 inStreamReleaser.FilterCoder = filterStreamSpec;686 inStreamNew = filterStream;687 if (wzAesMode)688 {689 if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())690 result = S_FALSE;691 }692 }693 }694 else695 inStreamNew = inStream;696 if (result == S_OK)697 result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);698 if (result == S_FALSE)699 return S_OK;700 if (result == E_NOTIMPL)701 {702 res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;703 return S_OK;704 }706 RINOK(result);707 }708 bool crcOK = true;709 bool authOk = true;710 if (needCRC)711 crcOK = (outStreamSpec->GetCRC() == item.FileCRC);712 if (wzAesMode)713 {714 inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));715 if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)716 authOk = false;717 }719 res = ((crcOK && authOk) ?720 NArchive::NExtract::NOperationResult::kOK :721 NArchive::NExtract::NOperationResult::kCRCError);722 return S_OK;723 }726 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,727 Int32 _aTestMode, IArchiveExtractCallback *extractCallback)728 {729 COM_TRY_BEGIN730 CZipDecoder myDecoder;731 bool testMode = (_aTestMode != 0);732 UInt64 totalUnPacked = 0, totalPacked = 0;733 bool allFilesMode = (numItems == UInt32(-1));734 if (allFilesMode)735 numItems = m_Items.Size();736 if(numItems == 0)737 return S_OK;738 UInt32 i;739 for(i = 0; i < numItems; i++)740 {741 const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];742 totalUnPacked += item.UnPackSize;743 totalPacked += item.PackSize;744 }745 RINOK(extractCallback->SetTotal(totalUnPacked));747 UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;748 UInt64 currentItemUnPacked, currentItemPacked;750 CLocalProgress *lps = new CLocalProgress;751 CMyComPtr<ICompressProgressInfo> progress = lps;752 lps->Init(extractCallback, false);754 for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,755 currentTotalPacked += currentItemPacked)756 {757 currentItemUnPacked = 0;758 currentItemPacked = 0;760 lps->InSize = currentTotalPacked;761 lps->OutSize = currentTotalUnPacked;762 RINOK(lps->SetCur());764 CMyComPtr<ISequentialOutStream> realOutStream;765 Int32 askMode = testMode ?766 NArchive::NExtract::NAskMode::kTest :767 NArchive::NExtract::NAskMode::kExtract;768 Int32 index = allFilesMode ? i : indices[i];770 RINOK(extractCallback->GetStream(index, &realOutStream, askMode));772 CItemEx item = m_Items[index];773 if (!item.FromLocal)774 {775 HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);776 if (res == S_FALSE)777 {778 if (item.IsDir() || realOutStream || testMode)779 {780 RINOK(extractCallback->PrepareOperation(askMode));781 realOutStream.Release();782 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));783 }784 continue;785 }786 RINOK(res);787 }789 if (item.IsDir() || item.IgnoreItem())790 {791 // if (!testMode)792 {793 RINOK(extractCallback->PrepareOperation(askMode));794 realOutStream.Release();795 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));796 }797 continue;798 }800 currentItemUnPacked = item.UnPackSize;801 currentItemPacked = item.PackSize;803 if (!testMode && (!realOutStream))804 continue;806 RINOK(extractCallback->PrepareOperation(askMode));808 #ifndef COMPRESS_MT809 #define _numThreads 1810 #endif812 Int32 res;813 RINOK(myDecoder.Decode(814 EXTERNAL_CODECS_VARS815 m_Archive, item, realOutStream, extractCallback,816 progress,817 _numThreads,818 res));819 realOutStream.Release();821 RINOK(extractCallback->SetOperationResult(res))822 }823 return S_OK;824 COM_TRY_END825 }827 #ifndef EXTRACT_ONLY828 IMPL_ISetCompressCodecsInfo829 #endif831 }}