Windows平台下使用C++和Windows API计算文件MD5的方法

#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <string>
#include <cassert>
#include <functional>

typedef std::basic_string<TCHAR> StringT;
typedef std::string StringA;

#define _PP_CAT_IMPL_(a, b ) a ## b
#define PP_CAT(a, b) _PP_CAT_IMPL_( a, b )

namespace Details
{
    template <typename TCallable>
    class ScopedExit
    {
    public:
        ScopedExit(TCallable func) :
            Func(func)
        {
        }

        ~ScopedExit()
        {
            Func();
        }

        ScopedExit(const ScopedExit&) = delete;
        const ScopedExit& operator=(const ScopedExit&) = delete;

    private:
        TCallable Func;
    };
}

#define SCOPED_EXIT(expression) \
	::Details::ScopedExit<std::function<void()> > PP_CAT(ScopedExitInstalce_, __COUNTER__)([&]()\
{ \
	expression;\
})


StringA CalculateFileMD5(const StringT& filepath)
{
#define BUFSIZE 1024
#define MD5LEN  16

    DWORD dwStatus = 0;
    BOOL bResult = FALSE;
    HCRYPTPROV hProv = 0;
    HCRYPTHASH hHash = 0;
    HANDLE hFile = NULL;
    BYTE rgbFile[BUFSIZE];
    DWORD cbRead = 0;
    BYTE rgbHash[MD5LEN];
    DWORD cbHash = 0;
    CHAR rgbDigits[] = "0123456789abcdef";
    // Logic to check usage goes here.

    hFile = CreateFile(filepath.c_str(),
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);

    if (INVALID_HANDLE_VALUE == hFile)
    {
        return "";
    }

    SCOPED_EXIT(CloseHandle(hFile));

    // Get handle to the crypto provider
    if (!CryptAcquireContext(&hProv,
        NULL,
        NULL,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT))
    {
        return "";
    }

    SCOPED_EXIT(CryptReleaseContext(hProv, 0));

    if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
    {
        return "";
    }

    SCOPED_EXIT(CryptDestroyHash(hHash));

    while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL))
    {
        if (0 == cbRead)
        {
            break;
        }

        if (!CryptHashData(hHash, rgbFile, cbRead, 0))
        {
            return "";
        }
    }

    if (!bResult)
    {
        return "";
    }

    cbHash = MD5LEN;
    if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
    {
        StringA result;
        result.reserve(40);

        for (DWORD i = 0; i < cbHash; i++)
        {
            result.push_back(rgbDigits[rgbHash[i] >> 4]);
            result.push_back(rgbDigits[rgbHash[i] & 0xf]);
        }

        return result;
    }

    return "";
}

int main()
{
    auto md5 = CalculateFileMD5(_T("E:\\aow-install-apk-100.xml"));
    std::cout << md5 << std::endl;

    return 0;
}

  测试:

 

posted @ 2024-05-30 11:41  bodong  阅读(39)  评论(0编辑  收藏  举报