1 // HashGUI.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/IntToString.h"
6 #include "../../../Common/StringConvert.h"
7 
8 #include "../../../Windows/ErrorMsg.h"
9 
10 #include "../FileManager/FormatUtils.h"
11 #include "../FileManager/LangUtils.h"
12 #include "../FileManager/ListViewDialog.h"
13 #include "../FileManager/OverwriteDialogRes.h"
14 #include "../FileManager/ProgressDialog2.h"
15 #include "../FileManager/ProgressDialog2Res.h"
16 #include "../FileManager/PropertyNameRes.h"
17 #include "../FileManager/resourceGui.h"
18 
19 #include "HashGUI.h"
20 
21 using namespace NWindows;
22 
23 
24 
25 class CHashCallbackGUI: public CProgressThreadVirt, public IHashCallbackUI
26 {
27   UInt64 NumFiles;
28   bool _curIsFolder;
29   UString FirstFileName;
30   // UString MainPath;
31 
32   CPropNameValPairs PropNameValPairs;
33 
34   HRESULT ProcessVirt();
35   virtual void ProcessWasFinished_GuiVirt();
36 
37 public:
38   const NWildcard::CCensor *censor;
39   const CHashOptions *options;
40 
41   DECL_EXTERNAL_CODECS_LOC_VARS2;
42 
CHashCallbackGUI()43   CHashCallbackGUI() {}
~CHashCallbackGUI()44   ~CHashCallbackGUI() { }
45 
46   INTERFACE_IHashCallbackUI(;)
47 
AddErrorMessage(DWORD systemError,const wchar_t * name)48   void AddErrorMessage(DWORD systemError, const wchar_t *name)
49   {
50     Sync.AddError_Code_Name(systemError, name);
51   }
52 };
53 
54 
AddValuePair(CPropNameValPairs & pairs,UINT resourceID,UInt64 value)55 void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
56 {
57   CProperty &pair = pairs.AddNew();
58   AddLangString(pair.Name, resourceID);
59   char sz[32];
60   ConvertUInt64ToString(value, sz);
61   pair.Value = sz;
62 }
63 
64 
AddSizeValue(UString & s,UInt64 value)65 void AddSizeValue(UString &s, UInt64 value)
66 {
67   {
68     wchar_t sz[32];
69     ConvertUInt64ToString(value, sz);
70     s += MyFormatNew(IDS_FILE_SIZE, sz);
71   }
72   if (value >= (1 << 10))
73   {
74     char c;
75           if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }
76     else  if (value >=         (10 << 20)) { value >>= 20; c = 'M'; }
77     else                                   { value >>= 10; c = 'K'; }
78 
79     s += " (";
80     s.Add_UInt64(value);
81     s.Add_Space();
82     s += (wchar_t)c;
83     s += "iB)";
84   }
85 }
86 
AddSizeValuePair(CPropNameValPairs & pairs,UINT resourceID,UInt64 value)87 void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
88 {
89   CProperty &pair = pairs.AddNew();
90   LangString(resourceID, pair.Name);
91   AddSizeValue(pair.Value, value);
92 }
93 
94 
StartScanning()95 HRESULT CHashCallbackGUI::StartScanning()
96 {
97   CProgressSync &sync = Sync;
98   sync.Set_Status(LangString(IDS_SCANNING));
99   return CheckBreak();
100 }
101 
ScanProgress(const CDirItemsStat & st,const FString & path,bool isDir)102 HRESULT CHashCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
103 {
104   return Sync.ScanProgress(st.NumFiles, st.GetTotalBytes(), path, isDir);
105 }
106 
ScanError(const FString & path,DWORD systemError)107 HRESULT CHashCallbackGUI::ScanError(const FString &path, DWORD systemError)
108 {
109   AddErrorMessage(systemError, fs2us(path));
110   return CheckBreak();
111 }
112 
FinishScanning(const CDirItemsStat & st)113 HRESULT CHashCallbackGUI::FinishScanning(const CDirItemsStat &st)
114 {
115   return ScanProgress(st, FString(), false);
116 }
117 
CheckBreak()118 HRESULT CHashCallbackGUI::CheckBreak()
119 {
120   return Sync.CheckStop();
121 }
122 
SetNumFiles(UInt64 numFiles)123 HRESULT CHashCallbackGUI::SetNumFiles(UInt64 numFiles)
124 {
125   CProgressSync &sync = Sync;
126   sync.Set_NumFilesTotal(numFiles);
127   return CheckBreak();
128 }
129 
SetTotal(UInt64 size)130 HRESULT CHashCallbackGUI::SetTotal(UInt64 size)
131 {
132   CProgressSync &sync = Sync;
133   sync.Set_NumBytesTotal(size);
134   return CheckBreak();
135 }
136 
SetCompleted(const UInt64 * completed)137 HRESULT CHashCallbackGUI::SetCompleted(const UInt64 *completed)
138 {
139   return Sync.Set_NumBytesCur(completed);
140 }
141 
BeforeFirstFile(const CHashBundle &)142 HRESULT CHashCallbackGUI::BeforeFirstFile(const CHashBundle & /* hb */)
143 {
144   return S_OK;
145 }
146 
GetStream(const wchar_t * name,bool isFolder)147 HRESULT CHashCallbackGUI::GetStream(const wchar_t *name, bool isFolder)
148 {
149   if (NumFiles == 0)
150     FirstFileName = name;
151   _curIsFolder = isFolder;
152   CProgressSync &sync = Sync;
153   sync.Set_FilePath(name, isFolder);
154   return CheckBreak();
155 }
156 
OpenFileError(const FString & path,DWORD systemError)157 HRESULT CHashCallbackGUI::OpenFileError(const FString &path, DWORD systemError)
158 {
159   // if (systemError == ERROR_SHARING_VIOLATION)
160   {
161     AddErrorMessage(systemError, fs2us(path));
162     return S_FALSE;
163   }
164   // return systemError;
165 }
166 
SetOperationResult(UInt64,const CHashBundle &,bool)167 HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashBundle & /* hb */, bool /* showHash */)
168 {
169   CProgressSync &sync = Sync;
170   if (!_curIsFolder)
171     NumFiles++;
172   sync.Set_NumFilesCur(NumFiles);
173   return CheckBreak();
174 }
175 
176 static const unsigned k_DigestStringSize = k_HashCalc_DigestSize_Max * 2 + k_HashCalc_ExtraSize * 2 + 16;
177 
AddHashString(CProperty & s,const CHasherState & h,unsigned digestIndex)178 static void AddHashString(CProperty &s, const CHasherState &h, unsigned digestIndex)
179 {
180   char temp[k_DigestStringSize];
181   h.WriteToString(digestIndex, temp);
182   s.Value = temp;
183 }
184 
AddHashResString(CPropNameValPairs & s,const CHasherState & h,unsigned digestIndex,UInt32 resID)185 static void AddHashResString(CPropNameValPairs &s, const CHasherState &h, unsigned digestIndex, UInt32 resID)
186 {
187   CProperty &pair = s.AddNew();
188   UString &s2 = pair.Name;
189   LangString(resID, s2);
190   UString name (h.Name);
191   s2.Replace(L"CRC", name);
192   s2.Replace(L":", L"");
193   AddHashString(pair, h, digestIndex);
194 }
195 
196 
AddHashBundleRes(CPropNameValPairs & s,const CHashBundle & hb)197 void AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb)
198 {
199   if (hb.NumErrors != 0)
200     AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors);
201 
202   if (hb.NumFiles == 1 && hb.NumDirs == 0 && !hb.FirstFileName.IsEmpty())
203   {
204     CProperty &pair = s.AddNew();
205     LangString(IDS_PROP_NAME, pair.Name);
206     pair.Value = hb.FirstFileName;
207   }
208   else
209   {
210     if (!hb.MainName.IsEmpty())
211     {
212       CProperty &pair = s.AddNew();
213       LangString(IDS_PROP_NAME, pair.Name);
214       pair.Value = hb.MainName;
215     }
216     if (hb.NumDirs != 0)
217       AddValuePair(s, IDS_PROP_FOLDERS, hb.NumDirs);
218     AddValuePair(s, IDS_PROP_FILES, hb.NumFiles);
219   }
220 
221   AddSizeValuePair(s, IDS_PROP_SIZE, hb.FilesSize);
222 
223   if (hb.NumAltStreams != 0)
224   {
225     AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, hb.NumAltStreams);
226     AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize);
227   }
228 
229   FOR_VECTOR (i, hb.Hashers)
230   {
231     const CHasherState &h = hb.Hashers[i];
232     if (hb.NumFiles == 1 && hb.NumDirs == 0)
233     {
234       CProperty &pair = s.AddNew();
235       pair.Name += h.Name;
236       AddHashString(pair, h, k_HashCalc_Index_DataSum);
237     }
238     else
239     {
240       AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA);
241       AddHashResString(s, h, k_HashCalc_Index_NamesSum, IDS_CHECKSUM_CRC_DATA_NAMES);
242     }
243     if (hb.NumAltStreams != 0)
244     {
245       AddHashResString(s, h, k_HashCalc_Index_StreamsSum, IDS_CHECKSUM_CRC_STREAMS_NAMES);
246     }
247   }
248 }
249 
250 
AddHashBundleRes(UString & s,const CHashBundle & hb)251 void AddHashBundleRes(UString &s, const CHashBundle &hb)
252 {
253   CPropNameValPairs pairs;
254   AddHashBundleRes(pairs, hb);
255 
256   FOR_VECTOR (i, pairs)
257   {
258     const CProperty &pair = pairs[i];
259     s += pair.Name;
260     s += ": ";
261     s += pair.Value;
262     s.Add_LF();
263   }
264 
265   if (hb.NumErrors == 0 && hb.Hashers.IsEmpty())
266   {
267     s.Add_LF();
268     AddLangString(s, IDS_MESSAGE_NO_ERRORS);
269     s.Add_LF();
270   }
271 }
272 
273 
AfterLastFile(CHashBundle & hb)274 HRESULT CHashCallbackGUI::AfterLastFile(CHashBundle &hb)
275 {
276   hb.FirstFileName = FirstFileName;
277   // MainPath
278   AddHashBundleRes(PropNameValPairs, hb);
279 
280   CProgressSync &sync = Sync;
281   sync.Set_NumFilesCur(hb.NumFiles);
282 
283   // CProgressMessageBoxPair &pair = GetMessagePair(hb.NumErrors != 0);
284   // pair.Message = s;
285   // LangString(IDS_CHECKSUM_INFORMATION, pair.Title);
286 
287   return S_OK;
288 }
289 
290 
ProcessVirt()291 HRESULT CHashCallbackGUI::ProcessVirt()
292 {
293   NumFiles = 0;
294   AString errorInfo;
295   HRESULT res = HashCalc(EXTERNAL_CODECS_LOC_VARS
296       *censor, *options, errorInfo, this);
297   return res;
298 }
299 
300 
HashCalcGUI(DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor & censor,const CHashOptions & options,bool & messageWasDisplayed)301 HRESULT HashCalcGUI(
302     DECL_EXTERNAL_CODECS_LOC_VARS
303     const NWildcard::CCensor &censor,
304     const CHashOptions &options,
305     bool &messageWasDisplayed)
306 {
307   CHashCallbackGUI t;
308   #ifdef EXTERNAL_CODECS
309   t.__externalCodecs = __externalCodecs;
310   #endif
311   t.censor = &censor;
312   t.options = &options;
313 
314   t.ShowCompressionInfo = false;
315 
316   const UString title = LangString(IDS_CHECKSUM_CALCULATING);
317 
318   t.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
319   t.MainAddTitle = title;
320   t.MainAddTitle.Add_Space();
321 
322   RINOK(t.Create(title));
323   messageWasDisplayed = t.ThreadFinishedOK && t.MessagesDisplayed;
324   return S_OK;
325 }
326 
327 
ShowHashResults(const CPropNameValPairs & propPairs,HWND hwnd)328 void ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd)
329 {
330   CListViewDialog lv;
331 
332   FOR_VECTOR (i, propPairs)
333   {
334     const CProperty &pair = propPairs[i];
335     lv.Strings.Add(pair.Name);
336     lv.Values.Add(pair.Value);
337   }
338 
339   lv.Title = LangString(IDS_CHECKSUM_INFORMATION);
340   lv.DeleteIsAllowed = true;
341   lv.SelectFirst = false;
342   lv.NumColumns = 2;
343 
344   lv.Create(hwnd);
345 }
346 
347 
ShowHashResults(const CHashBundle & hb,HWND hwnd)348 void ShowHashResults(const CHashBundle &hb, HWND hwnd)
349 {
350   CPropNameValPairs propPairs;
351   AddHashBundleRes(propPairs, hb);
352   ShowHashResults(propPairs, hwnd);
353 }
354 
355 
ProcessWasFinished_GuiVirt()356 void CHashCallbackGUI::ProcessWasFinished_GuiVirt()
357 {
358   ShowHashResults(PropNameValPairs, *this);
359 }
360