1cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// HashCalc.cpp 2cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 3cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "StdAfx.h" 4cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 5cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../../../C/Alloc.h" 6cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 7cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../../Common/StringToInt.h" 8cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 9cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../Common/FileStreams.h" 10cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../Common/StreamUtils.h" 11cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 12cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "EnumDirItems.h" 13cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "HashCalc.h" 14cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 15cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyusing namespace NWindows; 16cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 17cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyclass CHashMidBuf 18cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 19cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky void *_data; 20cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckypublic: 21cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHashMidBuf(): _data(0) {} 22cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky operator void *() { return _data; } 23cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky bool Alloc(size_t size) 24cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 25cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (_data != 0) 26cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return false; 27cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky _data = ::MidAlloc(size); 28cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return _data != 0; 29cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 30cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky ~CHashMidBuf() { ::MidFree(_data); } 31cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}; 32cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 33cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystruct CEnumDirItemCallback_Hash: public IEnumDirItemCallback 34cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 35cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky IHashCallbackUI *Callback; 36cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 37cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) 38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 39cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir); 40cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 41cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}; 42cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 43cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic const wchar_t *k_DefaultHashMethod = L"CRC32"; 44cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 45cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyHRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) 46cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 47cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UStringVector names = hashMethods; 48cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (names.IsEmpty()) 49cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky names.Add(k_DefaultHashMethod); 50cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 51cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CRecordVector<CMethodId> ids; 52cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CObjectVector<COneMethodInfo> methods; 53cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 54cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky unsigned i; 55cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (i = 0; i < names.Size(); i++) 56cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 57cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky COneMethodInfo m; 58cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(m.ParseMethodFromString(names[i])); 59cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 60cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (m.MethodName.IsEmpty()) 61cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky m.MethodName = k_DefaultHashMethod; 62cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 63cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (m.MethodName == L"*") 64cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 65cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CRecordVector<CMethodId> tempMethods; 66cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); 67cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky methods.Clear(); 68cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky ids.Clear(); 69cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FOR_VECTOR (t, tempMethods) 70cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 71cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky int index = ids.AddToUniqueSorted(tempMethods[t]); 72cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (ids.Size() != methods.Size()) 73cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky methods.Insert(index, m); 74cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 75cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky break; 76cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 77cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else 78cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 79cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky // m.MethodName.RemoveChar(L'-'); 80cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CMethodId id; 81cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) 82cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_NOTIMPL; 83cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky int index = ids.AddToUniqueSorted(id); 84cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (ids.Size() != methods.Size()) 85cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky methods.Insert(index, m); 86cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 87cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 88cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 89cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (i = 0; i < ids.Size(); i++) 90cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 91cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CMyComPtr<IHasher> hasher; 92cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UString name; 93cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)); 94cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!hasher) 95cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky throw "Can't create hasher"; 96cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const COneMethodInfo &m = methods[i]; 97cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 98cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CMyComPtr<ICompressSetCoderProperties> scp; 99cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); 100cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (scp) 101cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 102cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(m.SetCoderProps(scp, NULL)); 103cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 104cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 105cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt32 digestSize = hasher->GetDigestSize(); 106cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (digestSize > k_HashCalc_DigestSize_Max) 107cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_NOTIMPL; 108cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHasherState &h = Hashers.AddNew(); 109cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher = hasher; 110cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Name = name; 111cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.DigestSize = digestSize; 112cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (int i = 0; i < k_HashCalc_NumGroups; i++) 113cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memset(h.Digests[i], 0, digestSize); 114cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 115cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return S_OK; 116cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 117cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 118cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CHashBundle::InitForNewFile() 119cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 120cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CurSize = 0; 121cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FOR_VECTOR (i, Hashers) 122cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 123cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHasherState &h = Hashers[i]; 124cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Init(); 125cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize); 126cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 128cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 129cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CHashBundle::Update(const void *data, UInt32 size) 130cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 131cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CurSize += size; 132cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FOR_VECTOR (i, Hashers) 133cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Hashers[i].Hasher->Update(data, size); 134cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 135cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 136cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CHashBundle::SetSize(UInt64 size) 137cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 138cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CurSize = size; 139cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 140cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 141cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic void AddDigests(Byte *dest, const Byte *src, UInt32 size) 142cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 143cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky unsigned next = 0; 144cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (UInt32 i = 0; i < size; i++) 145cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 146cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky next += (unsigned)dest[i] + (unsigned)src[i]; 147cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[i] = (Byte)next; 148cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky next >>= 8; 149cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 150cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 151cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 152cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) 153cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 154cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (isDir) 155cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky NumDirs++; 156cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else if (isAltStream) 157cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 158cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky NumAltStreams++; 159cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky AltStreamsSize += CurSize; 160cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 161cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else 162cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 163cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky NumFiles++; 164cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FilesSize += CurSize; 165cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 166cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 167cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Byte pre[16]; 168cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky memset(pre, 0, sizeof(pre)); 169cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (isDir) 170cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky pre[0] = 1; 171cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 172cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FOR_VECTOR (i, Hashers) 173cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 174cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHasherState &h = Hashers[i]; 175cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!isDir) 176cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 177cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Final(h.Digests[0]); 178cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!isAltStream) 179cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize); 180cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 181cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 182cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Init(); 183cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Update(pre, sizeof(pre)); 184cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Update(h.Digests[0], h.DigestSize); 185cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 186cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (unsigned k = 0; k < path.Len(); k++) 187cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 188cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky wchar_t c = path[k]; 189cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; 190cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Update(temp, 2); 191cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 192cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 193cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Byte tempDigest[k_HashCalc_DigestSize_Max]; 194cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky h.Hasher->Final(tempDigest); 195cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!isAltStream) 196cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize); 197cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize); 198cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 199cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 200cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 201cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 202cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyHRESULT HashCalc( 203cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky DECL_EXTERNAL_CODECS_LOC_VARS 204cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const NWildcard::CCensor &censor, 205cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const CHashOptions &options, 206cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UString &errorInfo, 207cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky IHashCallbackUI *callback) 208cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 209cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CDirItems dirItems; 210cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 211cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt64 numErrors = 0; 212cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt64 totalBytes = 0; 213cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (options.StdInMode) 214cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 215cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CDirItem di; 216cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky di.Size = (UInt64)(Int64)-1; 217cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky di.Attrib = 0; 218cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky di.MTime.dwLowDateTime = 0; 219cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky di.MTime.dwHighDateTime = 0; 220cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky di.CTime = di.ATime = di.MTime; 221cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dirItems.Items.Add(di); 222cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 223cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else 224cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 225cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CEnumDirItemCallback_Hash enumCallback; 226cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky enumCallback.Callback = callback; 227cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->StartScanning()); 228cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dirItems.ScanAltStreams = options.AltStreamsMode; 229cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky HRESULT res = EnumerateItems(censor, 230cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky options.PathMode, 231cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UString(), 232cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dirItems, &enumCallback); 233cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky totalBytes = dirItems.TotalSize; 234cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky FOR_VECTOR (i, dirItems.ErrorPaths) 235cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 236cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i])); 237cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 238cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky numErrors = dirItems.ErrorPaths.Size(); 239cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (res != S_OK) 240cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 241cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (res != E_ABORT) 242cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky errorInfo = L"Scanning error"; 243cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return res; 244cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 245cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->FinishScanning()); 246cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 247cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 248cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky unsigned i; 249cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHashBundle hb; 250cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)); 251cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.Init(); 252cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.NumErrors = numErrors; 253cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 254cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (options.StdInMode) 255cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 256cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->SetNumFiles(1)); 257cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 258cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else 259cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 260cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->SetTotal(totalBytes)); 261cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 262cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 263cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const UInt32 kBufSize = 1 << 15; 264cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CHashMidBuf buf; 265cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!buf.Alloc(kBufSize)) 266cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return E_OUTOFMEMORY; 267cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 268cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt64 completeValue = 0; 269cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 270cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->BeforeFirstFile(hb)); 271cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 272cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (i = 0; i < dirItems.Items.Size(); i++) 273cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 274cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CMyComPtr<ISequentialInStream> inStream; 275cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UString path; 276cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky bool isDir = false; 277cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky bool isAltStream = false; 278cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (options.StdInMode) 279cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 280cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky inStream = new CStdInFileStream; 281cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 282cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky else 283cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 284cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky CInFileStream *inStreamSpec = new CInFileStream; 285cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky inStream = inStreamSpec; 286cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky const CDirItem &dirItem = dirItems.Items[i]; 287cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky isDir = dirItem.IsDir(); 288cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky isAltStream = dirItem.IsAltStream; 289cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky path = dirItems.GetLogPath(i); 290cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!isDir) 291cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 292cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UString phyPath = dirItems.GetPhyPath(i); 293cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite)) 294cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 295cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); 296cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.NumErrors++; 297cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (res != S_FALSE) 298cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return res; 299cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky continue; 300cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 301cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 302cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 303cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->GetStream(path, isDir)); 304cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt64 fileSize = 0; 305cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 306cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.InitForNewFile(); 307cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!isDir) 308cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 309cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (UInt32 step = 0;; step++) 310cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 311cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if ((step & 0xFF) == 0) 312cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->SetCompleted(&completeValue)); 313cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky UInt32 size; 314cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(inStream->Read(buf, kBufSize, &size)); 315cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (size == 0) 316cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky break; 317cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.Update(buf, size); 318cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky fileSize += size; 319cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky completeValue += size; 320cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 321cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 322cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky hb.Final(isDir, isAltStream, path); 323cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->SetOperationResult(fileSize, hb, !isDir)); 324cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky RINOK(callback->SetCompleted(&completeValue)); 325cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 326cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return callback->AfterLastFile(hb); 327cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 328cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 329cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 330cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic inline char GetHex(Byte value) 331cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 332cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); 333cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 334cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky 335cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckyvoid AddHashHexToString(char *dest, const Byte *data, UInt32 size) 336cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{ 337cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[size * 2] = 0; 338cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (!data) 339cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 340cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (UInt32 i = 0; i < size; i++) 341cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 342cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[0] = ' '; 343cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[1] = ' '; 344cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest += 2; 345cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 346cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky return; 347cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 348cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky int step = 2; 349cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky if (size <= 8) 350cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 351cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky step = -2; 352cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest += size * 2 - 2; 353cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 354cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky for (UInt32 i = 0; i < size; i++) 355cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky { 356cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky Byte b = data[i]; 357cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[0] = GetHex((Byte)((b >> 4) & 0xF)); 358cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest[1] = GetHex((Byte)(b & 0xF)); 359cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky dest += step; 360cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky } 361cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky} 362