1 // ExtractGUI.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/IntToString.h"
6 #include "../../../Common/StringConvert.h"
7 
8 #include "../../../Windows/FileDir.h"
9 #include "../../../Windows/FileFind.h"
10 #include "../../../Windows/FileName.h"
11 #include "../../../Windows/Thread.h"
12 
13 #include "../FileManager/ExtractCallback.h"
14 #include "../FileManager/FormatUtils.h"
15 #include "../FileManager/LangUtils.h"
16 #include "../FileManager/resourceGui.h"
17 #include "../FileManager/OverwriteDialogRes.h"
18 
19 #include "../Common/ArchiveExtractCallback.h"
20 #include "../Common/PropIDUtils.h"
21 
22 #include "../Explorer/MyMessages.h"
23 
24 #include "resource2.h"
25 #include "ExtractRes.h"
26 
27 #include "ExtractDialog.h"
28 #include "ExtractGUI.h"
29 #include "HashGUI.h"
30 
31 #include "../FileManager/PropertyNameRes.h"
32 
33 using namespace NWindows;
34 using namespace NFile;
35 using namespace NDir;
36 
37 static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
38 
39 #ifndef _SFX
40 
AddValuePair(UString & s,UINT resourceID,UInt64 value,bool addColon=true)41 static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)
42 {
43   wchar_t sz[32];
44   s += LangString(resourceID);
45   if (addColon)
46     s += L':';
47   s += L' ';
48   ConvertUInt64ToString(value, sz);
49   s += sz;
50   s += L'\n';
51 }
52 
AddSizePair(UString & s,UINT resourceID,UInt64 value)53 static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
54 {
55   wchar_t sz[32];
56   s += LangString(resourceID);
57   s += L": ";
58   ConvertUInt64ToString(value, sz);
59   s += MyFormatNew(IDS_FILE_SIZE, sz);
60   // s += sz;
61   if (value >= (1 << 20))
62   {
63     ConvertUInt64ToString(value >> 20, sz);
64     s += L" (";
65     s += sz;
66     s += L" MB)";
67   }
68   s += L'\n';
69 }
70 
71 #endif
72 
73 class CThreadExtracting: public CProgressThreadVirt
74 {
75   HRESULT ProcessVirt();
76 public:
77   CCodecs *codecs;
78   CExtractCallbackImp *ExtractCallbackSpec;
79   const CObjectVector<COpenType> *FormatIndices;
80   const CIntVector *ExcludedFormatIndices;
81 
82   UStringVector *ArchivePaths;
83   UStringVector *ArchivePathsFull;
84   const NWildcard::CCensorNode *WildcardCensor;
85   const CExtractOptions *Options;
86   #ifndef _SFX
87   CHashBundle *HashBundle;
88   #endif
89   CMyComPtr<IExtractCallbackUI> ExtractCallback;
90   UString Title;
91 };
92 
ProcessVirt()93 HRESULT CThreadExtracting::ProcessVirt()
94 {
95   CDecompressStat Stat;
96   #ifndef _SFX
97   if (HashBundle)
98     HashBundle->Init();
99   #endif
100 
101   HRESULT res = Extract(codecs,
102       *FormatIndices, *ExcludedFormatIndices,
103       *ArchivePaths, *ArchivePathsFull,
104       *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback,
105       #ifndef _SFX
106         HashBundle,
107       #endif
108       FinalMessage.ErrorMessage.Message, Stat);
109   #ifndef _SFX
110   if (res == S_OK && Options->TestMode && ExtractCallbackSpec->IsOK())
111   {
112     UString s;
113 
114     AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);
115     AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);
116 
117     if (!HashBundle)
118     {
119       if (Stat.NumFolders != 0)
120         AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);
121       AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);
122       AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);
123       if (Stat.NumAltStreams != 0)
124       {
125         s += L'\n';
126         AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);
127         AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);
128       }
129     }
130 
131     if (HashBundle)
132     {
133       s += L'\n';
134       AddHashBundleRes(s, *HashBundle, UString());
135     }
136 
137     s += L'\n';
138     s += LangString(IDS_MESSAGE_NO_ERRORS);
139 
140     FinalMessage.OkMessage.Title = Title;
141     FinalMessage.OkMessage.Message = s;
142   }
143   #endif
144   return res;
145 }
146 
ExtractGUI(CCodecs * codecs,const CObjectVector<COpenType> & formatIndices,const CIntVector & excludedFormatIndices,UStringVector & archivePaths,UStringVector & archivePathsFull,const NWildcard::CCensorNode & wildcardCensor,CExtractOptions & options,CHashBundle * hb,bool showDialog,bool & messageWasDisplayed,CExtractCallbackImp * extractCallback,HWND hwndParent)147 HRESULT ExtractGUI(
148     CCodecs *codecs,
149     const CObjectVector<COpenType> &formatIndices,
150     const CIntVector &excludedFormatIndices,
151     UStringVector &archivePaths,
152     UStringVector &archivePathsFull,
153     const NWildcard::CCensorNode &wildcardCensor,
154     CExtractOptions &options,
155     #ifndef _SFX
156     CHashBundle *hb,
157     #endif
158     bool showDialog,
159     bool &messageWasDisplayed,
160     CExtractCallbackImp *extractCallback,
161     HWND hwndParent)
162 {
163   messageWasDisplayed = false;
164 
165   CThreadExtracting extracter;
166   extracter.codecs = codecs;
167   extracter.FormatIndices = &formatIndices;
168   extracter.ExcludedFormatIndices = &excludedFormatIndices;
169 
170   if (!options.TestMode)
171   {
172     FString outputDir = options.OutputDir;
173     #ifndef UNDER_CE
174     if (outputDir.IsEmpty())
175       GetCurrentDir(outputDir);
176     #endif
177     if (showDialog)
178     {
179       CExtractDialog dialog;
180       FString outputDirFull;
181       if (!MyGetFullPathName(outputDir, outputDirFull))
182       {
183         ShowErrorMessage(kIncorrectOutDir);
184         messageWasDisplayed = true;
185         return E_FAIL;
186       }
187       NName::NormalizeDirPathPrefix(outputDirFull);
188 
189       dialog.DirPath = fs2us(outputDirFull);
190 
191       dialog.OverwriteMode = options.OverwriteMode;
192       dialog.OverwriteMode_Force = options.OverwriteMode_Force;
193       dialog.PathMode = options.PathMode;
194       dialog.PathMode_Force = options.PathMode_Force;
195       dialog.ElimDup = options.ElimDup;
196 
197       if (archivePathsFull.Size() == 1)
198         dialog.ArcPath = archivePathsFull[0];
199 
200       #ifndef _SFX
201       // dialog.AltStreams = options.NtOptions.AltStreams;
202       dialog.NtSecurity = options.NtOptions.NtSecurity;
203       if (extractCallback->PasswordIsDefined)
204         dialog.Password = extractCallback->Password;
205       #endif
206 
207       if (dialog.Create(hwndParent) != IDOK)
208         return E_ABORT;
209 
210       outputDir = us2fs(dialog.DirPath);
211 
212       options.OverwriteMode = dialog.OverwriteMode;
213       options.PathMode = dialog.PathMode;
214       options.ElimDup = dialog.ElimDup;
215 
216       #ifndef _SFX
217       // options.NtOptions.AltStreams = dialog.AltStreams;
218       options.NtOptions.NtSecurity = dialog.NtSecurity;
219       extractCallback->Password = dialog.Password;
220       extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();
221       #endif
222     }
223     if (!MyGetFullPathName(outputDir, options.OutputDir))
224     {
225       ShowErrorMessage(kIncorrectOutDir);
226       messageWasDisplayed = true;
227       return E_FAIL;
228     }
229     NName::NormalizeDirPathPrefix(options.OutputDir);
230 
231     /*
232     if(!CreateComplexDirectory(options.OutputDir))
233     {
234       UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));
235       UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
236       #ifdef LANG
237       0x02000603,
238       #endif
239       options.OutputDir);
240       MyMessageBox(s2 + UString(L'\n') + s);
241       return E_FAIL;
242     }
243     */
244   }
245 
246   UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING);
247 
248   extracter.Title = title;
249   extracter.ExtractCallbackSpec = extractCallback;
250   extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;
251   extracter.ExtractCallback = extractCallback;
252   extracter.ExtractCallbackSpec->Init();
253 
254   extracter.ProgressDialog.CompressingMode = false;
255 
256   extracter.ArchivePaths = &archivePaths;
257   extracter.ArchivePathsFull = &archivePathsFull;
258   extracter.WildcardCensor = &wildcardCensor;
259   extracter.Options = &options;
260   #ifndef _SFX
261   extracter.HashBundle = hb;
262   #endif
263 
264   extracter.ProgressDialog.IconID = IDI_ICON;
265 
266   RINOK(extracter.Create(title, hwndParent));
267   messageWasDisplayed = extracter.ThreadFinishedOK &
268       extracter.ProgressDialog.MessagesDisplayed;
269   return extracter.Result;
270 }
271