// CompressCall.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Common/Random.h" #include "Common/StringConvert.h" #include "Windows/FileDir.h" #include "Windows/FileMapping.h" #include "Windows/Process.h" #include "Windows/Synchronization.h" #include "../FileManager/ProgramLocation.h" #include "../FileManager/RegistryUtils.h" #include "CompressCall.h" using namespace NWindows; #define MY_TRY_BEGIN try { #define MY_TRY_FINISH } \ catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; } static LPCWSTR kShowDialogSwitch = L" -ad"; static LPCWSTR kEmailSwitch = L" -seml."; static LPCWSTR kIncludeSwitch = L" -i"; static LPCWSTR kArchiveTypeSwitch = L" -t"; static LPCWSTR kArcIncludeSwitches = L" -an -ai"; static LPCWSTR kStopSwitchParsing = L" --"; static LPCWSTR kLargePagesDisable = L" -slp-"; UString GetQuotedString(const UString &s) { return UString(L'\"') + s + UString(L'\"'); } static void ErrorMessage(LPCWSTR message) { MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK); } static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL) { UString s2 = HResultToMessage(res); if (s) { s2 += L'\n'; s2 += s; } ErrorMessage(s2); } static HRESULT MyCreateProcess(LPCWSTR imageName, const UString ¶ms, LPCWSTR curDir, bool waitFinish, NSynchronization::CBaseEvent *event) { CProcess process; WRes res = process.Create(imageName, params, curDir); if (res != 0) { ErrorMessageHRESULT(res, imageName); return res; } if (waitFinish) process.Wait(); else if (event != NULL) { HANDLE handles[] = { process, *event }; ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]), handles, FALSE, INFINITE); } return S_OK; } static void AddLagePagesSwitch(UString ¶ms) { if (!ReadLockMemoryEnable()) params += kLargePagesDisable; } static UString Get7zGuiPath() { UString path; GetProgramFolderPath(path); return path + L"7zG.exe"; } class CRandNameGenerator { CRandom _random; public: CRandNameGenerator() { _random.Init(); } UString GenerateName() { wchar_t temp[16]; ConvertUInt32ToString((UInt32)_random.Generate(), temp); return temp; } }; static HRESULT CreateMap(const UStringVector &names, CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event, UString ¶ms) { UInt32 totalSize = 1; for (int i = 0; i < names.Size(); i++) totalSize += (names[i].Length() + 1); totalSize *= sizeof(wchar_t); CRandNameGenerator random; UString mappingName; for (;;) { mappingName = L"7zMap" + random.GenerateName(); WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName)); if (fileMapping.IsCreated() && res == 0) break; if (res != ERROR_ALREADY_EXISTS) return res; fileMapping.Close(); } UString eventName; for (;;) { eventName = L"7zEvent" + random.GenerateName(); WRes res = event.CreateWithName(false, GetSystemString(eventName)); if (event.IsCreated() && res == 0) break; if (res != ERROR_ALREADY_EXISTS) return res; event.Close(); } params += L'#'; params += mappingName; params += L':'; wchar_t temp[16]; ConvertUInt32ToString(totalSize, temp); params += temp; params += L':'; params += eventName; LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize); if (data == NULL) return E_FAIL; CFileUnmapper unmapper(data); { wchar_t *cur = (wchar_t *)data; *cur++ = 0; for (int i = 0; i < names.Size(); i++) { const UString &s = names[i]; int len = s.Length() + 1; memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t)); cur += len; } } return S_OK; } HRESULT CompressFiles( const UString &arcPathPrefix, const UString &arcName, const UString &arcType, const UStringVector &names, bool email, bool showDialog, bool waitFinish) { MY_TRY_BEGIN UString params = L'a'; CFileMapping fileMapping; NSynchronization::CManualResetEvent event; params += kIncludeSwitch; RINOK(CreateMap(names, fileMapping, event, params)); if (!arcType.IsEmpty()) { params += kArchiveTypeSwitch; params += arcType; } if (email) params += kEmailSwitch; if (showDialog) params += kShowDialogSwitch; AddLagePagesSwitch(params); params += kStopSwitchParsing; params += L' '; params += GetQuotedString( #ifdef UNDER_CE arcPathPrefix + #endif arcName); return MyCreateProcess(Get7zGuiPath(), params, (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event); MY_TRY_FINISH } static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms) { AddLagePagesSwitch(params); params += kArcIncludeSwitches; CFileMapping fileMapping; NSynchronization::CManualResetEvent event; RINOK(CreateMap(arcPaths, fileMapping, event, params)); return MyCreateProcess(Get7zGuiPath(), params, 0, false, &event); } HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog) { MY_TRY_BEGIN UString params = L'x'; if (!outFolder.IsEmpty()) { params += L" -o"; params += GetQuotedString(outFolder); } if (showDialog) params += kShowDialogSwitch; return ExtractGroupCommand(arcPaths, params); MY_TRY_FINISH } HRESULT TestArchives(const UStringVector &arcPaths) { MY_TRY_BEGIN UString params = L't'; return ExtractGroupCommand(arcPaths, params); MY_TRY_FINISH } HRESULT Benchmark() { MY_TRY_BEGIN return MyCreateProcess(Get7zGuiPath(), L'b', 0, false, NULL); MY_TRY_FINISH }