用windows api 计算文件的md5值

我自己封装了一个函数GetMd5(LPCWSTR FileDirectory)。其中调用了windows api:CryptAcquireContext,CryptCreateHash,CryptHashData等。要计算不同文件的md5值,只需在调用此函数时传入不同文件的全路径即可,不需要额外的dll。示例代码在vs2008中测试通过

#include "stdafx.h"
#include <iostream>
#include "windows.h"
using namespace std;

void GetMd5(LPCWSTR FileDirectory)
{
	HANDLE hFile=CreateFile(FileDirectory,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
	if (hFile==INVALID_HANDLE_VALUE)                                        //如果CreateFile调用失败
	{
		cout<<"CreateFile go wrong :"<<GetLastError()<<endl;                //提示CreateFile调用失败,并输出错误号。visual studio中可在“工具”>“错误查找”中利用错误号得到错误信息。
		CloseHandle(hFile);
	}
	HCRYPTPROV hProv=NULL;
	if(CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)==FALSE)       //获得CSP中一个密钥容器的句柄
	{
		cout<<"CryptAcquireContext go wrong:"<<GetLastError()<<endl;
	}
	HCRYPTPROV hHash=NULL;
	if(CryptCreateHash(hProv,CALG_MD5,0,0,&hHash)==FALSE)     //初始化对数据流的hash,创建并返回一个与CSP的hash对象相关的句柄。这个句柄接下来将被CryptHashData调用。
	{
		cout<<"CryptCreateHash go wrong:"<<GetLastError()<<endl;
	}
	DWORD dwFileSize=GetFileSize(hFile,0);    //获取文件的大小
	if (dwFileSize==0xFFFFFFFF)               //如果获取文件大小失败
	{
		cout<<"GetFileSize go wrong:"<<GetLastError()<<endl;
	}
	byte* lpReadFileBuffer=new byte[dwFileSize];
	DWORD lpReadNumberOfBytes;
	if (ReadFile(hFile,lpReadFileBuffer,dwFileSize,&lpReadNumberOfBytes,NULL)==0)        //读取文件
	{
		cout<<"ReadFile go wrong:"<<GetLastError()<<endl;
	}
    if(CryptHashData(hHash,lpReadFileBuffer,lpReadNumberOfBytes,0)==FALSE)      //hash文件
	{
		cout<<"CryptHashData go wrong:"<<GetLastError()<<endl;
	}

	delete[] lpReadFileBuffer;
	CloseHandle(hFile);          //关闭文件句柄
    BYTE *pbHash;
	DWORD dwHashLen=sizeof(DWORD);
	//以下注释掉的代码不用使用,因为已经知道md5值就占32个字节,没有必要通过CryptGetHashParam函数来得到字节数。
	/*
	BYTE *pbHashSize;
	if (!(pbHashSize=(byte*)malloc(dwHashLen)))      //为pbHashSize分配内存
	{
		cout<<"memory allocation failed:"<<GetLastError()<<endl;
	}
	//将第二个参数的值设为HP_HASHSIZE。dwHashLen中存放着hash值的字节数。这个调用必须在将第三个参数设置为HP_HASHVAL的调用前,这样才能分配正确数量的内存。
	if (CryptGetHashParam(hHash,HP_HASHSIZE,pbHashSize,&dwHashLen,0))      
	{
		free(pbHashSize);
	}
	else
	{
		cout<<"get size go wrong"<<GetLastError()<<endl;
	}*/
	if (CryptGetHashParam(hHash,HP_HASHVAL,NULL,&dwHashLen,0))      //我也不知道为什么要先这样调用CryptGetHashParam,这块是参照的msdn       
	{
	}
	else
	{
		cout<<"get length wrong"<<endl;
	}
	if(pbHash=(byte*)malloc(dwHashLen))
	{}
	else
	{
		cout<<"allocation failed"<<endl;
	}
	if(CryptGetHashParam(hHash,HP_HASHVAL,pbHash,&dwHashLen,0))            //获得md5值
	{
		for(DWORD i=0;i<dwHashLen;i++)         //输出md5值
		{
			printf("%02x",pbHash[i]);
		}
		cout<<endl;
	}
	//善后工作
	if(CryptDestroyHash(hHash)==FALSE)          //销毁hash对象
	{
		cout<<"CryptDestroyHash go wrong:"<<GetLastError()<<endl;
	}
	if(CryptReleaseContext(hProv,0)==FALSE)
	{
		cout<<"CryptReleaseContext go wrong:"<<GetLastError()<<endl;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	GetMd5(L"C:\\Windows\\System32\\kernel32.dll");
	system("pause");
	return 0;
}
此代码输出系统文件kernel32.dll的md5值,在我电脑上运行结果如下图所示:



你可能感兴趣的:(windows,api,null,byte,Go,Allocation)