You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3902 lines
96 KiB
3902 lines
96 KiB
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
|
|
|
|
File: Certificate.cpp
|
|
|
|
Content: Implementation of CCertificate.
|
|
|
|
History: 11-15-99 dsie created
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "CAPICOM.h"
|
|
#include "Certificate.h"
|
|
#include "CertHlpr.h"
|
|
#include "Convert.h"
|
|
#include "Common.h"
|
|
#include "PFXHlpr.h"
|
|
#include "PrivateKey.h"
|
|
#include "Settings.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// typedefs.
|
|
//
|
|
|
|
typedef BOOL (WINAPI * PCRYPTUIDLGVIEWCERTIFICATEW)
|
|
(IN PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo,
|
|
OUT BOOL *pfPropertiesChanged);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Exported functions.
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CreateCertificateObject
|
|
|
|
Synopsis : Create an ICertificate object.
|
|
|
|
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
|
|
to initialize the ICertificate
|
|
object.
|
|
|
|
DWORD dwCurrentSafety - Current safety setting.
|
|
|
|
ICertificate2 ** ppICertificate - Pointer to pointer ICertificate
|
|
object.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT CreateCertificateObject (PCCERT_CONTEXT pCertContext,
|
|
DWORD dwCurrentSafety,
|
|
ICertificate2 ** ppICertificate)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComObject<CCertificate> * pCCertificate = NULL;
|
|
|
|
DebugTrace("Entering CreateCertificateObject().\n", hr);
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
ATLASSERT(ppICertificate);
|
|
|
|
try
|
|
{
|
|
//
|
|
// Create the object. Note that the ref count will still be 0
|
|
// after the object is created.
|
|
//
|
|
if (FAILED(hr = CComObject<CCertificate>::CreateInstance(&pCCertificate)))
|
|
{
|
|
DebugTrace("Error [%#x]: CComObject<CCertificate>::CreateInstance() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Initialize object.
|
|
//
|
|
if (FAILED(hr = pCCertificate->PutContext(pCertContext, dwCurrentSafety)))
|
|
{
|
|
DebugTrace("Error [%#x]: pCCertificate->PutContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return interface pointer to caller.
|
|
//
|
|
if (FAILED(hr = pCCertificate->QueryInterface(ppICertificate)))
|
|
{
|
|
DebugTrace("Error [%#x]: pCCertificate->QueryInterface() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving CreateCertificateObject().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
if (pCCertificate)
|
|
{
|
|
delete pCCertificate;
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetCertContext
|
|
|
|
Synopsis : Return the certificate's PCERT_CONTEXT.
|
|
|
|
Parameter: ICertificate * pICertificate - Pointer to ICertificate for which
|
|
the PCERT_CONTEXT is to be returned.
|
|
|
|
PCCERT_CONTEXT * ppCertContext - Pointer to PCERT_CONTEXT.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT GetCertContext (ICertificate * pICertificate,
|
|
PCCERT_CONTEXT * ppCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<ICertContext> pICertContext = NULL;
|
|
|
|
DebugTrace("Entering GetCertContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pICertificate);
|
|
ATLASSERT(ppCertContext);
|
|
|
|
//
|
|
// Get ICCertificate interface pointer.
|
|
//
|
|
if (FAILED(hr = pICertificate->QueryInterface(IID_ICertContext, (void **) &pICertContext)))
|
|
{
|
|
DebugTrace("Error [%#x]: pICertificate->QueryInterface() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Get the CERT_CONTEXT.
|
|
//
|
|
if (FAILED(hr = pICertContext->get_CertContext((long *) ppCertContext)))
|
|
{
|
|
DebugTrace("Error [%#x]: pICertContext->get_CertContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving GetCertContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Local functions.
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetCertNameInfo
|
|
|
|
Synopsis : Return the name for the subject or issuer field.
|
|
|
|
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
|
|
|
|
DWORD dwNameType - 0 for subject name or CERT_NAME_ISSUER_FLAG
|
|
for issuer name.
|
|
|
|
DWORD dwDisplayType - Display type.
|
|
|
|
BSTR * pbstrName - Pointer to BSTR to receive resulting name
|
|
string.
|
|
|
|
Remark : It is the caller's responsibility to free the BSTR.
|
|
No checking of any of the flags is done, so be sure to call
|
|
with the right flags.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static HRESULT GetCertNameInfo (PCCERT_CONTEXT pCertContext,
|
|
DWORD dwNameType,
|
|
DWORD dwDisplayType,
|
|
BSTR * pbstrName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbNameLen = 0;
|
|
LPWSTR pwszName = NULL;
|
|
DWORD dwStrType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
|
|
|
|
DebugTrace("Entering GetCertNameInfo().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
ATLASSERT(pbstrName);
|
|
|
|
//
|
|
// Get the length needed.
|
|
//
|
|
if (!(cbNameLen = ::CertGetNameStringW(pCertContext,
|
|
dwDisplayType,
|
|
dwNameType,
|
|
dwDisplayType == CERT_NAME_RDN_TYPE ? (LPVOID) &dwStrType : NULL,
|
|
NULL,
|
|
0)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
|
|
|
|
DebugTrace("Error [%#x]: CertGetNameStringW() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create returned BSTR.
|
|
//
|
|
if (!(pwszName = (LPWSTR) ::CoTaskMemAlloc(cbNameLen * sizeof(WCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now actually get the name string.
|
|
//
|
|
if (!::CertGetNameStringW(pCertContext,
|
|
dwDisplayType,
|
|
dwNameType,
|
|
dwDisplayType == CERT_NAME_RDN_TYPE ? (LPVOID) &dwStrType : NULL,
|
|
(LPWSTR) pwszName,
|
|
cbNameLen))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
|
|
|
|
DebugTrace("Error [%#x]: CertGetNameStringW() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return BSTR to caller.
|
|
//
|
|
if (!(*pbstrName = ::SysAllocString(pwszName)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
CommonExit:
|
|
//
|
|
// Free resource.
|
|
//
|
|
if (pwszName)
|
|
{
|
|
::CoTaskMemFree(pwszName);
|
|
}
|
|
|
|
DebugTrace("Leaving GetCertNameInfo().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CertToStore
|
|
|
|
Synopsis : Add the cert, optionally with the chain, to the store.
|
|
|
|
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
|
|
|
|
CAPICOM_CERTIFICATE_INCLUDE_OPTION IncludeOption - Include option.
|
|
|
|
HCERTSTORE hCertStore - Store to add to.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
static HRESULT CertToStore(PCCERT_CONTEXT pCertContext,
|
|
CAPICOM_CERTIFICATE_INCLUDE_OPTION IncludeOption,
|
|
HCERTSTORE hCertStore)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
|
|
|
|
DebugTrace("Entering CertToStore().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
ATLASSERT(hCertStore);
|
|
|
|
//
|
|
// No need to build chain if only including end cert.
|
|
//
|
|
if (CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY == IncludeOption)
|
|
{
|
|
//
|
|
// Add the only cert to store.
|
|
//
|
|
if (!::CertAddCertificateContextToStore(hCertStore,
|
|
pCertContext,
|
|
CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertAddCertificateContextToStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD i;
|
|
BOOL bAddRoot;
|
|
CERT_CHAIN_PARA ChainPara = {0};
|
|
|
|
//
|
|
// Initialize.
|
|
//
|
|
ChainPara.cbSize = sizeof(ChainPara);
|
|
|
|
switch (IncludeOption)
|
|
{
|
|
case CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN:
|
|
{
|
|
bAddRoot = TRUE;
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT:
|
|
//
|
|
// Fall thru to default.
|
|
//
|
|
default:
|
|
{
|
|
bAddRoot = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Build the chain.
|
|
//
|
|
if (!::CertGetCertificateChain(NULL,
|
|
pCertContext,
|
|
NULL,
|
|
NULL,
|
|
&ChainPara,
|
|
0,
|
|
NULL,
|
|
&pChainContext))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertGetCertificateChain() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pChainContext->cChain);
|
|
|
|
//
|
|
// Now add the chain to store and skip root cert if requested.
|
|
//
|
|
for (i = 0; i < pChainContext->rgpChain[0]->cElement; i++)
|
|
{
|
|
//
|
|
// Skip the root cert, if requested.
|
|
//
|
|
if (!bAddRoot &&
|
|
(pChainContext->rgpChain[0]->rgpElement[i]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Add to store.
|
|
//
|
|
if (!::CertAddCertificateContextToStore(hCertStore,
|
|
pChainContext->rgpChain[0]->rgpElement[i]->pCertContext,
|
|
CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertAddCertificateContextToStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
}
|
|
|
|
CommonExit:
|
|
//
|
|
// Free resource.
|
|
//
|
|
if (pChainContext)
|
|
{
|
|
::CertFreeCertificateChain(pChainContext);
|
|
}
|
|
|
|
DebugTrace("Leaving CertToStore().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCertificate
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_Version
|
|
|
|
Synopsis : Return the cert version number.
|
|
|
|
Parameter: long * pVersion - Pointer to long to receive version number.
|
|
|
|
Remark : The returned value is 1 for V1, 2 for V2, 3 for V3, and so on.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_Version (long * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::get_Version().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: Certificate object has not been initalized.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
*pVal = (long) m_pCertContext->pCertInfo->dwVersion + 1;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::get_Version().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_SerialNumber
|
|
|
|
Synopsis : Return the Serial Number field as HEX string in BSTR.
|
|
|
|
Parameter: BSTR * pVal - Pointer to BSTR to receive the serial number.
|
|
|
|
Remark : Upper case 'A' - 'F' is used for the returned HEX string with
|
|
no embeded space (i.e. 46A2FC01).
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_SerialNumber (BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::get_SerialNumber().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Convert integer blob to BSTR.
|
|
//
|
|
if (FAILED(hr = ::IntBlobToHexString(&m_pCertContext->pCertInfo->SerialNumber, pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: IntBlobToHexString() 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 CCertificate::get_SerialNumber().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_SubjectName
|
|
|
|
Synopsis : Return the Subject field.
|
|
|
|
Parameter: BSTR * pVal - Pointer to BSTR to receive the subject's name.
|
|
|
|
Remark : This method returns the full DN in the SubjectName field in the
|
|
form of "CN = Daniel Sie OU = Outlook O = Microsoft L = Redmond
|
|
S = WA C = US"
|
|
|
|
The returned name has the same format as specifying
|
|
CERT_NAME_RDN_TYPE for the CertGetNameString() API..
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_SubjectName (BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::get_SubjectName().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return requested name string.
|
|
//
|
|
if (FAILED(hr = ::GetCertNameInfo(m_pCertContext,
|
|
0,
|
|
CERT_NAME_RDN_TYPE,
|
|
pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: GetCertNameInfo() 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 CCertificate::get_SubjectName().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_IssuerName
|
|
|
|
Synopsis : Return the Issuer field.
|
|
|
|
Parameter: BSTR * pVal - Pointer to BSTR to receive the issuer's name.
|
|
|
|
Remark : This method returns the full DN in the IssuerName field in the
|
|
form of "CN = Daniel Sie OU = Outlook O = Microsoft L = Redmond
|
|
S = WA C = US"
|
|
|
|
The returned name has the same format as specifying
|
|
CERT_NAME_RDN_TYPE for the CertGetNameString() API.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_IssuerName (BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::get_IssuerName().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return requested name string.
|
|
//
|
|
if (FAILED(hr = ::GetCertNameInfo(m_pCertContext,
|
|
CERT_NAME_ISSUER_FLAG,
|
|
CERT_NAME_RDN_TYPE,
|
|
pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: GetCertNameInfo() 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 CCertificate::get_IssuerName().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_ValidFromDate
|
|
|
|
Synopsis : Return the NotBefore field.
|
|
|
|
Parameter: DATE * pDate - Pointer to DATE to receive the valid from date.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_ValidFromDate (DATE * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FILETIME ftLocal;
|
|
SYSTEMTIME stLocal;
|
|
|
|
DebugTrace("Entering CCertificate::get_ValidFromDate().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Convert to local time.
|
|
//
|
|
if (!(::FileTimeToLocalFileTime(&m_pCertContext->pCertInfo->NotBefore, &ftLocal) &&
|
|
::FileTimeToSystemTime(&ftLocal, &stLocal) &&
|
|
::SystemTimeToVariantTime(&stLocal, pVal)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: unable to convert FILETIME to DATE.\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 CCertificate::get_ValidFromDate().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_ValidToDate
|
|
|
|
Synopsis : Return the NotAfter field.
|
|
|
|
Parameter: DATE * pDate - Pointer to DATE to receive valid to date.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_ValidToDate (DATE * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FILETIME ftLocal;
|
|
SYSTEMTIME stLocal;
|
|
|
|
DebugTrace("Entering CCertificate::get_ValidToDate().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Convert to local time.
|
|
//
|
|
if (!(::FileTimeToLocalFileTime(&m_pCertContext->pCertInfo->NotAfter, &ftLocal) &&
|
|
::FileTimeToSystemTime(&ftLocal, &stLocal) &&
|
|
::SystemTimeToVariantTime(&stLocal, pVal)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: unable to convert FILETIME to DATE.\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 CCertificate::get_ValidToDate().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_Thumbprint
|
|
|
|
Synopsis : Return the SHA1 hash as HEX string.
|
|
|
|
Parameter: BSTR * pVal - Pointer to BSTR to receive hash.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_Thumbprint (BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE * pbHash = NULL;
|
|
DWORD cbHash = 0;
|
|
|
|
DebugTrace("Entering CCertificate::get_Thumbprint().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Calculate length needed.
|
|
//
|
|
if (!::CertGetCertificateContextProperty(m_pCertContext,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
NULL,
|
|
&cbHash))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory.
|
|
//
|
|
if (!(pbHash = (BYTE *) ::CoTaskMemAlloc(cbHash)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now get the hash.
|
|
//
|
|
if (!::CertGetCertificateContextProperty(m_pCertContext,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
(LPVOID) pbHash,
|
|
&cbHash))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Conver to HEX BSTR.
|
|
//
|
|
if (FAILED(hr = ::BinaryToHexString(pbHash, cbHash, pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: BinaryToHexString() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Free resource.
|
|
//
|
|
if (pbHash)
|
|
{
|
|
::CoTaskMemFree((LPVOID) pbHash);
|
|
}
|
|
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::get_Thumbprint().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::HasPrivateKey
|
|
|
|
Synopsis : Check to see if the cert has the associated private key.
|
|
|
|
Parameter: VARIANT_BOOL * pVal - Pointer to BOOL to receive result.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::HasPrivateKey (VARIANT_BOOL * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cb = 0;
|
|
|
|
DebugTrace("Entering CCertificate::HasPrivateKey().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return result.
|
|
//
|
|
*pVal = ::CertGetCertificateContextProperty(m_pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
NULL,
|
|
&cb) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::HasPrivateKey().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::GetInfo
|
|
|
|
Synopsis : Get other simple info from the certificate.
|
|
|
|
|
|
Parameter: CAPICOM_CERT_INFO_TYPE InfoType - Info type
|
|
|
|
BSTR * pVal - Pointer to BSTR to receive the result.
|
|
|
|
Remark : Note that an empty string "" is returned if the requested info is
|
|
not available in the certificate.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::GetInfo (CAPICOM_CERT_INFO_TYPE InfoType,
|
|
BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwDisplayType = 0;
|
|
|
|
DebugTrace("Entering CCertificate::GetInfo().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Process request.
|
|
//
|
|
switch (InfoType)
|
|
{
|
|
case CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME:
|
|
{
|
|
dwFlags = CERT_NAME_ISSUER_FLAG;
|
|
|
|
//
|
|
// Warning: dropping thru.
|
|
//
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME:
|
|
{
|
|
//
|
|
// Get requested simple name string.
|
|
//
|
|
dwDisplayType = CERT_NAME_SIMPLE_DISPLAY_TYPE;
|
|
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_ISSUER_EMAIL_NAME:
|
|
{
|
|
dwFlags = CERT_NAME_ISSUER_FLAG;
|
|
|
|
//
|
|
// Warning: dropping thru.
|
|
//
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_SUBJECT_EMAIL_NAME:
|
|
{
|
|
//
|
|
// Get requested email name string.
|
|
//
|
|
dwDisplayType = CERT_NAME_EMAIL_TYPE;
|
|
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_ISSUER_UPN:
|
|
{
|
|
dwFlags = CERT_NAME_ISSUER_FLAG;
|
|
|
|
//
|
|
// Warning: dropping thru.
|
|
//
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_SUBJECT_UPN:
|
|
{
|
|
//
|
|
// Get requested UPN name string.
|
|
//
|
|
dwDisplayType = CERT_NAME_UPN_TYPE;
|
|
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_ISSUER_DNS_NAME:
|
|
{
|
|
dwFlags = CERT_NAME_ISSUER_FLAG;
|
|
|
|
//
|
|
// Warning: dropping thru.
|
|
//
|
|
}
|
|
|
|
case CAPICOM_CERT_INFO_SUBJECT_DNS_NAME:
|
|
{
|
|
//
|
|
// Get requested DNS name string.
|
|
//
|
|
dwDisplayType = CERT_NAME_DNS_TYPE;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Unknown cert info type (%#x).\n", hr, InfoType);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr = ::GetCertNameInfo(m_pCertContext,
|
|
dwFlags,
|
|
dwDisplayType,
|
|
pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: GetCertNameInfo() failed for display type = %d.\n", hr, dwDisplayType);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::GetInfo().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::IsValid
|
|
|
|
Synopsis : Return an ICertificateStatus object for certificate validity check.
|
|
|
|
Parameter: ICertificateStatus ** pVal - Pointer to pointer to
|
|
ICertificateStatus object to receive
|
|
the interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::IsValid (ICertificateStatus ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::IsValid().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded ICertificateStatus object, if not already done so.
|
|
//
|
|
if (!m_pICertificateStatus)
|
|
{
|
|
if (FAILED(hr = ::CreateCertificateStatusObject(m_pCertContext, &m_pICertificateStatus)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateCertificateStatusObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pICertificateStatus);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pICertificateStatus->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pICertificateStatus->QueryInterface() 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 CCertificate::IsValid().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::KeyUsage
|
|
|
|
Synopsis : Return the Key Usage extension as an IKeyUsage object.
|
|
|
|
Parameter: IKeyUsage ** pVal - Pointer to pointer to IKeyUsage to receive the
|
|
interface pointer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::KeyUsage (IKeyUsage ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::KeyUsage().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded IKeyUsage object, if not already done so.
|
|
//
|
|
if (!m_pIKeyUsage)
|
|
{
|
|
if (FAILED(hr = ::CreateKeyUsageObject(m_pCertContext, &m_pIKeyUsage)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateKeyUsageObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pIKeyUsage);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pIKeyUsage->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pIKeyUsage->QueryInterface() 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 CCertificate::KeyUsage().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::ExtendedKeyUsage
|
|
|
|
Synopsis : Return the EKU extension as an IExtendedKeyUsage object.
|
|
|
|
Parameter: IExtendedKeyUsage ** pVal - Pointer to pointer to IExtendedKeyUsage
|
|
to receive the interface pointer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::ExtendedKeyUsage (IExtendedKeyUsage ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::ExtendedKeyUsage().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded IExtendedKeyUsage object, if not already done so.
|
|
//
|
|
if (!m_pIExtendedKeyUsage)
|
|
{
|
|
if (FAILED(hr = ::CreateExtendedKeyUsageObject(m_pCertContext, &m_pIExtendedKeyUsage)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateExtendedKeyUsageObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pIExtendedKeyUsage);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pIExtendedKeyUsage->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pIExtendedKeyUsage->QueryInterface() 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 CCertificate::ExtendedKeyUsage().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::BasicConstraints
|
|
|
|
Synopsis : Return the BasicConstraints extension as an IBasicConstraints
|
|
object.
|
|
|
|
Parameter: IBasicConstraints ** pVal - Pointer to pointer to IBasicConstraints
|
|
to receive the interface pointer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::BasicConstraints (IBasicConstraints ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::BasicConstraints().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded IBasicConstraints object, if not already done so.
|
|
//
|
|
if (!m_pIBasicConstraints)
|
|
{
|
|
if (FAILED(hr = ::CreateBasicConstraintsObject(m_pCertContext, &m_pIBasicConstraints)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateBasicConstraintsObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pIBasicConstraints);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pIBasicConstraints->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pIBasicConstraints->QueryInterface() 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 CCertificate::BasicConstraints().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Export
|
|
|
|
Synopsis : Export the certificate.
|
|
|
|
Parameter: CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
|
|
|
|
BSTR * pVal - Pointer to BSTR to receive the certificate blob.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Export (CAPICOM_ENCODING_TYPE EncodingType,
|
|
BSTR * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DATA_BLOB CertBlob = {0, NULL};
|
|
|
|
DebugTrace("Entering CCertificate::Export().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Determine encoding type.
|
|
//
|
|
CertBlob.cbData = m_pCertContext->cbCertEncoded;
|
|
CertBlob.pbData = m_pCertContext->pbCertEncoded;
|
|
|
|
//
|
|
// Export certificate.
|
|
//
|
|
if (FAILED(hr = ::ExportData(CertBlob, EncodingType, pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: ExportData() 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 CCertificate::Export().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Import
|
|
|
|
Synopsis : Imoprt a certificate.
|
|
|
|
Parameter: BSTR EncodedCertificate - BSTR containing the encoded certificate
|
|
blob.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Import (BSTR EncodedCertificate)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DATA_BLOB CertBlob = {0, NULL};
|
|
|
|
DebugTrace("Entering CCertificate::Import().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Make sure parameter is valid.
|
|
//
|
|
if ((NULL == (CertBlob.pbData = (LPBYTE) EncodedCertificate)) ||
|
|
(0 == (CertBlob.cbData = ::SysStringByteLen(EncodedCertificate))))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: EncodedCertificate = %#x, SysStringByteLen(EncodedCertificate) = %d.\n",
|
|
hr, EncodedCertificate, EncodedCertificate);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now import the blob.
|
|
//
|
|
if (FAILED(hr = ImportBlob(&CertBlob,
|
|
FALSE,
|
|
(CAPICOM_KEY_LOCATION) 0,
|
|
NULL,
|
|
(CAPICOM_KEY_STORAGE_FLAG) 0)))
|
|
{
|
|
DebugTrace("Error [%#x]: CCertificate::ImportBlob() 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("Entering CCertificate::Import().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Display
|
|
|
|
Synopsis : Display the certificate using CryptUIDlgViewCertificateW() API.
|
|
|
|
Parameter: None
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Display()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HINSTANCE hDLL = NULL;
|
|
|
|
PCRYPTUIDLGVIEWCERTIFICATEW pCryptUIDlgViewCertificateW = NULL;
|
|
CRYPTUI_VIEWCERTIFICATE_STRUCTW ViewInfo;
|
|
|
|
DebugTrace("Entering CCertificate::Display().\n");
|
|
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Get pointer to CryptUIDlgViewCertificateW().
|
|
//
|
|
if (hDLL = ::LoadLibrary("CryptUI.dll"))
|
|
{
|
|
pCryptUIDlgViewCertificateW = (PCRYPTUIDLGVIEWCERTIFICATEW) ::GetProcAddress(hDLL, "CryptUIDlgViewCertificateW");
|
|
}
|
|
|
|
//
|
|
// Is CryptUIDlgViewCertificateW() available?
|
|
//
|
|
if (!pCryptUIDlgViewCertificateW)
|
|
{
|
|
hr = CAPICOM_E_NOT_SUPPORTED;
|
|
|
|
DebugTrace("Error: CryptUIDlgViewCertificateW() API not available.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Initialize view structure.
|
|
//
|
|
::ZeroMemory((void *) &ViewInfo, sizeof(ViewInfo));
|
|
ViewInfo.dwSize = sizeof(ViewInfo);
|
|
ViewInfo.pCertContext = m_pCertContext;
|
|
|
|
//
|
|
// View it.
|
|
//
|
|
if (!pCryptUIDlgViewCertificateW(&ViewInfo, 0))
|
|
{
|
|
//
|
|
// CryptUIDlgViewCertificateW() returns ERROR_CANCELLED if user closed
|
|
// the window through the x button!!!
|
|
//
|
|
DWORD dwWinError = ::GetLastError();
|
|
if (ERROR_CANCELLED != dwWinError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwWinError);
|
|
|
|
DebugTrace("Error [%#x]: CryptUIDlgViewCertificateW() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Release resources.
|
|
//
|
|
if (hDLL)
|
|
{
|
|
::FreeLibrary(hDLL);
|
|
}
|
|
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::Display().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Certificate2
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_Archived
|
|
|
|
Synopsis : Return the archived status.
|
|
|
|
Parameter: VARIANT_BOOL * pVal - Pointer to BOOL to receive result.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_Archived (VARIANT_BOOL * pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cb = 0;
|
|
|
|
DebugTrace("Entering CCertificate::get_Archived().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return result.
|
|
//
|
|
*pVal = ::CertGetCertificateContextProperty(m_pCertContext,
|
|
CERT_ARCHIVED_PROP_ID,
|
|
NULL,
|
|
&cb) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::get_Archived().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::put_Archived
|
|
|
|
Synopsis : Set the archived status.
|
|
|
|
Parameter: VARIANT_BOOL newVal - Pointer to BOOL to receive result.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::put_Archived (VARIANT_BOOL newVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPVOID pvData = NULL;
|
|
DATA_BLOB DataBlob = {0, NULL};
|
|
|
|
DebugTrace("Entering CCertificate::put_Archived().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Not allowed if called from WEB script.
|
|
//
|
|
if (m_dwCurrentSafety)
|
|
{
|
|
hr = CAPICOM_E_NOT_ALLOWED;
|
|
|
|
DebugTrace("Error [%#x]: Changing archived bit from within WEB script is not allowed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Set/Reset archive property.
|
|
//
|
|
if (newVal)
|
|
{
|
|
pvData = (LPVOID) &DataBlob;
|
|
}
|
|
|
|
if (!::CertSetCertificateContextProperty(m_pCertContext,
|
|
CERT_ARCHIVED_PROP_ID,
|
|
0,
|
|
pvData))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
|
|
DebugTrace("Error [%#x]: CertSetCertificateContextProperty() 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 CCertificate::put_Archived().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Template
|
|
|
|
Synopsis : Return the ITemplate object.
|
|
|
|
Parameter: ITemplate ** pVal - Pointer to pointer to ITemplate
|
|
to receive the interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Template (ITemplate ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::Template().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded ITemplate object, if not already done so.
|
|
//
|
|
if (!m_pITemplate)
|
|
{
|
|
if (FAILED(hr = ::CreateTemplateObject(m_pCertContext, &m_pITemplate)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateTemplateObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pITemplate);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pITemplate->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pITemplate->QueryInterface() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ATLASSERT(*pVal);
|
|
|
|
DebugTrace("Info: ITemplate vtable value = %#x\n", (PVOID) *pVal);
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::Template().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::PublicKey
|
|
|
|
Synopsis : Return the IPublicKey object.
|
|
|
|
Parameter: IPublicKey ** pVal - Pointer to pointer to IPublicKey
|
|
to receive the interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::PublicKey (IPublicKey ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::PublicKey().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded IPublicKey object, if not already done so.
|
|
//
|
|
if (!m_pIPublicKey)
|
|
{
|
|
if (FAILED(hr = ::CreatePublicKeyObject(m_pCertContext, &m_pIPublicKey)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreatePublicKeybject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pIPublicKey);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pIPublicKey->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pIPublicKey->QueryInterface() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ATLASSERT(*pVal);
|
|
|
|
DebugTrace("Info: IPublicKey vtable value = %#x\n", (PVOID) *pVal);
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::PublicKey().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_PrivateKey
|
|
|
|
Synopsis : Return the IPrivateKey object.
|
|
|
|
Parameter: IPrivateKey ** pVal - Pointer to pointer to IPrivateKey
|
|
to receive the interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_PrivateKey (IPrivateKey ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IPrivateKey> pIPrivateKey = NULL;
|
|
|
|
DebugTrace("Entering CCertificate::get_PrivateKey().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the object on the fly (read-only if called from WEB script).
|
|
//
|
|
if (FAILED(hr = ::CreatePrivateKeyObject(m_pCertContext, m_dwCurrentSafety ? TRUE : FALSE, &pIPrivateKey)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreatePrivateKeybject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = pIPrivateKey->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: pIPrivateKey->QueryInterface() 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 CCertificate::get_PrivateKey().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::put_PrivateKey
|
|
|
|
Synopsis : Set the IPrivateKey object.
|
|
|
|
Parameter: IPrivateKey * newVal - Pointer to IPrivateKey.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::put_PrivateKey (IPrivateKey * newVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
|
|
|
|
DebugTrace("Entering CCertificate::put_PrivateKey().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Not allowed if called from WEB script.
|
|
//
|
|
if (m_dwCurrentSafety)
|
|
{
|
|
hr = CAPICOM_E_NOT_ALLOWED;
|
|
|
|
DebugTrace("Error [%#x]: Changing PrivateKey from within WEB script is not allowed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == newVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter newVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// NULL to disassociate.
|
|
//
|
|
if (newVal)
|
|
{
|
|
//
|
|
// Get copy of key prov info.
|
|
//
|
|
if (FAILED(hr = ::GetKeyProvInfo(newVal, &pKeyProvInfo)))
|
|
{
|
|
DebugTrace("Error [%#x]: GetKeyProvInfo() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure public keys match.
|
|
//
|
|
if (FAILED(hr = ::CompareCertAndContainerPublicKey(m_pCertContext,
|
|
pKeyProvInfo->pwszContainerName,
|
|
pKeyProvInfo->pwszProvName,
|
|
pKeyProvInfo->dwProvType,
|
|
pKeyProvInfo->dwKeySpec,
|
|
pKeyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET)))
|
|
{
|
|
DebugTrace("Error [%#x]: CompareCertAndContainerPublicKey() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the association.
|
|
//
|
|
if (!::CertSetCertificateContextProperty(m_pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
0,
|
|
pKeyProvInfo))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertSetCertificateContextProperty() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pKeyProvInfo)
|
|
{
|
|
::CoTaskMemFree(pKeyProvInfo);
|
|
}
|
|
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::put_PrivateKey().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Extensions
|
|
|
|
Synopsis : Return the IExtensions collection object.
|
|
|
|
Parameter: IExtensions ** pVal - Pointer to pointer to IExtensions
|
|
to receive the interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Extensions (IExtensions ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::Extensions().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the embeded IExtensions object, if not already done so.
|
|
//
|
|
if (!m_pIExtensions)
|
|
{
|
|
if (FAILED(hr = ::CreateExtensionsObject(m_pCertContext, &m_pIExtensions)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateExtensionsObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(m_pIExtensions);
|
|
|
|
//
|
|
// Return interface pointer to user.
|
|
//
|
|
if (FAILED(hr = m_pIExtensions->QueryInterface(pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: m_pIExtensions->QueryInterface() 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 CCertificate::Extensions().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::ExtendedProperties
|
|
|
|
Synopsis : Return the IExtendedProperties collection object.
|
|
|
|
Parameter: IExtendedProperties ** pVal - Pointer to pointer to
|
|
IExtendedProperties to receive the
|
|
interface pointer.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::ExtendedProperties (IExtendedProperties ** pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::ExtendedProperties().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Create the dynamic IExtendedProperties object.
|
|
//
|
|
if (FAILED(hr = ::CreateExtendedPropertiesObject(m_pCertContext,
|
|
m_dwCurrentSafety ? TRUE : FALSE,
|
|
pVal)))
|
|
{
|
|
DebugTrace("Error [%#x]: CreateExtendedPropertiesObject() 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 CCertificate::ExtendedProperties().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Load
|
|
|
|
Synopsis : Method to load certificate(s) from a file.
|
|
|
|
Parameter: BSTR FileName - File name.
|
|
|
|
BSTR Password - Password (required for PFX file.)
|
|
|
|
CAPICOM_KEY_STORAGE_FLAG KeyStorageFlag - Key storage flag.
|
|
|
|
CAPICOM_KEY_LOCATION KeyLocation - Key location.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Load (BSTR FileName,
|
|
BSTR Password,
|
|
CAPICOM_KEY_STORAGE_FLAG KeyStorageFlag,
|
|
CAPICOM_KEY_LOCATION KeyLocation)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DATA_BLOB CertBlob = {0, NULL};
|
|
|
|
DebugTrace("Entering CCertificate::Load().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Not allowed if called from WEB script.
|
|
//
|
|
if (m_dwCurrentSafety)
|
|
{
|
|
hr = CAPICOM_E_NOT_ALLOWED;
|
|
|
|
DebugTrace("Error [%#x]: Loading cert file from WEB script is not allowed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (0 == ::SysStringLen(FileName))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter FileName is NULL or empty.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Work around MIDL problem.
|
|
//
|
|
if (0 == ::SysStringLen(Password))
|
|
{
|
|
Password = NULL;
|
|
}
|
|
|
|
//
|
|
// Read entire file in.
|
|
//
|
|
if (FAILED(hr = ::ReadFileContent((LPWSTR) FileName, &CertBlob)))
|
|
{
|
|
DebugTrace("Error [%#x]: ReadFileContent() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now import the blob.
|
|
//
|
|
if (FAILED(hr = ImportBlob(&CertBlob, TRUE, KeyLocation, Password, KeyStorageFlag)))
|
|
{
|
|
DebugTrace("Error [%#x]: CCertificate::ImportBlob() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Free resource.
|
|
//
|
|
if (CertBlob.pbData)
|
|
{
|
|
::UnmapViewOfFile(CertBlob.pbData);
|
|
}
|
|
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::Load().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::Save
|
|
|
|
Synopsis : Method to save certificate(s) to a file.
|
|
|
|
Parameter: BSTR FileName - File name.
|
|
|
|
BSTR Password - Password (required for PFX file.)
|
|
|
|
CAPICOM_CERTIFICATE_SAVE_AS_TYPE FileType - SaveAs type.
|
|
|
|
CAPICOM_CERTIFICATE_INCLUDE_OPTION IncludeOption - Include option.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::Save (BSTR FileName,
|
|
BSTR Password,
|
|
CAPICOM_CERTIFICATE_SAVE_AS_TYPE SaveAs,
|
|
CAPICOM_CERTIFICATE_INCLUDE_OPTION IncludeOption)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCERTSTORE hCertStore = NULL;
|
|
|
|
DebugTrace("Entering CCertificate::Save().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Not allowed if called from WEB script.
|
|
//
|
|
if (m_dwCurrentSafety)
|
|
{
|
|
hr = CAPICOM_E_NOT_ALLOWED;
|
|
|
|
DebugTrace("Error [%#x]: Saving cert file from WEB script is not allowed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Check parameters.
|
|
//
|
|
if (0 == ::SysStringLen(FileName))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error [%#x]: Parameter FileName is NULL or empty.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Work around MIDL problem.
|
|
//
|
|
if (0 == ::SysStringLen(Password))
|
|
{
|
|
Password = NULL;
|
|
}
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Check file type.
|
|
//
|
|
switch (SaveAs)
|
|
{
|
|
case CAPICOM_CERTIFICATE_SAVE_AS_CER:
|
|
{
|
|
DATA_BLOB DataBlob;
|
|
|
|
//
|
|
// Simply write the encoded cert blob to file.
|
|
//
|
|
DataBlob.cbData = m_pCertContext->cbCertEncoded;
|
|
DataBlob.pbData = m_pCertContext->pbCertEncoded;
|
|
|
|
if (FAILED(hr = ::WriteFileContent(FileName, DataBlob)))
|
|
{
|
|
DebugTrace("Error [%#x]: WriteFileContent() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case CAPICOM_CERTIFICATE_SAVE_AS_PFX:
|
|
{
|
|
//
|
|
// Create a memory store.
|
|
//
|
|
if (!(hCertStore = ::CertOpenStore(CERT_STORE_PROV_MEMORY,
|
|
CAPICOM_ASN_ENCODING,
|
|
0,
|
|
0,
|
|
NULL)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertOpenStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Add all requested certs to the store.
|
|
//
|
|
if (FAILED(hr = ::CertToStore(m_pCertContext, IncludeOption, hCertStore)))
|
|
{
|
|
DebugTrace("Error [%#x]: CertToStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Save as PFX file.
|
|
//
|
|
if (FAILED(hr = ::PFXSaveStore(hCertStore,
|
|
FileName,
|
|
Password,
|
|
EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)))
|
|
{
|
|
DebugTrace("Error [%#x]: PFXSaveStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
DebugTrace("Error: invalid parameter, unknown save as type.\n");
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
hr = E_POINTER;
|
|
|
|
DebugTrace("Exception: invalid parameter.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
UnlockExit:
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (hCertStore)
|
|
{
|
|
::CertCloseStore(hCertStore, 0);
|
|
}
|
|
|
|
//
|
|
// Unlock access to this object.
|
|
//
|
|
m_Lock.Unlock();
|
|
|
|
DebugTrace("Leaving CCertificate::Save().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Custom interfaces.
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::get_CertContext
|
|
|
|
Synopsis : Return the certificate's PCCERT_CONTEXT.
|
|
|
|
Parameter: long * ppCertContext - Pointer to PCCERT_CONTEXT disguished in a
|
|
long.
|
|
|
|
Remark : We need to use long instead of PCCERT_CONTEXT because VB can't
|
|
handle double indirection (i.e. vb would bark on this
|
|
PCCERT_CONTEXT * ppCertContext).
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::get_CertContext (long * ppCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::get_CertContext().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Return cert context to caller.
|
|
//
|
|
if (FAILED(hr = GetContext((PCCERT_CONTEXT *) ppCertContext)))
|
|
{
|
|
DebugTrace("Error [%#x]: CCertificate::GetContext() 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 CCertificate::get_CertContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::put_CertContext
|
|
|
|
Synopsis : Initialize the object with a CERT_CONTEXT.
|
|
|
|
Parameter: long pCertContext - Poiner to CERT_CONTEXT, disguised in a long,
|
|
used to initialize this object.
|
|
|
|
Remark : Note that this is NOT 64-bit compatiable. Plese see remark of
|
|
get_CertContext for more detail.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::put_CertContext (long pCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::put_CertContext().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Reset the object with this context.
|
|
//
|
|
if (FAILED(hr = PutContext((PCCERT_CONTEXT) pCertContext, m_dwCurrentSafety)))
|
|
{
|
|
DebugTrace("Error [%#x]: CCertificate::PutContext() 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 CCertificate::put_CertContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::FreeContext
|
|
|
|
Synopsis : Free a CERT_CONTEXT.
|
|
|
|
Parameter: long pCertContext - Poiner to CERT_CONTEXT, disguised in a long,
|
|
to be freed.
|
|
|
|
Remark : Note that this is NOT 64-bit compatiable. Plese see remark of
|
|
get_CertContext for more detail.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::FreeContext (long pCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::FreeContext().\n");
|
|
|
|
try
|
|
{
|
|
//
|
|
// Lock access to this object.
|
|
//
|
|
m_Lock.Lock();
|
|
|
|
//
|
|
// Free the context.
|
|
//
|
|
if (!::CertFreeCertificateContext((PCCERT_CONTEXT) pCertContext))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertFreeCertificateContext() 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 CCertificate::FreeContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
ReportError(hr);
|
|
|
|
goto UnlockExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Private methods.
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::ImportBlob
|
|
|
|
Synopsis : Private function to load a certificate from blob.
|
|
|
|
Parameter: DATA_BLOB * pCertBlob
|
|
|
|
BOOL bAllowPfx
|
|
|
|
CAPICOM_KEY_LOCATION KeyLocation - Key location.
|
|
|
|
BSTR pwszPassword - Password (required for PFX file.)
|
|
|
|
CAPICOM_KEY_STORAGE_FLAG KeyStorageFlag - Key storage flag.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::ImportBlob (DATA_BLOB * pCertBlob,
|
|
BOOL bAllowPfx,
|
|
CAPICOM_KEY_LOCATION KeyLocation,
|
|
BSTR pwszPassword,
|
|
CAPICOM_KEY_STORAGE_FLAG KeyStorageFlag)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCERTSTORE hCertStore = NULL;
|
|
PCCERT_CONTEXT pEnumContext = NULL;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
DWORD dwContentType = 0;
|
|
DWORD cb = 0;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwExpectedType = CERT_QUERY_CONTENT_FLAG_CERT |
|
|
CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT;
|
|
|
|
DebugTrace("Entering CCertificate::ImportBlob().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertBlob);
|
|
|
|
//
|
|
// Set PFX flag, if allowed.
|
|
//
|
|
if (bAllowPfx)
|
|
{
|
|
dwExpectedType |= CERT_QUERY_CONTENT_FLAG_PFX;
|
|
}
|
|
|
|
//
|
|
// Crack the blob.
|
|
//
|
|
if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
|
|
(LPCVOID) pCertBlob,
|
|
dwExpectedType,
|
|
CERT_QUERY_FORMAT_FLAG_ALL,
|
|
0,
|
|
NULL,
|
|
&dwContentType,
|
|
NULL,
|
|
&hCertStore,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptQueryObject() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
DebugTrace("Info: CryptQueryObject() returns dwContentType = %#x.\n", dwContentType);
|
|
|
|
//
|
|
// Need to import it ourselves for PFX file.
|
|
//
|
|
if (CERT_QUERY_CONTENT_PFX == dwContentType)
|
|
{
|
|
//
|
|
// Make sure PFX is allowed.
|
|
//
|
|
if (!bAllowPfx)
|
|
{
|
|
hr = CAPICOM_E_NOT_SUPPORTED;
|
|
|
|
DebugTrace("Error [%#x]: Importing PFX where not supported.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Setup import flags.
|
|
//
|
|
if (CAPICOM_LOCAL_MACHINE_KEY == KeyLocation)
|
|
{
|
|
dwFlags |= CRYPT_MACHINE_KEYSET;
|
|
}
|
|
else if (IsWin2KAndAbove())
|
|
{
|
|
dwFlags |= CRYPT_USER_KEYSET;
|
|
}
|
|
|
|
if (KeyStorageFlag & CAPICOM_KEY_STORAGE_EXPORTABLE)
|
|
{
|
|
dwFlags |= CRYPT_EXPORTABLE;
|
|
}
|
|
|
|
if (KeyStorageFlag & CAPICOM_KEY_STORAGE_USER_PROTECTED)
|
|
{
|
|
dwFlags |= CRYPT_USER_PROTECTED;
|
|
}
|
|
|
|
DebugTrace("Info: dwFlags = %#x.", dwFlags);
|
|
|
|
//
|
|
// Now import the blob to store.
|
|
//
|
|
if (!(hCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB *) pCertBlob,
|
|
pwszPassword,
|
|
dwFlags)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: PFXImportCertStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(hCertStore);
|
|
|
|
//
|
|
// Find the first cert with private key, if none, then simply take
|
|
// the very first cert.
|
|
//
|
|
while (pEnumContext = ::CertEnumCertificatesInStore(hCertStore, pEnumContext))
|
|
{
|
|
//
|
|
// Does this cert has a private key?
|
|
//
|
|
if (::CertGetCertificateContextProperty(pEnumContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
NULL,
|
|
&cb))
|
|
{
|
|
//
|
|
// Yes, so free the one without private key, had we found one previously.
|
|
//
|
|
if (pCertContext)
|
|
{
|
|
if (!::CertFreeCertificateContext(pCertContext))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertFreeCertificateContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
if (!(pCertContext = ::CertDuplicateCertificateContext(pEnumContext)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Set last error before we break out of loop.
|
|
//
|
|
::SetLastError((DWORD) CRYPT_E_NOT_FOUND);
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Keep the first one.
|
|
//
|
|
if (!pCertContext)
|
|
{
|
|
if (!(pCertContext = ::CertDuplicateCertificateContext(pEnumContext)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Above loop can exit either because there is no more certificate in
|
|
// the store or an error. Need to check last error to be certain.
|
|
//
|
|
if (CRYPT_E_NOT_FOUND != ::GetLastError())
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertEnumCertificatesInStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// It is a CER file, so it must have only 1 cert.
|
|
//
|
|
if (!(pCertContext = ::CertEnumCertificatesInStore(hCertStore, NULL)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertEnumCertificatesInStore() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
|
|
//
|
|
// Now initialize the object with the found cert.
|
|
//
|
|
if (FAILED(hr = PutContext(pCertContext, m_dwCurrentSafety)))
|
|
{
|
|
DebugTrace("Error [%#x]: CCertificate::PutContext() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
CommonExit:
|
|
//
|
|
// Free resource.
|
|
//
|
|
if (pCertContext)
|
|
{
|
|
::CertFreeCertificateContext(pCertContext);
|
|
}
|
|
|
|
if (pEnumContext)
|
|
{
|
|
::CertFreeCertificateContext(pEnumContext);
|
|
}
|
|
|
|
if (hCertStore)
|
|
{
|
|
::CertCloseStore(hCertStore, 0);
|
|
}
|
|
|
|
DebugTrace("Leaving CCertificate::ImportBlob().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::GetContext
|
|
|
|
Synopsis : Return the certificate's PCCERT_CONTEXT.
|
|
|
|
Parameter: PCCERT_CONTEXT * ppCertContext - Pointer to PCCERT_CONTEXT.
|
|
|
|
Remark : This method is designed for internal use only, and therefore,
|
|
should not be exposed to user.
|
|
|
|
Note that this is a custom interface, not a dispinterface.
|
|
|
|
Note that the cert context ref count is incremented by
|
|
CertDuplicateCertificateContext(), so it is the caller's
|
|
responsibility to free the context.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::GetContext (PCCERT_CONTEXT * ppCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DebugTrace("Entering CCertificate::GetContext().\n");
|
|
|
|
//
|
|
// Make sure cert is already initialized.
|
|
//
|
|
if (!m_pCertContext)
|
|
{
|
|
hr = CAPICOM_E_CERTIFICATE_NOT_INITIALIZED;
|
|
|
|
DebugTrace("Error [%#x]: object does not represent an initialized certificate.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(ppCertContext);
|
|
|
|
//
|
|
// Duplicate the cert context.
|
|
//
|
|
if (!(*ppCertContext = ::CertDuplicateCertificateContext(m_pCertContext)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving CCertificate::GetContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : CCertificate::PutContext
|
|
|
|
Synopsis : Initialize the object with a CERT_CONTEXT.
|
|
|
|
Parameter: PCERT_CONTEXT pCertContext - Poiner to CERT_CONTEXT used to
|
|
initialize this object.
|
|
|
|
DWORD dwCurrentSafety - Current safety setting.
|
|
|
|
Remark : This method is not part of the COM interface (it is a normal C++
|
|
member function). We need it to initialize the object created
|
|
internally by us.
|
|
|
|
Since it is only a normal C++ member function, this function can
|
|
only be called from a C++ class pointer, not an interface pointer.
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
STDMETHODIMP CCertificate::PutContext (PCCERT_CONTEXT pCertContext,
|
|
DWORD dwCurrentSafety)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCCERT_CONTEXT pCertContext2 = NULL;
|
|
|
|
DebugTrace("Entering CCertificate::PutContext().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(pCertContext);
|
|
|
|
//
|
|
// Duplicate the cert context.
|
|
//
|
|
if (!(pCertContext2 = ::CertDuplicateCertificateContext(pCertContext)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertDupliacteCertificateContext() failed.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Free previous context, if any.
|
|
//
|
|
if (m_pCertContext)
|
|
{
|
|
if (!::CertFreeCertificateContext(m_pCertContext))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertFreeCertificateContext() failed.\n");
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reset.
|
|
//
|
|
m_pCertContext = pCertContext2;
|
|
m_pIKeyUsage.Release();
|
|
m_pIExtendedKeyUsage.Release();
|
|
m_pIBasicConstraints.Release();
|
|
m_pICertificateStatus.Release();
|
|
m_pITemplate.Release();
|
|
m_pIPublicKey.Release();
|
|
m_pIExtensions.Release();
|
|
m_dwCurrentSafety = dwCurrentSafety;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving CCertificate::PutContext().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pCertContext2)
|
|
{
|
|
::CertFreeCertificateContext(pCertContext2);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|