16 октября 2007

Hash calculation

Как правильно заметил Not a kernel guy, лишний раз бросаться исключениями не стоит. Если знаешь как обработать ошибку - обработай ее сразу. Не знаешь - брось исключение, "на верху" разберутся.

В качестве примера - код получения хэша. В фокусе - вызов CryptGetHashParam:
#include <windows.h>
#include <Loki/ScopeGuard.h>
#include <boost/range/size.hpp>
#include <boost/static_assert.hpp>
#include "TestWinFn.h"

template <class TOutputContainer, typename TInputContainer>
void Hash(ALG_ID Algorithm, const TInputContainer& Input, TOutputContainer& Output)
{
BOOST_STATIC_ASSERT(sizeof(typename TOutputContainer::value_type) == sizeof(BYTE));

HCRYPTPROV hProv = 0;
TestWinFn(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
LOKI_ON_BLOCK_EXIT(CryptReleaseContext, hProv, 0);

HCRYPTHASH hHash = 0;
TestWinFn(CryptCreateHash(hProv, Algorithm, 0, 0, &hHash));
LOKI_ON_BLOCK_EXIT(CryptDestroyHash, hHash);

TestWinFn(CryptHashData(hHash, reinterpret_cast<const BYTE*>(&Input[0]),
static_cast<DWORD>(boost::size(Input) * sizeof(Input[0])), 0));

DWORD HashSize = 0;
DWORD Error = CryptGetHashParam(hHash, HP_HASHVAL, NULL, &HashSize, 0) ? 0 : ::GetLastError();
if ((Error == ERROR_MORE_DATA) || (!Error && HashSize))
{
Output.resize(HashSize);
TestWinFn(CryptGetHashParam(hHash, HP_HASHVAL, &Output[0], &HashSize, 0));
}
else
throw WindowsError(Error);
}

1 комментарий:

alexandroid комментирует...

Заметь, тут ты неявно предполагаешь, что GetLastError (или другая функция, которая используется вместо нее) не может бросать ничего. Хотя, наверное, в таких API это довольно безопасное предположение. Иначе надо было бы разбить вызов и сделать CryptCreateHash - LOKI_ON_BLOCK_EXIT - TestWinFn...