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