xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/CompressCall.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // CompressCall.cpp
2 
3 #include "StdAfx.h"
4 
5 #include <wchar.h>
6 
7 #include "../../../Common/IntToString.h"
8 #include "../../../Common/MyCom.h"
9 #include "../../../Common/Random.h"
10 #include "../../../Common/StringConvert.h"
11 
12 #include "../../../Windows/DLL.h"
13 #include "../../../Windows/ErrorMsg.h"
14 #include "../../../Windows/FileDir.h"
15 #include "../../../Windows/FileMapping.h"
16 #include "../../../Windows/MemoryLock.h"
17 #include "../../../Windows/ProcessUtils.h"
18 #include "../../../Windows/Synchronization.h"
19 
20 #include "../FileManager/RegistryUtils.h"
21 
22 #include "CompressCall.h"
23 
24 using namespace NWindows;
25 
26 #define MY_TRY_BEGIN try {
27 
28 #define MY_TRY_FINISH } \
29   catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }
30 
31 #define MY_TRY_FINISH_VOID } \
32   catch(...) { ErrorMessageHRESULT(E_FAIL); }
33 
34 #define k7zGui  "7zG.exe"
35 
36 // 21.07 : we can disable wildcard
37 // #define ISWITCH_NO_WILDCARD_POSTFIX "w-"
38 #define ISWITCH_NO_WILDCARD_POSTFIX
39 
40 #define kShowDialogSwitch  " -ad"
41 #define kEmailSwitch  " -seml."
42 #define kArchiveTypeSwitch  " -t"
43 #define kIncludeSwitch  " -i" ISWITCH_NO_WILDCARD_POSTFIX
44 #define kArcIncludeSwitches  " -an -ai" ISWITCH_NO_WILDCARD_POSTFIX
45 #define kHashIncludeSwitches  kIncludeSwitch
46 #define kStopSwitchParsing  " --"
47 
48 extern HWND g_HWND;
49 
GetQuotedString(const UString & s)50 UString GetQuotedString(const UString &s)
51 {
52   UString s2 ('\"');
53   s2 += s;
54   s2.Add_Char('\"');
55   return s2;
56 }
57 
ErrorMessage(LPCWSTR message)58 static void ErrorMessage(LPCWSTR message)
59 {
60   MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK);
61 }
62 
ErrorMessageHRESULT(HRESULT res,LPCWSTR s=NULL)63 static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)
64 {
65   UString s2 = NError::MyFormatMessage(res);
66   if (s)
67   {
68     s2.Add_LF();
69     s2 += s;
70   }
71   ErrorMessage(s2);
72 }
73 
Call7zGui(const UString & params,bool waitFinish,NSynchronization::CBaseEvent * event)74 static HRESULT Call7zGui(const UString &params,
75     // LPCWSTR curDir,
76     bool waitFinish,
77     NSynchronization::CBaseEvent *event)
78 {
79   UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
80   imageName += k7zGui;
81 
82   CProcess process;
83   const WRes wres = process.Create(imageName, params, NULL); // curDir);
84   if (wres != 0)
85   {
86     const HRESULT hres = HRESULT_FROM_WIN32(wres);
87     ErrorMessageHRESULT(hres, imageName);
88     return hres;
89   }
90   if (waitFinish)
91     process.Wait();
92   else if (event != NULL)
93   {
94     HANDLE handles[] = { process, *event };
95     ::WaitForMultipleObjects(Z7_ARRAY_SIZE(handles), handles, FALSE, INFINITE);
96   }
97   return S_OK;
98 }
99 
AddLagePagesSwitch(UString & params)100 static void AddLagePagesSwitch(UString &params)
101 {
102   if (ReadLockMemoryEnable())
103   #ifndef UNDER_CE
104   if (NSecurity::Get_LargePages_RiskLevel() == 0)
105   #endif
106     params += " -slp";
107 }
108 
109 class CRandNameGenerator
110 {
111   CRandom _random;
112 public:
CRandNameGenerator()113   CRandNameGenerator() { _random.Init(); }
GenerateName(UString & s,const char * prefix)114   void GenerateName(UString &s, const char *prefix)
115   {
116     s += prefix;
117     s.Add_UInt32((UInt32)(unsigned)_random.Generate());
118   }
119 };
120 
CreateMap(const UStringVector & names,CFileMapping & fileMapping,NSynchronization::CManualResetEvent & event,UString & params)121 static HRESULT CreateMap(const UStringVector &names,
122     CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,
123     UString &params)
124 {
125   size_t totalSize = 1;
126   {
127     FOR_VECTOR (i, names)
128       totalSize += (names[i].Len() + 1);
129   }
130   totalSize *= sizeof(wchar_t);
131 
132   CRandNameGenerator random;
133 
134   UString mappingName;
135   for (;;)
136   {
137     random.GenerateName(mappingName, "7zMap");
138     const WRes wres = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));
139     if (fileMapping.IsCreated() && wres == 0)
140       break;
141     if (wres != ERROR_ALREADY_EXISTS)
142       return HRESULT_FROM_WIN32(wres);
143     fileMapping.Close();
144   }
145 
146   UString eventName;
147   for (;;)
148   {
149     random.GenerateName(eventName, "7zEvent");
150     const WRes wres = event.CreateWithName(false, GetSystemString(eventName));
151     if (event.IsCreated() && wres == 0)
152       break;
153     if (wres != ERROR_ALREADY_EXISTS)
154       return HRESULT_FROM_WIN32(wres);
155     event.Close();
156   }
157 
158   params.Add_Char('#');
159   params += mappingName;
160   params.Add_Colon();
161   char temp[32];
162   ConvertUInt64ToString(totalSize, temp);
163   params += temp;
164 
165   params.Add_Colon();
166   params += eventName;
167 
168   LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);
169   if (!data)
170     return E_FAIL;
171   CFileUnmapper unmapper(data);
172   {
173     wchar_t *cur = (wchar_t *)data;
174     *cur++ = 0; // it means wchar_t strings (UTF-16 in WIN32)
175     FOR_VECTOR (i, names)
176     {
177       const UString &s = names[i];
178       const unsigned len = s.Len() + 1;
179       wmemcpy(cur, (const wchar_t *)s, len);
180       cur += len;
181     }
182   }
183   return S_OK;
184 }
185 
CompressFiles(const UString & arcPathPrefix,const UString & arcName,const UString & arcType,bool addExtension,const UStringVector & names,bool email,bool showDialog,bool waitFinish)186 HRESULT CompressFiles(
187     const UString &arcPathPrefix,
188     const UString &arcName,
189     const UString &arcType,
190     bool addExtension,
191     const UStringVector &names,
192     bool email, bool showDialog, bool waitFinish)
193 {
194   MY_TRY_BEGIN
195   UString params ('a');
196 
197   CFileMapping fileMapping;
198   NSynchronization::CManualResetEvent event;
199   params += kIncludeSwitch;
200   RINOK(CreateMap(names, fileMapping, event, params))
201 
202   if (!arcType.IsEmpty())
203   {
204     params += kArchiveTypeSwitch;
205     params += arcType;
206   }
207 
208   if (email)
209     params += kEmailSwitch;
210 
211   if (showDialog)
212     params += kShowDialogSwitch;
213 
214   AddLagePagesSwitch(params);
215 
216   if (arcName.IsEmpty())
217     params += " -an";
218 
219   if (addExtension)
220     params += " -saa";
221   else
222     params += " -sae";
223 
224   params += kStopSwitchParsing;
225   params.Add_Space();
226 
227   if (!arcName.IsEmpty())
228   {
229     params += GetQuotedString(
230     // #ifdef UNDER_CE
231       arcPathPrefix +
232     // #endif
233     arcName);
234   }
235 
236   return Call7zGui(params,
237       // (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix),
238       waitFinish, &event);
239   MY_TRY_FINISH
240 }
241 
ExtractGroupCommand(const UStringVector & arcPaths,UString & params,bool isHash)242 static void ExtractGroupCommand(const UStringVector &arcPaths, UString &params, bool isHash)
243 {
244   AddLagePagesSwitch(params);
245   params += (isHash ? kHashIncludeSwitches : kArcIncludeSwitches);
246   CFileMapping fileMapping;
247   NSynchronization::CManualResetEvent event;
248   HRESULT result = CreateMap(arcPaths, fileMapping, event, params);
249   if (result == S_OK)
250     result = Call7zGui(params, false, &event);
251   if (result != S_OK)
252     ErrorMessageHRESULT(result);
253 }
254 
ExtractArchives(const UStringVector & arcPaths,const UString & outFolder,bool showDialog,bool elimDup,UInt32 writeZone)255 void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone)
256 {
257   MY_TRY_BEGIN
258   UString params ('x');
259   if (!outFolder.IsEmpty())
260   {
261     params += " -o";
262     params += GetQuotedString(outFolder);
263   }
264   if (elimDup)
265     params += " -spe";
266   if (writeZone != (UInt32)(Int32)-1)
267   {
268     params += " -snz";
269     params.Add_UInt32(writeZone);
270   }
271   if (showDialog)
272     params += kShowDialogSwitch;
273   ExtractGroupCommand(arcPaths, params, false);
274   MY_TRY_FINISH_VOID
275 }
276 
277 
TestArchives(const UStringVector & arcPaths,bool hashMode)278 void TestArchives(const UStringVector &arcPaths, bool hashMode)
279 {
280   MY_TRY_BEGIN
281   UString params ('t');
282   if (hashMode)
283   {
284     params += kArchiveTypeSwitch;
285     params += "hash";
286   }
287   ExtractGroupCommand(arcPaths, params, false);
288   MY_TRY_FINISH_VOID
289 }
290 
291 
CalcChecksum(const UStringVector & paths,const UString & methodName,const UString & arcPathPrefix,const UString & arcFileName)292 void CalcChecksum(const UStringVector &paths,
293     const UString &methodName,
294     const UString &arcPathPrefix,
295     const UString &arcFileName)
296 {
297   MY_TRY_BEGIN
298 
299   if (!arcFileName.IsEmpty())
300   {
301     CompressFiles(
302       arcPathPrefix,
303       arcFileName,
304       UString("hash"),
305       false, // addExtension,
306       paths,
307       false, // email,
308       false, // showDialog,
309       false  // waitFinish
310       );
311     return;
312   }
313 
314   UString params ('h');
315   if (!methodName.IsEmpty())
316   {
317     params += " -scrc";
318     params += methodName;
319     /*
320     if (!arcFileName.IsEmpty())
321     {
322       // not used alternate method of generating file
323       params += " -scrf=";
324       params += GetQuotedString(arcPathPrefix + arcFileName);
325     }
326     */
327   }
328   ExtractGroupCommand(paths, params, true);
329   MY_TRY_FINISH_VOID
330 }
331 
Benchmark(bool totalMode)332 void Benchmark(bool totalMode)
333 {
334   MY_TRY_BEGIN
335   UString params ('b');
336   if (totalMode)
337     params += " -mm=*";
338   AddLagePagesSwitch(params);
339   const HRESULT result = Call7zGui(params, false, NULL);
340   if (result != S_OK)
341     ErrorMessageHRESULT(result);
342   MY_TRY_FINISH_VOID
343 }
344