#include "stdafx.h"
#include <string>
#include <Windows.h>
#include <wincrypt.h>
using namespace std;
string ComputeFileMD5(const TCHAR *szFilename)
{
HCRYPTPROV hCryptProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hMapFile = 0;
BYTE bHash[0x7f];
DWORD dwHashLen = 16;
BYTE *pBuf;
string digest;
DWORD dwFileSize = 0, dwHighFileSize = 0;
HANDLE hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return digest;
}
dwFileSize = GetFileSize(hFile, &dwHighFileSize);
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE)
{
goto release;
}
if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
{
if (CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
{
UINT64 filesize = (UINT64)dwHighFileSize << 32 | dwFileSize;
for (UINT64 i = 0; i <= filesize; i += 1048576) // 1024*1024
{
size_t bufsize = size_t(min(filesize - i, 1048576));
pBuf = (BYTE *)MapViewOfFile(hMapFile, FILE_MAP_READ, (DWORD)(i >> 32), (DWORD)i, bufsize);
if (pBuf == NULL)
{
goto release;
}
if (!CryptHashData(hHash, pBuf, bufsize, 0))
{
goto release;
}
UnmapViewOfFile(pBuf);
}
if (CryptGetHashParam(hHash, HP_HASHVAL, bHash, &dwHashLen, 0))
{
digest.resize(32);
BYTE value;
for (int i = 0; i < 16; i++)
{
value = bHash[i] >> 4;
digest[i * 2] = value < 10 ? char(value + '0') : char(value - 10 + 'a');
value = bHash[i] & 0x0F;
digest[i * 2 + 1] = value < 10 ? char(value + '0') : char(value - 10 + 'a');
}
}
}
}
release:
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
CloseHandle(hFile);
return digest;
}