1 // GUI.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifdef _WIN32
6 #include "../../../../C/DllSecur.h"
7 #endif
8 
9 #include "../../../Common/MyWindows.h"
10 
11 #include <Shlwapi.h>
12 
13 #include "../../../Common/MyInitGuid.h"
14 
15 #include "../../../Common/CommandLineParser.h"
16 #include "../../../Common/MyException.h"
17 #include "../../../Common/StringConvert.h"
18 
19 #include "../../../Windows/FileDir.h"
20 #include "../../../Windows/NtCheck.h"
21 
22 #include "../Common/ArchiveCommandLine.h"
23 #include "../Common/ExitCode.h"
24 
25 #include "../FileManager/StringUtils.h"
26 #include "../FileManager/MyWindowsNew.h"
27 
28 #include "BenchmarkDialog.h"
29 #include "ExtractGUI.h"
30 #include "HashGUI.h"
31 #include "UpdateGUI.h"
32 
33 #include "ExtractRes.h"
34 
35 using namespace NWindows;
36 
37 #ifdef EXTERNAL_CODECS
38 const CExternalCodecs *g_ExternalCodecs_Ptr;
39 #endif
40 
41 extern
42 HINSTANCE g_hInstance;
43 HINSTANCE g_hInstance;
44 
45 #ifndef UNDER_CE
46 
47 extern
48 DWORD g_ComCtl32Version;
49 DWORD g_ComCtl32Version;
50 
GetDllVersion(LPCTSTR dllName)51 static DWORD GetDllVersion(LPCTSTR dllName)
52 {
53   DWORD dwVersion = 0;
54   HINSTANCE hinstDll = LoadLibrary(dllName);
55   if (hinstDll)
56   {
57     DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)(void *)GetProcAddress(hinstDll, "DllGetVersion");
58     if (pDllGetVersion)
59     {
60       DLLVERSIONINFO dvi;
61       ZeroMemory(&dvi, sizeof(dvi));
62       dvi.cbSize = sizeof(dvi);
63       HRESULT hr = (*pDllGetVersion)(&dvi);
64       if (SUCCEEDED(hr))
65         dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
66     }
67     FreeLibrary(hinstDll);
68   }
69   return dwVersion;
70 }
71 
72 #endif
73 
74 extern
75 bool g_LVN_ITEMACTIVATE_Support;
76 bool g_LVN_ITEMACTIVATE_Support = true;
77 
ErrorMessage(LPCWSTR message)78 static void ErrorMessage(LPCWSTR message)
79 {
80   MessageBoxW(NULL, message, L"7-Zip", MB_ICONERROR | MB_OK);
81 }
82 
ErrorMessage(const char * s)83 static void ErrorMessage(const char *s)
84 {
85   ErrorMessage(GetUnicodeString(s));
86 }
87 
ErrorLangMessage(UINT resourceID)88 static void ErrorLangMessage(UINT resourceID)
89 {
90   ErrorMessage(LangString(resourceID));
91 }
92 
93 static const char * const kNoFormats = "7-Zip cannot find the code that works with archives.";
94 
ShowMemErrorMessage()95 static int ShowMemErrorMessage()
96 {
97   ErrorLangMessage(IDS_MEM_ERROR);
98   return NExitCode::kMemoryError;
99 }
100 
ShowSysErrorMessage(DWORD errorCode)101 static int ShowSysErrorMessage(DWORD errorCode)
102 {
103   if ((HRESULT)errorCode == E_OUTOFMEMORY)
104     return ShowMemErrorMessage();
105   ErrorMessage(HResultToMessage(errorCode));
106   return NExitCode::kFatalError;
107 }
108 
ThrowException_if_Error(HRESULT res)109 static void ThrowException_if_Error(HRESULT res)
110 {
111   if (res != S_OK)
112     throw CSystemException(res);
113 }
114 
Main2()115 static int Main2()
116 {
117   UStringVector commandStrings;
118   NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
119 
120   #ifndef UNDER_CE
121   if (commandStrings.Size() > 0)
122     commandStrings.Delete(0);
123   #endif
124   if (commandStrings.Size() == 0)
125   {
126     MessageBoxW(0, L"Specify command", L"7-Zip", 0);
127     return 0;
128   }
129 
130   CArcCmdLineOptions options;
131   CArcCmdLineParser parser;
132 
133   parser.Parse1(commandStrings, options);
134   parser.Parse2(options);
135 
136   CREATE_CODECS_OBJECT
137 
138   codecs->CaseSensitiveChange = options.CaseSensitiveChange;
139   codecs->CaseSensitive = options.CaseSensitive;
140   ThrowException_if_Error(codecs->Load());
141   Codecs_AddHashArcHandler(codecs);
142 
143   #ifdef EXTERNAL_CODECS
144   {
145     g_ExternalCodecs_Ptr = &__externalCodecs;
146     UString s;
147     codecs->GetCodecsErrorMessage(s);
148     if (!s.IsEmpty())
149     {
150       MessageBoxW(0, s, L"7-Zip", MB_ICONERROR);
151     }
152 
153   }
154   #endif
155 
156   const bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
157 
158   if (codecs->Formats.Size() == 0 &&
159         (isExtractGroupCommand
160 
161         || options.Command.IsFromUpdateGroup()))
162   {
163     #ifdef EXTERNAL_CODECS
164     if (!codecs->MainDll_ErrorPath.IsEmpty())
165     {
166       UString s ("7-Zip cannot load module: ");
167       s += fs2us(codecs->MainDll_ErrorPath);
168       throw s;
169     }
170     #endif
171     throw kNoFormats;
172   }
173 
174   CObjectVector<COpenType> formatIndices;
175   if (!ParseOpenTypes(*codecs, options.ArcType, formatIndices))
176   {
177     ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
178     return NExitCode::kFatalError;
179   }
180 
181   CIntVector excludedFormats;
182   FOR_VECTOR (k, options.ExcludedArcTypes)
183   {
184     CIntVector tempIndices;
185     if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
186         || tempIndices.Size() != 1)
187     {
188       ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
189       return NExitCode::kFatalError;
190     }
191     excludedFormats.AddToUniqueSorted(tempIndices[0]);
192     // excludedFormats.Sort();
193   }
194 
195   #ifdef EXTERNAL_CODECS
196   if (isExtractGroupCommand
197       || options.Command.IsFromUpdateGroup()
198       || options.Command.CommandType == NCommandType::kHash
199       || options.Command.CommandType == NCommandType::kBenchmark)
200     ThrowException_if_Error(__externalCodecs.Load());
201   #endif
202 
203   if (options.Command.CommandType == NCommandType::kBenchmark)
204   {
205     HRESULT res = Benchmark(
206         EXTERNAL_CODECS_VARS_L
207         options.Properties,
208         options.NumIterations_Defined ?
209           options.NumIterations :
210           k_NumBenchIterations_Default);
211     /*
212     if (res == S_FALSE)
213     {
214       stdStream << "\nDecoding Error\n";
215       return NExitCode::kFatalError;
216     }
217     */
218     ThrowException_if_Error(res);
219   }
220   else if (isExtractGroupCommand)
221   {
222     UStringVector ArchivePathsSorted;
223     UStringVector ArchivePathsFullSorted;
224 
225     CExtractCallbackImp *ecs = new CExtractCallbackImp;
226     CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
227 
228     #ifndef _NO_CRYPTO
229     ecs->PasswordIsDefined = options.PasswordEnabled;
230     ecs->Password = options.Password;
231     #endif
232 
233     ecs->Init();
234 
235     CExtractOptions eo;
236     (CExtractOptionsBase &)eo = options.ExtractOptions;
237     eo.StdInMode = options.StdInMode;
238     eo.StdOutMode = options.StdOutMode;
239     eo.YesToAll = options.YesToAll;
240     eo.TestMode = options.Command.IsTestCommand();
241 
242     #ifndef _SFX
243     eo.Properties = options.Properties;
244     #endif
245 
246     bool messageWasDisplayed = false;
247 
248     #ifndef _SFX
249     CHashBundle hb;
250     CHashBundle *hb_ptr = NULL;
251 
252     if (!options.HashMethods.IsEmpty())
253     {
254       hb_ptr = &hb;
255       ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
256     }
257     #endif
258 
259     {
260       CDirItemsStat st;
261       HRESULT hresultMain = EnumerateDirItemsAndSort(
262           options.arcCensor,
263           NWildcard::k_RelatPath,
264           UString(), // addPathPrefix
265           ArchivePathsSorted,
266           ArchivePathsFullSorted,
267           st,
268           NULL // &scan: change it!!!!
269           );
270       if (hresultMain != S_OK)
271       {
272         /*
273         if (hresultMain != E_ABORT && messageWasDisplayed)
274           return NExitCode::kFatalError;
275         */
276         throw CSystemException(hresultMain);
277       }
278     }
279 
280     ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
281 
282     HRESULT result = ExtractGUI(
283           // EXTERNAL_CODECS_VARS_L
284           codecs,
285           formatIndices, excludedFormats,
286           ArchivePathsSorted,
287           ArchivePathsFullSorted,
288           options.Censor.Pairs.Front().Head,
289           eo,
290           #ifndef _SFX
291           hb_ptr,
292           #endif
293           options.ShowDialog, messageWasDisplayed, ecs);
294     if (result != S_OK)
295     {
296       if (result != E_ABORT && messageWasDisplayed)
297         return NExitCode::kFatalError;
298       throw CSystemException(result);
299     }
300     if (!ecs->IsOK())
301       return NExitCode::kFatalError;
302   }
303   else if (options.Command.IsFromUpdateGroup())
304   {
305     #ifndef _NO_CRYPTO
306     bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty();
307     #endif
308 
309     CUpdateCallbackGUI callback;
310     // callback.EnablePercents = options.EnablePercents;
311 
312     #ifndef _NO_CRYPTO
313     callback.PasswordIsDefined = passwordIsDefined;
314     callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
315     callback.Password = options.Password;
316     #endif
317 
318     // callback.StdOutMode = options.UpdateOptions.StdOutMode;
319     callback.Init();
320 
321     if (!options.UpdateOptions.InitFormatIndex(codecs, formatIndices, options.ArchiveName) ||
322         !options.UpdateOptions.SetArcPath(codecs, options.ArchiveName))
323     {
324       ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED);
325       return NExitCode::kFatalError;
326     }
327     bool messageWasDisplayed = false;
328     HRESULT result = UpdateGUI(
329         codecs, formatIndices,
330         options.ArchiveName,
331         options.Censor,
332         options.UpdateOptions,
333         options.ShowDialog,
334         messageWasDisplayed,
335         &callback);
336 
337     if (result != S_OK)
338     {
339       if (result != E_ABORT && messageWasDisplayed)
340         return NExitCode::kFatalError;
341       throw CSystemException(result);
342     }
343     if (callback.FailedFiles.Size() > 0)
344     {
345       if (!messageWasDisplayed)
346         throw CSystemException(E_FAIL);
347       return NExitCode::kWarning;
348     }
349   }
350   else if (options.Command.CommandType == NCommandType::kHash)
351   {
352     bool messageWasDisplayed = false;
353     HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS_L
354         options.Censor, options.HashOptions, messageWasDisplayed);
355 
356     if (result != S_OK)
357     {
358       if (result != E_ABORT && messageWasDisplayed)
359         return NExitCode::kFatalError;
360       throw CSystemException(result);
361     }
362     /*
363     if (callback.FailedFiles.Size() > 0)
364     {
365       if (!messageWasDisplayed)
366         throw CSystemException(E_FAIL);
367       return NExitCode::kWarning;
368     }
369     */
370   }
371   else
372   {
373     throw "Unsupported command";
374   }
375   return 0;
376 }
377 
378 #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
379 #define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return NExitCode::kFatalError;
380 #endif
381 
WinMain(HINSTANCE hInstance,HINSTANCE,LPWSTR,int)382 int APIENTRY WinMain(HINSTANCE  hInstance, HINSTANCE /* hPrevInstance */,
383   #ifdef UNDER_CE
384   LPWSTR
385   #else
386   LPSTR
387   #endif
388   /* lpCmdLine */, int /* nCmdShow */)
389 {
390   g_hInstance = hInstance;
391 
392   #ifdef _WIN32
393   NT_CHECK
394   #endif
395 
396   InitCommonControls();
397 
398   #ifndef UNDER_CE
399   g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
400   g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
401   #endif
402 
403   // OleInitialize is required for ProgressBar in TaskBar.
404   #ifndef UNDER_CE
405   OleInitialize(NULL);
406   #endif
407 
408   LoadLangOneTime();
409 
410   // setlocale(LC_COLLATE, ".ACP");
411   try
412   {
413     #ifdef _WIN32
414     My_SetDefaultDllDirectories();
415     #endif
416 
417     return Main2();
418   }
419   catch(const CNewException &)
420   {
421     return ShowMemErrorMessage();
422   }
423   catch(const CMessagePathException &e)
424   {
425     ErrorMessage(e);
426     return NExitCode::kUserError;
427   }
428   catch(const CSystemException &systemError)
429   {
430     if (systemError.ErrorCode == E_ABORT)
431       return NExitCode::kUserBreak;
432     return ShowSysErrorMessage(systemError.ErrorCode);
433   }
434   catch(const UString &s)
435   {
436     ErrorMessage(s);
437     return NExitCode::kFatalError;
438   }
439   catch(const AString &s)
440   {
441     ErrorMessage(s);
442     return NExitCode::kFatalError;
443   }
444   catch(const wchar_t *s)
445   {
446     ErrorMessage(s);
447     return NExitCode::kFatalError;
448   }
449   catch(const char *s)
450   {
451     ErrorMessage(s);
452     return NExitCode::kFatalError;
453   }
454   catch(int v)
455   {
456     AString e ("Error: ");
457     e.Add_UInt32(v);
458     ErrorMessage(e);
459     return NExitCode::kFatalError;
460   }
461   catch(...)
462   {
463     ErrorMessage("Unknown error");
464     return NExitCode::kFatalError;
465   }
466 }
467