static void schannel_checksum(const unsigned char *input,
                              size_t inputlen,
                              unsigned char *checksum,
                              size_t checksumlen,
                              DWORD provType,
                              const unsigned int algId)
{
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  DWORD cbHashSize = 0;
  DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
  DWORD dwChecksumLen = (DWORD)checksumlen;

  /* since this can fail in multiple ways, zero memory first so we never
   * return old data
   */
  memset(checksum, 0, checksumlen);

  if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
    return; /* failed */

  do {
    if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
      break; /* failed */

    /* workaround for original MinGW, should be (const BYTE*) */
    if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
      break; /* failed */

    /* get hash size */
    if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
                          &dwHashSizeLen, 0))
      break; /* failed */

    /* check hash size */
    if(checksumlen < cbHashSize)
      break; /* failed */

    if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
      break; /* failed */
  } while(0);

  if(hHash)
    CryptDestroyHash(hHash);

  if(hProv)
    CryptReleaseContext(hProv, 0);
}
static void schannel_checksum(const unsigned char *input,
                              size_t inputlen,
                              unsigned char *checksum,
                              size_t checksumlen,
                              DWORD provType,
                              const unsigned int algId)
{
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  DWORD cbHashSize = 0;
  DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
  DWORD dwChecksumLen = (DWORD)checksumlen;

   
  memset(checksum, 0, checksumlen);

  if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
    return;  

  do {
    if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
      break;  

     
    if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
      break;  

     
    if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
                          &dwHashSizeLen, 0))
      break;  

     
    if(checksumlen < cbHashSize)
      break;  

    if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
      break;  
  } while(0);

  if(hHash)
    CryptDestroyHash(hHash);

  if(hProv)
    CryptReleaseContext(hProv, 0);
}