HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { if (header.FilterID > 1) return E_NOTIMPL; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5)); } CMyComPtr<ICompressSetOutStream> setOutStream; bool filteredMode = (header.FilterID == 1); if (filteredMode) { _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *Size = header.HasSize() ? &header.Size : NULL; HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { HRESULT res2 = flush->Flush(); if (res == S_OK) res = res2; } HRESULT res2 = setOutStream->ReleaseOutStream(); if (res == S_OK) res = res2; } RINOK(res); if (header.HasSize()) if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) return S_FALSE; return S_OK; }
HRESULT UpdateArchive(UInt64 unpackSize, ISequentialOutStream *outStream, int indexInClient, UInt32 dictionary, UInt32 numPasses, #ifdef COMPRESS_MT UInt32 numThreads, #endif IArchiveUpdateCallback *updateCallback) { RINOK(updateCallback->SetTotal(unpackSize)); UInt64 complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CMyComPtr<ISequentialInStream> fileInStream; RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); CLocalProgress *localProgressSpec = new CLocalProgress; CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; localProgressSpec->Init(updateCallback, true); #ifndef COMPRESS_BZIP2 CCoderLibrary lib; #endif CMyComPtr<ICompressCoder> encoder; #ifdef COMPRESS_BZIP2 encoder = new NCompress::NBZip2::CEncoder; #else RINOK(lib.LoadAndCreateCoder(GetBZip2CodecPath(), CLSID_CCompressBZip2Encoder, &encoder)); #endif CMyComPtr<ICompressSetCoderProperties> setCoderProperties; encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); if (setCoderProperties) { NWindows::NCOM::CPropVariant properties[] = { dictionary, numPasses #ifdef COMPRESS_MT , numThreads #endif }; PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kNumPasses #ifdef COMPRESS_MT , NCoderPropID::kNumThreads #endif }; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); } RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress)); return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); }
HRESULT OpenArchive( CCodecs *codecs, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { HRESULT result = OpenArchive(codecs, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || getStream == 0) return S_OK; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK) return S_OK; CMyComPtr<IInStream> subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK) return S_OK; if (!subStream) return S_OK; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return S_OK; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); return S_OK; }
HRESULT CDecoder::Create( DECL_EXTERNAL_CODECS_LOC_VARS bool filteredMode, ISequentialInStream *inStream) { if (!_lzmaDecoder) { _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; _lzmaDecoder = _lzmaDecoderSpec; } if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } } return _lzmaDecoderSpec->SetInStream(inStream); }
void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain) { Progress = progress; Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress); _inSizeIsMain = inSizeIsMain; ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0; }
HRESULT CPanelCopyThread::ProcessVirt() { /* CMyComPtr<IFolderSetReplaceAltStreamCharsMode> iReplace; FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace); if (iReplace) { RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0)); } */ if (options->testMode) { CMyComPtr<IArchiveFolder> archiveFolder; FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder); if (!archiveFolder) return E_NOTIMPL; CMyComPtr<IFolderArchiveExtractCallback> extractCallback2; RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); NExtract::NPathMode::EEnum pathMode = NExtract::NPathMode::kCurPaths; // NExtract::NPathMode::kFullPathnames; Result = archiveFolder->Extract(&Indices.Front(), Indices.Size(), BoolToInt(options->includeAltStreams), BoolToInt(options->replaceAltStreamChars), pathMode, NExtract::NOverwriteMode::kAsk, options->folder, BoolToInt(true), extractCallback2); } else Result = FolderOperations->CopyTo( BoolToInt(options->moveMode), &Indices.Front(), Indices.Size(), BoolToInt(options->includeAltStreams), BoolToInt(options->replaceAltStreamChars), options->folder, ExtractCallback); if (Result == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors && (!options->hashMethods.IsEmpty() || options->testMode)) { CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0); AddHashBundleRes(pair.Message, Hash, FirstFilePath); } return Result; }
STDMETHODIMP CArchiveFolderManager::OpenFolderFile(IInStream *inStream, const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress) { CMyComPtr<IArchiveOpenCallback> openArchiveCallback; if (progress != 0) { CMyComPtr<IProgress> progressWrapper = progress; progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback); } CAgent *agent = new CAgent(); CMyComPtr<IInFolderArchive> archive = agent; RINOK(agent->Open(inStream, filePath, NULL, openArchiveCallback)); return agent->BindToRootFolder(resultFolder); }
void CPanel::CreateSevenZipMenu(HMENU menuSpec, const CRecordVector<UInt32> &operatedIndices, CMyComPtr<IContextMenu> &sevenZipContextMenu) { sevenZipContextMenu.Release(); CMenu menu; menu.Attach(menuSpec); // CMenuDestroyer menuDestroyer(menu); // menu.CreatePopup(); bool sevenZipMenuCreated = false; CMyComPtr<IContextMenu> contextMenu; if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK) { CMyComPtr<IInitContextMenu> initContextMenu; if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK) return; UString currentFolderUnicode = _currentFolderPrefix; UStringVector names; int i; for(i = 0; i < operatedIndices.Size(); i++) names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i])); CRecordVector<const wchar_t *> namePointers; for(i = 0; i < operatedIndices.Size(); i++) namePointers.Add(names[i]); // NFile::NDirectory::MySetCurrentDirectory(currentFolderUnicode); if (initContextMenu->InitContextMenu(currentFolderUnicode, &namePointers.Front(), operatedIndices.Size()) == S_OK) { HRESULT res = contextMenu->QueryContextMenu(menu, 0, kSevenZipStartMenuID, kSystemStartMenuID - 1, 0); sevenZipMenuCreated = (HRESULT_SEVERITY(res) == SEVERITY_SUCCESS); if (sevenZipMenuCreated) sevenZipContextMenu = contextMenu; // int code = HRESULT_CODE(res); // int nextItemID = code; } } }
STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder) { _archiveNamePrefix.Empty(); if (folder == NULL) { _agentFolder = NULL; return S_OK; } else { CMyComPtr<IFolderFolder> archiveFolder = folder; CMyComPtr<IArchiveFolderInternal> archiveFolderInternal; RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal)); RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder)); } UStringVector pathParts; pathParts.Clear(); CMyComPtr<IFolderFolder> folderItem = folder; if (folderItem != NULL) for (;;) { CMyComPtr<IFolderFolder> newFolder; folderItem->BindToParentFolder(&newFolder); if (newFolder == NULL) break; NCOM::CPropVariant prop; if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK) if (prop.vt == VT_BSTR) pathParts.Insert(0, (const wchar_t *)prop.bstrVal); folderItem = newFolder; } for (int i = 0; i < pathParts.Size(); i++) { _archiveNamePrefix += pathParts[i]; _archiveNamePrefix += WCHAR_PATH_SEPARATOR; } return S_OK; }
STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems, Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, const wchar_t *path, IFolderOperationsExtractCallback *callback) { if (moveMode) return E_NOTIMPL; COM_TRY_BEGIN CMyComPtr<IFolderArchiveExtractCallback> extractCallback2; { CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback; RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2)); } NExtract::NPathMode::EEnum pathMode = _flatMode ? NExtract::NPathMode::kNoPaths : NExtract::NPathMode::kCurPaths; return Extract(indices, numItems, includeAltStreams, replaceAltStreamCharsMode, pathMode, NExtract::NOverwriteMode::kAsk, path, BoolToInt(false), extractCallback2); COM_TRY_END }
HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; }
STDMETHODIMP CAgent::DoOperation( CCodecs *codecs, int formatIndex, const wchar_t *newArchiveName, const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100) { if (!CanUpdate()) return E_NOTIMPL; NUpdateArchive::CActionSet actionSet; int i; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i]; CDirItems dirItems; { UString folderPrefix = _folderPrefix; NFile::NName::NormalizeDirPathPrefix(folderPrefix); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes); if (errorCodes.Size() > 0) return errorCodes.Front(); } CMyComPtr<IOutArchive> outArchive; if (GetArchive()) { RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive)); } else { if (formatIndex < 0) return E_FAIL; RINOK(codecs->CreateOutArchive(formatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kDOS: case NFileTimeType::kUnix: fileTimeType = NFileTimeType::EEnum(value); break; default: return E_FAIL; } CObjectVector<CArcItem> arcItems; if (GetArchive()) { RINOK(ReadItems()); EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", arcItems); } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); CAgUpCallbackImp upCallback(&arcItems, updateCallback100); UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback); } UInt32 numFiles = 0; for (i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; if (updateCallback100) { RINOK(updateCallback100->SetNumFiles(numFiles)); } CUpdateCallbackAgent updateCallbackAgent; updateCallbackAgent.SetCallback(updateCallback100); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec ); updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; updateCallbackSpec->Archive = GetArchive(); updateCallbackSpec->Callback = &updateCallbackAgent; COutFileStream *outStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outStream(outStreamSpec); UString archiveName = newArchiveName; { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) return E_FAIL; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } if (!outStreamSpec->Create(archiveName, true)) { // ShowLastErrorMessage(); return E_FAIL; } CMyComPtr<ISetProperties> setProperties; if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK) { if (m_PropNames.Size() == 0) { RINOK(setProperties->SetProperties(0, 0, 0)); } else { CRecordVector<const wchar_t *> names; for(i = 0; i < m_PropNames.Size(); i++) names.Add((const wchar_t *)m_PropNames[i]); NWindows::NCOM::CPropVariant *propValues = new NWindows::NCOM::CPropVariant[m_PropValues.Size()]; try { for (int i = 0; i < m_PropValues.Size(); i++) propValues[i] = m_PropValues[i]; RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size())); } catch(...) { delete []propValues; return E_FAIL; } delete []propValues; } } m_PropNames.Clear(); m_PropValues.Clear(); if (sfxModule != NULL) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) return E_FAIL; // throw "Can't open sfx module"; RINOK(CopyBlock(sfxStream, outStream)); } RINOK(outArchive->UpdateItems(outStream, updatePairs2.Size(),updateCallback)); return outStreamSpec->Close(); }
HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<ICryptoGetTextPassword> getTextPassword; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; CVolumeName seqName; UInt64 totalBytes = 0; UInt64 curBytes = 0; if (openArchiveCallback != NULL) { openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); } for (;;) { CMyComPtr<IInStream> inStream; if (!_archives.IsEmpty()) { if (!openVolumeCallback) break; if (_archives.Size() == 1) { if (!_archiveInfo.IsVolume()) break; UString baseName; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; baseName = prop.bstrVal; } seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName()); } UString fullName = seqName.GetNextName(); HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; } else inStream = stream; UInt64 endPos = 0; if (openArchiveCallback != NULL) { RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); totalBytes += endPos; RINOK(openArchiveCallback->SetTotal(NULL, &totalBytes)); } NArchive::NRar::CInArchive archive; RINOK(archive.Open(inStream, maxCheckStartPosition)); if (_archives.IsEmpty()) archive.GetArchiveInfo(_archiveInfo); CItemEx item; for (;;) { bool decryptionError; HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError); if (result == S_FALSE) { if (decryptionError && _items.IsEmpty()) return S_FALSE; break; } RINOK(result); if (item.IgnoreItem()) continue; bool needAdd = true; if (item.IsSplitBefore()) { if (!_refItems.IsEmpty()) { CRefItem &refItem = _refItems.Back(); refItem.NumItems++; needAdd = false; } } if (needAdd) { CRefItem refItem; refItem.ItemIndex = _items.Size(); refItem.NumItems = 1; refItem.VolumeIndex = _archives.Size(); _refItems.Add(refItem); } _items.Add(item); if (openArchiveCallback != NULL && _items.Size() % 100 == 0) { UInt64 numFiles = _items.Size(); UInt64 numBytes = curBytes + item.Position; RINOK(openArchiveCallback->SetCompleted(&numFiles, &numBytes)); } } curBytes += endPos; _archives.Add(archive); } } return S_OK; }
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) { COM_TRY_BEGIN Close(); HRESULT res = S_FALSE; CInArchive archive; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = callback; openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); } CMyComPtr<IInStream> nextStream = inStream; bool prevChecked = false; UInt64 numItems = 0; try { while(nextStream != 0) { CDatabaseEx db; db.Stream = nextStream; res = archive.Open(maxCheckStartPosition, db); if (res == S_OK) { if (!m_Database.Volumes.IsEmpty()) { const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0]; if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID || dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) != db.ArchiveInfo.CabinetNumber) res = S_FALSE; } } if (res == S_OK) m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db); else if (res != S_FALSE) return res; else { if (m_Database.Volumes.IsEmpty()) return S_FALSE; if (prevChecked) break; prevChecked = true; } numItems += db.Items.Size(); RINOK(callback->SetCompleted(&numItems, NULL)); nextStream = 0; for (;;) { const COtherArchive *otherArchive = 0; if (!prevChecked) { const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo; if (ai.IsTherePrev()) otherArchive = &ai.PreviousArchive; else prevChecked = true; } if (otherArchive == 0) { const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; if (ai.IsThereNext()) otherArchive = &ai.NextArchive; } if (!otherArchive) break; const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP); HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_OK) break; if (result != S_FALSE) return result; if (prevChecked) break; prevChecked = true; } } if (res == S_OK) { m_Database.FillSortAndShrink(); if (!m_Database.Check()) res = S_FALSE; } } catch(...) { res = S_FALSE; } if (res != S_OK) { Close(); return res; } COM_TRY_END return S_OK; }
HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const UInt32 kBufferSize = (200 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); for (UInt32 pos = 0; pos < processedSize; pos++) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() == 0) continue; if (pos + sig.GetCapacity() > processedSize) continue; if (TestSignature(buffer + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices.Delete(i--); } } } orderIndices2 += orderIndices; orderIndices = orderIndices2; /* begin: extracted from 4.65 */ if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } /* end: extracted from 4.65 */ } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] && 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif HRESULT badResult = S_OK; for(i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; if(result != S_OK) { badResult = result; if(result == E_ABORT) break; continue; } *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } if (badResult != S_OK) return badResult; return S_FALSE; }
HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); }
HRESULT CArchiveLink::Open( CCodecs *codecs, const CIntVector &formatIndices, bool stdInMode, IInStream *stream, const UString &filePath, IArchiveOpenCallback *callback) { Release(); if (formatIndices.Size() >= 32) return E_NOTIMPL; HRESULT resSpec; for (;;) { resSpec = S_OK; int formatIndex = -1; if (formatIndices.Size() >= 1) { if (Arcs.Size() >= formatIndices.Size()) break; formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; } else if (Arcs.Size() >= 32) break; if (Arcs.IsEmpty()) { CArc arc; arc.Path = filePath; arc.SubfileIndex = (UInt32)(Int32)-1; RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); Arcs.Add(arc); continue; } const CArc &arc = Arcs.Back(); resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); UInt32 mainSubfile; { NCOM::CPropVariant prop; RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop)); if (prop.vt == VT_UI4) mainSubfile = prop.ulVal; else break; UInt32 numItems; RINOK(arc.Archive->GetNumberOfItems(&numItems)); if (mainSubfile >= numItems) break; } CMyComPtr<IInArchiveGetStream> getStream; if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) break; CMyComPtr<ISequentialInStream> subSeqStream; if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) break; CMyComPtr<IInStream> subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) break; CArc arc2; RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(arc2.Path); arc2.SubfileIndex = mainSubfile; HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result == S_FALSE) break; RINOK(result); RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); Arcs.Add(arc2); } IsOpen = !Arcs.IsEmpty(); return S_OK; }
HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifndef _7ZIP_ST { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword = new CCryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { UString & password = _options.Password; /* const UInt32 sizeInBytes = (_options.Password.Length()+1) * 2; CByteBuffer buffer; buffer.SetCapacity(sizeInBytes); parallel::_for( 0,password.Length(), [&buffer, &password]( int i, bool & breakFlag ) { if( breakFlag ) return; wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } , 4 ); buffer[sizeInBytes-1] = 0; buffer[sizeInBytes-2] = 0; RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes-2)); */ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(&_options.Password[0]), password.Length()*2)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; }
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<ICryptoGetTextPassword> getTextPassword; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; CVolumeName seqName; if (openArchiveCallback != NULL) { openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); RINOK(openArchiveCallback->SetTotal(NULL, NULL)); UInt64 numFiles = _items.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); } for (;;) { CMyComPtr<IInStream> inStream; if (!_archives.IsEmpty()) { if (!openVolumeCallback) break; if(_archives.Size() == 1) { if (!_archiveInfo.IsVolume()) break; UString baseName; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; baseName = prop.bstrVal; } seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName()); } UString fullName = seqName.GetNextName(); HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; } else inStream = stream; NArchive::NRar::CInArchive archive; if(!archive.Open(inStream, maxCheckStartPosition)) return S_FALSE; if (_archives.IsEmpty()) archive.GetArchiveInfo(_archiveInfo); CItemEx item; for (;;) { HRESULT result = archive.GetNextItem(item, getTextPassword); if (result == S_FALSE) break; RINOK(result); if (item.IgnoreItem()) continue; bool needAdd = true; if (item.IsSplitBefore()) { if (!_refItems.IsEmpty()) { CRefItem &refItem = _refItems.Back(); refItem.NumItems++; needAdd = false; } } 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 }
HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { if (pluginPanelItems.Size() == 0) return E_FAIL; UStringVector fileNames; int i; for (i = 0; i < pluginPanelItems.Size(); i++) { const PluginPanelItem &panelItem = pluginPanelItems[i]; if (strcmp(panelItem.FindData.cFileName, "..") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; if (strcmp(panelItem.FindData.cFileName, ".") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; FString fullPath; FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP)); if (!MyGetFullPathName(fileNameUnicode, fullPath)) return E_FAIL; fileNames.Add(fs2us(fullPath)); } NCompression::CInfo compressionInfo; compressionInfo.Load(); int archiverIndex = 0; CCodecs *codecs = new CCodecs; CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; if (codecs->Load() != S_OK) throw "Can't load 7-Zip codecs"; { for (int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arcInfo = codecs->Formats[i]; if (arcInfo.UpdateEnabled) { if (archiverIndex == -1) archiverIndex = i; if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0) archiverIndex = i; } } } UString resultPath; { CParsedPath parsedPath; parsedPath.ParsePath(fileNames.Front()); if (parsedPath.PathParts.Size() == 0) return E_FAIL; if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1) { // CSysString pureName, dot, extension; resultPath = parsedPath.PathParts.Back(); } else { parsedPath.PathParts.DeleteBack(); resultPath = parsedPath.PathParts.Back(); } } UString archiveNameSrc = resultPath; UString archiveName = archiveNameSrc; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; int prevFormat = archiverIndex; if (!arcInfo.KeepName) { int dotPos = archiveName.ReverseFind('.'); int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); if (dotPos > slashPos) archiveName = archiveName.Left(dotPos); } archiveName += L'.'; archiveName += arcInfo.GetMainExt(); const CActionSet *actionSet = &kAddActionSet; for (;;) { AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP); const int kYSize = 16; const int kXMid = 38; const int kArchiveNameIndex = 2; const int kMethodRadioIndex = kArchiveNameIndex + 2; const int kModeRadioIndex = kMethodRadioIndex + 7; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; char updateAddToArchiveString[512]; const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP); sprintf(updateAddToArchiveString, g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s); int methodIndex = 0; int i; for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; break; } struct CInitDialogItem initItems[]= { { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL }, { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL }, { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName}, // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL}, { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL }, { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL }, { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1, 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL }, { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2, 0, false, NMessageID::kUpdateMethodFast, NULL, NULL }, { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3, 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL }, { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4, false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL }, { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5, false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL }, { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, actionSet == &kAddActionSet, DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, actionSet == &kUpdateActionSet, 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, actionSet == &kFreshActionSet, 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, actionSet == &kSynchronizeActionSet, 0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL }, { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL } }; const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); const int kOkButtonIndex = kNumDialogItems - 3; const int kSelectarchiverButtonIndex = kNumDialogItems - 2; FarDialogItem dialogItems[kNumDialogItems]; g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); int askCode = g_StartupInfo.ShowDialog(76, kYSize, kHelpTopic, dialogItems, kNumDialogItems); archiveNameA = dialogItems[kArchiveNameIndex].Data; archiveNameA.Trim(); archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP); compressionInfo.Level = g_MethodMap[0]; for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) if (dialogItems[kMethodRadioIndex + i].Selected) compressionInfo.Level = g_MethodMap[i]; if (dialogItems[kModeRadioIndex].Selected) actionSet = &kAddActionSet; else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &kUpdateActionSet; else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &kFreshActionSet; else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &kSynchronizeActionSet; else throw 51751; if (askCode == kSelectarchiverButtonIndex) { CIntVector indices; CSysStringVector archiverNames; for (int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; if (arc.UpdateEnabled) { indices.Add(i); archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP)); } } int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT, g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle), NULL, archiverNames, archiverIndex); if (index >= 0) { const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat]; if (prevArchiverInfo.KeepName) { const UString &prevExtension = prevArchiverInfo.GetMainExt(); const int prevExtensionLen = prevExtension.Length(); if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0) { int pos = archiveName.Length() - prevExtensionLen; if (pos > 1) { int dotPos = archiveName.ReverseFind('.'); if (dotPos == pos - 1) archiveName = archiveName.Left(dotPos); } } } archiverIndex = indices[index]; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; prevFormat = archiverIndex; if (arcInfo.KeepName) archiveName = archiveNameSrc; else { int dotPos = archiveName.ReverseFind('.'); int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); if (dotPos > slashPos) archiveName = archiveName.Left(dotPos); } archiveName += L'.'; archiveName += arcInfo.GetMainExt(); } continue; } if (askCode != kOkButtonIndex) return E_ABORT; break; } const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex]; compressionInfo.ArcType = archiverInfoFinal.Name; compressionInfo.Save(); NWorkDir::CInfo workDirInfo; workDirInfo.Load(); FString fullArchiveName; if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName)) return E_FAIL; CWorkDirTempFile tempFile; RINOK(tempFile.CreateTempFile(fullArchiveName)); CScreenRestorer screenRestorer; CProgressBox progressBox; CProgressBox *progressBoxPointer = NULL; screenRestorer.Save(); progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); NFind::CFileInfo fileInfo; CMyComPtr<IOutFolderArchive> outArchive; CMyComPtr<IInFolderArchive> archiveHandler; if (fileInfo.Find(fullArchiveName)) { if (fileInfo.IsDir()) throw "There is Directory with such name"; CAgent *agentSpec = new CAgent; archiveHandler = agentSpec; // CLSID realClassID; CMyComBSTR archiveType; RINOK(agentSpec->Open(NULL, GetUnicodeString(fullArchiveName, CP_OEMCP), UString(), // &realClassID, &archiveType, NULL)); if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0) throw "Type of existing archive differs from specified type"; HRESULT result = archiveHandler.QueryInterface( IID_IOutFolderArchive, &outArchive); if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return E_FAIL; } } else { // HRESULT result = outArchive.CoCreateInstance(classID); CAgent *agentSpec = new CAgent; outArchive = agentSpec; /* HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler); if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return E_FAIL; } */ } CRecordVector<const wchar_t *> fileNamePointers; fileNamePointers.Reserve(fileNames.Size()); for (i = 0; i < fileNames.Size(); i++) fileNamePointers.Add(fileNames[i]); outArchive->SetFolder(NULL); outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer); RINOK(SetOutProperties(outArchive, compressionInfo.Level)); HRESULT result = outArchive->DoOperation( codecs, archiverIndex, tempFile.OutStream, actionSetByte, NULL, updateCallback); updateCallback.Release(); outArchive.Release(); if (result != S_OK) { ShowErrorMessage(result); return result; } if (archiveHandler) { archiveHandler->Close(); } if (!tempFile.MoveToOriginal(archiveHandler != NULL)) { ShowLastErrorMessage(); return E_FAIL; } return S_OK; }
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, const CObjectVector<NArchive::NTar::CItemEx> &inputItems, const CObjectVector<CUpdateItem> &updateItems, UINT codePage, IArchiveUpdateCallback *updateCallback) { COutArchive outArchive; outArchive.Create(outStream); outArchive.Pos = 0; CMyComPtr<IOutStream> outSeekStream; outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); UInt64 complexity = 0; unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) complexity += ui.Size; else complexity += inputItems[ui.IndexInArchive].GetFullSize(); } RINOK(updateCallback->SetTotal(complexity)); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); complexity = 0; for (i = 0; i < updateItems.Size(); i++) { lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); const CUpdateItem &ui = updateItems[i]; CItem item; if (ui.NewProps) { item.Mode = ui.Mode; item.Name = ui.Name; item.User = ui.User; item.Group = ui.Group; if (ui.IsDir) { item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; item.PackSize = 0; } else { item.LinkFlag = NFileHeader::NLinkFlag::kNormal; item.PackSize = ui.Size; } item.MTime = ui.MTime; item.DeviceMajorDefined = false; item.DeviceMinorDefined = false; item.UID = 0; item.GID = 0; memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8); } else item = inputItems[ui.IndexInArchive]; AString symLink; if (ui.NewData || ui.NewProps) { RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, true)); if (!symLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kSymLink; item.LinkName = symLink; } } if (ui.NewData) { item.SparseBlocks.Clear(); item.PackSize = ui.Size; item.Size = ui.Size; if (ui.Size == (UInt64)(Int64)-1) return E_INVALIDARG; CMyComPtr<ISequentialInStream> fileInStream; bool needWrite = true; if (!symLink.IsEmpty()) { item.PackSize = 0; item.Size = 0; } else { HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream); if (res == S_FALSE) needWrite = false; else { RINOK(res); if (fileInStream) { CMyComPtr<IStreamGetProps> getProps; fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps); if (getProps) { FILETIME mTime; UInt64 size2; if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) { item.PackSize = size2; item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; } } } { AString hardLink; RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true)); if (!hardLink.IsEmpty()) { item.LinkFlag = NFileHeader::NLinkFlag::kHardLink; item.LinkName = hardLink; item.PackSize = 0; item.Size = 0; fileInStream.Release(); } } } } if (needWrite) { UInt64 fileHeaderStartPos = outArchive.Pos; RINOK(outArchive.WriteHeader(item)); if (fileInStream) { RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress)); outArchive.Pos += copyCoderSpec->TotalSize; if (copyCoderSpec->TotalSize != item.PackSize) { if (!outSeekStream) return E_FAIL; UInt64 backOffset = outArchive.Pos - fileHeaderStartPos; RINOK(outSeekStream->Seek(-(Int64)backOffset, STREAM_SEEK_CUR, NULL)); outArchive.Pos = fileHeaderStartPos; item.PackSize = copyCoderSpec->TotalSize; RINOK(outArchive.WriteHeader(item)); RINOK(outSeekStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL)); outArchive.Pos += item.PackSize; } RINOK(outArchive.FillDataResidual(item.PackSize)); } } complexity += item.PackSize; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } else { const CItemEx &existItem = inputItems[ui.IndexInArchive]; UInt64 size; if (ui.NewProps) { // memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8); if (!symLink.IsEmpty()) { item.PackSize = 0; item.Size = 0; } else { if (ui.IsDir == existItem.IsDir()) item.LinkFlag = existItem.LinkFlag; item.SparseBlocks = existItem.SparseBlocks; item.Size = existItem.Size; item.PackSize = existItem.PackSize; } item.DeviceMajorDefined = existItem.DeviceMajorDefined; item.DeviceMinorDefined = existItem.DeviceMinorDefined; item.DeviceMajor = existItem.DeviceMajor; item.DeviceMinor = existItem.DeviceMinor; item.UID = existItem.UID; item.GID = existItem.GID; RINOK(outArchive.WriteHeader(item)); RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL)); size = existItem.PackSize; } else { RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL)); size = existItem.GetFullSize(); } streamSpec->Init(size); RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); if (copyCoderSpec->TotalSize != size) return E_FAIL; outArchive.Pos += size; RINOK(outArchive.FillDataResidual(existItem.PackSize)); complexity += size; } } lps->InSize = lps->OutSize = complexity; RINOK(lps->SetCur()); return outArchive.WriteFinishHeader(); }
static HRESULT InternalOpenArchive(C7ZipLibrary * pLibrary, C7ZipDllHandler * pHandler, C7ZipInStream * pInStream, C7ZipArchiveOpenCallback * pOpenCallBack, C7ZipArchive ** ppArchive, HRESULT * pResult, bool fCheckFileTypeBySignature) { CMyComPtr<IInArchive> archive = NULL; CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo = NULL; CMyComPtr<IInArchiveGetStream> getStream = NULL; wstring extension = pInStream->GetExt(); C7ZipInStreamWrapper * pArchiveStream = new C7ZipInStreamWrapper(pInStream); CMyComPtr<IInStream> inStream(pArchiveStream); CMyComPtr<IArchiveOpenCallback> openCallBack(pOpenCallBack); std::vector<IInArchive *> archives; do { if (archive != NULL) archives.push_back(archive); FAIL_RET(CreateInArchive(pHandler->GetFunctions(), pHandler->GetFormatInfoArray(), inStream, extension, archive, fCheckFileTypeBySignature), pResult); if (archive == NULL) return false; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { C7ZipCompressCodecsInfo * pCompressCodecsInfo = new C7ZipCompressCodecsInfo(pLibrary); RBOOLOK(setCompressCodecsInfo->SetCompressCodecsInfo(pCompressCodecsInfo)); } FAIL_RET(archive->Open(inStream, &kMaxCheckStartPosition, openCallBack), pResult); UInt32 mainSubfile; { NCOM::CPropVariant prop; FAIL_RET(archive->GetArchiveProperty(kpidMainSubfile, &prop), pResult); if (prop.vt == VT_UI4) mainSubfile = prop.ulVal; else { break; } UInt32 numItems; FAIL_RET(archive->GetNumberOfItems(&numItems), pResult); if (mainSubfile >= numItems) break; } if (archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) break; CMyComPtr<ISequentialInStream> subSeqStream; if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) break; inStream = NULL; if (subSeqStream.QueryInterface(IID_IInStream, &inStream) != S_OK || !inStream) break; wstring path; FAIL_RET(GetArchiveItemPath(archive, mainSubfile, path), pResult); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openCallBack->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) { setSubArchiveName->SetSubArchiveName(path.c_str()); } FAIL_RET(GetFilePathExt(path, extension), pResult); } while(true); if (archive == NULL) return S_FALSE; return Create7ZipArchive(pLibrary, archives, archive, ppArchive) ? S_OK : S_FALSE; }
HRESULT UpdateArchive( DECL_EXTERNAL_CODECS_LOC_VARS IInStream * /* inStream */, UInt64 unpackSize, ISequentialOutStream *outStream, const CItem &newItem, const CCompressionMethodMode &compressionMethod, int indexInClient, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = unpackSize; RINOK(updateCallback->SetTotal(complexity)); CMyComPtr<ICompressCoder> deflateEncoder; complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CMyComPtr<ISequentialInStream> fileInStream; RINOK(updateCallback->GetStream(indexInClient, &fileInStream)); CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC; CMyComPtr<ISequentialInStream> crcStream(inStreamSpec); inStreamSpec->SetStream(fileInStream); inStreamSpec->Init(); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); COutArchive outArchive; outArchive.Create(outStream); CItem item = newItem; item.CompressionMethod = NFileHeader::NCompressionMethod::kDeflate; item.ExtraFlags = 0; item.HostOS = kHostOS; RINOK(outArchive.WriteHeader(item)); { RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS kMethodId_Deflate, deflateEncoder, true)); if (!deflateEncoder) return E_NOTIMPL; NWindows::NCOM::CPropVariant properties[] = { compressionMethod.Algo, compressionMethod.NumPasses, compressionMethod.NumFastBytes, compressionMethod.NumMatchFinderCycles }; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kNumPasses, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinderCycles }; int numProps = sizeof(propIDs) / sizeof(propIDs[0]); if (!compressionMethod.NumMatchFinderCyclesDefined) numProps--; CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(deflateEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps)); } RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress)); item.FileCRC = inStreamSpec->GetCRC(); item.UnPackSize32 = (UInt32)inStreamSpec->GetSize(); RINOK(outArchive.WritePostHeader(item)); return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); }
void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode) { const UString name = GetItemName(index); if (IsNameVirus(name)) { MessageBoxErrorLang(IDS_VIRUS, 0x03020284); return; } CMyComPtr<IFolderOperations> folderOperations; if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) { MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name)); UString fullVirtPath = _currentFolderPrefix + name; NFile::NDirectory::CTempDirectoryW tempDirectory; tempDirectory.Create(kTempDirPrefix); UString tempDir = tempDirectory.GetPath(); UString tempDirNorm = tempDir; NFile::NName::NormalizeDirPathPrefix(tempDirNorm); UString tempFilePath = tempDirNorm + GetCorrectFsPath(name); CTempFileInfo tempFileInfo; tempFileInfo.ItemName = name; tempFileInfo.FolderPath = tempDir; tempFileInfo.FilePath = tempFilePath; tempFileInfo.NeedDelete = true; if (tryAsArchive) { CMyComPtr<IInArchiveGetStream> getStream; _folder.QueryInterface(IID_IInArchiveGetStream, &getStream); if (getStream) { CMyComPtr<ISequentialInStream> subSeqStream; getStream->GetStream(index, &subSeqStream); if (subSeqStream) { CMyComPtr<IInStream> subStream; subSeqStream.QueryInterface(IID_IInStream, &subStream); if (subStream) { bool encrypted; if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, encrypted) == S_OK) { tempDirectory.DisableDeleting(); RefreshListCtrl(); return; } } } } } CRecordVector<UInt32> indices; indices.Add(index); UStringVector messages; bool usePassword = false; UString password; if (_parentFolders.Size() > 0) { const CFolderLink &fl = _parentFolders.Back(); usePassword = fl.UsePassword; password = fl.Password; } HRESULT result = CopyTo(indices, tempDirNorm, false, true, &messages, usePassword, password); if (_parentFolders.Size() > 0) { CFolderLink &fl = _parentFolders.Back(); fl.UsePassword = usePassword; fl.Password = password; } if (!messages.IsEmpty()) return; if (result != S_OK) { if (result != E_ABORT) MessageBoxError(result); return; } if (tryAsArchive) { bool encrypted; if (OpenItemAsArchive(NULL, tempFileInfo, fullVirtPath, encrypted) == S_OK) { tempDirectory.DisableDeleting(); RefreshListCtrl(); return; } } CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo()); CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get(); tmpProcessInfo->FolderPath = tempDir; tmpProcessInfo->FilePath = tempFilePath; tmpProcessInfo->NeedDelete = true; tmpProcessInfo->UsePassword = usePassword; tmpProcessInfo->Password = password; if (!tmpProcessInfo->FileInfo.Find(tempFilePath)) return; CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo); if (!tryExternal) return; CProcess process; HRESULT res; if (editMode) res = StartEditApplication(tempFilePath, (HWND)*this, process); else res = StartApplication(tempDirNorm, tempFilePath, (HWND)*this, process); if ((HANDLE)process == 0) return; tmpProcessInfo->Window = (HWND)(*this); tmpProcessInfo->FullPathFolderPrefix = _currentFolderPrefix; tmpProcessInfo->ItemName = name; tmpProcessInfo->ProcessHandle = process.Detach(); NWindows::CThread thread; if (thread.Create(MyThreadFunction, tmpProcessInfo) != S_OK) throw 271824; tempDirectory.DisableDeleting(); tmpProcessInfoPtr.release(); tmpProcessInfoRelease._needDelete = false; }
HRESULT CZipDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS CInArchive &archive, const CItemEx &item, ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, UInt32 numThreads, Int32 &res) { res = NArchive::NExtract::NOperationResult::kDataError; CInStreamReleaser inStreamReleaser; bool needCRC = true; bool wzAesMode = false; bool pkAesMode = false; UInt16 methodId = item.CompressionMethod; if (item.IsEncrypted()) { if (item.IsStrongEncrypted()) { CStrongCryptoField f; if (item.CentralExtra.GetStrongCryptoField(f)) { pkAesMode = true; } if (!pkAesMode) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } } if (methodId == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtraField aesField; if (item.CentralExtra.GetWzAesField(aesField)) { wzAesMode = true; needCRC = aesField.NeedCrc(); } } } COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(needCRC); UInt64 authenticationPos; CMyComPtr<ISequentialInStream> inStream; { UInt64 packSize = item.PackSize; if (wzAesMode) { if (packSize < NCrypto::NWzAes::kMacSize) return S_OK; packSize -= NCrypto::NWzAes::kMacSize; } UInt64 dataPos = item.GetDataPosition(); inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); authenticationPos = dataPos + packSize; } CMyComPtr<ICompressFilter> cryptoFilter; if (item.IsEncrypted()) { if (wzAesMode) { CWzAesExtraField aesField; if (!item.CentralExtra.GetWzAesField(aesField)) return S_OK; methodId = aesField.Method; if (!_wzAesDecoder) { _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder; _wzAesDecoder = _wzAesDecoderSpec; } cryptoFilter = _wzAesDecoder; Byte properties = aesField.Strength; RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1)); } else if (pkAesMode) { if (!_pkAesDecoder) { _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder; _pkAesDecoder = _pkAesDecoderSpec; } cryptoFilter = _pkAesDecoder; } else { if (!_zipCryptoDecoder) { _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder; _zipCryptoDecoder = _zipCryptoDecoderSpec; } cryptoFilter = _zipCryptoDecoder; } CMyComPtr<ICryptoSetPassword> cryptoSetPassword; RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); if (!getTextPassword) extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); if (getTextPassword) { CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); AString charPassword; if (wzAesMode || pkAesMode) { charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); /* for (int i = 0;; i++) { wchar_t c = password[i]; if (c == 0) break; if (c >= 0x80) { res = NArchive::NExtract::NOperationResult::kDataError; return S_OK; } charPassword += (char)c; } */ } else { // we use OEM. WinZip/Windows probably use ANSI for some files charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); } HRESULT result = cryptoSetPassword->CryptoSetPassword( (const Byte *)(const char *)charPassword, charPassword.Length()); if (result != S_OK) return S_OK; } else { RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); } } int m; for (m = 0; m < methodItems.Size(); m++) if (methodItems[m].ZipMethod == methodId) break; if (m == methodItems.Size()) { CMethodItem mi; mi.ZipMethod = methodId; if (methodId == NFileHeader::NCompressionMethod::kStored) mi.Coder = new NCompress::CCopyCoder; else if (methodId == NFileHeader::NCompressionMethod::kShrunk) mi.Coder = new NCompress::NShrink::CDecoder; else if (methodId == NFileHeader::NCompressionMethod::kImploded) mi.Coder = new NCompress::NImplode::NDecoder::CCoder; else if (methodId == NFileHeader::NCompressionMethod::kLZMA) mi.Coder = new CLzmaDecoder; else { CMethodId szMethodID; if (methodId == NFileHeader::NCompressionMethod::kBZip2) szMethodID = kMethodId_BZip2; else { if (methodId > 0xFF) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } szMethodID = kMethodId_ZipBase + (Byte)methodId; } RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false)); if (mi.Coder == 0) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } } 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 { HRESULT result = S_OK; CMyComPtr<ISequentialInStream> inStreamNew; if (item.IsEncrypted()) { if (!filterStream) { filterStreamSpec = new CFilterCoder; filterStream = filterStreamSpec; } filterStreamSpec->Filter = cryptoFilter; if (wzAesMode) { result = _wzAesDecoderSpec->ReadHeader(inStream); } else if (pkAesMode) { result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize); if (result == S_OK) { bool passwOK; result = _pkAesDecoderSpec->CheckPassword(passwOK); if (result == S_OK && !passwOK) result = S_FALSE; } } else { result = _zipCryptoDecoderSpec->ReadHeader(inStream); } if (result == S_OK) { RINOK(filterStreamSpec->SetInStream(inStream)); inStreamReleaser.FilterCoder = filterStreamSpec; inStreamNew = filterStream; if (wzAesMode) { if (!_wzAesDecoderSpec->CheckPasswordVerifyCode()) result = S_FALSE; } } } else inStreamNew = inStream; if (result == S_OK) result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress); if (result == S_FALSE) return S_OK; if (result == E_NOTIMPL) { res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; return S_OK; } RINOK(result); } bool crcOK = true; bool authOk = true; if (needCRC) crcOK = (outStreamSpec->GetCRC() == item.FileCRC); if (wzAesMode) { inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize)); if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) authOk = false; } res = ((crcOK && authOk) ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError); return S_OK; }
HRESULT CArc::OpenStream( CCodecs *codecs, int formatIndex, IInStream *stream, ISequentialInStream *seqStream, IArchiveOpenCallback *callback) { Archive.Release(); ErrorMessage.Empty(); const UString fileName = ExtractFileNameFromPath(Path); UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (formatIndex >= 0) orderIndices.Add(formatIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); if (!stream) { if (numFinded != 1) return E_NOTIMPL; orderIndices.DeleteFrom(1); } #ifndef _SFX if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0)) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(stream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; CByteBuffer hashBuffer; const UInt32 kNumVals = 1 << (kNumHashBytes * 8); hashBuffer.SetCapacity(kNumVals); Byte *hash = hashBuffer; memset(hash, 0xFF, kNumVals); Byte prevs[256]; if (orderIndices.Size() >= 256) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < kNumHashBytes) continue; UInt32 v = HASH_VAL(sig, 0); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize -= (kNumHashBytes - 1); for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = HASH_VAL(buf, pos); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) && TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } else ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(stream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf > iIso && iIso >= 0) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } #endif } for (int i = 0; i < orderIndices.Size(); i++) { if (stream) { RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); } CMyComPtr<IInArchive> archive; FormatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(FormatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif // OutputDebugStringW(codecs->Formats[FormatIndex].Name); HRESULT result; if (stream) result = archive->Open(stream, &kMaxCheckStartPosition, callback); else { CMyComPtr<IArchiveOpenSeq> openSeq; archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); if (!openSeq) return E_NOTIMPL; result = openSeq->OpenSeq(seqStream); } if (result == S_FALSE) continue; RINOK(result); { NCOM::CPropVariant prop; archive->GetArchiveProperty(kpidError, &prop); if (prop.vt != VT_EMPTY) ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error"; } Archive = archive; const CArcInfoEx &format = codecs->Formats[FormatIndex]; if (format.Exts.Size() == 0) DefaultName = GetDefaultName2(fileName, L"", L""); else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; const CArcExtInfo &extInfo = format.Exts[subExtIndex]; DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } return S_OK; } return S_FALSE; }
HRESULT CDecoder::Init(IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter) { useFilter = false; CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; if (_decoderInStream) if (method != _method) Release(); _method = method; if (!_codecInStream) { CMyComPtr<ICompressCoder> coder; #ifndef EXCLUDE_COM const NArchive::N7z::CMethodID *methodID = 0; switch (method) { case NMethodType::kCopy: methodID = &k_Copy; break; case NMethodType::kDeflate: methodID = &k_Deflate; break; case NMethodType::kBZip2: methodID = &k_BZip2; break; case NMethodType::kLZMA: methodID = &k_LZMA; break; default: return E_NOTIMPL; } N7z::CMethodInfo methodInfo; if (!N7z::GetMethodInfo(*methodID, methodInfo)) return E_NOTIMPL; RINOK(_libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &coder)); #else switch(method) { case NMethodType::kCopy: coder = new NCompress::CCopyCoder(); break; case NMethodType::kDeflate: coder = new NCompress::NDeflate::NDecoder::CCOMCoder(); break; case NMethodType::kBZip2: coder = new NCompress::NBZip2::CDecoder(); break; case NMethodType::kLZMA: new NCompress::NLZMA::CDecoder(); break; default: return E_NOTIMPL; } #endif coder.QueryInterface(IID_ISequentialInStream, &_codecInStream); if (!_codecInStream) return E_NOTIMPL; } if (thereIsFilterFlag) { UInt32 processedSize; BYTE flag; RINOK(inStream->Read(&flag, 1, &processedSize)); if (processedSize != 1) return E_FAIL; if (flag > 1) return E_NOTIMPL; useFilter = (flag != 0); } if (useFilter) { if (!_filterInStream) { #ifndef EXCLUDE_COM N7z::CMethodInfo methodInfo; if (!N7z::GetMethodInfo(k_BCJ_X86, methodInfo)) return E_NOTIMPL; CMyComPtr<ICompressCoder> coder; RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath, methodInfo.Decoder, &coder)); coder.QueryInterface(IID_ISequentialInStream, &_filterInStream); if (!_filterInStream) return E_NOTIMPL; #else return E_NOTIMPL; #endif } CMyComPtr<ICompressSetInStream> setInStream; _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); if (!setInStream) return E_NOTIMPL; RINOK(setInStream->SetInStream(_codecInStream)); _decoderInStream = _filterInStream; } else _decoderInStream = _codecInStream; if (method == NMethodType::kLZMA) { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { static const UInt32 kPropertiesSize = 5; BYTE properties[kPropertiesSize]; UInt32 processedSize; RINOK(inStream->Read(properties, kPropertiesSize, &processedSize)); if (processedSize != kPropertiesSize) return E_FAIL; RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize)); } } { CMyComPtr<ICompressSetInStream> setInStream; _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream); if (!setInStream) return E_NOTIMPL; RINOK(setInStream->SetInStream(inStream)); } { CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); if (!setOutStreamSize) return E_NOTIMPL; RINOK(setOutStreamSize->SetOutStreamSize(NULL)); } if (useFilter) { /* CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); if (!setOutStreamSize) return E_NOTIMPL; RINOK(setOutStreamSize->SetOutStreamSize(NULL)); */ } return S_OK; }