Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / Common / CompressCall.cpp
1 // CompressCall.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "Common/IntToString.h"\r
6 #include "Common/MyCom.h"\r
7 #include "Common/Random.h"\r
8 #include "Common/StringConvert.h"\r
9 \r
10 #include "Windows/FileDir.h"\r
11 #include "Windows/FileMapping.h"\r
12 #include "Windows/Process.h"\r
13 #include "Windows/Synchronization.h"\r
14 \r
15 #include "../FileManager/ProgramLocation.h"\r
16 #include "../FileManager/RegistryUtils.h"\r
17 \r
18 #include "CompressCall.h"\r
19 \r
20 using namespace NWindows;\r
21 \r
22 #define MY_TRY_BEGIN try {\r
23 #define MY_TRY_FINISH } \\r
24   catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }\r
25 \r
26 static LPCWSTR kShowDialogSwitch = L" -ad";\r
27 static LPCWSTR kEmailSwitch = L" -seml.";\r
28 static LPCWSTR kIncludeSwitch = L" -i";\r
29 static LPCWSTR kArchiveTypeSwitch = L" -t";\r
30 static LPCWSTR kArcIncludeSwitches = L" -an -ai";\r
31 static LPCWSTR kStopSwitchParsing = L" --";\r
32 static LPCWSTR kLargePagesDisable = L" -slp-";\r
33 \r
34 UString GetQuotedString(const UString &s)\r
35 {\r
36   return UString(L'\"') + s + UString(L'\"');\r
37 }\r
38 static void ErrorMessage(LPCWSTR message)\r
39 {\r
40   MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK);\r
41 }\r
42 \r
43 static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)\r
44 {\r
45   UString s2 = HResultToMessage(res);\r
46   if (s)\r
47   {\r
48     s2 += L'\n';\r
49     s2 += s;\r
50   }\r
51   ErrorMessage(s2);\r
52 }\r
53 \r
54 static HRESULT MyCreateProcess(LPCWSTR imageName, const UString &params,\r
55     LPCWSTR curDir, bool waitFinish,\r
56     NSynchronization::CBaseEvent *event)\r
57 {\r
58   CProcess process;\r
59   WRes res = process.Create(imageName, params, curDir);\r
60   if (res != 0)\r
61   {\r
62     ErrorMessageHRESULT(res, imageName);\r
63     return res;\r
64   }\r
65   if (waitFinish)\r
66     process.Wait();\r
67   else if (event != NULL)\r
68   {\r
69     HANDLE handles[] = { process, *event };\r
70     ::WaitForMultipleObjects(sizeof(handles) / sizeof(handles[0]), handles, FALSE, INFINITE);\r
71   }\r
72   return S_OK;\r
73 }\r
74 \r
75 static void AddLagePagesSwitch(UString &params)\r
76 {\r
77   if (!ReadLockMemoryEnable())\r
78     params += kLargePagesDisable;\r
79 }\r
80 \r
81 static UString Get7zGuiPath()\r
82 {\r
83   UString path;\r
84   GetProgramFolderPath(path);\r
85   return path + L"7zG.exe";\r
86 }\r
87 \r
88 class CRandNameGenerator\r
89 {\r
90   CRandom _random;\r
91 public:\r
92   CRandNameGenerator() { _random.Init(); }\r
93   UString GenerateName()\r
94   {\r
95     wchar_t temp[16];\r
96     ConvertUInt32ToString((UInt32)_random.Generate(), temp);\r
97     return temp;\r
98   }\r
99 };\r
100 \r
101 static HRESULT CreateMap(const UStringVector &names,\r
102     CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,\r
103     UString &params)\r
104 {\r
105   UInt32 totalSize = 1;\r
106   for (int i = 0; i < names.Size(); i++)\r
107     totalSize += (names[i].Length() + 1);\r
108   totalSize *= sizeof(wchar_t);\r
109   \r
110   CRandNameGenerator random;\r
111 \r
112   UString mappingName;\r
113   for (;;)\r
114   {\r
115     mappingName = L"7zMap" + random.GenerateName();\r
116 \r
117     WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));\r
118     if (fileMapping.IsCreated() && res == 0)\r
119       break;\r
120     if (res != ERROR_ALREADY_EXISTS)\r
121       return res;\r
122     fileMapping.Close();\r
123   }\r
124   \r
125   UString eventName;\r
126   for (;;)\r
127   {\r
128     eventName = L"7zEvent" + random.GenerateName();\r
129     WRes res = event.CreateWithName(false, GetSystemString(eventName));\r
130     if (event.IsCreated() && res == 0)\r
131       break;\r
132     if (res != ERROR_ALREADY_EXISTS)\r
133       return res;\r
134     event.Close();\r
135   }\r
136 \r
137   params += L'#';\r
138   params += mappingName;\r
139   params += L':';\r
140   wchar_t temp[16];\r
141   ConvertUInt32ToString(totalSize, temp);\r
142   params += temp;\r
143   \r
144   params += L':';\r
145   params += eventName;\r
146 \r
147   LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);\r
148   if (data == NULL)\r
149     return E_FAIL;\r
150   CFileUnmapper unmapper(data);\r
151   {\r
152     wchar_t *cur = (wchar_t *)data;\r
153     *cur++ = 0;\r
154     for (int i = 0; i < names.Size(); i++)\r
155     {\r
156       const UString &s = names[i];\r
157       int len = s.Length() + 1;\r
158       memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t));\r
159       cur += len;\r
160     }\r
161   }\r
162   return S_OK;\r
163 }\r
164 \r
165 HRESULT CompressFiles(\r
166     const UString &arcPathPrefix,\r
167     const UString &arcName,\r
168     const UString &arcType,\r
169     const UStringVector &names,\r
170     bool email, bool showDialog, bool waitFinish)\r
171 {\r
172   MY_TRY_BEGIN\r
173   UString params = L'a';\r
174   \r
175   CFileMapping fileMapping;\r
176   NSynchronization::CManualResetEvent event;\r
177   params += kIncludeSwitch;\r
178   RINOK(CreateMap(names, fileMapping, event, params));\r
179 \r
180   if (!arcType.IsEmpty())\r
181   {\r
182     params += kArchiveTypeSwitch;\r
183     params += arcType;\r
184   }\r
185 \r
186   if (email)\r
187     params += kEmailSwitch;\r
188 \r
189   if (showDialog)\r
190     params += kShowDialogSwitch;\r
191 \r
192   AddLagePagesSwitch(params);\r
193 \r
194   params += kStopSwitchParsing;\r
195   params += L' ';\r
196   \r
197   params += GetQuotedString(\r
198     #ifdef UNDER_CE\r
199     arcPathPrefix +\r
200     #endif\r
201     arcName);\r
202   \r
203   return MyCreateProcess(Get7zGuiPath(), params,\r
204       (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix), waitFinish, &event);\r
205   MY_TRY_FINISH\r
206 }\r
207 \r
208 static HRESULT ExtractGroupCommand(const UStringVector &arcPaths, UString &params)\r
209 {\r
210   AddLagePagesSwitch(params);\r
211   params += kArcIncludeSwitches;\r
212   CFileMapping fileMapping;\r
213   NSynchronization::CManualResetEvent event;\r
214   RINOK(CreateMap(arcPaths, fileMapping, event, params));\r
215   return MyCreateProcess(Get7zGuiPath(), params, 0, false, &event);\r
216 }\r
217 \r
218 HRESULT ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog)\r
219 {\r
220   MY_TRY_BEGIN\r
221   UString params = L'x';\r
222   if (!outFolder.IsEmpty())\r
223   {\r
224     params += L" -o";\r
225     params += GetQuotedString(outFolder);\r
226   }\r
227   if (showDialog)\r
228     params += kShowDialogSwitch;\r
229   return ExtractGroupCommand(arcPaths, params);\r
230   MY_TRY_FINISH\r
231 }\r
232 \r
233 HRESULT TestArchives(const UStringVector &arcPaths)\r
234 {\r
235   MY_TRY_BEGIN\r
236   UString params = L't';\r
237   return ExtractGroupCommand(arcPaths, params);\r
238   MY_TRY_FINISH\r
239 }\r
240 \r
241 HRESULT Benchmark()\r
242 {\r
243   MY_TRY_BEGIN\r
244   return MyCreateProcess(Get7zGuiPath(), L'b', 0, false, NULL);\r
245   MY_TRY_FINISH\r
246 }\r