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 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; }
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; }