OSDN Git Service

Webpage Compare: Add support for generating report files (#1941)
[winmerge-jp/winmerge-jp.git] / Src / HashCalc.cpp
1 /** 
2  * @file  HashCalc.cpp
3  *
4  * @brief Implementation file for HashCalc
5  */
6 #include "pch.h"
7 #include "HashCalc.h"
8
9 #ifdef _WIN64
10
11 #pragma comment(lib, "bcrypt.lib")
12  
13 static NTSTATUS CalculateHashValue(HANDLE hFile, BCRYPT_HASH_HANDLE hHash, ULONG hashSize, std::vector<uint8_t>& hash)
14 {
15         hash.resize(hashSize);
16         std::vector<uint8_t> buffer(64 * 1024);
17         NTSTATUS status = 0;
18         while (status == 0)
19         {
20                 DWORD dwRead = 0;
21                 if (!ReadFile(hFile, buffer.data(), static_cast<DWORD>(buffer.size()), &dwRead, nullptr))
22                 {
23                         status = 1; // STATUS_UNSUCCESSFUL
24                         hash.clear();
25                         break;
26                 }
27                 status = BCryptHashData(hHash, buffer.data(), dwRead, 0);
28                 if (buffer.size() != dwRead)
29                         break;
30         }
31         if (status == 0)
32         {
33                 status = BCryptFinishHash(hHash, hash.data(), static_cast<ULONG>(hash.size()), 0);
34         }
35         return status;
36 }
37
38 NTSTATUS CalculateHashValue(HANDLE hFile, const wchar_t *pAlgoId, std::vector<uint8_t>& hash)
39 {
40         hash.clear();
41         BCRYPT_ALG_HANDLE hAlg = nullptr;
42         NTSTATUS status = BCryptOpenAlgorithmProvider(&hAlg, pAlgoId, nullptr, 0);
43         if (status == 0)
44         {
45                 ULONG bytesWritten = 0;
46                 ULONG objectSize = 0;
47                 status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PUCHAR>(&objectSize), sizeof(DWORD), &bytesWritten, 0);
48                 if (status == 0)
49                 {
50                         std::vector<uint8_t> hashObject(objectSize);
51                         BCRYPT_HASH_HANDLE hHash = nullptr;
52                         status = BCryptCreateHash(hAlg, &hHash, hashObject.data(), static_cast<ULONG>(hashObject.size()), nullptr, 0, 0);
53                         if (status == 0)
54                         {
55                                 ULONG hashSize = 0;
56                                 status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, reinterpret_cast<PUCHAR>(&hashSize), sizeof(DWORD), &bytesWritten, 0);
57                                 if (status == 0)
58                                 {
59                                         status = CalculateHashValue(hFile, hHash, hashSize, hash);
60                                 }
61                                 BCryptDestroyHash(hHash);
62                         }
63                 }
64                 BCryptCloseAlgorithmProvider(hAlg, 0);
65         }
66         return status;
67 }
68
69 #endif