📄 ziphandler.cpp
字号:
/* catch(...) { return S_FALSE; } */ COM_TRY_END return S_OK;}STDMETHODIMP CHandler::Close(){ m_Items.Clear(); m_Archive.Close(); m_ArchiveIsOpen = false; return S_OK;}//////////////////////////////////////// CHandler::DecompressItemsstruct CMethodItem{ Byte ZipMethod; CMyComPtr<ICompressCoder> Coder;};STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback){ COM_TRY_BEGIN CMyComPtr<ICryptoGetTextPassword> getTextPassword; bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; UInt64 totalUnPacked = 0, totalPacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = m_Items.Size(); if(numItems == 0) return S_OK; UInt32 i; for(i = 0; i < numItems; i++) { const CItemEx &item = m_Items[allFilesMode ? i : indices[i]]; totalUnPacked += item.UnPackSize; totalPacked += item.PackSize; } extractCallback->SetTotal(totalUnPacked); UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; UInt64 currentItemUnPacked, currentItemPacked; #ifndef EXCLUDE_COM N7z::LoadMethodMap(); CCoderLibraries libraries; #endif CObjectVector<CMethodItem> methodItems; /* CCoderLibraries _libraries; #ifndef COMPRESS_IMPLODE CCoderLibrary implodeLib; #endif CMyComPtr<ICompressCoder> implodeDecoder; CMyComPtr<ICompressCoder> deflateDecoder; CMyComPtr<ICompressCoder> deflate64Decoder; CMyComPtr<ICompressCoder> bzip2Decoder; #ifndef CRYPTO_ZIP CCoderLibrary cryptoLib; #endif */ NCrypto::NZip::CDecoder *cryptoDecoderSpec; CMyComPtr<ICompressFilter> cryptoDecoder; CFilterCoder *filterStreamSpec; CMyComPtr<ISequentialInStream> filterStream; // UInt16 mixerCoderMethod; for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, currentTotalPacked += currentItemPacked) { currentItemUnPacked = 0; currentItemPacked = 0; RINOK(extractCallback->SetCompleted(¤tTotalUnPacked)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = allFilesMode ? i : indices[i]; const CItemEx &item = m_Items[index]; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); if(item.IsDirectory() || item.IgnoreItem()) { // if (!testMode) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); } continue; } if (!testMode && (!realOutStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); currentItemUnPacked = item.UnPackSize; currentItemPacked = item.PackSize; CInStreamReleaser inStreamReleaser; { COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(realOutStream); realOutStream.Release(); CMyComPtr<ISequentialInStream> inStream; inStream.Attach(m_Archive.CreateLimitedStream(item.GetDataPosition(), item.PackSize)); CLocalProgress *localProgressSpec = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = localProgressSpec; localProgressSpec->Init(extractCallback, false); CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec; localCompressProgressSpec->Init(progress, ¤tTotalPacked, ¤tTotalUnPacked); if (item.IsEncrypted()) { if (!cryptoDecoder) { cryptoDecoderSpec = new NCrypto::NZip::CDecoder; cryptoDecoder = cryptoDecoderSpec; } CMyComPtr<ICryptoSetPassword> cryptoSetPassword; RINOK(cryptoDecoder.QueryInterface( IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) { CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); AString anOemPassword = UnicodeStringToMultiByte( (const wchar_t *)password, CP_OEMCP); RINOK(cryptoSetPassword->CryptoSetPassword( (const Byte *)(const char *)anOemPassword, anOemPassword.Length())); } else { RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); } } int m; for (m = 0; m < methodItems.Size(); m++) if (methodItems[m].ZipMethod == item.CompressionMethod) break; if (m == methodItems.Size()) { CMethodItem mi; mi.ZipMethod = (Byte)item.CompressionMethod; if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored) mi.Coder = new NCompress::CCopyCoder; else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kShrunk) mi.Coder = new NCompress::NShrink::CDecoder; else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kImploded) mi.Coder = new NCompress::NImplode::NDecoder::CCoder; else { #ifdef EXCLUDE_COM switch(item.CompressionMethod) { case NFileHeader::NCompressionMethod::kDeflated: mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder; break; case NFileHeader::NCompressionMethod::kDeflated64: mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder64; break; case NFileHeader::NCompressionMethod::kBZip2: mi.Coder = new NCompress::NBZip2::CDecoder; break; default: RINOK(extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } #else N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 }; methodID.ID[2] = mi.ZipMethod; if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored) { methodID.ID[0] = 0; methodID.IDSize = 1; } else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kBZip2) { methodID.ID[1] = 0x02; methodID.ID[2] = 0x02; } N7z::CMethodInfo methodInfo; if (!N7z::GetMethodInfo(methodID, methodInfo)) { RINOK(extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } RINOK(libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &mi.Coder)); #endif } m = methodItems.Add(mi); } ICompressCoder *coder = methodItems[m].Coder; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); if (setDecoderProperties) { Byte properties = (Byte)item.Flags; RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1)); } } #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_numThreads)); } } #endif // case NFileHeader::NCompressionMethod::kImploded: // switch(item.CompressionMethod) try { HRESULT result; CMyComPtr<ISequentialInStream> inStreamNew; if (item.IsEncrypted()) { if (!filterStream) { filterStreamSpec = new CFilterCoder; filterStream = filterStreamSpec; filterStreamSpec->Filter = cryptoDecoder; } RINOK(cryptoDecoderSpec->ReadHeader(inStream)); RINOK(filterStreamSpec->SetInStream(inStream)); inStreamReleaser.FilterCoder = filterStreamSpec; /* switch(item.CompressionMethod) { case NFileHeader::NCompressionMethod::kStored: mixerCoderSpec->SetCoderInfo(0, ¤tItemPacked, ¤tItemUnPacked); mixerCoderSpec->SetCoderInfo(1, NULL, NULL); break; default: mixerCoderSpec->SetCoderInfo(0, ¤tItemPacked, NULL); mixerCoderSpec->SetCoderInfo(1, NULL, ¤tItemUnPacked); break; } */ inStreamNew = filterStream; } else { inStreamNew = inStream; } result = coder->Code(inStreamNew, outStream, NULL, ¤tItemUnPacked, compressProgress); if (result == S_FALSE) throw "data error"; if (result != S_OK) return result; } catch(...) { outStream.Release(); RINOK(extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kDataError)); continue; } bool crcOK = outStreamSpec->GetCRC() == item.FileCRC; outStream.Release(); RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)) } } return S_OK; COM_TRY_END}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -