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; }
STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream) { CMyComPtr<IInArchiveGetStream> getStream; _agentSpec->GetArchive()->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (!getStream) return S_OK; const CProxyFolder *folder; UInt32 realIndex; if (_flatMode) { const CProxyItem &item = _items[index]; folder = item.Folder; realIndex = item.Index; } else { folder = _proxyFolderItem; realIndex = index; } UInt32 indexInArchive; if (realIndex < (UInt32)folder->Folders.Size()) { const CProxyFolder &item = folder->Folders[realIndex]; if (!item.IsLeaf) return S_OK; indexInArchive = item.Index; } else indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index; return getStream->GetStream(indexInArchive, stream); }
HRESULT CCabFolderOutStream::OpenFile() { Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract) : NExtract::NAskMode::kSkip; RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); if (!m_RealOutStream && !m_TestMode) askMode = NArchive::NExtract::NAskMode::kSkip; return m_ExtractCallback->PrepareOperation(askMode); }
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { Close(); if (!callback) return S_FALSE; CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback; callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); if (!volumeCallback) return S_FALSE; UString name; { NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; name = prop.bstrVal; } int dotPos = name.ReverseFind_Dot(); const UString prefix = name.Left(dotPos + 1); const UString ext = name.Ptr(dotPos + 1); UString ext2 = ext; ext2.MakeLower_Ascii(); CSeqName seqName; unsigned numLetters = 2; bool splitStyle = false; if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) { splitStyle = true; while (numLetters < ext2.Len()) { if (ext2[ext2.Len() - numLetters - 1] != 'a') break; numLetters++; } } else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01")) { while (numLetters < ext2.Len()) { if (ext2[ext2.Len() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Len()) return S_FALSE; } else return S_FALSE; seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); seqName._changedPart = ext.RightPtr(numLetters); seqName._splitStyle = splitStyle; if (prefix.Len() < 1) _subName.SetFromAscii("file"); else _subName.SetFrom(prefix, prefix.Len() - 1); UInt64 size; { NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(stream); { UInt64 numFiles = _streams.Size(); RINOK(callback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName; if (!seqName.GetNextName(fullName)) break; CMyComPtr<IInStream> nextStream; HRESULT result = volumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(volumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); { UInt64 numFiles = _streams.Size(); RINOK(callback->SetCompleted(&numFiles, NULL)); } } if (_streams.Size() == 1) { if (splitStyle) return S_FALSE; } 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 }
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 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; }
HRESULT CFolderOutStream::OpenFile() { if (NumIdenticalFiles == 0) { const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex]; const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; int numExtractItems = 0; int curIndex; for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++) { const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex]; const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex]; if (item.Offset != item2.Offset || item.Size != item2.Size || item.Size == 0) break; if (!m_TestMode && (*m_ExtractStatuses)[curIndex]) numExtractItems++; } NumIdenticalFiles = (curIndex - m_CurrentIndex); if (NumIdenticalFiles == 0) NumIdenticalFiles = 1; TempBufMode = false; if (numExtractItems > 1) { if (!TempBuf || item.Size > TempBufSize) { FreeTempBuf(); TempBuf = (Byte *)MyAlloc(item.Size); TempBufSize = item.Size; if (TempBuf == NULL) return E_OUTOFMEMORY; } TempBufMode = true; m_BufStartFolderOffset = item.Offset; } else if (numExtractItems == 1) { while (NumIdenticalFiles && !(*m_ExtractStatuses)[m_CurrentIndex]) { CMyComPtr<ISequentialOutStream> stream; RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &stream, NExtract::NAskMode::kSkip)); if (stream) return E_FAIL; RINOK(m_ExtractCallback->PrepareOperation(NExtract::NAskMode::kSkip)); m_CurrentIndex++; m_FileIsOpen = true; CloseFile(); } } } Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ? NExtract::NAskMode::kTest : NExtract::NAskMode::kExtract) : NExtract::NAskMode::kSkip; RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode)); if (!m_RealOutStream && !m_TestMode) askMode = NExtract::NAskMode::kSkip; return m_ExtractCallback->PrepareOperation(askMode); }
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) { COM_TRY_BEGIN Close(); HRESULT res = S_FALSE; CInArchive archive; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&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.PrevArc; else prevChecked = true; } if (otherArchive == 0) { const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo; if (ai.IsThereNext()) otherArchive = &ai.NextArc; } if (!otherArchive) break; const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP); if (!openVolumeCallback) break; 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 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; }
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) { COM_TRY_BEGIN Close(); CInArchive archive; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); CMyComPtr<IInStream> nextStream = inStream; bool prevChecked = false; UInt64 numItems = 0; unsigned numTempVolumes = 0; // try { while (nextStream != NULL) { CDatabaseEx db; db.Stream = nextStream; HRESULT res = archive.Open(db, maxCheckStartPosition); _errorInHeaders |= archive.HeaderError; _errorInHeaders |= archive.ErrorInNames; _unexpectedEnd |= archive.UnexpectedEnd; if (res == S_OK && !m_Database.Volumes.IsEmpty()) { const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo; unsigned cabNumber = db.ArcInfo.CabinetNumber; if (lastArc.SetID != db.ArcInfo.SetID) res = S_FALSE; else if (prevChecked) { if (cabNumber != lastArc.CabinetNumber + 1) res = S_FALSE; } else if (cabNumber >= lastArc.CabinetNumber) res = S_FALSE; else if (numTempVolumes != 0) { const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo; if (cabNumber != prevArc.CabinetNumber + 1) res = S_FALSE; } } if (archive.IsArc || res == S_OK) { _isArc = true; if (m_Database.Volumes.IsEmpty()) { _offset = db.StartPosition; _phySize = db.ArcInfo.Size; } } if (res == S_OK) { numItems += db.Items.Size(); m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db); if (!prevChecked && m_Database.Volumes.Size() > 1) { numTempVolumes++; if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber) numTempVolumes = 0; } } else { if (res != S_FALSE) return res; if (m_Database.Volumes.IsEmpty()) return S_FALSE; if (prevChecked) break; prevChecked = true; if (numTempVolumes != 0) { m_Database.Volumes.DeleteFrontal(numTempVolumes); numTempVolumes = 0; } } RINOK(callback->SetCompleted(&numItems, NULL)); nextStream = NULL; for (;;) { const COtherArc *otherArc = NULL; if (!prevChecked) { if (numTempVolumes == 0) { const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo; if (ai.IsTherePrev()) otherArc = &ai.PrevArc; else prevChecked = true; } else { const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo; if (ai.IsThereNext()) otherArc = &ai.NextArc; else { prevChecked = true; m_Database.Volumes.DeleteFrontal(numTempVolumes); numTempVolumes = 0; } } } if (!otherArc) { const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo; if (ai.IsThereNext()) otherArc = &ai.NextArc; } if (!otherArc) break; if (!openVolumeCallback) break; // printf("\n%s", otherArc->FileName); const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP); HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_OK) break; if (result != S_FALSE) return result; if (!_errorMessage.IsEmpty()) _errorMessage.Add_LF(); _errorMessage.AddAscii("Can't open volume: "); _errorMessage += fullName; if (prevChecked) break; prevChecked = true; if (numTempVolumes != 0) { m_Database.Volumes.DeleteFrontal(numTempVolumes); numTempVolumes = 0; } } } // read nextStream iteration if (numTempVolumes != 0) { m_Database.Volumes.DeleteFrontal(numTempVolumes); numTempVolumes = 0; } if (m_Database.Volumes.IsEmpty()) return S_FALSE; else { m_Database.FillSortAndShrink(); if (!m_Database.Check()) return S_FALSE; } } COM_TRY_END return S_OK; }
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; }
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) { COM_TRY_BEGIN Close(); { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CVolumeName seqName; if (callback) callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); UInt32 numVolumes = 1; for (UInt32 i = 1; i <= numVolumes; i++) { CMyComPtr<IInStream> curStream; if (i == 1) curStream = inStream; else { UString fullName = seqName.GetNextName(i); HRESULT result = openVolumeCallback->GetStream(fullName, &curStream); if (result == S_FALSE) continue; if (result != S_OK) return result; if (!curStream) break; } CHeader header; HRESULT res = NWim::ReadHeader(curStream, header, _phySize); if (res != S_OK) { if (i != 1 && res == S_FALSE) continue; return res; } _isArc = true; _bootIndex = header.BootIndex; _version = header.Version; _isOldVersion = header.IsOldVersion(); if (_firstVolumeIndex >= 0) if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header)) break; if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream) break; CWimXml xml; xml.VolIndex = header.PartNumber; res = _db.OpenXml(curStream, header, xml.Data); if (res == S_OK) { if (!xml.Parse()) _xmlError = true; UInt64 totalFiles = xml.GetTotalFilesAndDirs() + xml.Images.Size(); totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items if (totalFiles >= ((UInt32)1 << 30)) totalFiles = 0; res = _db.Open(curStream, header, (unsigned)totalFiles, callback); } if (res != S_OK) { if (i != 1 && res == S_FALSE) continue; return res; } while (_volumes.Size() <= header.PartNumber) _volumes.AddNew(); CVolume &volume = _volumes[header.PartNumber]; volume.Header = header; volume.Stream = curStream; _firstVolumeIndex = header.PartNumber; if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data) { wchar_t sz[16]; ConvertUInt32ToString(xml.VolIndex, sz); xml.FileName = L'['; xml.FileName += sz; xml.FileName += L"].xml"; _xmls.Add(xml); } if (i == 1) { if (header.PartNumber != 1) break; if (!openVolumeCallback) break; numVolumes = header.NumParts; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; seqName.InitName(prop.bstrVal); } } } RINOK(_db.FillAndCheck()); int defaultImageIndex = (int)_defaultImageNumber - 1; bool showImageNumber = (_db.Images.Size() != 1 && defaultImageIndex < 0); if (!showImageNumber && _set_use_ShowImageNumber) showImageNumber = _set_showImageNumber; if (!showImageNumber && _keepMode_ShowImageNumber) showImageNumber = true; _showImageNumber = showImageNumber; RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber)); RINOK(_db.ExtractReparseStreams(_volumes, callback)); /* wchar_t sz[16]; ConvertUInt32ToString(_db.DataStreams.Size(), sz); _nameLenForStreams = MyStringLen(sz); */ _xmlInComments = !_showImageNumber; _numXmlItems = (_xmlInComments ? 0 : _xmls.Size()); _numIgnoreItems = _db.ThereAreDeletedStreams ? 1 : 0; } return S_OK; COM_TRY_END }
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CVolumeName seqName; if (openArchiveCallback != NULL) openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); UInt32 numVolumes = 1; int firstVolumeIndex = -1; for (UInt32 i = 1; i <= numVolumes; i++) { CMyComPtr<IInStream> curStream; if (i != 1) { UString fullName = seqName.GetNextName(i); HRESULT result = openVolumeCallback->GetStream(fullName, &curStream); if (result == S_FALSE) continue; if (result != S_OK) return result; if (!curStream) break; } else curStream = inStream; CHeader header; HRESULT res = NWim::ReadHeader(curStream, header); if (res != S_OK) { if (i == 1) return res; if (res == S_FALSE) continue; return res; } if (firstVolumeIndex >= 0) if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header)) break; if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream) break; CXml xml; xml.VolIndex = header.PartNumber; res = OpenArchive(curStream, header, xml.Data, m_Database); if (res != S_OK) { if (i == 1) return res; if (res == S_FALSE) continue; return res; } while (m_Volumes.Size() <= header.PartNumber) m_Volumes.Add(CVolume()); CVolume &volume = m_Volumes[header.PartNumber]; volume.Header = header; volume.Stream = curStream; firstVolumeIndex = header.PartNumber; bool needAddXml = true; if (m_Xmls.Size() != 0) if (xml.Data == m_Xmls[0].Data) needAddXml = false; if (needAddXml) { xml.Parse(); m_Xmls.Add(xml); } if (i == 1) { if (header.PartNumber != 1) break; if (!openVolumeCallback) break; numVolumes = header.NumParts; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; seqName.InitName(prop.bstrVal); } } } RINOK(SortDatabase(m_Database)); wchar_t sz[32]; ConvertUInt64ToString(m_Database.Streams.Size(), sz); m_NameLenForStreams = MyStringLen(sz); } catch(...) { return S_FALSE; } return S_OK; COM_TRY_END }