Exemplo n.º 1
0
void CApp::CalculateCrc()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFsOrDrivesFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;

  {
  CThreadCrc t;
  for (int i = 0; i < indices.Size(); i++)
    t.Enumerator.FileNames.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));
  t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath());
  t.Enumerator.FlatMode = GetFlatMode();

  t.ProgressDialog.ShowCompressionInfo = false;

  UString title = LangString(IDS_CHECKSUM_CALCULATING, 0x03020710);

  t.ProgressDialog.MainWindow = _window;
  t.ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);
  t.ProgressDialog.MainAddTitle = title + UString(L' ');

  if (t.Create(title, _window) != S_OK)
    return;
  }
  RefreshTitleAlways();
}
Exemplo n.º 2
0
void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
{
  GetSelectedItemsIndices(indices);
  if (!indices.IsEmpty())
    return;
  if (_listView.GetSelectedCount() == 0)
    return;
  int focusedItem = _listView.GetFocusedItem();
  if (focusedItem >= 0)
  {
    if (_listView.IsItemSelected(focusedItem))
    {
      int realIndex = GetRealItemIndex(focusedItem);
      if (realIndex != kParentIndex)
        indices.Add(realIndex);
    }
  }
}
Exemplo n.º 3
0
void CApp::Link()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  if (indices.Size() != 1)
  {
    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE);
    return;
  }
  int index = indices[0];
  const UString itemName = srcPanel.GetItemName(index);

  const UString fsPrefix = srcPanel.GetFsPath();
  const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  {
    int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
    CPanel &destPanel = Panels[destPanelIndex];
    if (NumPanels > 1)
      if (destPanel.IsFSFolder())
        path = destPanel.GetFsPath();
  }

  CLinkDialog dlg;
  dlg.CurDirPrefix = fsPrefix;
  dlg.FilePath = srcPath + itemName;
  dlg.AnotherPath = path;

  if (dlg.Create(srcPanel.GetParent()) != IDOK)
    return;

  RefreshTitleAlways();
}
void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
{
  CDisableTimerProcessing disableTimerProcessing(*this);
  CRecordVector<UInt32> indices;
  GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  CSelectedState state;
  SaveSelectedState(state);

  #ifndef UNDER_CE
  // WM6 / SHFileOperationW doesn't ask user! So we use internal delete
  if (IsFSFolder() && toRecycleBin)
  {
    bool useInternalDelete = false;
    #ifndef _UNICODE
    if (!g_IsNT)
    {
      CDynamicBuffer<CHAR> buffer;
      FOR_VECTOR (i, indices)
      {
        const AString path = GetSystemString(GetItemFullPath(indices[i]));
        buffer.AddData(path, path.Len() + 1);
      }
      *buffer.GetCurPtrAndGrow(1) = 0;
      SHFILEOPSTRUCTA fo;
      fo.hwnd = GetParent();
      fo.wFunc = FO_DELETE;
      fo.pFrom = (const CHAR *)buffer;
      fo.pTo = 0;
      fo.fFlags = 0;
      if (toRecycleBin)
        fo.fFlags |= FOF_ALLOWUNDO;
      // fo.fFlags |= FOF_NOCONFIRMATION;
      // fo.fFlags |= FOF_NOERRORUI;
      // fo.fFlags |= FOF_SILENT;
      // fo.fFlags |= FOF_WANTNUKEWARNING;
      fo.fAnyOperationsAborted = FALSE;
      fo.hNameMappings = 0;
      fo.lpszProgressTitle = 0;
      /* int res = */ ::SHFileOperationA(&fo);
    }
Exemplo n.º 5
0
void CPanel::InvokeSystemCommand(const char *command)
{
  NCOM::CComInitializer comInitializer;
  if (!IsFsOrPureDrivesFolder())
    return;
  CRecordVector<UInt32> operatedIndices;
  GetOperatedItemIndices(operatedIndices);
  if (operatedIndices.IsEmpty())
    return;
  CMyComPtr<IContextMenu> contextMenu;
  if (CreateShellContextMenu(operatedIndices, contextMenu) != S_OK)
    return;

  CMINVOKECOMMANDINFO ci;
  ZeroMemory(&ci, sizeof(ci));
  ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
  ci.hwnd = GetParent();
  ci.lpVerb = command;
  contextMenu->InvokeCommand(&ci);
}
Exemplo n.º 6
0
Arquivo: 7zIn.cpp Projeto: bks/qz7
void CInArchive::ReadPackInfo(
    UInt64 &dataOffset,
    CRecordVector<UInt64> &packSizes,
    CRecordVector<bool> &packCRCsDefined,
    CRecordVector<UInt32> &packCRCs)
{
    dataOffset = ReadNumber();
    CNum numPackStreams = ReadNum();

    WaitAttribute(NID::kSize);
    packSizes.Clear();
    packSizes.Reserve(numPackStreams);
    for (CNum i = 0; i < numPackStreams; i++)
        packSizes.Add(ReadNumber());

    UInt64 type;
    for (;;)
    {
        type = ReadID();
        if (type == NID::kEnd)
            break;
        if (type == NID::kCRC)
        {
            ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
            continue;
        }
        SkeepData();
    }
    if (packCRCsDefined.IsEmpty())
    {
        packCRCsDefined.Reserve(numPackStreams);
        packCRCsDefined.Clear();
        packCRCs.Reserve(numPackStreams);
        packCRCs.Clear();
        for (CNum i = 0; i < numPackStreams; i++)
        {
            packCRCsDefined.Add(false);
            packCRCs.Add(0);
        }
    }
}
Exemplo n.º 7
0
void CPanel::GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const
{
  GetOperatedItemIndices(indices);
  if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1))
    GetAllItemIndices(indices);
}
Exemplo n.º 8
0
void CApp::Combine()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  int index = indices[0];
  if (indices.Size() != 1 || srcPanel.IsItemFolder(index))
  {
    srcPanel.MessageBox(LangString(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620));
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel._currentFolderPrefix;
  CCopyDialog copyDialog;
  copyDialog.Value = path;
  copyDialog.Title = LangString(IDS_COMBINE, 0x03020600);
  copyDialog.Title += ' ';
  copyDialog.Title += srcPanel.GetItemRelPath(index);

  copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601);;
  if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)
    return;

  CThreadCombine combiner;
  // combiner.Panel = this;

  {
  CProgressDialog progressDialog;
  combiner.ProgressDialog = &progressDialog;

  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
  UString title = LangString(IDS_COMBINING, 0x03020610);

  progressDialog.MainWindow = _window;
  progressDialog.MainTitle = progressWindowTitle;
  progressDialog.MainAddTitle = title + UString(L" ");

  path = copyDialog.Value;
  NFile::NName::NormalizeDirPathPrefix(path);
  if (!NFile::NDirectory::CreateComplexDirectory(path))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));
    return;
  }

  combiner.InputDirPrefix = srcPath;
  combiner.FirstVolumeName = itemName;
  combiner.OutputDirPrefix = path;

  // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
  // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);

  NWindows::CThread thread;
  if (thread.Create(CThreadCombine::MyThreadFunction, &combiner) != S_OK)
    throw 271824;
  progressDialog.Create(title, _window);
  }
  RefreshTitleAlways();

  if (!combiner.Error.IsEmpty())
    srcPanel.MessageBoxMyError(combiner.Error);
  // disableTimerProcessing1.Restore();
  // disableTimerProcessing2.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
Exemplo n.º 9
0
void CApp::Combine()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  int index = indices[0];
  if (indices.Size() != 1 || srcPanel.IsItemFolder(index))
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620);
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel._currentFolderPrefix;

  CVolSeqName volSeqName;
  if (!volSeqName.ParseName(itemName))
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621);
    return;
  }
  
  {
  CThreadCombine combiner;
  
  UString nextName = itemName;
  combiner.TotalSize = 0;
  for (;;)
  {
    NFile::NFind::CFileInfoW fileInfo;
    if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir())
      break;
    combiner.Names.Add(nextName);
    combiner.TotalSize += fileInfo.Size;
    nextName = volSeqName.GetNextName();
  }
  if (combiner.Names.Size() == 1)
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622);
    return;
  }
  
  if (combiner.TotalSize == 0)
  {
    srcPanel.MessageBoxMyError(L"No data");
    return;
  }
  
  UString info;
  AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info);
  
  info += L"\n";
  info += srcPath;
  
  int i;
  for (i = 0; i < combiner.Names.Size() && i < 2; i++)
    AddInfoFileName(combiner.Names[i], info);
  if (i != combiner.Names.Size())
  {
    if (i + 1 != combiner.Names.Size())
      AddInfoFileName(L"...", info);
    AddInfoFileName(combiner.Names.Back(), info);
  }
  
  {
    CCopyDialog copyDialog;
    copyDialog.Value = path;
    copyDialog.Title = LangString(IDS_COMBINE, 0x03020600);
    copyDialog.Title += ' ';
    copyDialog.Title += srcPanel.GetItemRelPath(index);
    copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601);
    copyDialog.Info = info;
    if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)
      return;
    path = copyDialog.Value;
  }

  NFile::NName::NormalizeDirPathPrefix(path);
  if (!NFile::NDirectory::CreateComplexDirectory(path))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));
    return;
  }
  
  UString outName = volSeqName.UnchangedPart;
  while (!outName.IsEmpty())
  {
    int lastIndex = outName.Length() - 1;
    if (outName[lastIndex] != L'.')
      break;
    outName.Delete(lastIndex);
  }
  if (outName.IsEmpty())
    outName = L"file";
  
  NFile::NFind::CFileInfoW fileInfo;
  UString destFilePath = path + outName;
  combiner.OutputPath = destFilePath;
  if (fileInfo.Find(destFilePath))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath));
    return;
  }
  
    CProgressDialog &progressDialog = combiner.ProgressDialog;
    progressDialog.ShowCompressionInfo = false;
  
    UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
    UString title = LangString(IDS_COMBINING, 0x03020610);
    
    progressDialog.MainWindow = _window;
    progressDialog.MainTitle = progressWindowTitle;
    progressDialog.MainAddTitle = title + UString(L" ");
    
    combiner.InputDirPrefix = srcPath;
    
    // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
    // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
    
    if (combiner.Create(title, _window) != 0)
      return;
  }
  RefreshTitleAlways();

  // disableTimerProcessing1.Restore();
  // disableTimerProcessing2.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
Exemplo n.º 10
0
void CApp::Split()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  if (indices.Size() != 1)
  {
    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);
    return;
  }
  int index = indices[0];
  if (srcPanel.IsItemFolder(index))
  {
    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel._currentFolderPrefix;
  CSplitDialog splitDialog;
  splitDialog.FilePath = srcPanel.GetItemRelPath(index);
  splitDialog.Path = path;
  if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL)
    return;

  NFile::NFind::CFileInfoW fileInfo;
  if (!fileInfo.Find(srcPath + itemName))
  {
    srcPanel.MessageBoxMyError(L"Can not find file");
    return;
  }
  if (fileInfo.Size <= splitDialog.VolumeSizes.Front())
  {
    srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522);
    return;
  }
  const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
  if (numVolumes >= 100)
  {
    wchar_t s[32];
    ConvertUInt64ToString(numVolumes, s);
    if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s),
        LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520),
        MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
      return;
  }

  path = splitDialog.Path;
  NFile::NName::NormalizeDirPathPrefix(path);
  if (!NFile::NDirectory::CreateComplexDirectory(path))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));
    return;
  }

  {
  CThreadSplit spliter;
  spliter.NumVolumes = numVolumes;

  CProgressDialog &progressDialog = spliter.ProgressDialog;

  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
  UString title = LangString(IDS_SPLITTING, 0x03020510);

  progressDialog.ShowCompressionInfo = false;

  progressDialog.MainWindow = _window;
  progressDialog.MainTitle = progressWindowTitle;
  progressDialog.MainAddTitle = title + UString(L" ");
  progressDialog.Sync.SetTitleFileName(itemName);


  spliter.FilePath = srcPath + itemName;
  spliter.VolBasePath = path + itemName;
  spliter.VolumeSizes = splitDialog.VolumeSizes;
  
  // if (splitDialog.VolumeSizes.Size() == 0) return;

  // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
  // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);

  if (spliter.Create(title, _window) != 0)
    return;
  }
  RefreshTitleAlways();


  // disableTimerProcessing1.Restore();
  // disableTimerProcessing2.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
Exemplo n.º 11
0
void CApp::CalculateCrc(const UString &methodName)
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];

  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedIndicesSmart(indices);
  if (indices.IsEmpty())
    return;

  if (!srcPanel.IsFsOrDrivesFolder())
  {
    CCopyToOptions options;
    options.streamMode = true;
    options.showErrorMessages = true;
    options.hashMethods.Add(methodName);

    UStringVector messages;
    HRESULT res = srcPanel.CopyTo(options, indices, &messages);
    if (res != S_OK)
    {
      if (res != E_ABORT)
        srcPanel.MessageBoxError(res);
    }
    return;
  }

  CCodecs *codecs = new CCodecs;
  #ifdef EXTERNAL_CODECS
  CExternalCodecs __externalCodecs;
  __externalCodecs.GetCodecs = codecs;
  __externalCodecs.GetHashers = codecs;
  #else
  CMyComPtr<IUnknown> compressCodecsInfo = codecs;
  #endif
  ThrowException_if_Error(codecs->Load());

  #ifdef EXTERNAL_CODECS
  ThrowException_if_Error(__externalCodecs.LoadCodecs());
  #endif

  {
    CThreadCrc t;
    {
      UStringVector methods;
      methods.Add(methodName);
      t.Hash.SetMethods(EXTERNAL_CODECS_VARS methods);
    }
    FOR_VECTOR (i, indices)
      t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));
    t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath());
    t.Enumerator.EnterToDirs = !GetFlatMode();
    
    t.ProgressDialog.ShowCompressionInfo = false;
    
    UString title = LangString(IDS_CHECKSUM_CALCULATING);
    
    t.ProgressDialog.MainWindow = _window;
    t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
    t.ProgressDialog.MainAddTitle = title + UString(L' ');
    
    if (t.Create(title, _window) != S_OK)
      return;
  }
  RefreshTitleAlways();
}
Exemplo n.º 12
0
void CPanel::DeleteItems(bool toRecycleBin)
{
  CPanel::CDisableTimerProcessing disableTimerProcessing2(*this);
  CRecordVector<UInt32> indices;
  GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  CSelectedState state;
  SaveSelectedState(state);

  #ifndef UNDER_CE
  // WM6 / SHFileOperationW doesn't ask user! So we use internal delete
  bool useInternalDelete = false;
  if (IsFSFolder() && toRecycleBin)
  {
    #ifndef _UNICODE
    if (!g_IsNT)
    {
      CDynamicBuffer<CHAR> buffer;
      size_t size = 0;
      for (int i = 0; i < indices.Size(); i++)
      {
        const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i]));
        buffer.EnsureCapacity(size + path.Length() + 1);
        memmove(((CHAR *)buffer) + size, (const CHAR *)path, (path.Length() + 1) * sizeof(CHAR));
        size += path.Length() + 1;
      }
      buffer.EnsureCapacity(size + 1);
      ((CHAR *)buffer)[size]  = 0;
      SHFILEOPSTRUCTA fo;
      fo.hwnd = GetParent();
      fo.wFunc = FO_DELETE;
      fo.pFrom = (const CHAR *)buffer;
      fo.pTo = 0;
      fo.fFlags = 0;
      if (toRecycleBin)
        fo.fFlags |= FOF_ALLOWUNDO;
      // fo.fFlags |= FOF_NOCONFIRMATION;
      // fo.fFlags |= FOF_NOERRORUI;
      // fo.fFlags |= FOF_SILENT;
      // fo.fFlags |= FOF_WANTNUKEWARNING;
      fo.fAnyOperationsAborted = FALSE;
      fo.hNameMappings = 0;
      fo.lpszProgressTitle = 0;
      /* int res = */ ::SHFileOperationA(&fo);
    }
    else
    #endif
    {
      CDynamicBuffer<WCHAR> buffer;
      size_t size = 0;
      int maxLen = 0;
      for (int i = 0; i < indices.Size(); i++)
      {
        // L"\\\\?\\") doesn't work here.
        const UString path = GetFsPath() + GetItemRelPath(indices[i]);
        if (path.Length() > maxLen)
          maxLen = path.Length();
        buffer.EnsureCapacity(size + path.Length() + 1);
        memmove(((WCHAR *)buffer) + size, (const WCHAR *)path, (path.Length() + 1) * sizeof(WCHAR));
        size += path.Length() + 1;
      }
      buffer.EnsureCapacity(size + 1);
      ((WCHAR *)buffer)[size] = 0;
      if (maxLen >= MAX_PATH)
      {
        if (toRecycleBin)
        {
          MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE, 0x03020218);
          return;
        }
        useInternalDelete = true;
      }
      else
      {
        SHFILEOPSTRUCTW fo;
        fo.hwnd = GetParent();
        fo.wFunc = FO_DELETE;
        fo.pFrom = (const WCHAR *)buffer;
        fo.pTo = 0;
        fo.fFlags = 0;
        if (toRecycleBin)
          fo.fFlags |= FOF_ALLOWUNDO;
        fo.fAnyOperationsAborted = FALSE;
        fo.hNameMappings = 0;
        fo.lpszProgressTitle = 0;
        int res;
        #ifdef _UNICODE
        res = ::SHFileOperationW(&fo);
        #else
        SHFileOperationWP shFileOperationW = (SHFileOperationWP)
          ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW");
        if (shFileOperationW == 0)
          return;
        res = shFileOperationW(&fo);
        #endif
      }
    }
    /*
    if (fo.fAnyOperationsAborted)
      MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217));
    */
  }
  else
    useInternalDelete = true;
  if (useInternalDelete)
  #endif
    DeleteItemsInternal(indices);
  RefreshListCtrl(state);
}
Exemplo n.º 13
0
HRESULT CInArchive::ReadHeader(
    DECL_EXTERNAL_CODECS_LOC_VARS
    CArchiveDatabaseEx &db
    #ifndef _NO_CRYPTO
    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
    #endif
    )
{
  UInt64 type = ReadID();

  if (type == NID::kArchiveProperties)
  {
    ReadArchiveProperties(db.ArchiveInfo);
    type = ReadID();
  }
 
  CObjectVector<CByteBuffer> dataVector;
  
  if (type == NID::kAdditionalStreamsInfo)
  {
    HRESULT result = ReadAndDecodePackedStreams(
        EXTERNAL_CODECS_LOC_VARS
        db.ArchiveInfo.StartPositionAfterHeader,
        db.ArchiveInfo.DataStartPosition2,
        dataVector
        #ifndef _NO_CRYPTO
        , getTextPassword, passwordIsDefined
        #endif
        );
    RINOK(result);
    db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;
    type = ReadID();
  }

  CRecordVector<UInt64> unpackSizes;
  CBoolVector digestsDefined;
  CRecordVector<UInt32> digests;
  
  if (type == NID::kMainStreamsInfo)
  {
    ReadStreamsInfo(&dataVector,
        db.ArchiveInfo.DataStartPosition,
        db.PackSizes,
        db.PackCRCsDefined,
        db.PackCRCs,
        db.Folders,
        db.NumUnpackStreamsVector,
        unpackSizes,
        digestsDefined,
        digests);
    db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader;
    type = ReadID();
  }
  else
  {
    for (int i = 0; i < db.Folders.Size(); i++)
    {
      db.NumUnpackStreamsVector.Add(1);
      CFolder &folder = db.Folders[i];
      unpackSizes.Add(folder.GetUnpackSize());
      digestsDefined.Add(folder.UnpackCRCDefined);
      digests.Add(folder.UnpackCRC);
    }
  }

  db.Files.Clear();

  if (type == NID::kEnd)
    return S_OK;
  if (type != NID::kFilesInfo)
    ThrowIncorrect();
  
  CNum numFiles = ReadNum();
  db.Files.Reserve(numFiles);
  CNum i;
  for (i = 0; i < numFiles; i++)
    db.Files.Add(CFileItem());

  db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);
  if (!db.PackSizes.IsEmpty())
    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);
  if (numFiles > 0  && !digests.IsEmpty())
    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);

  CBoolVector emptyStreamVector;
  BoolVector_Fill_False(emptyStreamVector, (int)numFiles);
  CBoolVector emptyFileVector;
  CBoolVector antiFileVector;
  CNum numEmptyStreams = 0;

  for (;;)
  {
    UInt64 type = ReadID();
    if (type == NID::kEnd)
      break;
    UInt64 size = ReadNumber();
    size_t ppp = _inByteBack->_pos;
    bool addPropIdToList = true;
    bool isKnownType = true;
    if (type > ((UInt32)1 << 30))
      isKnownType = false;
    else switch((UInt32)type)
    {
      case NID::kName:
      {
        CStreamSwitch streamSwitch;
        streamSwitch.Set(this, &dataVector);
        for (int i = 0; i < db.Files.Size(); i++)
          _inByteBack->ReadString(db.Files[i].Name);
        break;
      }
      case NID::kWinAttributes:
      {
        CBoolVector boolVector;
        ReadBoolVector2(db.Files.Size(), boolVector);
        CStreamSwitch streamSwitch;
        streamSwitch.Set(this, &dataVector);
        for (i = 0; i < numFiles; i++)
        {
          CFileItem &file = db.Files[i];
          file.AttribDefined = boolVector[i];
          if (file.AttribDefined)
            file.Attrib = ReadUInt32();
        }
        break;
      }
      case NID::kEmptyStream:
      {
        ReadBoolVector(numFiles, emptyStreamVector);
        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
          if (emptyStreamVector[i])
            numEmptyStreams++;

        BoolVector_Fill_False(emptyFileVector, numEmptyStreams);
        BoolVector_Fill_False(antiFileVector, numEmptyStreams);

        break;
      }
      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;
      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;
      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break;
      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break;
      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break;
      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break;
      case NID::kDummy:
      {
        for (UInt64 j = 0; j < size; j++)
          if (ReadByte() != 0)
            ThrowIncorrect();
        addPropIdToList = false;
        break;
      }
      default:
        addPropIdToList = isKnownType = false;
    }
    if (isKnownType)
    {
      if(addPropIdToList)
        db.ArchiveInfo.FileInfoPopIDs.Add(type);
    }
    else
      SkipData(size);
    bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||
        db.ArchiveInfo.Version.Minor > 2);
    if (checkRecordsSize && _inByteBack->_pos - ppp != size)
      ThrowIncorrect();
  }

  CNum emptyFileIndex = 0;
  CNum sizeIndex = 0;

  CNum numAntiItems = 0;
  for (i = 0; i < numEmptyStreams; i++)
    if (antiFileVector[i])
      numAntiItems++;
    
  for (i = 0; i < numFiles; i++)
  {
    CFileItem &file = db.Files[i];
    bool isAnti;
    file.HasStream = !emptyStreamVector[i];
    if (file.HasStream)
    {
      file.IsDir = false;
      isAnti = false;
      file.Size = unpackSizes[sizeIndex];
      file.Crc = digests[sizeIndex];
      file.CrcDefined = digestsDefined[sizeIndex];
      sizeIndex++;
    }
    else
    {
      file.IsDir = !emptyFileVector[emptyFileIndex];
      isAnti = antiFileVector[emptyFileIndex];
      emptyFileIndex++;
      file.Size = 0;
      file.CrcDefined = false;
    }
    if (numAntiItems != 0)
      db.IsAnti.Add(isAnti);
  }
  return S_OK;
}
Exemplo n.º 14
0
void CInArchive::ReadSubStreamsInfo(
    const CObjectVector<CFolder> &folders,
    CRecordVector<CNum> &numUnpackStreamsInFolders,
    CRecordVector<UInt64> &unpackSizes,
    CBoolVector &digestsDefined,
    CRecordVector<UInt32> &digests)
{
  numUnpackStreamsInFolders.Clear();
  numUnpackStreamsInFolders.Reserve(folders.Size());
  UInt64 type;
  for (;;)
  {
    type = ReadID();
    if (type == NID::kNumUnpackStream)
    {
      for (int i = 0; i < folders.Size(); i++)
        numUnpackStreamsInFolders.Add(ReadNum());
      continue;
    }
    if (type == NID::kCRC || type == NID::kSize)
      break;
    if (type == NID::kEnd)
      break;
    SkipData();
  }

  if (numUnpackStreamsInFolders.IsEmpty())
    for (int i = 0; i < folders.Size(); i++)
      numUnpackStreamsInFolders.Add(1);

  int i;
  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
  {
    // v3.13 incorrectly worked with empty folders
    // v4.07: we check that folder is empty
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams == 0)
      continue;
    UInt64 sum = 0;
    for (CNum j = 1; j < numSubstreams; j++)
      if (type == NID::kSize)
      {
        UInt64 size = ReadNumber();
        unpackSizes.Add(size);
        sum += size;
      }
    unpackSizes.Add(folders[i].GetUnpackSize() - sum);
  }
  if (type == NID::kSize)
    type = ReadID();

  int numDigests = 0;
  int numDigestsTotal = 0;
  for (i = 0; i < folders.Size(); i++)
  {
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
      numDigests += numSubstreams;
    numDigestsTotal += numSubstreams;
  }

  for (;;)
  {
    if (type == NID::kCRC)
    {
      CBoolVector digestsDefined2;
      CRecordVector<UInt32> digests2;
      ReadHashDigests(numDigests, digestsDefined2, digests2);
      int digestIndex = 0;
      for (i = 0; i < folders.Size(); i++)
      {
        CNum numSubstreams = numUnpackStreamsInFolders[i];
        const CFolder &folder = folders[i];
        if (numSubstreams == 1 && folder.UnpackCRCDefined)
        {
          digestsDefined.Add(true);
          digests.Add(folder.UnpackCRC);
        }
        else
          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
          {
            digestsDefined.Add(digestsDefined2[digestIndex]);
            digests.Add(digests2[digestIndex]);
          }
      }
    }
    else if (type == NID::kEnd)
    {
      if (digestsDefined.IsEmpty())
      {
        BoolVector_Fill_False(digestsDefined, numDigestsTotal);
        digests.Clear();
        for (int i = 0; i < numDigestsTotal; i++)
          digests.Add(0);
      }
      return;
    }
    else
      SkipData();
    type = ReadID();
  }
}
Exemplo n.º 15
0
void CApp::Split()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.Is_IO_FS_Folder())
  {
    srcPanel.MessageBox_Error_UnsupportOperation();
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  if (indices.Size() != 1)
  {
    srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
    return;
  }
  int index = indices[0];
  if (srcPanel.IsItem_Folder(index))
  {
    srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel.GetFsPath();
  CSplitDialog splitDialog;
  splitDialog.FilePath = srcPanel.GetItemRelPath(index);
  splitDialog.Path = path;
  if (splitDialog.Create(srcPanel.GetParent()) != IDOK)
    return;

  NFind::CFileInfo fileInfo;
  if (!fileInfo.Find(us2fs(srcPath + itemName)))
  {
    srcPanel.MessageBox_Error(L"Can not find file");
    return;
  }
  if (fileInfo.Size <= splitDialog.VolumeSizes.Front())
  {
    srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER);
    return;
  }
  const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
  if (numVolumes >= 100)
  {
    wchar_t s[32];
    ConvertUInt64ToString(numVolumes, s);
    if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, s),
        LangString(IDS_SPLIT_CONFIRM_TITLE),
        MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
      return;
  }

  path = splitDialog.Path;
  NName::NormalizeDirPathPrefix(path);
  if (!CreateComplexDir(us2fs(path)))
  {
    DWORD lastError = ::GetLastError();
    srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
    return;
  }

  {
  CThreadSplit spliter;
  spliter.NumVolumes = numVolumes;

  CProgressDialog &progressDialog = spliter;

  UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
  UString title = LangString(IDS_SPLITTING);

  progressDialog.ShowCompressionInfo = false;

  progressDialog.MainWindow = _window;
  progressDialog.MainTitle = progressWindowTitle;
  progressDialog.MainAddTitle = title;
  progressDialog.MainAddTitle.Add_Space();
  progressDialog.Sync.Set_TitleFileName(itemName);


  spliter.FilePath = us2fs(srcPath + itemName);
  spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index));
  spliter.VolumeSizes = splitDialog.VolumeSizes;
  
  // if (splitDialog.VolumeSizes.Size() == 0) return;

  // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
  // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);

  if (spliter.Create(title, _window) != 0)
    return;
  }
  RefreshTitleAlways();


  // disableNotify.Restore();
  // disableNotify.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
Exemplo n.º 16
0
HRESULT CContentsView::CalculateCrc2(const UString &methodName)
{
  CContentsView &srcPanel = *this;

  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedIndicesSmart(indices);
  if (indices.IsEmpty())
    return S_OK;

  if (!srcPanel.Is_IO_FS_Folder())
  {
    CCopyToOptions options;
    options.streamMode = true;
    options.showErrorMessages = true;
    options.hashMethods.Add(methodName);

    UStringVector messages;
    return srcPanel.CopyTo(options, indices, &messages);
  }

  #ifdef EXTERNAL_CODECS

  LoadGlobalCodecs();
    
  #endif

  {
    CThreadCrc t;
    {
      UStringVector methods;
      methods.Add(methodName);
      RINOK(t.Hash.SetMethods(EXTERNAL_CODECS_VARS_G methods));
    }
    FOR_VECTOR (i, indices)
      t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));

    UString basePrefix = srcPanel.GetFsPath();
    UString basePrefix2 = basePrefix;
    if (basePrefix2.Back() == ':')
    {
      int pos = basePrefix2.ReverseFind_PathSepar();
      if (pos >= 0)
        basePrefix2.DeleteFrom(pos + 1);
    }

    t.Enumerator.BasePrefix = us2fs(basePrefix);
    t.Enumerator.BasePrefix_for_Open = us2fs(basePrefix2);

    t.Enumerator.EnterToDirs = !GetFlatMode();
    
    t.ProgressDialog.ShowCompressionInfo = false;
    
    UString title = LangString(IDS_CHECKSUM_CALCULATING);
    
    t.ProgressDialog.MainWindow = *GetTopLevelParent();
    t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
    t.ProgressDialog.MainAddTitle = title;
    t.ProgressDialog.MainAddTitle.Add_Space();
    
    RINOK(t.Create(title, *GetTopLevelParent()));
  }
  RefreshTitle();
  return S_OK;
}
Exemplo n.º 17
0
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
    Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{
  COM_TRY_BEGIN
  bool allFilesMode = (numItems == (UInt32)-1);

  if (allFilesMode)
    numItems = m_Database.NewFormat ? 1:
      (m_Database.LowLevel ?
      m_Database.Items.Size():
      m_Database.Indices.Size());
  if (numItems == 0)
    return S_OK;
  bool testMode = (testModeSpec != 0);

  UInt64 currentTotalSize = 0;

  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
  UInt32 i;

  CLocalProgress *lps = new CLocalProgress;
  CMyComPtr<ICompressProgressInfo> progress = lps;
  lps->Init(extractCallback, false);

  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
  CMyComPtr<ISequentialInStream> inStream(streamSpec);
  streamSpec->SetStream(m_Stream);

  if (m_Database.LowLevel)
  {
    UInt64 currentItemSize = 0;
    UInt64 totalSize = 0;
    if (m_Database.NewFormat)
      totalSize = m_Database.NewFormatString.Length();
    else
      for (i = 0; i < numItems; i++)
        totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
    extractCallback->SetTotal(totalSize);
    
    for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
    {
      currentItemSize = 0;
      lps->InSize = currentTotalSize; // Change it
      lps->OutSize = currentTotalSize;

      RINOK(lps->SetCur());
      CMyComPtr<ISequentialOutStream> realOutStream;
      Int32 askMode= testMode ?
          NExtract::NAskMode::kTest :
          NExtract::NAskMode::kExtract;
      Int32 index = allFilesMode ? i : indices[i];
      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));

      if (m_Database.NewFormat)
      {
        if (index != 0)
          return E_FAIL;
        if (!testMode && !realOutStream)
          continue;
        if (!testMode)
        {
          UInt32 size = m_Database.NewFormatString.Length();
          RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size));
        }
        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
        continue;
      }
      const CItem &item = m_Database.Items[index];
      
      currentItemSize = item.Size;
      
      if (!testMode && !realOutStream)
        continue;
      RINOK(extractCallback->PrepareOperation(askMode));
      if (item.Section != 0)
      {
        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
        continue;
      }

      if (testMode)
      {
        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
        continue;
      }
      
      RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
      streamSpec->Init(item.Size);
      
      RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
      realOutStream.Release();
      RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
          NExtract::NOperationResult::kOK:
          NExtract::NOperationResult::kDataError));
    }
    return S_OK;
  }
  
  UInt64 lastFolderIndex = ((UInt64)0 - 1);
  for (i = 0; i < numItems; i++)
  {
    UInt32 index = allFilesMode ? i : indices[i];
    int entryIndex = m_Database.Indices[index];
    const CItem &item = m_Database.Items[entryIndex];
    UInt64 sectionIndex = item.Section;
    if (item.IsDir() || item.Size == 0)
      continue;
    if (sectionIndex == 0)
    {
      currentTotalSize += item.Size;
      continue;
    }
    const CSectionInfo &section = m_Database.Sections[(int)item.Section];
    if (section.IsLzx())
    {
      const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
      UInt64 folderIndex = m_Database.GetFolder(index);
      if (lastFolderIndex == folderIndex)
        folderIndex++;
      lastFolderIndex = m_Database.GetLastFolder(index);
      for (; folderIndex <= lastFolderIndex; folderIndex++)
        currentTotalSize += lzxInfo.GetFolderSize();
    }
  }

  RINOK(extractCallback->SetTotal(currentTotalSize));

  NCompress::NLzx::CDecoder *lzxDecoderSpec = 0;
  CMyComPtr<ICompressCoder> lzxDecoder;
  CChmFolderOutStream *chmFolderOutStream = 0;
  CMyComPtr<ISequentialOutStream> outStream;

  currentTotalSize = 0;

  CRecordVector<bool> extractStatuses;
  for (i = 0; i < numItems;)
  {
    RINOK(extractCallback->SetCompleted(&currentTotalSize));
    UInt32 index = allFilesMode ? i : indices[i];
    i++;
    int entryIndex = m_Database.Indices[index];
    const CItem &item = m_Database.Items[entryIndex];
    UInt64 sectionIndex = item.Section;
    Int32 askMode= testMode ?
        NExtract::NAskMode::kTest :
        NExtract::NAskMode::kExtract;
    if (item.IsDir())
    {
      CMyComPtr<ISequentialOutStream> realOutStream;
      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
      RINOK(extractCallback->PrepareOperation(askMode));
      realOutStream.Release();
      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
      continue;
    }

    lps->InSize = currentTotalSize; // Change it
    lps->OutSize = currentTotalSize;

    if (item.Size == 0 || sectionIndex == 0)
    {
      CMyComPtr<ISequentialOutStream> realOutStream;
      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
      if (!testMode && !realOutStream)
        continue;
      RINOK(extractCallback->PrepareOperation(askMode));
      Int32 opRes = NExtract::NOperationResult::kOK;
      if (!testMode && item.Size != 0)
      {
        RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
        streamSpec->Init(item.Size);
        RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
        if (copyCoderSpec->TotalSize != item.Size)
          opRes = NExtract::NOperationResult::kDataError;
      }
      realOutStream.Release();
      RINOK(extractCallback->SetOperationResult(opRes));
      currentTotalSize += item.Size;
      continue;
    }
  
    const CSectionInfo &section = m_Database.Sections[(int)sectionIndex];

    if (!section.IsLzx())
    {
      CMyComPtr<ISequentialOutStream> realOutStream;
      RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
      if (!testMode && !realOutStream)
        continue;
      RINOK(extractCallback->PrepareOperation(askMode));
      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
      continue;
    }

    const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;

    if (chmFolderOutStream == 0)
    {
      chmFolderOutStream = new CChmFolderOutStream;
      outStream = chmFolderOutStream;
    }

    chmFolderOutStream->Init(&m_Database, extractCallback, testMode);

    if (lzxDecoderSpec == NULL)
    {
      lzxDecoderSpec = new NCompress::NLzx::CDecoder;
      lzxDecoder = lzxDecoderSpec;
    }

    UInt64 folderIndex = m_Database.GetFolder(index);

    UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
    UInt32 numDictBits = lzxInfo.GetNumDictBits();
    RINOK(lzxDecoderSpec->SetParams(numDictBits));

    const CItem *lastItem = &item;
    extractStatuses.Clear();
    extractStatuses.Add(true);

    for (;; folderIndex++)
    {
      RINOK(extractCallback->SetCompleted(&currentTotalSize));

      UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
      UInt64 finishPos = lastItem->Offset + lastItem->Size;
      UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);

      lastFolderIndex = m_Database.GetLastFolder(index);
      UInt64 folderSize = lzxInfo.GetFolderSize();
      UInt64 unPackSize = folderSize;
      if (extractStatuses.IsEmpty())
        chmFolderOutStream->m_StartIndex = index + 1;
      else
        chmFolderOutStream->m_StartIndex = index;
      if (limitFolderIndex == folderIndex)
      {
        for (; i < numItems; i++)
        {
          UInt32 nextIndex = allFilesMode ? i : indices[i];
          int entryIndex = m_Database.Indices[nextIndex];
          const CItem &nextItem = m_Database.Items[entryIndex];
          if (nextItem.Section != sectionIndex)
            break;
          UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
          if (nextFolderIndex != folderIndex)
            break;
          for (index++; index < nextIndex; index++)
            extractStatuses.Add(false);
          extractStatuses.Add(true);
          index = nextIndex;
          lastItem = &nextItem;
          if (nextItem.Size != 0)
            finishPos = nextItem.Offset + nextItem.Size;
          lastFolderIndex = m_Database.GetLastFolder(index);
        }
      }
      unPackSize = MyMin(finishPos - startPos, unPackSize);

      chmFolderOutStream->m_FolderSize = folderSize;
      chmFolderOutStream->m_PosInFolder = 0;
      chmFolderOutStream->m_PosInSection = startPos;
      chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
      chmFolderOutStream->m_NumFiles = extractStatuses.Size();
      chmFolderOutStream->m_CurrentIndex = 0;
      try
      {
        UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
        const CResetTable &rt = lzxInfo.ResetTable;
        UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
        for (UInt32 b = 0; b < numBlocks; b++)
        {
          UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
          RINOK(extractCallback->SetCompleted(&completedSize));
          UInt64 bCur = startBlock + b;
          if (bCur >= rt.ResetOffsets.Size())
            return E_FAIL;
          UInt64 offset = rt.ResetOffsets[(int)bCur];
          UInt64 compressedSize;
          rt.GetCompressedSizeOfBlock(bCur, compressedSize);
          UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;
          if (rem > rt.BlockSize)
            rem = rt.BlockSize;
          RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));
          streamSpec->SetStream(m_Stream);
          streamSpec->Init(compressedSize);
          lzxDecoderSpec->SetKeepHistory(b > 0);
          HRESULT res = lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL);
          if (res != S_OK)
          {
            if (res != S_FALSE)
              return res;
            throw 1;
          }
        }
      }
      catch(...)
      {
        RINOK(chmFolderOutStream->FlushCorrupted(unPackSize));
      }
      currentTotalSize += folderSize;
      if (folderIndex == lastFolderIndex)
        break;
      extractStatuses.Clear();
    }
  }
  return S_OK;
  COM_TRY_END
}