📄 ziphandler.cpp
字号:
propgressImp.Init(openArchiveCallback);
RINOK(m_Archive.ReadHeaders(m_Items, &propgressImp));
}
/*
catch(...)
{
return S_FALSE;
}
*/
COM_TRY_END
return S_OK;
}
STDMETHODIMP CHandler::Close()
{
m_Archive.Close();
m_ArchiveIsOpen = false;
return S_OK;
}
//////////////////////////////////////
// CHandler::DecompressItems
struct 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
*/
CMyComPtr<ICompressCoder> cryptoDecoder;
CCoderMixer *mixerCoderSpec;
CMyComPtr<ICompressCoder> mixerCoder;
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;
{
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)
{
#ifdef CRYPTO_ZIP
cryptoDecoder = new NCrypto::NZip::CDecoder;
#else
RINOK(cryptoLib.LoadAndCreateCoder(
GetBaseFolderPrefix() + TEXT("\\Crypto\\Zip.dll"),
CLSID_CCryptoZipDecoder, &cryptoDecoder));
#endif
}
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 = item.CompressionMethod;
#ifdef EXCLUDE_COM
switch(item.CompressionMethod)
{
case NFileHeader::NCompressionMethod::kStored:
mi.Coder = new NCompress::CCopyCoder;
break;
case NFileHeader::NCompressionMethod::kImploded:
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
break;
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] = item.CompressionMethod;
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<ICompressSetDecoderProperties> compressSetDecoderProperties;
if (coder->QueryInterface(IID_ICompressSetDecoderProperties, (void **)&compressSetDecoderProperties) == S_OK)
{
// BYTE properties = (item.Flags & 6);
BYTE properties = item.Flags;
CSequentialInStreamImp *inStreamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> inStreamProperties(inStreamSpec);
inStreamSpec->Init(&properties, 1);
RINOK(compressSetDecoderProperties->SetDecoderProperties(inStreamProperties));
}
// case NFileHeader::NCompressionMethod::kImploded:
// switch(item.CompressionMethod)
try
{
HRESULT result;
if (item.IsEncrypted())
{
if (!mixerCoder || mixerCoderMethod != item.CompressionMethod)
{
mixerCoder.Release();
mixerCoderSpec = new CCoderMixer;
mixerCoder = mixerCoderSpec;
mixerCoderSpec->AddCoder(cryptoDecoder);
mixerCoderSpec->AddCoder(coder);
mixerCoderSpec->FinishAddingCoders();
mixerCoderMethod = item.CompressionMethod;
}
mixerCoderSpec->ReInit();
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;
}
mixerCoderSpec->SetProgressCoderIndex(1);
result = mixerCoder->Code(inStream, outStream,
NULL, NULL, compressProgress);
}
else
{
result = coder->Code(inStream, 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 + -