めいくりぷとのブログ

技術的なことやゲームのことやら・・・

ファイルのハッシュ値を取得する。

BOOL CCalcHash::GetMD2(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD2);
}

BOOL CCalcHash::GetMD4(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD4);
}

BOOL CCalcHash::GetMD5(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD5);
}

BOOL CCalcHash::GetSHA1(__in LPCSTR lpcszFileName, __inout BYTE pbData[20])
{
	return GetFileHashA(lpcszFileName, pbData, 20, CALG_SHA1);
}

BOOL CCalcHash::GetMD2(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD2);
}

BOOL CCalcHash::GetMD4(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD4);
}

BOOL CCalcHash::GetMD5(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD5);
}

BOOL CCalcHash::GetSHA1(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[20])
{
	return GetFileHashW(lpcwszFileName, pbData, 20, CALG_SHA1);
}

BOOL CCalcHash::GetFileHashA(__in LPCSTR lpcszFileName, __inout BYTE* pbData, __in DWORD dwLength, __in DWORD dwFlags)
{
	INT nLength = MultiByteToWideChar(CP_ACP, 0, lpcszFileName, -1, NULL, 0);
	if (nLength == 0)
		return FALSE;

	std::unique_ptr<WCHAR> wszBuffer(new WCHAR[nLength]);
	if (MultiByteToWideChar(CP_ACP, 0, lpcszFileName, nLength, wszBuffer.get(), nLength) == 0)
		return FALSE;

	return GetFileHashW(wszBuffer.get(), pbData, dwLength, dwFlags);
}


BOOL CCalcHash::GetFileHashW(__in LPCWSTR lpcwszFileName, __inout BYTE* pbData, __in DWORD dwLength, __in DWORD dwFlags)
{
	BOOL bResult;
	HCRYPTPROV hProv;
	HCRYPTHASH hHash;
	HANDLE hFile;
	ULARGE_INTEGER lSize;
	BYTE pbHash[MAX_HASH_SIZE];

	if (lpcwszFileName == NULL || dwLength == 0 || dwLength > _countof(pbHash))
		return FALSE;

	ZeroMemory(pbHash, dwLength);

	hFile = CreateFile(lpcwszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return FALSE;	

	lSize.LowPart = GetFileSize(hFile, &lSize.HighPart);
	bResult = FALSE;
	hProv = NULL;
	hHash = NULL;

	if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
	{
		ULARGE_INTEGER lPos;
		DWORD dwReadBytes;
		BYTE pbTemp[64000]; // 64kb		

		if (CryptCreateHash(hProv, dwFlags, NULL, 0, &hHash))
		{
			lPos.QuadPart = 0;			

			while (TRUE)
			{
				ReadFile(hFile, pbTemp, _countof(pbTemp), &dwReadBytes, NULL);
				if (dwReadBytes <= 0)
					break;

				lPos.QuadPart += dwReadBytes;
				if (!CryptHashData(hHash, pbTemp, dwReadBytes, 0))
					break;

				if (lPos.QuadPart == lSize.QuadPart)
				{
					if (CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwLength, 0))
					{
						memcpy_s(pbData, dwLength, pbHash, dwLength);

						if (!bResult)
						{
							bResult = TRUE;
							break;
						}
					}
				}
			}
		}
	}

	if (!bResult) 
		ZeroMemory(pbHash, dwLength);

	if (hHash) 
		CryptDestroyHash(hHash);

	if (hProv) 
		CryptReleaseContext(hProv, 0);

	CloseHandle(hFile);	

	return bResult;
}