📄 compress.cpp
字号:
// 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 + -