您的位置:首页 > 其它

MFC版哈希值计算器的实现(二)

2012-01-29 13:57 218 查看
1 开始相关函数

void CHashToolDlg::BeginComputeHashInfo(CString filePath)
{
CString *tmp = new CString();
*tmp = filePath.GetBuffer();

if(PathIsDirectory(*tmp))
{
MessageBox("Does not support directory","Warning", MB_OK|MB_ICONWARNING);
return;
}

HWND hWnd = AfxGetMainWnd()->GetSafeHwnd();
if(::SendMessage(hWnd, WM_Create_Progress_Bar, (WPARAM)tmp, NULL))
{
//exist same file
return;
}

AfxBeginThread(ThreadComputeHashInfo, tmp);
}

UINT CHashToolDlg::ThreadComputeHashInfo(LPVOID pParam)
{
CString* filePath = (CString*)pParam;

CHashTool hashTool;
HWND hWndMainDlg = AfxGetMainWnd()->GetSafeHwnd();
if(!hashTool.GetHashInfo(*filePath, hWndMainDlg))
{
::SendMessage(hWndMainDlg, WM_Delete_Progress_Bar, (WPARAM)filePath, NULL);
}
delete filePath;

return 0;
}


2 计算相关函数

BOOL CHashTool::GetHashInfo(CString filePath, HWND mainDlg)
{
BOOL result;
bStopHash = FALSE;
fileInfo.FilePath = filePath;
hWndMainDlg = mainDlg;

CFileStatus fileStatus;
if(CFile::GetStatus(filePath, fileStatus))
{
fileInfo.Size = fileStatus.m_size;
fileInfo.LastModifyTime = fileStatus.m_mtime.Format("Modify on: %Y-%m-%d %H:%M:%S");
result = ComputeHash(fileInfo.FilePath);
}
else
{
AfxMessageBox("Get file status error: {0}", GetLastError(), MB_OK|MB_ICONWARNING);
result = FALSE;
}
return result;
}
BOOL CHashTool::InitCreateHash(HCRYPTPROV* hProv, HCRYPTHASH* hHash, ALG_ID algID)
{
if (!CryptAcquireContext(hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
return FALSE;

/*
BOOL WINAPI CryptCreateHash(
HCRYPTPROV hProv,			//CSP句柄
ALG_ID Algid,				//选择hash算法,比如CALG_MD5等
HCRYPTKEY hKey,				//HMAC 和MAC算法时有用
DWORD dwFlags,				//保留,传入0即可
HCRYPTHASH* phHash);		//返回hash句柄
*/
if(!CryptCreateHash(*hProv, algID, 0, 0, hHash))
{
CryptReleaseContext(*hProv, 0);
return FALSE;
}

return TRUE;
}

BOOL CHashTool::ComputeHashValue(HCRYPTPROV* hProv, HCRYPTHASH* hHash, BYTE* input, DWORD inputLength)
{
/*
BOOL WINAPI CryptHashData(
HCRYPTHASH hHash,			//hash对象
BYTE* pbData,				//被hash的数据
DWORD dwDataLen,			//数据的长度
DWORD dwFlags);				//微软的CSP这个值会被忽略
*/
if(!CryptHashData(*hHash, (BYTE*)input, inputLength, 0))
{
CryptDestroyHash(*hHash);
CryptReleaseContext(*hProv, 0);
return FALSE;
}

if(fileInfo.Percent >= 100)
{
DWORD dwSize;
DWORD dwLen = sizeof(dwSize);
CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE*)(&dwSize), &dwLen, 0);

BYTE* pHash = new BYTE[dwSize];
dwLen = dwSize;
CryptGetHashParam(*hHash, HP_HASHVAL, pHash, &dwLen, 0);

CString hash = "";
for(unsigned int i = 0 ; i < dwLen ; i++)
{
hash.Format("%02X", pHash[i]);
if(dwLen == 16)
fileInfo.MD5 += hash;
if(dwLen == 20)
fileInfo.SHA1 += hash;
}

ClearHash(hProv, hHash);
}
return TRUE;
}

void CHashTool::ClearHash(HCRYPTPROV* hProv, HCRYPTHASH* hHash)
{
if(*hHash)
CryptDestroyHash(*hHash);
if(*hProv)
CryptReleaseContext(*hProv, 0);
}

//
//ALG_ID: CALG_MD5, CALG_SHA1
//
BOOL CHashTool::ComputeHash(CString filePath)
{
HCRYPTPROV hProv_MD5 = 0; //CSP指针
HCRYPTHASH hHash_MD5 = 0;

HCRYPTPROV hProv_SHA1 = 0; //CSP指针
HCRYPTHASH hHash_SHA1 = 0;

if(!InitCreateHash(&hProv_MD5,&hHash_MD5, CALG_MD5))
{
CString errorInitMD5;
errorInitMD5.Format("Init MD5 error: %d" , GetLastError());
AfxMessageBox(errorInitMD5, MB_OK|MB_ICONWARNING);
return FALSE;
}

if(!InitCreateHash(&hProv_SHA1,&hHash_SHA1, CALG_SHA1))
{
CString errorInitSHA1;
errorInitSHA1.Format("Init SHA1 error: %d" , GetLastError());
AfxMessageBox(errorInitSHA1, MB_OK|MB_ICONWARNING);
return FALSE;
}

CFile file;
if(!file.Open(filePath, CFile::typeBinary|CFile::modeRead|CFile::shareDenyNone))
{
CString errorOpenFile;
errorOpenFile.Format("Open file error: %d" , GetLastError());
AfxMessageBox(errorOpenFile, MB_OK|MB_ICONWARNING);
return FALSE;
}

ULONG read = 0;
ULONGLONG position = 0;
ULONGLONG length = file.GetLength();
char buffer[BYTES_PER_READ] = {0};

do
{
if(bStopHash)
{
break;
}

read = file.Read(buffer, BYTES_PER_READ);
position += read;

if(length == 0)
{
fileInfo.Percent = 100;
}
else
{
fileInfo.Percent = (int)((double)position/length*100);
}

if(!ComputeHashValue(&hProv_MD5, &hHash_MD5, (BYTE*)buffer, read))
{
CString errorComputeMD5;
errorComputeMD5.Format("Compute MD5 error: %d" , GetLastError());
AfxMessageBox(errorComputeMD5, MB_OK|MB_ICONWARNING);
return FALSE;
}

if(!ComputeHashValue(&hProv_SHA1, &hHash_SHA1, (BYTE*)buffer, read))
{
CString errorComputeSHA1;
errorComputeSHA1.Format("Compute SHA1 error: %d" , GetLastError());
AfxMessageBox(errorComputeSHA1, MB_OK|MB_ICONWARNING);
return FALSE;
}

if(hWndMainDlg != NULL)
{
::SendMessage(hWndMainDlg, WM_Update_Progress_Step, (WPARAM)&fileInfo, NULL);
}
}while(position < length);

file.Close();

if(bStopHash)
return FALSE;
else
return TRUE;
}


3 停止计算

void CHashToolDlg::OnDestroy()
{
CHashTool::StopHash();

Sleep(3000);

CDialog::OnDestroy();
}


void CHashToolDlg::OnBnClickedStophashButton()
{
CHashTool::StopHash();
}
这个地方遇到个问题,关闭窗口后,需要等待所有线程正常退出才可以。搜了会解决方案,有人建议用WaitForMultipleObjects。但是感觉比较麻烦。暂时先Sleep 3s解决

如果完全转载,请注明出处,谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: