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/OverwriteDialogRes.h"
13 #include "../FileManager/ProgressDialog2.h"
14 #include "../FileManager/ProgressDialog2Res.h"
15 #include "../FileManager/PropertyNameRes.h"
16 #include "../FileManager/resourceGui.h"
17
18 #include "HashGUI.h"
19
20 using namespace NWindows;
21
22 class CHashCallbackGUI: public CProgressThreadVirt, public IHashCallbackUI
23 {
24 UInt64 NumFiles;
25 bool _curIsFolder;
26 UString FirstFileName;
27
28 HRESULT ProcessVirt();
29
30 public:
31 const NWildcard::CCensor *censor;
32 const CHashOptions *options;
33
34 DECL_EXTERNAL_CODECS_LOC_VARS2;
35
CHashCallbackGUI()36 CHashCallbackGUI() {}
~CHashCallbackGUI()37 ~CHashCallbackGUI() { }
38
39 INTERFACE_IHashCallbackUI(;)
40
AddErrorMessage(DWORD systemError,const wchar_t * name)41 void AddErrorMessage(DWORD systemError, const wchar_t *name)
42 {
43 ProgressDialog.Sync.AddError_Code_Name(systemError, name);
44 }
45 };
46
AddValuePair(UString & s,UINT resourceID,UInt64 value)47 static void AddValuePair(UString &s, UINT resourceID, UInt64 value)
48 {
49 AddLangString(s, resourceID);
50 s += ": ";
51 char sz[32];
52 ConvertUInt64ToString(value, sz);
53 s += sz;
54 s.Add_LF();
55 }
56
AddSizeValuePair(UString & s,UINT resourceID,UInt64 value)57 static void AddSizeValuePair(UString &s, UINT resourceID, UInt64 value)
58 {
59 AddLangString(s, resourceID);
60 s += ": ";
61 {
62 wchar_t sz[32];
63 ConvertUInt64ToString(value, sz);
64 s += MyFormatNew(IDS_FILE_SIZE, sz);
65 }
66 {
67 char sz[32];
68 ConvertUInt64ToString(value >> 20, sz);
69 s += " (";
70 s += sz;
71 s += " MB)";
72 s.Add_LF();
73 }
74 }
75
StartScanning()76 HRESULT CHashCallbackGUI::StartScanning()
77 {
78 CProgressSync &sync = ProgressDialog.Sync;
79 sync.Set_Status(LangString(IDS_SCANNING));
80 return CheckBreak();
81 }
82
ScanProgress(const CDirItemsStat & st,const FString & path,bool isDir)83 HRESULT CHashCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
84 {
85 return ProgressDialog.Sync.ScanProgress(st.NumFiles, st.GetTotalBytes(), path, isDir);
86 }
87
ScanError(const FString & path,DWORD systemError)88 HRESULT CHashCallbackGUI::ScanError(const FString &path, DWORD systemError)
89 {
90 AddErrorMessage(systemError, fs2us(path));
91 return CheckBreak();
92 }
93
FinishScanning(const CDirItemsStat & st)94 HRESULT CHashCallbackGUI::FinishScanning(const CDirItemsStat &st)
95 {
96 return ScanProgress(st, FString(), false);
97 }
98
CheckBreak()99 HRESULT CHashCallbackGUI::CheckBreak()
100 {
101 return ProgressDialog.Sync.CheckStop();
102 }
103
SetNumFiles(UInt64 numFiles)104 HRESULT CHashCallbackGUI::SetNumFiles(UInt64 numFiles)
105 {
106 CProgressSync &sync = ProgressDialog.Sync;
107 sync.Set_NumFilesTotal(numFiles);
108 return CheckBreak();
109 }
110
SetTotal(UInt64 size)111 HRESULT CHashCallbackGUI::SetTotal(UInt64 size)
112 {
113 CProgressSync &sync = ProgressDialog.Sync;
114 sync.Set_NumBytesTotal(size);
115 return CheckBreak();
116 }
117
SetCompleted(const UInt64 * completed)118 HRESULT CHashCallbackGUI::SetCompleted(const UInt64 *completed)
119 {
120 return ProgressDialog.Sync.Set_NumBytesCur(completed);
121 }
122
BeforeFirstFile(const CHashBundle &)123 HRESULT CHashCallbackGUI::BeforeFirstFile(const CHashBundle & /* hb */)
124 {
125 return S_OK;
126 }
127
GetStream(const wchar_t * name,bool isFolder)128 HRESULT CHashCallbackGUI::GetStream(const wchar_t *name, bool isFolder)
129 {
130 if (NumFiles == 0)
131 FirstFileName = name;
132 _curIsFolder = isFolder;
133 CProgressSync &sync = ProgressDialog.Sync;
134 sync.Set_FilePath(name, isFolder);
135 return CheckBreak();
136 }
137
OpenFileError(const FString & path,DWORD systemError)138 HRESULT CHashCallbackGUI::OpenFileError(const FString &path, DWORD systemError)
139 {
140 // if (systemError == ERROR_SHARING_VIOLATION)
141 {
142 AddErrorMessage(systemError, fs2us(path));
143 return S_FALSE;
144 }
145 // return systemError;
146 }
147
SetOperationResult(UInt64,const CHashBundle &,bool)148 HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashBundle & /* hb */, bool /* showHash */)
149 {
150 CProgressSync &sync = ProgressDialog.Sync;
151 if (!_curIsFolder)
152 NumFiles++;
153 sync.Set_NumFilesCur(NumFiles);
154 return CheckBreak();
155 }
156
AddHashString(UString & s,const CHasherState & h,unsigned digestIndex,const wchar_t * title)157 static void AddHashString(UString &s, const CHasherState &h, unsigned digestIndex, const wchar_t *title)
158 {
159 s += title;
160 s.Add_Space();
161 char temp[k_HashCalc_DigestSize_Max * 2 + 4];
162 AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize);
163 s += temp;
164 s.Add_LF();
165 }
166
AddHashResString(UString & s,const CHasherState & h,unsigned digestIndex,UInt32 resID)167 static void AddHashResString(UString &s, const CHasherState &h, unsigned digestIndex, UInt32 resID)
168 {
169 UString s2 = LangString(resID);
170 UString name (h.Name);
171 s2.Replace(L"CRC", name);
172 AddHashString(s, h, digestIndex, s2);
173 }
174
AddHashBundleRes(UString & s,const CHashBundle & hb,const UString & firstFileName)175 void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName)
176 {
177 if (hb.NumErrors != 0)
178 {
179 AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors);
180 s.Add_LF();
181 }
182
183 if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty())
184 {
185 AddLangString(s, IDS_PROP_NAME);
186 s += ": ";
187 s += firstFileName;
188 s.Add_LF();
189 }
190 else
191 {
192 AddValuePair(s, IDS_PROP_FOLDERS, hb.NumDirs);
193 AddValuePair(s, IDS_PROP_FILES, hb.NumFiles);
194 }
195
196 AddSizeValuePair(s, IDS_PROP_SIZE, hb.FilesSize);
197
198 if (hb.NumAltStreams != 0)
199 {
200 s.Add_LF();
201 AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, hb.NumAltStreams);
202 AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize);
203 }
204
205 if (hb.NumErrors == 0 && hb.Hashers.IsEmpty())
206 {
207 s.Add_LF();
208 AddLangString(s, IDS_MESSAGE_NO_ERRORS);
209 }
210
211 FOR_VECTOR (i, hb.Hashers)
212 {
213 s.Add_LF();
214 const CHasherState &h = hb.Hashers[i];
215 if (hb.NumFiles == 1 && hb.NumDirs == 0)
216 {
217 s += h.Name;
218 AddHashString(s, h, k_HashCalc_Index_DataSum, L":");
219 }
220 else
221 {
222 AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA);
223 AddHashResString(s, h, k_HashCalc_Index_NamesSum, IDS_CHECKSUM_CRC_DATA_NAMES);
224 }
225 if (hb.NumAltStreams != 0)
226 {
227 AddHashResString(s, h, k_HashCalc_Index_StreamsSum, IDS_CHECKSUM_CRC_STREAMS_NAMES);
228 }
229 }
230 }
231
AfterLastFile(const CHashBundle & hb)232 HRESULT CHashCallbackGUI::AfterLastFile(const CHashBundle &hb)
233 {
234 UString s;
235 AddHashBundleRes(s, hb, FirstFileName);
236
237 CProgressSync &sync = ProgressDialog.Sync;
238 sync.Set_NumFilesCur(hb.NumFiles);
239
240 CProgressMessageBoxPair &pair = GetMessagePair(hb.NumErrors != 0);
241 pair.Message = s;
242 LangString(IDS_CHECKSUM_INFORMATION, pair.Title);
243
244 return S_OK;
245 }
246
ProcessVirt()247 HRESULT CHashCallbackGUI::ProcessVirt()
248 {
249 NumFiles = 0;
250
251 AString errorInfo;
252 HRESULT res = HashCalc(EXTERNAL_CODECS_LOC_VARS
253 *censor, *options, errorInfo, this);
254
255 return res;
256 }
257
HashCalcGUI(DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor & censor,const CHashOptions & options,bool & messageWasDisplayed)258 HRESULT HashCalcGUI(
259 DECL_EXTERNAL_CODECS_LOC_VARS
260 const NWildcard::CCensor &censor,
261 const CHashOptions &options,
262 bool &messageWasDisplayed)
263 {
264 CHashCallbackGUI t;
265 #ifdef EXTERNAL_CODECS
266 t.__externalCodecs = __externalCodecs;
267 #endif
268 t.censor = &censor;
269 t.options = &options;
270
271 t.ProgressDialog.ShowCompressionInfo = false;
272
273 const UString title = LangString(IDS_CHECKSUM_CALCULATING);
274
275 t.ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
276 t.ProgressDialog.MainAddTitle = title;
277 t.ProgressDialog.MainAddTitle.Add_Space();
278
279 RINOK(t.Create(title));
280 messageWasDisplayed = t.ThreadFinishedOK && t.ProgressDialog.MessagesDisplayed;
281 return S_OK;
282 }
283