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