/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Microsoft Windows, Copyright (C) Microsoft Corporation, 2000 File: Utilities.cpp Content: Implementation of CUtilities. History: 11-15-99 dsie created ------------------------------------------------------------------------------*/ #include "stdafx.h" #include "CAPICOM.h" #include "Utilities.h" #include "Common.h" #include "Base64.h" #include "Convert.h" //////////////////////////////////////////////////////////////////////////////// // // CUtilities // /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : CUtilities::GetRandom Synopsis : Return a secure random number. Parameter: long Length - Number of bytes to generate. CAPICOM_ENCODING_TYPE EncodingType - Encoding type. BSTR * pVal - Pointer to BSTR to receive the random value. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::GetRandom (long Length, CAPICOM_ENCODING_TYPE EncodingType, BSTR * pVal) { HRESULT hr = S_OK; DWORD dwFlags = 0; DATA_BLOB RandomData = {0, NULL}; DebugTrace("Entering CUtilities::GetRandom().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Check parameter. // if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Do we have a cached provider? // if (!m_hCryptProv) { if (IsWin2KAndAbove()) { dwFlags = CRYPT_VERIFYCONTEXT; } // // Get a provider. // if (FAILED(hr = ::AcquireContext((LPSTR) NULL, (LPSTR) NULL, PROV_RSA_FULL, dwFlags, TRUE, &m_hCryptProv)) && FAILED(hr = ::AcquireContext(MS_ENHANCED_PROV_A, (LPSTR) NULL, PROV_RSA_FULL, dwFlags, TRUE, &m_hCryptProv)) && FAILED(hr = ::AcquireContext(MS_STRONG_PROV_A, (LPSTR) NULL, PROV_RSA_FULL, dwFlags, TRUE, &m_hCryptProv)) && FAILED(hr = ::AcquireContext(MS_DEF_PROV_A, (LPSTR) NULL, PROV_RSA_FULL, dwFlags, TRUE, &m_hCryptProv))) { DebugTrace("Error [%#x]: AcquireContext() failed.\n", hr); goto ErrorExit; } } // // Sanity check. // ATLASSERT(m_hCryptProv); // // Allocate memory. // RandomData.cbData = (DWORD) Length; if (!(RandomData.pbData = (PBYTE) ::CoTaskMemAlloc(RandomData.cbData))) { hr = E_OUTOFMEMORY; DebugTrace("Error [%#x]: CoTaskMemAlloc(RandomData.cbData) failed.\n", hr); goto ErrorExit; } // // Now generate the random value. // if (!::CryptGenRandom(m_hCryptProv, RandomData.cbData, RandomData.pbData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CryptGenRandom() failed.\n", hr); goto ErrorExit; } // // Export the random data. // if (FAILED(hr = ::ExportData(RandomData, EncodingType, pVal))) { DebugTrace("Error [%#x]: ExportData() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Free resources. // if (RandomData.pbData) { ::CoTaskMemFree(RandomData.pbData); } // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::GetRandom().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : Base64Encode Synopsis : Base64 encode the blob. Parameter: BSTR SrcString - Source string to be base64 encoded. BSTR * pVal - Pointer to BSTR to received base64 encoded string. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::Base64Encode (BSTR SrcString, BSTR * pVal) { HRESULT hr = S_OK; DATA_BLOB DataBlob = {0, NULL}; DebugTrace("Entering CUtilities::Base64Encode().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Check parameter. // if ((NULL == (DataBlob.pbData = (LPBYTE) SrcString)) || (0 == (DataBlob.cbData = ::SysStringByteLen(SrcString)))) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter SrcString is NULL or empty.\n", hr); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Now base64 encode. // if (FAILED(hr = ::Base64Encode(DataBlob, pVal))) { DebugTrace("Error [%#x]: Base64Encode() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::Base64Encode().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : Base64Decode Synopsis : Base64 decode the blob. Parameter: BSTR EncodedString - Base64 encoded string. BSTR * pVal - Pointer to BSTR to received base64 decoded string. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::Base64Decode (BSTR EncodedString, BSTR * pVal) { HRESULT hr = S_OK; DATA_BLOB DataBlob = {0, NULL}; DebugTrace("Entering CUtilities::Base64Decode().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Make sure parameters are valid. // if (0 == ::SysStringByteLen(EncodedString)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter EncodedString is NULL or empty.\n", hr); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Now base64 decode. // if (FAILED(hr = ::Base64Decode(EncodedString, &DataBlob))) { DebugTrace("Error [%#x]: Base64Decode() failed.\n", hr); goto ErrorExit; } // // Convert blob to BSTR. // if (FAILED(hr = ::BlobToBstr(&DataBlob, pVal))) { DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Free resources. // if (DataBlob.pbData) { ::CoTaskMemFree((LPVOID) DataBlob.pbData); } // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::Base64Decode().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : BinaryToHex Synopsis : Convert binary packed string to hex string. Parameter: BSTR BinaryString - Binary string to be converted. VARIANT * pVal - Pointer to BSTR to receive the converted string. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::BinaryToHex (BSTR BinaryString, BSTR * pVal) { HRESULT hr = S_OK; DWORD cbData = 0; DebugTrace("Entering CUtilities::BinaryToHex().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Make sure parameters are valid. // if (0 == (cbData = ::SysStringByteLen(BinaryString))) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter BinaryString is NULL or empty.\n", hr); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Convert to hex. // if (FAILED(hr = ::BinaryToHexString((LPBYTE) BinaryString, cbData, pVal))) { DebugTrace("Error [%#x]: BinaryToHexString() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::BinaryToHex().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : HexToBinary Synopsis : Convert hex string to binary packed string. Parameter: BSTR HexString - Hex string to be converted. VARIANT * pVal - Pointer to BSTR to receive the converted string. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::HexToBinary (BSTR HexString, BSTR * pVal) { HRESULT hr = S_OK; DebugTrace("Entering CUtilities::HexToBinary().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Make sure parameters are valid. // if (0 == ::SysStringByteLen(HexString)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter HexString is NULL or empty.\n", hr); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Convert to binary. // if (FAILED(hr = ::HexToBinaryString(HexString, pVal))) { DebugTrace("Error [%#x]: HexToBinaryString() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::HexToBinary().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : BinaryStringToByteArray Synopsis : Convert binary packed string to safearray of bytes. Parameter: BSTR BinaryString - Binary string to be converted. VARIANT * pVal - Pointer to VARIANT to receive the converted array. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::BinaryStringToByteArray (BSTR BinaryString, VARIANT * pVal) { HRESULT hr = S_OK; DWORD dwLength = 0; LPBYTE pbByte = NULL; LPBYTE pbElement = NULL; SAFEARRAY * psa = NULL; SAFEARRAYBOUND bound[1] = {0, 0}; DebugTrace("Entering CUtilities::BinaryStringToByteArray().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Make sure parameters are valid. // if (0 == (dwLength = ::SysStringByteLen(BinaryString))) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter BinaryString is NULL or empty.\n", hr); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Initialize. // ::VariantInit(pVal); pbByte = (LPBYTE) BinaryString; // // Create the array. // bound[0].cElements = dwLength; if (!(psa = ::SafeArrayCreate(VT_UI1, 1, bound))) { hr = E_OUTOFMEMORY; DebugTrace("Error [%#x]: SafeArrayCreate() failed.\n", hr); goto ErrorExit; } // // Now convert each byte in source binary BSTR to variant of byte. // #ifdef _DEBUG VARTYPE vt = VT_EMPTY; if (S_OK == ::SafeArrayGetVartype(psa, &vt)) { DebugTrace("Info: safearray vartype = %d.\n", vt); } #endif // // Point to array elements. // if (FAILED(hr = ::SafeArrayAccessData(psa, (void HUGEP **) &pbElement))) { DebugTrace("Error [%#x]: SafeArrayAccessData() failed.\n", hr); goto ErrorExit; } // // Fill the array. // while (dwLength--) { *pbElement++ = *pbByte++; } // // Unlock array. // if (FAILED(hr = ::SafeArrayUnaccessData(psa))) { DebugTrace("Error [%#x]: SafeArrayUnaccessData() failed.\n", hr); goto ErrorExit; } // // Return array to caller. // pVal->vt = VT_ARRAY | VT_UI1; pVal->parray = psa; } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::BinaryStringToByteArray().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); // // Free resources. // if (psa) { ::SafeArrayDestroy(psa); } ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : ByteArrayToBinaryString Synopsis : Convert safearray of bytes to binary packed string. Parameter: VARIANT varByteArray - VARIANT byte array. BSTR * pVal - Pointer to BSTR to receive the converted values. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::ByteArrayToBinaryString (VARIANT varByteArray, BSTR * pVal) { HRESULT hr = S_OK; VARIANT * pvarVal = NULL; SAFEARRAY * psa = NULL; LPBYTE pbElement = NULL; LPBYTE pbByte = NULL; long lLoBound = 0; long lUpBound = 0; BSTR bstrBinary = NULL; DebugTrace("Entering CUtilities::ByteArrayToBinaryString().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Skip over BYREF. // for (pvarVal = &varByteArray; pvarVal && ((VT_VARIANT | VT_BYREF) == V_VT(pvarVal)); pvarVal = V_VARIANTREF(pvarVal)); // // Make sure parameters are valid. // if (!pvarVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter varByteArray is NULL.\n", hr); goto ErrorExit; } if ((VT_ARRAY | VT_UI1) != V_VT(pvarVal)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter varByteArray is not a VT_UI1 array, V_VT(pvarVal) = %d\n", hr, V_VT(pvarVal)); goto ErrorExit; } if (NULL == pVal) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr); goto ErrorExit; } // // Point to the array. // psa = V_ARRAY(pvarVal); // // Check dimension. // if (1 != ::SafeArrayGetDim(psa)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: varByteArray is not 1 dimension, SafeArrayGetDim(psa) = %d.\n", hr, ::SafeArrayGetDim(psa)); goto ErrorExit; } // // Get array bound. // if (FAILED(hr = ::SafeArrayGetLBound(psa, 1, &lLoBound))) { DebugTrace("Error [%#x]: SafeArrayGetLBound() failed.\n", hr); goto ErrorExit; } if (FAILED(hr = ::SafeArrayGetUBound(psa, 1, &lUpBound))) { DebugTrace("Error [%#x]: SafeArrayGetUBound() failed.\n", hr); goto ErrorExit; } // // Point to array elements. // if (FAILED(hr = ::SafeArrayAccessData(psa, (void HUGEP **) &pbElement))) { DebugTrace("Error [%#x]: SafeArrayAccessData() failed.\n", hr); goto ErrorExit; } // // Allocate memory for the BSTR. // if (!(bstrBinary = ::SysAllocStringByteLen(NULL, lUpBound - lLoBound + 1))) { hr = E_OUTOFMEMORY; DebugTrace("Error [%#x]: SysAllocStringByteLen() failed.\n", hr); goto ErrorExit; } // // Fill the BSTR. // for (pbByte = (LPBYTE) bstrBinary; lLoBound <= lUpBound; lLoBound++) { *pbByte++ = *pbElement++; } // // Unlock array. // if (FAILED(hr = ::SafeArrayUnaccessData(psa))) { DebugTrace("Error [%#x]: SafeArrayUnaccessData() failed.\n", hr); goto ErrorExit; } // // Return converted string to caller. // *pVal = bstrBinary; } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::ByteArrayToBinaryString().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); // // Free resources. // if (bstrBinary) { ::SysFreeString(bstrBinary); } ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : LocalTimeToUTCTime Synopsis : Convert local time to UTC time. Parameter: DATE LocalTime - Local time to be converted. DATE * pVal - Pointer to DATE to receive the converted time. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::LocalTimeToUTCTime (DATE LocalTime, DATE * pVal) { HRESULT hr = S_OK; SYSTEMTIME stLocal; SYSTEMTIME stUTC; FILETIME ftLocal; FILETIME ftUTC; DebugTrace("Entering CUtilities::LocalTimeToUTCTime().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Convert to SYSTEMTIME format. // if (!::VariantTimeToSystemTime(LocalTime, &stLocal)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: VariantTimeToSystemTime() failed.\n", hr); goto ErrorExit; } // // Convert to FILETIME format. // if (!::SystemTimeToFileTime(&stLocal, &ftLocal)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: SystemTimeToFileTime() failed.\n", hr); goto ErrorExit; } // // Convert to UTC FILETIME. // if (!::LocalFileTimeToFileTime(&ftLocal, &ftUTC)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: LocalFileTimeToFileTime() failed.\n", hr); goto ErrorExit; } // // Convert to UTC SYSTEMTIME. // if (!::FileTimeToSystemTime(&ftUTC, &stUTC)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: FileTimeToSystemTime() failed.\n", hr); goto ErrorExit; } // // Finally convert it back to DATE format. // if (!::SystemTimeToVariantTime(&stUTC, pVal)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: SystemTimeToVariantTime() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::LocalTimeToUTCTime().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : UTCTimeToLocalTime Synopsis : Convert UTC time to local time. Parameter: DATE UTCTime - UTC time to be converted. DATE * pVal - Pointer to DATE to receive the converted time. Remark : ------------------------------------------------------------------------------*/ STDMETHODIMP CUtilities::UTCTimeToLocalTime (DATE UTCTime, DATE * pVal) { HRESULT hr = S_OK; SYSTEMTIME stLocal; SYSTEMTIME stUTC; FILETIME ftLocal; FILETIME ftUTC; DebugTrace("Entering CUtilities::UTCTimeToLocalTime().\n"); try { // // Lock access to this object. // m_Lock.Lock(); // // Convert to SYSTEMTIME format. // if (!::VariantTimeToSystemTime(UTCTime, &stUTC)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: VariantTimeToSystemTime() failed.\n", hr); goto ErrorExit; } // // Convert to FILETIME format. // if (!::SystemTimeToFileTime(&stUTC, &ftUTC)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: SystemTimeToFileTime() failed.\n", hr); goto ErrorExit; } // // Convert to local FILETIME. // if (!::FileTimeToLocalFileTime(&ftUTC, &ftLocal)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: FileTimeToLocalFileTime() failed.\n", hr); goto ErrorExit; } // // Convert to local SYSTEMTIME. // if (!::FileTimeToSystemTime(&ftLocal, &stLocal)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: FileTimeToSystemTime() failed.\n", hr); goto ErrorExit; } // // Finally convert it back to DATE format. // if (!::SystemTimeToVariantTime(&stLocal, pVal)) { hr = E_INVALIDARG; DebugTrace("Error [%#x]: SystemTimeToVariantTime() failed.\n", hr); goto ErrorExit; } } catch(...) { hr = E_POINTER; DebugTrace("Exception: invalid parameter.\n"); goto ErrorExit; } UnlockExit: // // Unlock access to this object. // m_Lock.Unlock(); DebugTrace("Leaving CUtilities::UTCTimeToLocalTime().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); ReportError(hr); goto UnlockExit; }