1 // PanelSplitFile.cpp
\r
5 #include "../../../../C/7zCrc.h"
\r
6 #include "../../../../C/Sha256.h"
\r
8 #include "Common/IntToString.h"
\r
10 #include "Windows/FileFind.h"
\r
11 #include "Windows/FileIO.h"
\r
12 #include "Windows/FileName.h"
\r
14 #include "OverwriteDialogRes.h"
\r
17 #include "FormatUtils.h"
\r
18 #include "LangUtils.h"
\r
20 #include "../Common/PropIDUtils.h"
\r
22 #include "resource.h"
\r
24 using namespace NWindows;
\r
25 using namespace NFile;
\r
27 static const UInt32 kBufSize = (1 << 15);
\r
29 struct CDirEnumerator
\r
33 UStringVector FileNames;
\r
35 CObjectVector<NFind::CEnumeratorW> Enumerators;
\r
36 UStringVector Prefixes;
\r
38 HRESULT GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &fullPath);
\r
41 CDirEnumerator(): FlatMode(false) {};
\r
44 void CDirEnumerator::Init()
\r
46 Enumerators.Clear();
\r
51 static HRESULT GetNormalizedError()
\r
53 HRESULT errorCode = GetLastError();
\r
54 return (errorCode == 0) ? E_FAIL : errorCode;
\r
57 HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath)
\r
62 if (Enumerators.IsEmpty())
\r
64 if (Index >= FileNames.Size())
\r
66 const UString &path = FileNames[Index];
\r
67 int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
\r
70 resPath = path.Left(pos + 1);
\r
73 // it's for "c:" paths/
\r
74 if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':')
\r
76 fileInfo.Name = path;
\r
77 fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY;
\r
82 if (!fileInfo.Find(BasePrefix + path))
\r
84 WRes errorCode = GetNormalizedError();
\r
92 if (!Enumerators.Back().Next(fileInfo, found))
\r
94 HRESULT errorCode = GetNormalizedError();
\r
95 resPath = Prefixes.Back();
\r
100 resPath = Prefixes.Back();
\r
103 Enumerators.DeleteBack();
\r
104 Prefixes.DeleteBack();
\r
106 resPath += fileInfo.Name;
\r
107 if (!FlatMode && fileInfo.IsDir())
\r
109 UString prefix = resPath + WCHAR_PATH_SEPARATOR;
\r
110 Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)NName::kAnyStringWildcard));
\r
111 Prefixes.Add(prefix);
\r
117 static void ConvertByteToHex(unsigned value, wchar_t *s)
\r
119 for (int i = 0; i < 2; i++)
\r
121 unsigned t = value & 0xF;
\r
123 s[1 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
\r
127 class CThreadCrc: public CProgressThreadVirt
\r
129 UInt64 NumFilesScan;
\r
134 Byte Sha256Sum[SHA256_DIGEST_SIZE];
\r
135 UInt32 DataNameCrcSum;
\r
137 UString GetResultMessage() const;
\r
138 HRESULT ProcessVirt();
\r
140 CDirEnumerator Enumerator;
\r
144 UString CThreadCrc::GetResultMessage() const
\r
149 s += LangString(IDS_FILES_COLON, 0x02000320);
\r
151 ConvertUInt64ToString(NumFiles, sz);
\r
155 s += LangString(IDS_FOLDERS_COLON, 0x02000321);
\r
157 ConvertUInt64ToString(NumFolders, sz);
\r
161 s += LangString(IDS_SIZE_COLON, 0x02000322);
\r
163 ConvertUInt64ToString(DataSize, sz);
\r
164 s += MyFormatNew(IDS_FILE_SIZE, 0x02000982, sz);
\r
167 s += LangString(IDS_CHECKSUM_CRC_DATA, 0x03020721);
\r
169 ConvertUInt32ToHex(DataCrcSum, sz);
\r
173 s += LangString(IDS_CHECKSUM_CRC_DATA_NAMES, 0x03020722);
\r
175 ConvertUInt32ToHex(DataNameCrcSum, sz);
\r
179 if (NumFiles == 1 && NumFilesScan == 1)
\r
182 for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
\r
185 ConvertByteToHex(Sha256Sum[i], s2);
\r
193 HRESULT CThreadCrc::ProcessVirt()
\r
195 DataSize = NumFolders = NumFiles = NumFilesScan = DataCrcSum = DataNameCrcSum = 0;
\r
196 memset(Sha256Sum, 0, SHA256_DIGEST_SIZE);
\r
197 // ProgressDialog.WaitCreating();
\r
199 CMyBuffer bufferObject;
\r
200 if (!bufferObject.Allocate(kBufSize))
\r
201 return E_OUTOFMEMORY;
\r
202 Byte *buffer = (Byte *)(void *)bufferObject;
\r
204 UInt64 totalSize = 0;
\r
208 UString scanningStr = LangString(IDS_SCANNING, 0x03020800);
\r
209 scanningStr += L' ';
\r
211 CProgressSync &sync = ProgressDialog.Sync;
\r
215 NFind::CFileInfoW fileInfo;
\r
218 HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath);
\r
219 if (errorCode != 0)
\r
221 ErrorPath1 = resPath;
\r
226 if (!fileInfo.IsDir())
\r
228 totalSize += fileInfo.Size;
\r
231 sync.SetCurrentFileName(scanningStr + resPath);
\r
232 sync.SetProgress(totalSize, 0);
\r
233 RINOK(sync.SetPosAndCheckPaused(0));
\r
235 sync.SetNumFilesTotal(NumFilesScan);
\r
236 sync.SetProgress(totalSize, 0);
\r
242 NFind::CFileInfoW fileInfo;
\r
245 HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath);
\r
246 if (errorCode != 0)
\r
248 ErrorPath1 = resPath;
\r
254 UInt32 crc = CRC_INIT_VAL;
\r
256 Sha256_Init(&sha256);
\r
258 if (fileInfo.IsDir())
\r
262 NIO::CInFile inFile;
\r
263 if (!inFile.Open(Enumerator.BasePrefix + resPath))
\r
265 errorCode = GetNormalizedError();
\r
266 ErrorPath1 = resPath;
\r
269 sync.SetCurrentFileName(resPath);
\r
270 sync.SetNumFilesCur(NumFiles);
\r
274 UInt32 processedSize;
\r
275 if (!inFile.Read(buffer, kBufSize, processedSize))
\r
277 errorCode = GetNormalizedError();
\r
278 ErrorPath1 = resPath;
\r
281 if (processedSize == 0)
\r
283 crc = CrcUpdate(crc, buffer, processedSize);
\r
284 if (NumFilesScan == 1)
\r
285 Sha256_Update(&sha256, buffer, processedSize);
\r
287 DataSize += processedSize;
\r
288 RINOK(sync.SetPosAndCheckPaused(DataSize));
\r
290 DataCrcSum += CRC_GET_DIGEST(crc);
\r
291 if (NumFilesScan == 1)
\r
292 Sha256_Final(&sha256, Sha256Sum);
\r
294 for (int i = 0; i < resPath.Length(); i++)
\r
296 wchar_t c = resPath[i];
\r
297 crc = CRC_UPDATE_BYTE(crc, ((Byte)(c & 0xFF)));
\r
298 crc = CRC_UPDATE_BYTE(crc, ((Byte)((c >> 8) & 0xFF)));
\r
300 DataNameCrcSum += CRC_GET_DIGEST(crc);
\r
301 RINOK(sync.SetPosAndCheckPaused(DataSize));
\r
303 sync.SetNumFilesCur(NumFiles);
\r
304 OkMessage = GetResultMessage();
\r
305 OkMessageTitle = LangString(IDS_CHECKSUM_INFORMATION, 0x03020720);
\r
309 void CApp::CalculateCrc()
\r
311 int srcPanelIndex = GetFocusedPanelIndex();
\r
312 CPanel &srcPanel = Panels[srcPanelIndex];
\r
313 if (!srcPanel.IsFsOrDrivesFolder())
\r
315 srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
\r
318 CRecordVector<UInt32> indices;
\r
319 srcPanel.GetOperatedItemIndices(indices);
\r
320 if (indices.IsEmpty())
\r
325 for (int i = 0; i < indices.Size(); i++)
\r
326 t.Enumerator.FileNames.Add(srcPanel.GetItemRelPath(indices[i]));
\r
327 t.Enumerator.BasePrefix = srcPanel.GetFsPath();
\r
328 t.Enumerator.FlatMode = GetFlatMode();
\r
330 t.ProgressDialog.ShowCompressionInfo = false;
\r
332 UString title = LangString(IDS_CHECKSUM_CALCULATING, 0x03020710);
\r
334 t.ProgressDialog.MainWindow = _window;
\r
335 t.ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);
\r
336 t.ProgressDialog.MainAddTitle = title + UString(L' ');
\r
338 if (t.Create(title, _window) != S_OK)
\r
341 RefreshTitleAlways();
\r