Exemple #1
0
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);
}
Exemple #3
0
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;
}
Exemple #4
0
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);
}
Exemple #5
0
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;
}
Exemple #6
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);
}
Exemple #8
0
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;
    }
  }
}
Exemple #9
0
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;
}
Exemple #12
0
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();
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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);
}
Exemple #17
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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
}
Exemple #20
0
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;
}
Exemple #21
0
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();
}
Exemple #22
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;
}
Exemple #23
0
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;
}
Exemple #25
0
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;
}
Exemple #26
0
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;
}