📄 rarhandler.cpp
字号:
}
if (needAdd)
{
CRefItem refItem;
refItem.ItemIndex = _items.Size();
refItem.NumItems = 1;
refItem.VolumeIndex = _archives.Size();
_refItems.Add(refItem);
}
_items.Add(item);
if (openArchiveCallback != NULL)
{
UINT64 numFiles = _items.Size();
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
}
}
_archives.Add(archive);
}
}
catch(...)
{
return S_FALSE;
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
{
COM_TRY_BEGIN
_refItems.Clear();
_items.Clear();
_archives.Clear();
return S_OK;
COM_TRY_END
}
struct CMethodItem
{
BYTE RarUnPackVersion;
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 censoredTotalUnPacked = 0,
// censoredTotalPacked = 0,
importantTotalUnPacked = 0;
// importantTotalPacked = 0;
bool allFilesMode = (numItems == UINT32(-1));
if (allFilesMode)
numItems = _refItems.Size();
if(numItems == 0)
return S_OK;
int lastIndex = 0;
CRecordVector<int> importantIndexes;
CRecordVector<bool> extractStatuses;
for(UINT32 t = 0; t < numItems; t++)
{
int index = allFilesMode ? t : indices[t];
const CRefItem &refItem = _refItems[index];
const CItemEx &item = _items[refItem.ItemIndex];
censoredTotalUnPacked += item.UnPackSize;
// censoredTotalPacked += item.PackSize;
for(int j = lastIndex; j <= index; j++)
// if(!_items[_refItems[j].ItemIndex].IsSolid())
if(!IsSolid(j))
lastIndex = j;
for(j = lastIndex; j <= index; j++)
{
const CRefItem &refItem = _refItems[j];
const CItemEx &item = _items[refItem.ItemIndex];
// const CItemEx &item = _items[j];
importantTotalUnPacked += item.UnPackSize;
// importantTotalPacked += item.PackSize;
importantIndexes.Add(j);
extractStatuses.Add(j == index);
}
lastIndex = index + 1;
}
extractCallback->SetTotal(importantTotalUnPacked);
UINT64 currentImportantTotalUnPacked = 0;
UINT64 currentImportantTotalPacked = 0;
UINT64 currentUnPackSize, currentPackSize;
/*
CSysString path = GetCodecsFolderPrefix() + TEXT("Rar29.dll");
TCHAR compressLibPath[MAX_PATH + 64];
if (!GetCompressFolderPrefix(compressLibPath))
return ::GetLastError();
lstrcat(compressLibPath, TEXT("Rar29.dll"));
*/
N7z::LoadMethodMap();
CCoderLibraries libraries;
CObjectVector<CMethodItem> methodItems;
/*
CCoderLibrary compressLib;
CMyComPtr<ICompressCoder> decoder15;
CMyComPtr<ICompressCoder> decoder20;
CMyComPtr<ICompressCoder> decoder29;
*/
NCompress::CCopyCoder *copyCoderSpec = NULL;
CMyComPtr<ICompressCoder> copyCoder;
CCoderMixer *mixerCoderSpec;
CMyComPtr<ICompressCoder> mixerCoder;
bool mixerCoderStoreMethod;
int mixerCryptoVersion;
CMyComPtr<ICompressCoder> rar20CryptoDecoder;
CMyComPtr<ICompressCoder> rar29CryptoDecoder;
CFolderInStream *folderInStreamSpec = NULL;
CMyComPtr<ISequentialInStream> folderInStream;
for(int i = 0; i < importantIndexes.Size(); i++,
currentImportantTotalUnPacked += currentUnPackSize,
currentImportantTotalPacked += currentPackSize)
{
RINOK(extractCallback->SetCompleted(
¤tImportantTotalUnPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
INT32 askMode;
if(extractStatuses[i])
askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
else
askMode = NArchive::NExtract::NAskMode::kSkip;
UINT32 index = importantIndexes[i];
const CRefItem &refItem = _refItems[index];
const CItemEx &item = _items[refItem.ItemIndex];
currentUnPackSize = item.UnPackSize;
currentPackSize = GetPackSize(index);
if(item.IgnoreItem())
continue;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if(item.IsDirectory())
{
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
continue;
}
bool mustBeProcessedAnywhere = false;
if(i < importantIndexes.Size() - 1)
{
// const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];
// const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];
// mustBeProcessedAnywhere = nextItemInfo.IsSolid();
mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);
}
if (!mustBeProcessedAnywhere && !testMode && !realOutStream)
continue;
if (!realOutStream && !testMode)
askMode = NArchive::NExtract::NAskMode::kSkip;
RINOK(extractCallback->PrepareOperation(askMode));
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init(realOutStream);
realOutStream.Release();
UINT64 packedPos = currentImportantTotalPacked;
UINT64 unpackedPos = currentImportantTotalUnPacked;
/*
for (int partIndex = 0; partIndex < 1; partIndex++)
{
CMyComPtr<ISequentialInStream> inStream;
// item redefinition
const CItemEx &item = _items[refItem.ItemIndex + partIndex];
NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex];
inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
item.PackSize));
*/
if (!folderInStream)
{
folderInStreamSpec = new CFolderInStream;
folderInStream = folderInStreamSpec;
}
folderInStreamSpec->Init(&_archives, &_items, refItem);
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
localProgressSpec->Init(extractCallback, false);
CLocalCompressProgressInfo *localCompressProgressSpec =
new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(progress,
&packedPos,
&unpackedPos);
UINT64 packSize = currentPackSize;
// packedPos += item.PackSize;
// unpackedPos += 0;
if (item.IsEncrypted())
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
if (item.UnPackVersion >= 29)
{
if (!rar29CryptoDecoder)
{
rar29CryptoDecoder = new NCrypto::NRar29::CDecoder();
// RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
}
CMyComPtr<ICompressSetDecoderProperties> cryptoProperties;
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties,
&cryptoProperties));
CSequentialInStreamImp *inStreamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> inStreamProperties(inStreamSpec);
inStreamSpec->Init(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0);
RINOK(cryptoProperties->SetDecoderProperties(inStreamProperties));
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICryptoSetPassword,
&cryptoSetPassword));
}
else if (item.UnPackVersion >= 20)
{
if (!rar20CryptoDecoder)
{
rar20CryptoDecoder = new NCrypto::NRar20::CDecoder();
// RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
}
RINOK(rar20CryptoDecoder.QueryInterface(IID_ICryptoSetPassword,
&cryptoSetPassword));
}
else
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
if (!getTextPassword)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword,
&getTextPassword);
if (getTextPassword)
{
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
if (item.UnPackVersion >= 29)
{
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const wchar_t *)password,
password.Length() * sizeof(wchar_t)));
}
else
{
AString oemPassword = UnicodeStringToMultiByte(
(const wchar_t *)password, CP_OEMCP);
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const char *)oemPassword, oemPassword.Length()));
}
}
else
{
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
}
}
switch(item.Method)
{
case '0':
{
if(copyCoderSpec == NULL)
{
copyCoderSpec = new NCompress::CCopyCoder;
copyCoder = copyCoderSpec;
}
if (item.IsEncrypted())
{
{
if (!mixerCoder || !mixerCoderStoreMethod ||
item.UnPackVersion != mixerCryptoVersion)
{
mixerCoder.Release();
mixerCoderSpec = new CCoderMixer;
mixerCoder = mixerCoderSpec;
if (item.UnPackVersion >= 29)
mixerCoderSpec->AddCoder(rar29CryptoDecoder);
else
mixerCoderSpec->AddCoder(rar20CryptoDecoder);
mixerCoderSpec->AddCoder(copyCoder);
mixerCoderSpec->FinishAddingCoders();
mixerCoderStoreMethod = true;
mixerCryptoVersion = item.UnPackVersion;
}
mixerCoderSpec->ReInit();
mixerCoderSpec->SetCoderInfo(0, &packSize, &item.UnPackSize);
mixerCoderSpec->SetCoderInfo(1, &item.UnPackSize, &item.UnPackSize);
mixerCoderSpec->SetProgressCoderIndex(1);
RINOK(mixerCoder->Code(folderInStream, outStream,
NULL, NULL, compressProgress));
}
}
else
{
RINOK(copyCoder->Code(folderInStream, outStream,
NULL, NULL, compressProgress));
}
break;
}
case '1':
case '2':
case '3':
case '4':
case '5':
{
/*
if (item.UnPackVersion >= 29)
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
*/
int m;
for (m = 0; m < methodItems.Size(); m++)
if (methodItems[m].RarUnPackVersion == item.UnPackVersion)
break;
if (m == methodItems.Size())
{
CMethodItem mi;
mi.RarUnPackVersion = item.UnPackVersion;
N7z::CMethodID methodID = { { 0x04, 0x03 } , 3 };
BYTE myID;
if (item.UnPackVersion < 20)
myID = 1;
else if (item.UnPackVersion < 29)
myID = 2;
else
myID = 3;
methodID.ID[2] = myID;
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));
m = methodItems.Add(mi);
}
CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;
CMyComPtr<ICompressSetDecoderProperties> compressSetDecoderProperties;
RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties,
&compressSetDecoderProperties));
BYTE isSolid = (
// item.IsSolid()
IsSolid(index)
||
item.IsSplitBefore())
? 1: 0;
CSequentialInStreamImp *inStreamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> inStreamProperties(inStreamSpec);
inStreamSpec->Init(&isSolid, 1);
RINOK(compressSetDecoderProperties->SetDecoderProperties(inStreamProperties));
HRESULT result;
if (item.IsEncrypted())
{
if (!mixerCoder || mixerCoderStoreMethod)
{
mixerCoder.Release();
mixerCoderSpec = new CCoderMixer;
mixerCoder = mixerCoderSpec;
if (item.UnPackVersion >= 29)
mixerCoderSpec->AddCoder(rar29CryptoDecoder);
else
mixerCoderSpec->AddCoder(rar20CryptoDecoder);
mixerCoderSpec->AddCoder(decoder);
mixerCoderSpec->FinishAddingCoders();
mixerCoderStoreMethod = false;
}
mixerCoderSpec->ReInit();
mixerCoderSpec->SetCoderInfo(1, &packSize,
&item.UnPackSize);
mixerCoderSpec->SetProgressCoderIndex(1);
result = mixerCoder->Code(folderInStream, outStream,
NULL, NULL, compressProgress);
}
else
{
result = decoder->Code(folderInStream, outStream,
&packSize, &item.UnPackSize, compressProgress);
}
if (result == S_FALSE)
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
continue;
}
if (result != S_OK)
return result;
break;
}
default:
outStream.Release();
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
/*
if (refItem.NumItems == 1 &&
!item.IsSplitBefore() && !item.IsSplitAfter())
*/
{
const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
outStream.Release();
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kCRCError));
}
/*
else
{
bool crcOK = true;
for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++)
{
const CItemEx &item = _items[refItem.ItemIndex + partIndex];
if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
{
crcOK = false;
break;
}
}
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:
NArchive::NExtract::NOperationResult::kCRCError));
}
*/
}
return S_OK;
COM_TRY_END
}
/*
STDMETHODIMP CHandler::ExtractAllItems(INT32 testMode,
IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
CRecordVector<UINT32> indices;
indices.Reserve(_refItems.Size());
for(int i = 0; i < _refItems.Size(); i++)
indices.Add(i);
return Extract(&indices.Front(), _refItems.Size(), testMode, extractCallback);
COM_TRY_END
}
*/
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -