⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compress.cpp

📁 7-Zip 3.11的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Compress.cpp

#include "StdAfx.h"

#include <mapi.h>

#include "Compress.h"
#include "CompressDialog.h"
#include "resource.h"

#include "Common/StringConvert.h"
#include "Common/IntToString.h"

#include "Windows/FileName.h"
#include "Windows/FileFind.h"
#include "Windows/FileDir.h"
#include "Windows/Thread.h"
#include "Windows/COM.h"
#include "Windows/PropVariant.h"

#include "../../FileManager/ProgramLocation.h"
#include "../../FileManager/FormatUtils.h"
#include "../../FileManager/UpdateCallback100.h"

#include "../Agent/Agent.h"
#include "../Common/UpdateAction.h"
#include "../Common/WorkDir.h"
#include "../Common/ZipRegistry.h"
#include "../Common/OpenArchive.h"
#include "../Resource/Extract/resource.h"
#include "../Explorer/MyMessages.h"

using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
using namespace NName;

static LPCWSTR kTempArchivePrefix = L"7zA";
static LPCWSTR kTempFolderPrefix = L"7zE";
static LPCWSTR kDefaultSfxModule = L"7zC.sfx";

static void SplitString(const UString &srcString, UStringVector &destStrings)
{
  destStrings.Clear();
  for (int pos = 0; pos < srcString.Length();)
  {
    int spacePos = srcString.Find(L' ', pos);
    if (spacePos < 0)
    {
      destStrings.Add(srcString.Mid(pos));
      return;
    }
    if (spacePos != pos)
      destStrings.Add(srcString.Mid(pos, spacePos - pos));
    pos = spacePos + 1;
  }
}

static bool ParseNumberString(const UString &string, UINT32 &number)
{
  wchar_t *endPtr;
  number = wcstoul(string, &endPtr, 10);
  return (endPtr - string == string.Length());
}

static void SetOptions(const UString &options,
    CObjectVector<CMyComBSTR> &realNames,
    std::vector<NCOM::CPropVariant> &values)
{
  UStringVector strings;
  SplitString(options, strings);
  for(int i = 0; i < strings.Size(); i++)
  {
    const UString &s = strings[i];
    int index = s.Find(L'=');
    CMyComBSTR name;
    NCOM::CPropVariant propVariant;
    if (index < 0)
      name = s;
    else
    {
      name = s.Left(index);
      UString value = s.Mid(index + 1);
      if (!value.IsEmpty())
      {
        UINT32 number;
        if (ParseNumberString(value, number))
          propVariant = number;
        else
          propVariant = value;
      }
    }
    realNames.Add(name);
    values.push_back(propVariant);
  }
}

static HRESULT SetOutProperties(IOutFolderArchive * outArchive, 
    bool is7z,
    UINT32 level, 
    const UString &method,
    UINT32 dictionary,
    bool orderMode,
    UINT32 order,
    bool solidModeIsAllowed, bool solidMode, 
    bool multiThreadIsAllowed, bool multiThread, 
    bool encryptHeadersIsAllowed, bool encryptHeaders,
    bool sfxMode,
    const UString &options)
{
  CMyComPtr<ISetProperties> setProperties;
  if (outArchive->QueryInterface(&setProperties) == S_OK)
  {
    CObjectVector<CMyComBSTR> realNames;
    std::vector<NCOM::CPropVariant> values;
    if (level != (UINT32)(INT32)-1)
    {
      CMyComBSTR comBSTR = L"x";
      realNames.Add(comBSTR);
      values.push_back(NCOM::CPropVariant((UINT32)level));
    }
    if (!method.IsEmpty())
    {
      CMyComBSTR comBSTR;
      if (is7z)
        comBSTR = L"0";
      else
        comBSTR = L"m";
      realNames.Add(comBSTR);
      values.push_back(NCOM::CPropVariant(method));
    }
    if (dictionary != (UINT32)(INT32)-1)
    {
      CMyComBSTR comBSTR;
      if (is7z)
        if (orderMode)
          comBSTR = L"0mem";
        else
          comBSTR = L"0d";
      else
        if (orderMode)
          comBSTR = L"mem";
        else
          comBSTR = L"d";
      realNames.Add(comBSTR);
      wchar_t s[32];
      ConvertUINT64ToString(dictionary, s);
      wcscat(s, L"B");
      values.push_back(NCOM::CPropVariant(s));
    }
    if (order != (UINT32)(INT32)-1)
    {
      CMyComBSTR comBSTR;
      if (is7z)
        if (orderMode)
          comBSTR = L"0o";
        else
          comBSTR = L"0fb";
      else
        if (orderMode)
          comBSTR = L"o";
        else
          comBSTR = L"fb";
      realNames.Add(comBSTR);
      values.push_back(NCOM::CPropVariant((UINT32)order));
    }

    if (sfxMode)
    {
      realNames.Add(L"rsfx");
      values.push_back(NCOM::CPropVariant(L"on"));
    }

    if (encryptHeadersIsAllowed)
    {
      if (encryptHeaders)
      {
        realNames.Add(L"he");
        values.push_back(NCOM::CPropVariant(L"on"));
      }
    }
   
    // Solid
    if (solidModeIsAllowed)
    {
      realNames.Add(L"s");
      values.push_back(NCOM::CPropVariant(solidMode ? L"on": L"off"));
    }
    if (multiThreadIsAllowed)
    {
      realNames.Add(L"mt");
      values.push_back(NCOM::CPropVariant(multiThread ? L"on": L"off"));
    }

    // Options 
    SetOptions(options, realNames, values);
    
    std::vector<BSTR> names;
    for(int i = 0; i < realNames.Size(); i++)
      names.push_back(realNames[i]);
    RINOK(setProperties->SetProperties(&names.front(), 
      &values.front(), names.size()));
  }
  return S_OK;
}

struct CThreadUpdateCompress
{
  CMyComPtr<IOutFolderArchive> OutArchive;
  UString LibPath;
  CLSID ClassID;
  UString OutArchivePath;
  BYTE ActionSetByte[NUpdateArchive::NPairState::kNumValues];
  bool SfxMode;
  UString SfxModule;
  

  UStringVector FileNames;
  CRecordVector<const wchar_t *> FileNamePointers;
  CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;
  CUpdateCallback100Imp *UpdateCallbackSpec;
  HRESULT Result;
  
  DWORD Process()
  {
    NCOM::CComInitializer comInitializer;
    UpdateCallbackSpec->ProgressDialog.WaitCreating();
    try
    {
      Result = OutArchive->DoOperation(
        LibPath, &ClassID,
        OutArchivePath, ActionSetByte, 
        (SfxMode ? (const wchar_t *)SfxModule: NULL),
        UpdateCallback);
    }
    catch(const UString &s)
    {
      MyMessageBox(s);
      Result = E_FAIL;
    }
    catch(...)
    {
      Result = E_FAIL;
    }
    UpdateCallbackSpec->ProgressDialog.MyClose();
    return 0;
  }

  static DWORD WINAPI MyThreadFunction(void *param)
  {
    return ((CThreadUpdateCompress *)param)->Process();
  }
};

static UString MakeFullArchiveName(const UString &name, 
    const UString &extension, bool sfx)
{
  if (sfx)
  {
    UString sfxExt = L".exe";
    if (sfxExt.CollateNoCase(name.Right(sfxExt.Length())) == 0)
      return name;
    return name + sfxExt;
  }

  if (extension.IsEmpty())
    return name;
  if (name.IsEmpty())
    return name;
  if (name[name.Length() - 1] == '.')
    return name.Left(name.Length() - 1);
  int slash1Pos = name.ReverseFind(L'\\');
  int slash2Pos = name.ReverseFind(L'/');
  int slashPos = MyMax(slash1Pos, slash2Pos);
  int dotPos = name.ReverseFind(L'.');
  if (dotPos >= 0 && (dotPos > slashPos || slashPos < 0))
    return name;
  return name + UString(L'.') + extension;
}

HRESULT CompressArchive(
    const UString &archivePath, 
    const UStringVector &fileNames, 
    const UString &archiveType, 
    bool email,
    bool showDialog)
{
  if (fileNames.Size() == 0)
    return S_OK;

  CObjectVector<CArchiverInfo> archivers;
  ReadArchiverInfoList(archivers);

  CArchiverInfo archiverInfo;
  UString password;
  bool encryptHeadersIsAllowed = false;
  bool encryptHeaders = false;
  const NUpdateArchive::CActionSet *actionSet;
  NCompressDialog::CInfo compressInfo;

  UString tempDirPath;
  UString currentDirPrefix;
  bool needTempFile = true;
  NDirectory::CTempDirectoryW tempDirectory;
  UString archiveName;
  int pos = archivePath.ReverseFind(L'\\');
  if (pos < 0)
  {
    archiveName = archivePath;
    MyGetCurrentDirectory(currentDirPrefix);
  }
  else
  {
    currentDirPrefix = archivePath.Left(pos + 1);
    archiveName = archivePath.Mid(pos + 1);
  }
  
  if (email)
  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -