예제 #1
0
파일: OpenArchive.cpp 프로젝트: yak1ex/ax7z
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}