Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarHandler.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 // RarHandler.cpp3 #include "StdAfx.h"5 #include "Common/ComTry.h"6 #include "Common/IntToString.h"7 #include "Common/StringConvert.h"9 #include "Windows/PropVariant.h"10 #include "Windows/Time.h"12 #include "../../IPassword.h"14 #include "../../Common/CreateCoder.h"15 #include "../../Common/FilterCoder.h"16 #include "../../Common/MethodId.h"17 #include "../../Common/ProgressUtils.h"19 #include "../../Compress/CopyCoder.h"21 #include "../../Crypto/Rar20Crypto.h"22 #include "../../Crypto/RarAes.h"24 #include "../Common/ItemNameUtils.h"25 #include "../Common/OutStreamWithCRC.h"27 #include "RarHandler.h"29 using namespace NWindows;30 using namespace NTime;32 namespace NArchive {33 namespace NRar {35 static const wchar_t *kHostOS[] =36 {37 L"MS DOS",38 L"OS/2",39 L"Win32",40 L"Unix",41 L"Mac OS",42 L"BeOS"43 };45 static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);47 static const wchar_t *kUnknownOS = L"Unknown";49 STATPROPSTG kProps[] =50 {51 { NULL, kpidPath, VT_BSTR},52 { NULL, kpidIsDir, VT_BOOL},53 { NULL, kpidSize, VT_UI8},54 { NULL, kpidPackSize, VT_UI8},55 { NULL, kpidMTime, VT_FILETIME},56 { NULL, kpidCTime, VT_FILETIME},57 { NULL, kpidATime, VT_FILETIME},58 { NULL, kpidAttrib, VT_UI4},60 { NULL, kpidEncrypted, VT_BOOL},61 { NULL, kpidSolid, VT_BOOL},62 { NULL, kpidCommented, VT_BOOL},63 { NULL, kpidSplitBefore, VT_BOOL},64 { NULL, kpidSplitAfter, VT_BOOL},65 { NULL, kpidCRC, VT_UI4},66 { NULL, kpidHostOS, VT_BSTR},67 { NULL, kpidMethod, VT_BSTR},68 { NULL, kpidUnpackVer, VT_UI1}69 };71 STATPROPSTG kArcProps[] =72 {73 { NULL, kpidSolid, VT_BOOL},74 { NULL, kpidNumBlocks, VT_UI4},75 // { NULL, kpidEncrypted, VT_BOOL},76 { NULL, kpidIsVolume, VT_BOOL},77 { NULL, kpidNumVolumes, VT_UI4},78 { NULL, kpidPhySize, VT_UI8}79 // { NULL, kpidCommented, VT_BOOL}80 };82 IMP_IInArchive_Props83 IMP_IInArchive_ArcProps85 UInt64 CHandler::GetPackSize(int refIndex) const86 {87 const CRefItem &refItem = _refItems[refIndex];88 UInt64 totalPackSize = 0;89 for (int i = 0; i < refItem.NumItems; i++)90 totalPackSize += _items[refItem.ItemIndex + i].PackSize;91 return totalPackSize;92 }94 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)95 {96 // COM_TRY_BEGIN97 NWindows::NCOM::CPropVariant prop;98 switch(propID)99 {100 case kpidSolid: prop = _archiveInfo.IsSolid(); break;101 // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names.102 case kpidIsVolume: prop = _archiveInfo.IsVolume(); break;103 case kpidNumVolumes: prop = (UInt32)_archives.Size(); break;104 case kpidOffset: if (_archiveInfo.StartPosition != 0) prop = _archiveInfo.StartPosition; break;105 // case kpidCommented: prop = _archiveInfo.IsCommented(); break;106 case kpidNumBlocks:107 {108 UInt32 numBlocks = 0;109 for (int i = 0; i < _refItems.Size(); i++)110 if (!IsSolid(i))111 numBlocks++;112 prop = (UInt32)numBlocks;113 break;114 }115 }116 prop.Detach(value);117 return S_OK;118 // COM_TRY_END119 }121 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)122 {123 *numItems = _refItems.Size();124 return S_OK;125 }127 static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result)128 {129 if (!DosTimeToFileTime(rarTime.DosTime, result))130 return false;131 UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime;132 value += (UInt64)rarTime.LowSecond * 10000000;133 value += ((UInt64)rarTime.SubTime[2] << 16) +134 ((UInt64)rarTime.SubTime[1] << 8) +135 ((UInt64)rarTime.SubTime[0]);136 result.dwLowDateTime = (DWORD)value;137 result.dwHighDateTime = DWORD(value >> 32);138 return true;139 }141 static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop)142 {143 FILETIME localFileTime, utcFileTime;144 if (RarTimeToFileTime(rarTime, localFileTime))145 {146 if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))147 utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;148 }149 else150 utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;151 prop = utcFileTime;152 }154 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)155 {156 COM_TRY_BEGIN157 NWindows::NCOM::CPropVariant prop;158 const CRefItem &refItem = _refItems[index];159 const CItemEx &item = _items[refItem.ItemIndex];160 switch(propID)161 {162 case kpidPath:163 {164 UString u;165 if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty())166 u = item.UnicodeName;167 else168 u = MultiByteToUnicodeString(item.Name, CP_OEMCP);169 prop = (const wchar_t *)NItemName::WinNameToOSName(u);170 break;171 }172 case kpidIsDir: prop = item.IsDir(); break;173 case kpidSize: prop = item.Size; break;174 case kpidPackSize: prop = GetPackSize(index); break;175 case kpidMTime: RarTimeToProp(item.MTime, prop); break;176 case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;177 case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break;178 case kpidAttrib: prop = item.GetWinAttributes(); break;179 case kpidEncrypted: prop = item.IsEncrypted(); break;180 case kpidSolid: prop = IsSolid(index); break;181 case kpidCommented: prop = item.IsCommented(); break;182 case kpidSplitBefore: prop = item.IsSplitBefore(); break;183 case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;184 case kpidCRC:185 {186 const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];187 prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);188 break;189 }190 case kpidUnpackVer: prop = item.UnPackVersion; break;191 case kpidMethod:192 {193 UString method;194 if (item.Method >= Byte('0') && item.Method <= Byte('5'))195 {196 method = L"m";197 wchar_t temp[32];198 ConvertUInt64ToString(item.Method - Byte('0'), temp);199 method += temp;200 if (!item.IsDir())201 {202 method += L":";203 ConvertUInt64ToString(16 + item.GetDictSize(), temp);204 method += temp;205 }206 }207 else208 {209 wchar_t temp[32];210 ConvertUInt64ToString(item.Method, temp);211 method += temp;212 }213 prop = method;214 break;215 }216 case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break;217 }218 prop.Detach(value);219 return S_OK;220 COM_TRY_END221 }223 class CVolumeName224 {225 bool _first;226 bool _newStyle;227 UString _unchangedPart;228 UString _changedPart;229 UString _afterPart;230 public:231 CVolumeName(): _newStyle(true) {};233 bool InitName(const UString &name, bool newStyle)234 {235 _first = true;236 _newStyle = newStyle;237 int dotPos = name.ReverseFind('.');238 UString basePart = name;239 if (dotPos >= 0)240 {241 UString ext = name.Mid(dotPos + 1);242 if (ext.CompareNoCase(L"rar") == 0)243 {244 _afterPart = name.Mid(dotPos);245 basePart = name.Left(dotPos);246 }247 else if (ext.CompareNoCase(L"exe") == 0)248 {249 _afterPart = L".rar";250 basePart = name.Left(dotPos);251 }252 else if (!_newStyle)253 {254 if (ext.CompareNoCase(L"000") == 0 || ext.CompareNoCase(L"001") == 0)255 {256 _afterPart.Empty();257 _first = false;258 _changedPart = ext;259 _unchangedPart = name.Left(dotPos + 1);260 return true;261 }262 }263 }265 if (!_newStyle)266 {267 _afterPart.Empty();268 _unchangedPart = basePart + UString(L".");269 _changedPart = L"r00";270 return true;271 }273 int numLetters = 1;274 if (basePart.Right(numLetters) == L"1" || basePart.Right(numLetters) == L"0")275 {276 while (numLetters < basePart.Length())277 {278 if (basePart[basePart.Length() - numLetters - 1] != '0')279 break;280 numLetters++;281 }282 }283 else284 return false;285 _unchangedPart = basePart.Left(basePart.Length() - numLetters);286 _changedPart = basePart.Right(numLetters);287 return true;288 }290 UString GetNextName()291 {292 UString newName;293 if (_newStyle || !_first)294 {295 int i;296 int numLetters = _changedPart.Length();297 for (i = numLetters - 1; i >= 0; i--)298 {299 wchar_t c = _changedPart[i];300 if (c == L'9')301 {302 c = L'0';303 newName = c + newName;304 if (i == 0)305 newName = UString(L'1') + newName;306 continue;307 }308 c++;309 newName = UString(c) + newName;310 i--;311 for (; i >= 0; i--)312 newName = _changedPart[i] + newName;313 break;314 }315 _changedPart = newName;316 }317 _first = false;318 return _unchangedPart + _changedPart + _afterPart;319 }320 };322 HRESULT CHandler::Open2(IInStream *stream,323 const UInt64 *maxCheckStartPosition,324 IArchiveOpenCallback *openArchiveCallback)325 {326 {327 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;328 CMyComPtr<ICryptoGetTextPassword> getTextPassword;329 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;331 CVolumeName seqName;333 UInt64 totalBytes = 0;334 UInt64 curBytes = 0;336 if (openArchiveCallback != NULL)337 {338 openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);339 openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);340 }342 for (;;)343 {344 CMyComPtr<IInStream> inStream;345 if (!_archives.IsEmpty())346 {347 if (!openVolumeCallback)348 break;350 if(_archives.Size() == 1)351 {352 if (!_archiveInfo.IsVolume())353 break;354 UString baseName;355 {356 NCOM::CPropVariant prop;357 RINOK(openVolumeCallback->GetProperty(kpidName, &prop));358 if (prop.vt != VT_BSTR)359 break;360 baseName = prop.bstrVal;361 }362 seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName());363 }365 UString fullName = seqName.GetNextName();366 HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);367 if (result == S_FALSE)368 break;369 if (result != S_OK)370 return result;371 if (!stream)372 break;373 }374 else375 inStream = stream;377 UInt64 endPos = 0;378 if (openArchiveCallback != NULL)379 {380 RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));381 RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));382 totalBytes += endPos;383 RINOK(openArchiveCallback->SetTotal(NULL, &totalBytes));384 }386 NArchive::NRar::CInArchive archive;387 RINOK(archive.Open(inStream, maxCheckStartPosition));389 if (_archives.IsEmpty())390 archive.GetArchiveInfo(_archiveInfo);392 CItemEx item;393 for (;;)394 {395 HRESULT result = archive.GetNextItem(item, getTextPassword);396 if (result == S_FALSE)397 break;398 RINOK(result);399 if (item.IgnoreItem())400 continue;402 bool needAdd = true;403 if (item.IsSplitBefore())404 {405 if (!_refItems.IsEmpty())406 {407 CRefItem &refItem = _refItems.Back();408 refItem.NumItems++;409 needAdd = false;410 }411 }412 if (needAdd)413 {414 CRefItem refItem;415 refItem.ItemIndex = _items.Size();416 refItem.NumItems = 1;417 refItem.VolumeIndex = _archives.Size();418 _refItems.Add(refItem);419 }420 _items.Add(item);421 if (openArchiveCallback != NULL && _items.Size() % 100 == 0)422 {423 UInt64 numFiles = _items.Size();424 UInt64 numBytes = curBytes + item.Position;425 RINOK(openArchiveCallback->SetCompleted(&numFiles, &numBytes));426 }427 }428 curBytes += endPos;429 _archives.Add(archive);430 }431 }432 return S_OK;433 }435 STDMETHODIMP CHandler::Open(IInStream *stream,436 const UInt64 *maxCheckStartPosition,437 IArchiveOpenCallback *openArchiveCallback)438 {439 COM_TRY_BEGIN440 Close();441 try442 {443 HRESULT res = Open2(stream, maxCheckStartPosition, openArchiveCallback);444 if (res != S_OK)445 Close();446 return res;447 }448 catch(const CInArchiveException &) { Close(); return S_FALSE; }449 catch(...) { Close(); throw; }450 COM_TRY_END451 }453 STDMETHODIMP CHandler::Close()454 {455 COM_TRY_BEGIN456 _refItems.Clear();457 _items.Clear();458 _archives.Clear();459 return S_OK;460 COM_TRY_END461 }463 struct CMethodItem464 {465 Byte RarUnPackVersion;466 CMyComPtr<ICompressCoder> Coder;467 };470 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,471 Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)472 {473 COM_TRY_BEGIN474 CMyComPtr<ICryptoGetTextPassword> getTextPassword;475 bool testMode = (_aTestMode != 0);476 CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;477 UInt64 censoredTotalUnPacked = 0,478 // censoredTotalPacked = 0,479 importantTotalUnPacked = 0;480 // importantTotalPacked = 0;481 bool allFilesMode = (numItems == UInt32(-1));482 if (allFilesMode)483 numItems = _refItems.Size();484 if(numItems == 0)485 return S_OK;486 int lastIndex = 0;487 CRecordVector<int> importantIndexes;488 CRecordVector<bool> extractStatuses;490 for(UInt32 t = 0; t < numItems; t++)491 {492 int index = allFilesMode ? t : indices[t];493 const CRefItem &refItem = _refItems[index];494 const CItemEx &item = _items[refItem.ItemIndex];495 censoredTotalUnPacked += item.Size;496 // censoredTotalPacked += item.PackSize;497 int j;498 for(j = lastIndex; j <= index; j++)499 // if(!_items[_refItems[j].ItemIndex].IsSolid())500 if(!IsSolid(j))501 lastIndex = j;502 for(j = lastIndex; j <= index; j++)503 {504 const CRefItem &refItem = _refItems[j];505 const CItemEx &item = _items[refItem.ItemIndex];507 // const CItemEx &item = _items[j];509 importantTotalUnPacked += item.Size;510 // importantTotalPacked += item.PackSize;511 importantIndexes.Add(j);512 extractStatuses.Add(j == index);513 }514 lastIndex = index + 1;515 }517 extractCallback->SetTotal(importantTotalUnPacked);518 UInt64 currentImportantTotalUnPacked = 0;519 UInt64 currentImportantTotalPacked = 0;520 UInt64 currentUnPackSize, currentPackSize;522 CObjectVector<CMethodItem> methodItems;524 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;525 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;527 CFilterCoder *filterStreamSpec = new CFilterCoder;528 CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;530 NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;531 CMyComPtr<ICompressFilter> rar20CryptoDecoder;532 NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;533 CMyComPtr<ICompressFilter> rar29CryptoDecoder;535 CFolderInStream *folderInStreamSpec = NULL;536 CMyComPtr<ISequentialInStream> folderInStream;538 CLocalProgress *lps = new CLocalProgress;539 CMyComPtr<ICompressProgressInfo> progress = lps;540 lps->Init(extractCallback, false);542 bool solidStart = true;543 for(int i = 0; i < importantIndexes.Size(); i++,544 currentImportantTotalUnPacked += currentUnPackSize,545 currentImportantTotalPacked += currentPackSize)546 {547 lps->InSize = currentImportantTotalPacked;548 lps->OutSize = currentImportantTotalUnPacked;549 RINOK(lps->SetCur());550 CMyComPtr<ISequentialOutStream> realOutStream;552 Int32 askMode;553 if(extractStatuses[i])554 askMode = testMode ?555 NArchive::NExtract::NAskMode::kTest :556 NArchive::NExtract::NAskMode::kExtract;557 else558 askMode = NArchive::NExtract::NAskMode::kSkip;560 UInt32 index = importantIndexes[i];562 const CRefItem &refItem = _refItems[index];563 const CItemEx &item = _items[refItem.ItemIndex];565 currentUnPackSize = item.Size;567 currentPackSize = GetPackSize(index);569 if(item.IgnoreItem())570 continue;572 RINOK(extractCallback->GetStream(index, &realOutStream, askMode));574 if (!IsSolid(index))575 solidStart = true;576 if(item.IsDir())577 {578 RINOK(extractCallback->PrepareOperation(askMode));579 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));580 continue;581 }583 bool mustBeProcessedAnywhere = false;584 if(i < importantIndexes.Size() - 1)585 {586 // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];587 // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];588 // mustBeProcessedAnywhere = nextItemInfo.IsSolid();589 mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);590 }592 if (!mustBeProcessedAnywhere && !testMode && !realOutStream)593 continue;595 if (!realOutStream && !testMode)596 askMode = NArchive::NExtract::NAskMode::kSkip;598 RINOK(extractCallback->PrepareOperation(askMode));600 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;601 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);602 outStreamSpec->SetStream(realOutStream);603 outStreamSpec->Init();604 realOutStream.Release();606 /*607 for (int partIndex = 0; partIndex < 1; partIndex++)608 {609 CMyComPtr<ISequentialInStream> inStream;611 // item redefinition612 const CItemEx &item = _items[refItem.ItemIndex + partIndex];614 NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex];616 inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),617 item.PackSize));618 */619 if (!folderInStream)620 {621 folderInStreamSpec = new CFolderInStream;622 folderInStream = folderInStreamSpec;623 }625 folderInStreamSpec->Init(&_archives, &_items, refItem);627 UInt64 packSize = currentPackSize;629 // packedPos += item.PackSize;630 // unpackedPos += 0;632 CMyComPtr<ISequentialInStream> inStream;633 if (item.IsEncrypted())634 {635 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;636 if (item.UnPackVersion >= 29)637 {638 if (!rar29CryptoDecoder)639 {640 rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;641 rar29CryptoDecoder = rar29CryptoDecoderSpec;642 // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));643 }644 rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);645 CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;646 RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,647 &cryptoProperties));648 RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));649 filterStreamSpec->Filter = rar29CryptoDecoder;650 }651 else if (item.UnPackVersion >= 20)652 {653 if (!rar20CryptoDecoder)654 {655 rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;656 rar20CryptoDecoder = rar20CryptoDecoderSpec;657 // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));658 }659 filterStreamSpec->Filter = rar20CryptoDecoder;660 }661 else662 {663 outStream.Release();664 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));665 continue;666 }667 RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,668 &cryptoSetPassword));670 if (!getTextPassword)671 extractCallback.QueryInterface(IID_ICryptoGetTextPassword,672 &getTextPassword);673 if (getTextPassword)674 {675 CMyComBSTR password;676 RINOK(getTextPassword->CryptoGetTextPassword(&password));677 if (item.UnPackVersion >= 29)678 {679 CByteBuffer buffer;680 UString unicodePassword(password);681 const UInt32 sizeInBytes = unicodePassword.Length() * 2;682 buffer.SetCapacity(sizeInBytes);683 for (int i = 0; i < unicodePassword.Length(); i++)684 {685 wchar_t c = unicodePassword[i];686 ((Byte *)buffer)[i * 2] = (Byte)c;687 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);688 }689 RINOK(cryptoSetPassword->CryptoSetPassword(690 (const Byte *)buffer, sizeInBytes));691 }692 else693 {694 AString oemPassword = UnicodeStringToMultiByte(695 (const wchar_t *)password, CP_OEMCP);696 RINOK(cryptoSetPassword->CryptoSetPassword(697 (const Byte *)(const char *)oemPassword, oemPassword.Length()));698 }699 }700 else701 {702 RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));703 }704 filterStreamSpec->SetInStream(folderInStream);705 inStream = filterStream;706 }707 else708 {709 inStream = folderInStream;710 }711 CMyComPtr<ICompressCoder> commonCoder;712 switch(item.Method)713 {714 case '0':715 {716 commonCoder = copyCoder;717 break;718 }719 case '1':720 case '2':721 case '3':722 case '4':723 case '5':724 {725 /*726 if (item.UnPackVersion >= 29)727 {728 outStream.Release();729 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));730 continue;731 }732 */733 int m;734 for (m = 0; m < methodItems.Size(); m++)735 if (methodItems[m].RarUnPackVersion == item.UnPackVersion)736 break;737 if (m == methodItems.Size())738 {739 CMethodItem mi;740 mi.RarUnPackVersion = item.UnPackVersion;742 mi.Coder.Release();743 if (item.UnPackVersion <= 30)744 {745 UInt32 methodID = 0x040300;746 if (item.UnPackVersion < 20)747 methodID += 1;748 else if (item.UnPackVersion < 29)749 methodID += 2;750 else751 methodID += 3;752 RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));753 }755 if (mi.Coder == 0)756 {757 outStream.Release();758 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));759 continue;760 }762 m = methodItems.Add(mi);763 }764 CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;766 CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;767 RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,768 &compressSetDecoderProperties));770 Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);771 if (solidStart)772 {773 isSolid = false;774 solidStart = false;775 }778 RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1));780 commonCoder = decoder;781 break;782 }783 default:784 outStream.Release();785 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));786 continue;787 }788 HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);789 if (item.IsEncrypted())790 filterStreamSpec->ReleaseInStream();791 if (result == S_FALSE)792 {793 outStream.Release();794 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));795 continue;796 }797 if (result != S_OK)798 return result;800 /*801 if (refItem.NumItems == 1 &&802 !item.IsSplitBefore() && !item.IsSplitAfter())803 */804 {805 const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];806 bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;807 outStream.Release();808 RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:809 NArchive::NExtract::NOperationResult::kCRCError));810 }811 /*812 else813 {814 bool crcOK = true;815 for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++)816 {817 const CItemEx &item = _items[refItem.ItemIndex + partIndex];818 if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])819 {820 crcOK = false;821 break;822 }823 }824 RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:825 NArchive::NExtract::NOperationResult::kCRCError));826 }827 */828 }829 return S_OK;830 COM_TRY_END831 }833 IMPL_ISetCompressCodecsInfo835 }}