1 // Main.cpp
2 
3 #include "StdAfx.h"
4 
5 #include <Shlwapi.h>
6 
7 #include "../../../Common/MyInitGuid.h"
8 
9 #include "../../../Common/CommandLineParser.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/FileName.h"
16 #include "../../../Windows/NtCheck.h"
17 #include "../../../Windows/ResourceString.h"
18 
19 #include "../../ICoder.h"
20 #include "../../IPassword.h"
21 #include "../../Archive/IArchive.h"
22 #include "../../UI/Common/Extract.h"
23 #include "../../UI/Common/ExitCode.h"
24 #include "../../UI/Explorer/MyMessages.h"
25 #include "../../UI/FileManager/MyWindowsNew.h"
26 #include "../../UI/GUI/ExtractGUI.h"
27 #include "../../UI/GUI/ExtractRes.h"
28 
29 using namespace NWindows;
30 using namespace NFile;
31 using namespace NDir;
32 
33 HINSTANCE g_hInstance;
34 
35 #ifndef UNDER_CE
36 
37 DWORD g_ComCtl32Version;
38 
GetDllVersion(LPCTSTR dllName)39 static DWORD GetDllVersion(LPCTSTR dllName)
40 {
41   DWORD dwVersion = 0;
42   HINSTANCE hinstDll = LoadLibrary(dllName);
43   if (hinstDll)
44   {
45     DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");
46     if (pDllGetVersion)
47     {
48       DLLVERSIONINFO dvi;
49       ZeroMemory(&dvi, sizeof(dvi));
50       dvi.cbSize = sizeof(dvi);
51       HRESULT hr = (*pDllGetVersion)(&dvi);
52       if (SUCCEEDED(hr))
53         dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
54     }
55     FreeLibrary(hinstDll);
56   }
57   return dwVersion;
58 }
59 
60 #endif
61 
62 bool g_LVN_ITEMACTIVATE_Support = true;
63 
64 static const wchar_t *kUnknownExceptionMessage = L"ERROR: Unknown Error!";
65 
ErrorMessageForHRESULT(HRESULT res)66 void ErrorMessageForHRESULT(HRESULT res)
67 {
68   ShowErrorMessage(HResultToMessage(res));
69 }
70 
WinMain2()71 int APIENTRY WinMain2()
72 {
73   // OleInitialize is required for ProgressBar in TaskBar.
74   #ifndef UNDER_CE
75   OleInitialize(NULL);
76   #endif
77 
78   #ifndef UNDER_CE
79   g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
80   g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
81   #endif
82 
83   UString password;
84   bool assumeYes = false;
85   bool outputFolderDefined = false;
86   FString outputFolder;
87   UStringVector commandStrings;
88   NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
89 
90   #ifndef UNDER_CE
91   if (commandStrings.Size() > 0)
92     commandStrings.Delete(0);
93   #endif
94 
95   FOR_VECTOR (i, commandStrings)
96   {
97     const UString &s = commandStrings[i];
98     if (s.Len() > 1 && s[0] == '-')
99     {
100       wchar_t c = MyCharLower_Ascii(s[1]);
101       if (c == 'y')
102       {
103         assumeYes = true;
104         if (s.Len() != 2)
105         {
106           ShowErrorMessage(L"Bad command");
107           return 1;
108         }
109       }
110       else if (c == 'o')
111       {
112         outputFolder = us2fs(s.Ptr(2));
113         NName::NormalizeDirPathPrefix(outputFolder);
114         outputFolderDefined = !outputFolder.IsEmpty();
115       }
116       else if (c == 'p')
117       {
118         password = s.Ptr(2);
119       }
120     }
121   }
122 
123   FString path;
124   NDLL::MyGetModuleFileName(path);
125 
126   FString fullPath;
127   if (!MyGetFullPathName(path, fullPath))
128   {
129     ShowErrorMessage(L"Error 1329484");
130     return 1;
131   }
132 
133   CCodecs *codecs = new CCodecs;
134   CMyComPtr<IUnknown> compressCodecsInfo = codecs;
135   HRESULT result = codecs->Load();
136   if (result != S_OK)
137   {
138     ErrorMessageForHRESULT(result);
139     return 1;
140   }
141 
142   // COpenCallbackGUI openCallback;
143 
144   // openCallback.PasswordIsDefined = !password.IsEmpty();
145   // openCallback.Password = password;
146 
147   CExtractCallbackImp *ecs = new CExtractCallbackImp;
148   CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
149   ecs->Init();
150 
151   #ifndef _NO_CRYPTO
152   ecs->PasswordIsDefined = !password.IsEmpty();
153   ecs->Password = password;
154   #endif
155 
156   CExtractOptions eo;
157 
158   FString dirPrefix;
159   if (!GetOnlyDirPrefix(path, dirPrefix))
160   {
161     ShowErrorMessage(L"Error 1329485");
162     return 1;
163   }
164 
165   eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;
166   eo.YesToAll = assumeYes;
167   eo.OverwriteMode = assumeYes ?
168       NExtract::NOverwriteMode::kOverwrite :
169       NExtract::NOverwriteMode::kAsk;
170   eo.PathMode = NExtract::NPathMode::kFullPaths;
171   eo.TestMode = false;
172 
173   UStringVector v1, v2;
174   v1.Add(fs2us(fullPath));
175   v2.Add(fs2us(fullPath));
176   NWildcard::CCensorNode wildcardCensor;
177   wildcardCensor.AddItem(true, L"*", true, true, true, true);
178 
179   bool messageWasDisplayed = false;
180   result = ExtractGUI(codecs,
181       CObjectVector<COpenType>(), CIntVector(),
182       v1, v2,
183       wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);
184 
185   if (result == S_OK)
186   {
187     if (!ecs->IsOK())
188       return NExitCode::kFatalError;
189     return 0;
190   }
191   if (result == E_ABORT)
192     return NExitCode::kUserBreak;
193   if (!messageWasDisplayed)
194   {
195     if (result == S_FALSE)
196       ShowErrorMessage(L"Error in archive");
197     else
198       ErrorMessageForHRESULT(result);
199   }
200   if (result == E_OUTOFMEMORY)
201     return NExitCode::kMemoryError;
202   return NExitCode::kFatalError;
203 }
204 
205 #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError;
206 
WinMain(HINSTANCE hInstance,HINSTANCE,LPWSTR,int)207 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
208   #ifdef UNDER_CE
209   LPWSTR
210   #else
211   LPSTR
212   #endif
213   /* lpCmdLine */, int /* nCmdShow */)
214 {
215   g_hInstance = (HINSTANCE)hInstance;
216 
217   NT_CHECK
218 
219   try
220   {
221     return WinMain2();
222   }
223   catch(const CNewException &)
224   {
225     ErrorMessageForHRESULT(E_OUTOFMEMORY);
226     return NExitCode::kMemoryError;
227   }
228   catch(...)
229   {
230     ShowErrorMessage(kUnknownExceptionMessage);
231     return NExitCode::kFatalError;
232   }
233 }
234