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 ¶ms,
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 ¶ms)
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 ¶ms)
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 ¶ms, 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