Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2660 lines
72 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: scrdenr.cpp
//
//--------------------------------------------------------------------------
// SCrdEnr.cpp : Implementation of CSCrdEnr
#define SECURITY_WIN32 //Or in the sources file -DSECURITY_WIN32
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#include <unicode.h>
#include <oleauto.h>
#include <objbase.h>
#include <cryptui.h>
#include "certca.h"
#include "certsrv.h"
#include "security.h"
#include <dbgdef.h>
#include "scrdenrl.h"
#include "SCrdEnr.h"
#include "enrlhelp.h"
#include "xEnroll.h"
#include "wzrdpvk.h"
/////////////////////////////////////////////////////////////////////////////
// CSCrdEnr
CSCrdEnr::CSCrdEnr(void)
{
DWORD dwIndex=0;
DSOP_SCOPE_INIT_INFO ScopeInit;
DSOP_INIT_INFO InitInfo;
m_dwCTCount=0;
m_dwCTIndex=0;
m_rgCTInfo=NULL;
m_pwszUserUPN=NULL;
m_pwszUserSAM=NULL;
m_pEnrolledCert=NULL;
m_dwCSPCount=0;
m_dwCSPIndex=0;
m_rgCSPInfo=NULL;
m_lEnrollmentStatus = CR_DISP_INCOMPLETE;
m_pSigningCert=NULL;
m_fSCardSigningCert=FALSE;
m_pszCSPNameSigningCert=NULL;
m_dwCSPTypeSigningCert=0;
m_pszContainerSigningCert=NULL;
m_pDsObjectPicker=NULL;
m_pCachedCTEs = NULL; //no need to free
m_pwszCachedCTEOid = NULL;
m_pCachedCTE = NULL;
// track whether our critsec is initialized
m_fInitializedCriticalSection = FALSE;
if(!FAILED(CoInitialize(NULL)))
m_fInitialize=TRUE;
// Initialize functions who's loading we've deferred.
InitializeThunks();
__try
{
InitializeCriticalSection(&m_cSection);
m_fInitializedCriticalSection = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
//we now need to get the CSP list
InitlializeCSPList(&m_dwCSPCount, &m_rgCSPInfo);
//we now need to initialize the CA and its cert types
InitializeCTList(&m_dwCTIndex, &m_dwCTCount, &m_rgCTInfo);
//init for the user selection dialogue
memset(&ScopeInit, 0, sizeof(DSOP_SCOPE_INIT_INFO));
memset(&InitInfo, 0, sizeof(InitInfo));
ScopeInit.cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
ScopeInit.flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN|DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
ScopeInit.flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; //this will give us the SAM name for the user
ScopeInit.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
ScopeInit.FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
InitInfo.cbSize = sizeof(InitInfo);
InitInfo.pwzTargetComputer = NULL; // NULL == local machine
InitInfo.cDsScopeInfos = 1;
InitInfo.aDsScopeInfos = &ScopeInit;
InitInfo.flOptions = 0; //we are doing single select
//create the COM object
if (S_OK == CoCreateInstance
(CLSID_DsObjectPicker,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDsObjectPicker,
(void **) &m_pDsObjectPicker))
{
if(S_OK != (m_pDsObjectPicker->Initialize(&InitInfo)))
{
m_pDsObjectPicker->Release();
m_pDsObjectPicker=NULL;
}
}
else
m_pDsObjectPicker=NULL;
}
CSCrdEnr::~CSCrdEnr(void)
{
if(m_pDsObjectPicker)
m_pDsObjectPicker->Release();
if(m_rgCTInfo)
FreeCTInfo(m_dwCTCount, m_rgCTInfo);
if(m_rgCSPInfo)
FreeCSPInfo(m_dwCSPCount, m_rgCSPInfo);
if(m_pwszUserUPN)
SCrdEnrollFree(m_pwszUserUPN);
if(m_pwszUserSAM)
SCrdEnrollFree(m_pwszUserSAM);
if(m_pSigningCert)
CertFreeCertificateContext(m_pSigningCert);
if(m_pszCSPNameSigningCert)
SCrdEnrollFree(m_pszCSPNameSigningCert);
if(m_pszContainerSigningCert)
SCrdEnrollFree(m_pszContainerSigningCert);
if(m_pEnrolledCert)
CertFreeCertificateContext(m_pEnrolledCert);
if (NULL != m_pwszCachedCTEOid)
{
LocalFree(m_pwszCachedCTEOid);
}
if (NULL != m_pCachedCTE)
{
LocalFree(m_pCachedCTE);
}
if(m_fInitialize)
CoUninitialize();
if (m_fInitializedCriticalSection)
DeleteCriticalSection(&m_cSection);
}
STDMETHODIMP CSCrdEnr::get_CSPCount(long * pVal)
{
if(NULL==pVal)
return E_INVALIDARG;
EnterCriticalSection(&m_cSection);
*pVal = (long)m_dwCSPCount;
LeaveCriticalSection(&m_cSection);
return S_OK;
}
STDMETHODIMP CSCrdEnr::get_CSPName(BSTR * pVal)
{
HRESULT hr = S_OK;
EnterCriticalSection(&m_cSection);
if(NULL==m_rgCSPInfo || 0==m_dwCSPCount)
{
*pVal=NULL;
hr=E_INVALIDARG;
}
else
{
if( NULL == (*pVal = SysAllocString(m_rgCSPInfo[m_dwCSPIndex].pwszCSPName)))
hr = E_OUTOFMEMORY;
}
LeaveCriticalSection(&m_cSection);
return(hr);
}
STDMETHODIMP CSCrdEnr::put_CSPName(BSTR newVal)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwIndex=0;
EnterCriticalSection(&m_cSection);
if(NULL == m_rgCSPInfo || 0 == m_dwCSPCount || NULL == newVal)
goto InvalidArgErr;
for(dwIndex=0; dwIndex < m_dwCSPCount; dwIndex++)
{
if(0 == _wcsicmp(newVal, m_rgCSPInfo[dwIndex].pwszCSPName))
{
m_dwCSPIndex=dwIndex;
break;
}
}
if(dwIndex == m_dwCSPCount)
goto InvalidArgErr;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
STDMETHODIMP CSCrdEnr::selectUserName
(/* [in] */ DWORD dwFlags)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
LPWSTR pwszSelectedUserSAM=NULL;
LPWSTR pwszSelectedUserUPN=NULL;
EnterCriticalSection(&m_cSection);
if(NULL == m_pDsObjectPicker)
goto InvalidArgErr;
if(S_OK != (hr = GetSelectedUserName(m_pDsObjectPicker,
&pwszSelectedUserSAM,
&pwszSelectedUserUPN)))
goto SelectUserErr;
//we should at least have the UserSAM name
if(NULL == pwszSelectedUserSAM)
{
if(pwszSelectedUserUPN)
SCrdEnrollFree(pwszSelectedUserUPN);
goto UnexpectedErr;
}
if(m_pwszUserSAM)
{
SCrdEnrollFree(m_pwszUserSAM);
m_pwszUserSAM=NULL;
}
if(m_pwszUserUPN)
{
SCrdEnrollFree(m_pwszUserUPN);
m_pwszUserUPN=NULL;
}
m_pwszUserSAM=pwszSelectedUserSAM;
m_pwszUserUPN=pwszSelectedUserUPN;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR_VAR(SelectUserErr, hr);
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(UnexpectedErr, E_UNEXPECTED);
}
STDMETHODIMP CSCrdEnr::enroll
(/* [in] */ DWORD dwFlags)
{
HRESULT hr = E_FAIL;
DWORD errBefore = GetLastError();
ULONG cbSize = 0;
SCrdEnroll_CA_INFO *pCAInfo = NULL;
SCrdEnroll_CT_INFO *pCertTypeInfo = NULL;
BSTR bstrAttribs = NULL;
BSTR bstrCA = NULL;
BSTR bstrCertificate = NULL;
BSTR bstrReq = NULL;
LPWSTR pwszRequesterName = NULL;
ICertRequest2 *pICertRequest = NULL;
IEnroll4 *pIEnroll = NULL;
CRYPT_DATA_BLOB PKCS10Blob;
CRYPT_DATA_BLOB PKCS7Request;
CRYPT_DATA_BLOB PKCS7Response;
DWORD dwDisposition;
DWORD dwRequestID;
LPWSTR pwszNewContainerName=NULL;
PCCERT_CONTEXT pArchivalCert = NULL;
LONG lKeySpec = XEKL_KEYSPEC_KEYX;
LONG lKeyMin, lKeyMax;
DWORD dwKeyMin, dwKeyMax, dwKeySize;
//------------------------------------------------------------
//
// Define locally scoped utility functions:
//
//------------------------------------------------------------
LocalScope(EnrollUtilities):
BSTR bstrConcat(LPWSTR pwsz1, LPWSTR pwsz2, LPWSTR pwsz3, LPWSTR pwsz4)
{
// Note: assumes valid input parameters!
BSTR bstrResult = NULL;
LPWSTR pwszResult = NULL;
pwszResult = (LPWSTR)SCrdEnrollAlloc(sizeof(WCHAR) * (wcslen(pwsz1) + wcslen(pwsz2) + wcslen(pwsz3) + wcslen(pwsz4) + 1));
if (pwszResult == NULL) { return NULL; }
else {
wcscpy(pwszResult, pwsz1);
wcscat(pwszResult, pwsz2);
wcscat(pwszResult, pwsz3);
wcscat(pwszResult, pwsz4);
// Convert the result to a BSTR
bstrResult = SysAllocString(pwszResult);
// Free the temporary storage.
SCrdEnrollFree(pwszResult);
// Return the result.
return bstrResult;
}
}
DWORD ICEnrollDispositionToCryptuiStatus(IN DWORD dwDisposition)
{
switch (dwDisposition)
{
case CR_DISP_INCOMPLETE: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED;
case CR_DISP_DENIED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED;
case CR_DISP_ISSUED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_CERT_ISSUED;
case CR_DISP_ISSUED_OUT_OF_BAND: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY;
case CR_DISP_UNDER_SUBMISSION: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION;
case CR_DISP_ERROR: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
default:
// Should never happen
return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
}
}
EndLocalScope;
//------------------------------------------------------------
//
// Begin procedure body
//
//------------------------------------------------------------
memset(&PKCS10Blob, 0, sizeof(CRYPT_DATA_BLOB));
memset(&PKCS7Request, 0, sizeof(CRYPT_DATA_BLOB));
memset(&PKCS7Response, 0, sizeof(CRYPT_DATA_BLOB));
EnterCriticalSection(&m_cSection);
//check for the status of the smart cards in the reader.
//return the fully qualified container name for the new user
//smart card
if(S_OK != (hr = ChkSCardStatus(m_fSCardSigningCert,
m_pSigningCert,
m_pszCSPNameSigningCert,
m_dwCSPTypeSigningCert,
m_pszContainerSigningCert,
m_rgCSPInfo[m_dwCSPIndex].pwszCSPName,
&pwszNewContainerName)))
goto StatusErr;
//delete the old certificate
if(m_pEnrolledCert)
{
CertFreeCertificateContext(m_pEnrolledCert);
m_pEnrolledCert=NULL;
}
//init enrollment status
m_lEnrollmentStatus = CR_DISP_INCOMPLETE;
//make sure that we have the correct information for processing
//the enrollment request
if(0 == m_dwCTCount || NULL == m_rgCTInfo || 0 == m_dwCSPCount ||
NULL == m_rgCSPInfo || NULL == m_pSigningCert ||
((NULL == m_pwszUserSAM) && (NULL == m_pwszUserUPN)))
goto InvalidArgErr;
//make sure that we have some CA
pCertTypeInfo=&(m_rgCTInfo[m_dwCTIndex]);
if(NULL == pCertTypeInfo->rgCAInfo || 0 == pCertTypeInfo->dwCACount)
goto InvalidArgErr;
pCAInfo=&(pCertTypeInfo->rgCAInfo[pCertTypeInfo->dwCAIndex]);
if(NULL == (pIEnroll=MyPIEnroll4GetNoCOM()))
goto TraceErr;
//we use our own My store to store the enrolled certificate
if(S_OK != (hr = pIEnroll->put_MyStoreNameWStr((LPWSTR)g_MyStoreName)))
goto xEnrollErr;
//we always use a new key
if(S_OK != (hr=pIEnroll->put_UseExistingKeySet(FALSE)))
goto xEnrollErr;
//we the key container name
if(S_OK != (hr=pIEnroll->put_ContainerNameWStr(pwszNewContainerName)))
goto xEnrollErr;
//set the CSP information
if(S_OK != (hr=pIEnroll->put_ProviderType(m_rgCSPInfo[m_dwCSPIndex].dwCSPType)))
goto xEnrollErr;
if(S_OK !=(hr=pIEnroll->put_ProviderNameWStr(m_rgCSPInfo[m_dwCSPIndex].pwszCSPName)))
goto xEnrollErr;
//dwKeySpec
if(S_OK !=(hr=pIEnroll->put_KeySpec(pCertTypeInfo->dwKeySpec)))
goto xEnrollErr;
//private key flags. Left half-word is the key size.
//If the key size is 0, then specify a default key size.
if (0 == (pCertTypeInfo->dwGenKeyFlags & 0xFFFF0000))
{
// If min key size is not set, use 1024 bits.
pCertTypeInfo->dwGenKeyFlags |= (1024 << 16);
}
dwKeySize = (pCertTypeInfo->dwGenKeyFlags & 0xFFFF0000) >> 16;
if (0x0 != dwKeySize)
{
//make sure key size is in the range
//let's get CSP key size information
if (AT_SIGNATURE == pCertTypeInfo->dwKeySpec)
{
lKeySpec = XEKL_KEYSPEC_SIG;
}
hr = pIEnroll->GetKeyLenEx(XEKL_KEYSIZE_MIN, lKeySpec, &lKeyMin);
// don't have error check because the CSP may not support it
if (S_OK == hr)
{
hr = pIEnroll->GetKeyLenEx(XEKL_KEYSIZE_MAX, lKeySpec, &lKeyMax);
if (S_OK != hr)
{
goto xEnrollErr;
}
dwKeyMin = (DWORD)lKeyMin;
dwKeyMax = (DWORD)lKeyMax;
if (dwKeySize < dwKeyMin)
{
//reset the current key size
pCertTypeInfo->dwGenKeyFlags &= 0x0000FFFF;
//set adjusted size
pCertTypeInfo->dwGenKeyFlags |= ((dwKeyMin & 0x0000FFFF) << 16);
}
if (dwKeySize > dwKeyMax)
{
//reset the current key size
pCertTypeInfo->dwGenKeyFlags &= 0x0000FFFF;
//set adjusted size
pCertTypeInfo->dwGenKeyFlags |= ((dwKeyMax & 0x0000FFFF) << 16);
}
}
}
if (S_OK !=(hr=pIEnroll->put_GenKeyFlags(pCertTypeInfo->dwGenKeyFlags)))
goto xEnrollErr;
// S/MIME supported?
if (S_OK !=(hr=pIEnroll->put_EnableSMIMECapabilities
(pCertTypeInfo->dwEnrollmentFlags & CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS)))
goto xEnrollErr;
// Set archival cert, if one has been specified.
// bstrCA <-- CA_location\CA_Name
//
bstrCA = local.bstrConcat
(pCAInfo->pwszCALocation,
L"\\",
pCAInfo->pwszCADisplayName ? pCAInfo->pwszCADisplayName : pCAInfo->pwszCAName,
L"\0");
if (NULL == bstrCA)
goto MemoryErr;
if (pCertTypeInfo->dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL)
{
if (S_OK != (hr = this->GetCAExchangeCertificate(bstrCA, &pArchivalCert)))
goto xEnrollErr;
if (S_OK != (hr = pIEnroll->SetPrivateKeyArchiveCertificate(pArchivalCert)))
goto xEnrollErr;
}
//cert Type extensions
if(pCertTypeInfo->pCertTypeExtensions)
{
if(S_OK != (hr=pIEnroll->AddExtensionsToRequest
(pCertTypeInfo->pCertTypeExtensions)))
goto xEnrollErr;
}
//no smart card stuff
if(S_OK != (hr=pIEnroll->put_ReuseHardwareKeyIfUnableToGenNew(FALSE)))
goto xEnrollErr;
//create a PKCS10 request
if(FAILED(hr=pIEnroll->createPKCS10WStr(NULL,
NULL,
&PKCS10Blob)))
goto xEnrollErr;
//add the name value pair of the enroll-on-behalf
pwszRequesterName=MkWStr(wszPROPREQUESTERNAME);
if(NULL==pwszRequesterName)
goto MemoryErr;
if(S_OK != (hr=pIEnroll->AddNameValuePairToSignatureWStr(
pwszRequesterName, m_pwszUserSAM)))
goto xEnrollErr;
//sign the request
if(S_OK != (hr=pIEnroll->CreatePKCS7RequestFromRequest(
&PKCS10Blob,
m_pSigningCert,
&PKCS7Request)))
goto xEnrollErr;
//send the request to the CA
//we set the purpose to the renew so that the format
//will be a PKCS7
bstrReq = SysAllocStringByteLen((LPCSTR)PKCS7Request.pbData, PKCS7Request.cbData);
if (NULL == bstrReq)
goto MemoryErr;
bstrAttribs = NULL;
// RECALL: bstrCA <-- CA_location\CA_Name
if (pICertRequest == NULL)
{
if (S_OK != (hr = CoCreateInstance
(CLSID_CCertRequest,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICertRequest2,
(void**)&pICertRequest)))
goto xEnrollErr;
}
if (S_OK != (hr = pICertRequest->Submit
(CR_IN_BINARY | CR_IN_PKCS7,
bstrReq,
bstrAttribs,
bstrCA,
(long *)&dwDisposition)))
goto xEnrollErr;
//use CR_DISP_ as enrollment status
m_lEnrollmentStatus = dwDisposition;
// check pending and save pending info
// however, smart card enrollment station don't know how to deal with
// this pending requests, may not necessary to do that
if (CR_DISP_UNDER_SUBMISSION == m_lEnrollmentStatus)
{
hr = pICertRequest->GetRequestId((long *)&dwRequestID);
if (S_OK != hr)
{
goto xEnrollErr;
}
hr = pIEnroll->setPendingRequestInfoWStr(
dwRequestID,
pCAInfo->pwszCALocation,
NULL != pCAInfo->pwszCADisplayName ?
pCAInfo->pwszCADisplayName : pCAInfo->pwszCAName,
NULL);
}
if (CR_DISP_ISSUED != m_lEnrollmentStatus)
{
//if not issued, return
goto CommonReturn;
}
//must be CR_DISP_ISSUED
hr = pICertRequest->GetCertificate(
CR_OUT_BINARY | CR_OUT_CHAIN, &bstrCertificate);
if (S_OK != hr)
{
goto xEnrollErr;
}
// Marshal the cert into a CRYPT_DATA_BLOB, and install it:
PKCS7Response.pbData = (LPBYTE)bstrCertificate;
PKCS7Response.cbData = SysStringByteLen(bstrCertificate);
m_pEnrolledCert = pIEnroll->getCertContextFromPKCS7(&PKCS7Response);
if (NULL == m_pEnrolledCert)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto TraceErr;
}
hr=pIEnroll->acceptPKCS7Blob(&PKCS7Response);
//we delete the enrolled certificate from the "My" store since it is added by
//xEnroll. No need to check the error
SearchAndDeleteCert(m_pEnrolledCert);
if(S_OK != hr)
{
goto TraceErr;
}
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwszNewContainerName)
LocalFree((HLOCAL)pwszNewContainerName);
if(pwszRequesterName)
FreeWStr(pwszRequesterName);
//the memory from xEnroll is freed via LocalFree
//since we use the PIEnrollGetNoCOM function
if(PKCS10Blob.pbData)
LocalFree(PKCS10Blob.pbData);
if(PKCS7Request.pbData)
LocalFree(PKCS7Request.pbData);
if (NULL != pArchivalCert)
CertFreeCertificateContext(pArchivalCert);
// PKCS7Respone's data is just an alias to m_pEnrolledCert's data: we don't need to free it.
if (NULL != bstrAttribs) { SysFreeString(bstrAttribs); }
if (NULL != bstrCA) { SysFreeString(bstrCA); }
if (NULL != bstrCertificate) { SysFreeString(bstrCertificate); }
if (NULL != pICertRequest) { pICertRequest->Release(); }
if(pIEnroll)
pIEnroll->Release();
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
//if an error has occurred, the free the enrolled certificate
if(m_pEnrolledCert)
{
CertFreeCertificateContext(m_pEnrolledCert);
m_pEnrolledCert=NULL;
}
goto CommonReturn;
TRACE_ERROR(TraceErr);
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR_VAR(xEnrollErr, hr);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
SET_ERROR_VAR(StatusErr, hr);
}
HRESULT CSCrdEnr::GetCAExchangeCertificate(IN BSTR bstrCAQualifiedName,
OUT PCCERT_CONTEXT *ppCert)
{
HRESULT hr = S_OK;
ICertRequest2 *pICertRequest = NULL;
VARIANT varExchangeCertificate;
// Input validation:
if (NULL == bstrCAQualifiedName || NULL == ppCert)
return E_INVALIDARG;
// Init:
*ppCert = NULL;
varExchangeCertificate.vt = VT_EMPTY;
varExchangeCertificate.bstrVal = NULL;
if (S_OK != (hr = CoCreateInstance
(CLSID_CCertRequest,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICertRequest2,
(void**)&pICertRequest)))
goto ErrorReturn;
if (S_OK != (hr = pICertRequest->GetCAProperty
(bstrCAQualifiedName, // CA Name/CA Location
CR_PROP_CAXCHGCERT, // Get the exchange certificate from the CA.
0, // Unused
PROPTYPE_BINARY, //
CR_OUT_BINARY, //
&varExchangeCertificate // Variant type representing the certificate.
)))
goto ErrorReturn;
if (VT_BSTR != varExchangeCertificate.vt || NULL == varExchangeCertificate.bstrVal)
goto UnexpectedErr;
*ppCert = CertCreateCertificateContext
(X509_ASN_ENCODING,
(LPBYTE)varExchangeCertificate.bstrVal,
SysStringByteLen(varExchangeCertificate.bstrVal));
if (*ppCert == NULL)
goto CertCliErr;
CommonReturn:
if (NULL != pICertRequest) { pICertRequest->Release(); }
if (NULL != varExchangeCertificate.bstrVal) { SysFreeString(varExchangeCertificate.bstrVal); }
return hr;
ErrorReturn:
if (ppCert != NULL && *ppCert != NULL)
{
CertFreeCertificateContext(*ppCert);
*ppCert = NULL;
}
goto CommonReturn;
SET_HRESULT(CertCliErr, HRESULT_FROM_WIN32(GetLastError()));
SET_HRESULT(UnexpectedErr, E_UNEXPECTED);
}
STDMETHODIMP CSCrdEnr::selectSigningCertificate
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
CRYPTUI_SELECTCERTIFICATE_STRUCT SelCert;
BOOL fSCardSigningCert=FALSE;
DWORD dwCSPTypeSigningCert=0;
DWORD dwSize=0;
DWORD dwImpType=0;
SCrdEnroll_CERT_SELECT_INFO CertSelectInfo;
HCRYPTPROV hProv=NULL; //no need to free it
LPSTR pszContainerSigningCert=NULL;
LPSTR pszCSPNameSigningCert=NULL;
PCCERT_CONTEXT pSigningCert=NULL;
HCERTSTORE hMyStore=NULL;
CERT_CHAIN_PARA ChainParams;
CERT_CHAIN_POLICY_PARA ChainPolicy;
CERT_CHAIN_POLICY_STATUS PolicyStatus;
CERT_CHAIN_CONTEXT const *pCertChain = NULL;
memset(&SelCert, 0, sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT));
EnterCriticalSection(&m_cSection);
//select a signing certificate in my store with private key
hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"my");
if(NULL==hMyStore)
goto TraceErr;
CertSelectInfo.dwFlags = dwFlags;
CertSelectInfo.pwszCertTemplateName = bstrCertTemplateName;
SelCert.dwSize=sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT);
SelCert.cDisplayStores=1;
SelCert.rghDisplayStores=&hMyStore;
SelCert.pFilterCallback=SelectSignCertCallBack;
SelCert.pvCallbackData=&CertSelectInfo;
pSigningCert=CryptUIDlgSelectCertificate(&SelCert);
if(NULL==pSigningCert)
{
//user clicks on the cancel button.
hr=S_OK;
goto CommonReturn;
}
//verification on the cert
ZeroMemory(&ChainParams, sizeof(ChainParams));
ChainParams.cbSize = sizeof(ChainParams);
ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
//get cert chain 1st
if (!CertGetCertificateChain(
HCCE_CURRENT_USER, //enrollment agent
pSigningCert, //signing cert
NULL, //use current system time
NULL, //no additional stores
&ChainParams, //chain params
0, //no crl check
NULL, //reserved
&pCertChain))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto CertGetCertificateChainError;
}
ZeroMemory(&ChainPolicy, sizeof(ChainPolicy));
ChainPolicy.cbSize = sizeof(ChainPolicy);
ChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
ZeroMemory(&PolicyStatus, sizeof(PolicyStatus));
PolicyStatus.cbSize = sizeof(PolicyStatus);
PolicyStatus.lChainIndex = -1;
PolicyStatus.lElementIndex = -1;
//verify the chain
if (!CertVerifyCertificateChainPolicy(
CERT_CHAIN_POLICY_BASE, //basic
pCertChain,
&ChainPolicy,
&PolicyStatus))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto CertVerifyCertificateChainPolicyError;
}
if (S_OK != PolicyStatus.dwError)
{
hr = PolicyStatus.dwError;
goto CertVerifyCertificateChainPolicyError;
}
//get the hProv
if(!CryptAcquireCertificatePrivateKey(
pSigningCert,
CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hProv, //this handle is cached and no need to be freed
NULL,
NULL))
goto TraceErr;
//get related information
//impType
dwSize = sizeof(dwImpType);
if(!CryptGetProvParam(hProv,
PP_IMPTYPE,
(BYTE *)(&dwImpType),
&dwSize,
0))
goto TraceErr;
if(CRYPT_IMPL_REMOVABLE & dwImpType)
fSCardSigningCert=TRUE;
//CSP Type
dwSize = sizeof(dwCSPTypeSigningCert);
if(!CryptGetProvParam(hProv,
PP_PROVTYPE,
(BYTE *)(&dwCSPTypeSigningCert),
&dwSize,
0))
{
goto TraceErr;
}
//CSP name
dwSize = 0;
if(!CryptGetProvParam(hProv,
PP_NAME,
NULL,
&dwSize,
0) || (0==dwSize))
goto TraceErr;
pszCSPNameSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
if(NULL == pszCSPNameSigningCert)
goto MemoryErr;
if(!CryptGetProvParam(hProv,
PP_NAME,
(BYTE *)pszCSPNameSigningCert,
&dwSize,
0))
goto TraceErr;
//Container name
dwSize = 0;
if(!CryptGetProvParam(hProv,
PP_CONTAINER,
NULL,
&dwSize,
0) || (0==dwSize))
goto TraceErr;
pszContainerSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
if(NULL == pszContainerSigningCert)
goto MemoryErr;
if(!CryptGetProvParam(hProv,
PP_CONTAINER,
(BYTE *)pszContainerSigningCert,
&dwSize,
0))
goto TraceErr;
//now, we need to perform a signig operation so that we
//can invoke the smard card dialogue and cash the reader information
//to the hProv handle. This operation is benign if the CSP of the signing
//certificate is not on a smart card
if(!SignWithCert(pszCSPNameSigningCert,
dwCSPTypeSigningCert,
pSigningCert))
goto TraceErr;
//the certificate looks good
if(m_pSigningCert)
CertFreeCertificateContext(m_pSigningCert);
if(m_pszContainerSigningCert)
SCrdEnrollFree(m_pszContainerSigningCert);
if(m_pszCSPNameSigningCert)
SCrdEnrollFree(m_pszCSPNameSigningCert);
m_pSigningCert=pSigningCert;
m_fSCardSigningCert = fSCardSigningCert;
m_pszCSPNameSigningCert = pszCSPNameSigningCert;
m_dwCSPTypeSigningCert = dwCSPTypeSigningCert;
m_pszContainerSigningCert = pszContainerSigningCert;
pSigningCert=NULL;
pszCSPNameSigningCert=NULL;
pszContainerSigningCert=NULL;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pSigningCert)
CertFreeCertificateContext(pSigningCert);
if(hMyStore)
CertCloseStore(hMyStore, 0);
if(pszContainerSigningCert)
SCrdEnrollFree(pszContainerSigningCert);
if(pszCSPNameSigningCert)
SCrdEnrollFree(pszCSPNameSigningCert);
if (NULL != pCertChain)
{
CertFreeCertificateChain(pCertChain);
}
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
TRACE_ERROR(TraceErr);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(CertGetCertificateChainError)
TRACE_ERROR(CertVerifyCertificateChainPolicyError)
}
STDMETHODIMP CSCrdEnr::setSigningCertificate
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
BOOL fSCardSigningCert=FALSE;
DWORD dwCSPTypeSigningCert=0;
DWORD dwSize=0;
DWORD dwImpType=0;
SCrdEnroll_CERT_SELECT_INFO CertSelectInfo;
BOOL fSetCert=FALSE;
HCRYPTPROV hProv=NULL; //no need to free it
PCCERT_CONTEXT pPreCert=NULL; //no need to free it
LPSTR pszContainerSigningCert=NULL;
LPSTR pszCSPNameSigningCert=NULL;
PCCERT_CONTEXT pSigningCert=NULL;
HCERTSTORE hMyStore=NULL;
EnterCriticalSection(&m_cSection);
//mark if the signing cert is set previously
if(m_pSigningCert)
fSetCert=TRUE;
//select a signing certificate in my store with private key
hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"my");
if(NULL==hMyStore)
goto TraceErr;
CertSelectInfo.dwFlags = dwFlags;
CertSelectInfo.pwszCertTemplateName = bstrCertTemplateName;
while(pSigningCert = CertEnumCertificatesInStore(hMyStore, pPreCert))
{
//check for the certificate
if(!SelectSignCertCallBack(pSigningCert, NULL, &CertSelectInfo))
goto NextCert;
//this is a detaul NO-UI selection. We can not handle the case
//when the signing certificate is on a smart card
if(SmartCardCSP(pSigningCert))
goto NextCert;
//get the hProv
if(!CryptAcquireCertificatePrivateKey(
pSigningCert,
CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hProv, //this handle is cached and no need to be freed
NULL,
NULL))
goto NextCert;
//get related information
//impType
dwSize = sizeof(dwImpType);
if(!CryptGetProvParam(hProv,
PP_IMPTYPE,
(BYTE *)(&dwImpType),
&dwSize,
0))
goto NextCert;
if(CRYPT_IMPL_REMOVABLE & dwImpType)
fSCardSigningCert=TRUE;
//CSP Type
dwSize = sizeof(dwCSPTypeSigningCert);
if(!CryptGetProvParam(hProv,
PP_PROVTYPE,
(BYTE *)(&dwCSPTypeSigningCert),
&dwSize,
0))
goto NextCert;
//CSP name
dwSize = 0;
if(!CryptGetProvParam(hProv,
PP_NAME,
NULL,
&dwSize,
0) || (0==dwSize))
goto NextCert;
pszCSPNameSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
if(NULL == pszCSPNameSigningCert)
goto MemoryErr;
if(!CryptGetProvParam(hProv,
PP_NAME,
(BYTE *)pszCSPNameSigningCert,
&dwSize,
0))
goto NextCert;
//Container name
dwSize = 0;
if(!CryptGetProvParam(hProv,
PP_CONTAINER,
NULL,
&dwSize,
0) || (0==dwSize))
goto NextCert;
pszContainerSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
if(NULL == pszContainerSigningCert)
goto MemoryErr;
if(!CryptGetProvParam(hProv,
PP_CONTAINER,
(BYTE *)pszContainerSigningCert,
&dwSize,
0))
goto NextCert;
//now, we need to perform a signig operation so that we
//can invoke the smard card dialogue and cash the reader information
//to the hProv handle. This operation is benign if the CSP of the signing
//certificate is not on a smart card
if(!SignWithCert(pszCSPNameSigningCert,
dwCSPTypeSigningCert,
pSigningCert))
goto NextCert;
//the certificate looks good
if((NULL == m_pSigningCert) || (TRUE == fSetCert) ||
(IsNewerCert(pSigningCert, m_pSigningCert)))
{
fSetCert = FALSE;
if(m_pSigningCert)
{
CertFreeCertificateContext(m_pSigningCert);
m_pSigningCert = NULL;
}
m_pSigningCert=CertDuplicateCertificateContext(pSigningCert);
if(NULL == m_pSigningCert)
goto DupErr;
//copy the data
if(m_pszContainerSigningCert)
SCrdEnrollFree(m_pszContainerSigningCert);
if(m_pszCSPNameSigningCert)
SCrdEnrollFree(m_pszCSPNameSigningCert);
m_fSCardSigningCert = fSCardSigningCert;
m_pszCSPNameSigningCert = pszCSPNameSigningCert;
m_dwCSPTypeSigningCert = dwCSPTypeSigningCert;
m_pszContainerSigningCert = pszContainerSigningCert;
pszCSPNameSigningCert=NULL;
pszContainerSigningCert=NULL;
// should select the 1st matched cert
break; //out of while loop
}
NextCert:
if(pszContainerSigningCert)
SCrdEnrollFree(pszContainerSigningCert);
if(pszCSPNameSigningCert)
SCrdEnrollFree(pszCSPNameSigningCert);
pszCSPNameSigningCert=NULL;
pszContainerSigningCert=NULL;
fSCardSigningCert=FALSE;
dwCSPTypeSigningCert=0;
dwSize=0;
dwImpType=0;
pPreCert = pSigningCert;
}
//we should find a certificate
if((NULL == m_pSigningCert) || (m_pSigningCert && (TRUE == fSetCert)))
goto CryptNotFindErr;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pSigningCert)
CertFreeCertificateContext(pSigningCert);
if(hMyStore)
CertCloseStore(hMyStore, 0);
if(pszContainerSigningCert)
SCrdEnrollFree(pszContainerSigningCert);
if(pszCSPNameSigningCert)
SCrdEnrollFree(pszCSPNameSigningCert);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
TRACE_ERROR(DupErr);
SET_ERROR(CryptNotFindErr, CRYPT_E_NOT_FOUND);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(TraceErr);
}
STDMETHODIMP CSCrdEnr::get_EnrollmentStatus
( /* [retval][out] */ LONG * plEnrollmentStatus)
{
if (plEnrollmentStatus == NULL)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_cSection);
*plEnrollmentStatus = m_lEnrollmentStatus;
LeaveCriticalSection(&m_cSection);
return S_OK;
}
STDMETHODIMP CSCrdEnr::getEnrolledCertificateName
(/*[in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pBstrCertName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwChar=0;
LPWSTR pwsz=NULL;
CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
EnterCriticalSection(&m_cSection);
if(NULL == m_pEnrolledCert)
goto InvalidArgErr;
*pBstrCertName=NULL;
if(0 == (SCARD_ENROLL_NO_DISPLAY_CERT & dwFlags))
{
//view the certificate
memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
CertViewStruct.pCertContext=m_pEnrolledCert;
CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE;
CryptUIDlgViewCertificate(&CertViewStruct, NULL);
}
dwChar=CertGetNameStringW(
m_pEnrolledCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0);
if ((dwChar != 0) && (NULL != (pwsz = (LPWSTR)SCrdEnrollAlloc(dwChar * sizeof(WCHAR)))))
{
CertGetNameStringW(
m_pEnrolledCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pwsz,
dwChar);
if( NULL == (*pBstrCertName = SysAllocString(pwsz)) )
goto MemoryErr;
}
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwsz)
SCrdEnrollFree(pwsz);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
}
STDMETHODIMP CSCrdEnr::resetUser()
{
EnterCriticalSection(&m_cSection);
if(m_pwszUserUPN)
{
SCrdEnrollFree(m_pwszUserUPN);
m_pwszUserUPN=NULL;
}
if(m_pwszUserSAM)
{
SCrdEnrollFree(m_pwszUserSAM);
m_pwszUserSAM=NULL;
}
if(m_pEnrolledCert)
{
CertFreeCertificateContext(m_pEnrolledCert);
m_pEnrolledCert=NULL;
}
LeaveCriticalSection(&m_cSection);
return S_OK;
}
STDMETHODIMP CSCrdEnr::enumCSPName
(/* [in] */ DWORD dwIndex,
/* [in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pbstrCSPName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
EnterCriticalSection(&m_cSection);
if(NULL == pbstrCSPName)
goto InvalidArgErr;
*pbstrCSPName=NULL;
if(0 == m_dwCSPCount || NULL == m_rgCSPInfo)
goto InvalidArgErr;
if(dwIndex >= m_dwCSPCount)
goto NoItemErr;
if( NULL == (*pbstrCSPName = SysAllocString(m_rgCSPInfo[dwIndex].pwszCSPName)))
goto MemoryErr;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
SET_ERROR(NoItemErr,ERROR_NO_MORE_ITEMS);
}
STDMETHODIMP CSCrdEnr::getUserName
(/* [in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pbstrUserName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
EnterCriticalSection(&m_cSection);
if(!pbstrUserName)
goto InvalidArgErr;
*pbstrUserName = NULL;
if((NULL==m_pwszUserUPN) && (NULL==m_pwszUserSAM))
goto InvalidArgErr;
if(SCARD_ENROLL_UPN_NAME & dwFlags)
{
if(NULL == m_pwszUserUPN)
goto InvalidArgErr;
if( NULL == (*pbstrUserName = SysAllocString(m_pwszUserUPN)))
goto MemoryErr;
}
else
{
if(NULL == m_pwszUserSAM)
goto InvalidArgErr;
if( NULL == (*pbstrUserName = SysAllocString(m_pwszUserSAM)))
goto MemoryErr;
}
hr= S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
}
STDMETHODIMP CSCrdEnr::setUserName
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrUserName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
LPWSTR pwszSAM=NULL;
EnterCriticalSection(&m_cSection);
if(!bstrUserName)
goto InvalidArgErr;
if(SCARD_ENROLL_UPN_NAME & dwFlags)
{
//the UPN name has to have a corresponding SAM name
if(!GetName(bstrUserName, NameUserPrincipal, NameSamCompatible, &pwszSAM))
goto TraceErr;
if(m_pwszUserUPN)
{
SCrdEnrollFree(m_pwszUserUPN);
m_pwszUserUPN=NULL;
}
if(m_pwszUserSAM)
{
SCrdEnrollFree(m_pwszUserSAM);
m_pwszUserSAM=NULL;
}
if(NULL == (m_pwszUserUPN=CopyWideString(bstrUserName)))
goto MemoryErr;
m_pwszUserSAM=pwszSAM;
pwszSAM = NULL;
}
else
{
if(m_pwszUserUPN)
{
SCrdEnrollFree(m_pwszUserUPN);
m_pwszUserUPN=NULL;
}
if(m_pwszUserSAM)
{
SCrdEnrollFree(m_pwszUserSAM);
m_pwszUserSAM=NULL;
}
if(NULL == (m_pwszUserSAM=CopyWideString(bstrUserName)))
goto MemoryErr;
GetName(m_pwszUserSAM,
NameSamCompatible,
NameUserPrincipal,
&m_pwszUserUPN);
}
hr= S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwszSAM)
SCrdEnrollFree(pwszSAM);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(TraceErr);
}
STDMETHODIMP CSCrdEnr::getCertTemplateCount
(/* [in] */ DWORD dwFlags,
/* [retval][out] */ long *pdwCertTemplateCount)
{
return CertTemplateCountOrName(
0, //index, doesn't matter what it is
dwFlags,
pdwCertTemplateCount,
NULL); //count
}
STDMETHODIMP CSCrdEnr::getCertTemplateName
(/* [in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pbstrCertTemplateName)
{
HRESULT hr = S_OK;
EnterCriticalSection(&m_cSection);
if(NULL==m_rgCTInfo || 0==m_dwCTCount)
{
*pbstrCertTemplateName=NULL;
hr=E_INVALIDARG;
}
else
{
if(dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME)
{
if( NULL == (*pbstrCertTemplateName = SysAllocString(m_rgCTInfo[m_dwCTIndex].pwszCTDisplayName)))
hr = E_OUTOFMEMORY;
}
else
{
if( NULL == (*pbstrCertTemplateName = SysAllocString(m_rgCTInfo[m_dwCTIndex].pwszCTName)))
hr = E_OUTOFMEMORY;
}
}
LeaveCriticalSection(&m_cSection);
return(hr);
}
STDMETHODIMP CSCrdEnr::setCertTemplateName
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwIndex=0;
EnterCriticalSection(&m_cSection);
if(NULL==m_rgCTInfo || 0==m_dwCTCount)
goto InvalidArgErr;
for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
{
if(dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME)
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTDisplayName))
{
m_dwCTIndex=dwIndex;
break;
}
}
else
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
{
m_dwCTIndex=dwIndex;
break;
}
}
}
if(dwIndex == m_dwCTCount)
goto InvalidArgErr;
//we need to get the CA information for the newly selected cert type
if(FALSE == m_rgCTInfo[m_dwCTIndex].fCAInfo)
{
GetCAInfoFromCertType(NULL,
m_rgCTInfo[m_dwCTIndex].pwszCTName,
&(m_rgCTInfo[m_dwCTIndex].dwCACount),
&(m_rgCTInfo[m_dwCTIndex].rgCAInfo));
m_rgCTInfo[m_dwCTIndex].dwCAIndex=0;
m_rgCTInfo[m_dwCTIndex].fCAInfo=TRUE;
}
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
HRESULT CSCrdEnr::CertTemplateCountOrName(
IN DWORD dwIndex,
IN DWORD dwFlags,
OUT long *pdwCertTemplateCount,
OUT BSTR *pbstrCertTemplateName)
{
HRESULT hr;
DWORD errBefore = GetLastError();
DWORD dwIdx = 0;
DWORD dwValidCount = 0;
BOOL fCount;
WCHAR *pwszName;
DWORD const OFFLINE_SUBJECT_NAME_FLAGS =
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT |
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME;
EnterCriticalSection(&m_cSection);
if (NULL == pdwCertTemplateCount && NULL == pbstrCertTemplateName)
{
//can't be both
goto InvalidParamErr;
}
//set flag for use of count or enum
fCount = (NULL != pdwCertTemplateCount);
if (fCount)
{
//init out
*pdwCertTemplateCount = 0;
}
else
{
//init out
*pbstrCertTemplateName = NULL;
if (0 == m_dwCTCount || NULL == m_rgCTInfo)
{
//no templates
goto InvalidArgErr;
}
if (dwIndex >= m_dwCTCount)
{
goto NoItemErr;
}
}
//set default flags if not defined by caller
if (0x0 == (dwFlags & SCARD_ENROLL_USER_CERT_TEMPLATE) &&
0x0 == (dwFlags & SCARD_ENROLL_MACHINE_CERT_TEMPLATE))
{
//assume both machine and user
dwFlags |= SCARD_ENROLL_USER_CERT_TEMPLATE |
SCARD_ENROLL_MACHINE_CERT_TEMPLATE;
}
if (0x0 == (dwFlags & SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE) &&
0x0 == (dwFlags & SCARD_ENROLL_OFFLINE_CERT_TEMPLATE))
{
//assume both enterprise and offline
dwFlags |= SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE |
SCARD_ENROLL_OFFLINE_CERT_TEMPLATE;
}
for (dwIdx = 0; dwIdx < m_dwCTCount; dwIdx++)
{
if (0x0 == (dwFlags & SCARD_ENROLL_CROSS_CERT_TEMPLATE) &&
0 < m_rgCTInfo[dwIdx].dwRASignature)
{
//don't include template require signatures
continue;
}
if((0x0 != (SCARD_ENROLL_USER_CERT_TEMPLATE & dwFlags) &&
FALSE == m_rgCTInfo[dwIdx].fMachine) ||
(0x0 != (SCARD_ENROLL_MACHINE_CERT_TEMPLATE & dwFlags) &&
TRUE == m_rgCTInfo[dwIdx].fMachine))
{
if (0 != (SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE & dwFlags) &&
0 == (OFFLINE_SUBJECT_NAME_FLAGS &
m_rgCTInfo[dwIdx].dwSubjectNameFlags))
{
//enterprise user/machine and no subject DN required
dwValidCount++;
}
else if (0 != (SCARD_ENROLL_OFFLINE_CERT_TEMPLATE & dwFlags) &&
0 != (OFFLINE_SUBJECT_NAME_FLAGS &
m_rgCTInfo[dwIdx].dwSubjectNameFlags))
{
//offline user/machine and subject DN required
dwValidCount++;
}
}
if (!fCount && dwValidCount == (dwIndex + 1))
{
//get name & hit the one by index. get display or real name
if (0x0 != (dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME))
{
//display name
pwszName = m_rgCTInfo[dwIdx].pwszCTDisplayName;
}
else
{
//real name
pwszName = m_rgCTInfo[dwIdx].pwszCTName;
}
*pbstrCertTemplateName = SysAllocString(pwszName);
if (NULL == *pbstrCertTemplateName)
{
goto MemoryErr;
}
else
{
//done
break;
}
}
}
if(!fCount && dwIdx == m_dwCTCount)
{
//go beyond
goto NoItemErr;
}
if (fCount)
{
*pdwCertTemplateCount = dwValidCount;
}
hr = S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG)
SET_ERROR(InvalidParamErr, HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
SET_ERROR(MemoryErr, E_OUTOFMEMORY)
SET_ERROR(NoItemErr,ERROR_NO_MORE_ITEMS)
}
STDMETHODIMP CSCrdEnr::enumCertTemplateName
(/* [in] */ DWORD dwIndex,
/* [in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pbstrCertTemplateName)
{
return CertTemplateCountOrName(
dwIndex,
dwFlags,
NULL, //get name
pbstrCertTemplateName);
}
HRESULT CSCrdEnr::_getCertTemplateExtensionInfo(
IN CERT_EXTENSIONS *pCertTypeExtensions,
IN LONG lType,
OUT VOID *pExtInfo)
{
HRESULT hr;
DWORD cwc = 0;
DWORD dwCTE;
DWORD i;
BOOL fV2 = FALSE; //default v1 template
BOOL fDword = TRUE;
DWORD dwValue;
EnterCriticalSection(&m_cSection);
if (NULL == m_pCachedCTEs || m_pCachedCTEs != pCertTypeExtensions)
{
//new template, don't use cache
//free the current cache if any
if (NULL != m_pwszCachedCTEOid)
{
LocalFree(m_pwszCachedCTEOid);
m_pwszCachedCTEOid = NULL;
}
if (NULL != m_pCachedCTE)
{
LocalFree(m_pCachedCTE);
m_pCachedCTE = NULL;
}
//reset extension pointer
m_pCachedCTEs = NULL;
//loop to find CT extension
for (i = 0; i < pCertTypeExtensions->cExtension; ++i)
{
if (0 == _stricmp(pCertTypeExtensions->rgExtension[i].pszObjId,
szOID_CERTIFICATE_TEMPLATE))
{
//v2 template
fV2 = TRUE;
//cache it
m_pCachedCTEs = pCertTypeExtensions;
break;
}
}
if (!fV2)
{
//v1 template, return empty string
m_pwszCachedCTEOid = (WCHAR*)LocalAlloc(LMEM_FIXED, sizeof(WCHAR));
if (NULL == m_pwszCachedCTEOid)
{
hr = E_OUTOFMEMORY;
goto MemoryErr;
}
m_pwszCachedCTEOid[0] = L'\0';
}
else
{
//decode cert template extension
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING,
X509_CERTIFICATE_TEMPLATE,
pCertTypeExtensions->rgExtension[i].Value.pbData,
pCertTypeExtensions->rgExtension[i].Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
NULL, //use default LocalAlloc
(void*)&m_pCachedCTE,
&dwCTE))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto CryptDecodeObjectExErr;
}
//have to convert asn to wchar
while (TRUE)
{
cwc = MultiByteToWideChar(
GetACP(),
0,
m_pCachedCTE->pszObjId,
-1,
m_pwszCachedCTEOid,
cwc);
if (0 >= cwc)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto MultiByteToWideCharErr;
}
if (NULL != m_pwszCachedCTEOid)
{
//done
break;
}
m_pwszCachedCTEOid = (WCHAR*)LocalAlloc(LMEM_FIXED,
cwc * sizeof(WCHAR));
if (NULL == m_pwszCachedCTEOid)
{
hr = E_OUTOFMEMORY;
goto MemoryErr;
}
}
}
}
//hit here, either from cached or new cache
switch (lType)
{
case SCARD_CTINFO_EXT_OID:
*(WCHAR**)pExtInfo = m_pwszCachedCTEOid;
break;
case SCARD_CTINFO_EXT_MAJOR:
if (NULL != m_pCachedCTE)
{
*(LONG*)pExtInfo = m_pCachedCTE->dwMajorVersion;
}
else
{
//must be v1
*(LONG*)pExtInfo = 0;
}
break;
case SCARD_CTINFO_EXT_MINOR:
if (NULL != m_pCachedCTE)
{
*(LONG*)pExtInfo = m_pCachedCTE->dwMinorVersion;
}
else
{
//must be v1
*(LONG*)pExtInfo = 0;
}
break;
case SCARD_CTINFO_EXT_MINOR_FLAG:
if (NULL != m_pCachedCTE)
{
*(LONG*)pExtInfo = m_pCachedCTE->fMinorVersion;
}
else
{
//must be v1
*(LONG*)pExtInfo = 0;
}
break;
default:
hr = E_INVALIDARG;
goto InvalidArgError;
}
hr = S_OK;
ErrorReturn:
LeaveCriticalSection(&m_cSection);
return hr;
TRACE_ERROR(CryptDecodeObjectExErr)
TRACE_ERROR(MemoryErr)
TRACE_ERROR(MultiByteToWideCharErr)
TRACE_ERROR(InvalidArgError)
}
HRESULT CSCrdEnr::_getStrCertTemplateCSPList(
IN DWORD dwIndex,
IN DWORD dwFlag,
OUT WCHAR **ppwszSupportedCSP)
{
HRESULT hr;
DWORD i;
WCHAR **ppwsz;
WCHAR *pwszOut = NULL;
EnterCriticalSection(&m_cSection);
//init
*ppwszSupportedCSP = NULL;
if (SCARD_CTINFO_CSPLIST_FIRST == dwFlag)
{
//reset to first
m_rgCTInfo[dwIndex].dwCurrentCSP = 0;
}
//get it
ppwsz = m_rgCTInfo[dwIndex].rgpwszSupportedCSPs;
for (i = 0; i < m_rgCTInfo[dwIndex].dwCurrentCSP && NULL != *ppwsz; ++i)
{
++ppwsz;
}
if (NULL == *ppwsz)
{
//hit the end
hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto NoMoreItemsErr;
}
// allocate buffer
pwszOut = (WCHAR*)LocalAlloc(LMEM_FIXED, (wcslen(*ppwsz) + 1) * sizeof(WCHAR));
if (NULL == pwszOut)
{
hr = E_OUTOFMEMORY;
goto MemoryErr;
}
//copy string
wcscpy(pwszOut, *ppwsz);
*ppwszSupportedCSP = pwszOut;
pwszOut = NULL;
++m_rgCTInfo[dwIndex].dwCurrentCSP;
hr = S_OK;
ErrorReturn:
LeaveCriticalSection(&m_cSection);
if (NULL != pwszOut)
{
LocalFree(pwszOut);
}
return hr;
TRACE_ERROR(MemoryErr)
TRACE_ERROR(NoMoreItemsErr)
}
STDMETHODIMP CSCrdEnr::getCertTemplateInfo(
/* [in] */ BSTR bstrCertTemplateName,
/* [in] */ LONG lType,
/* [retval][out] */ VARIANT *pvarCertTemplateInfo)
{
HRESULT hr;
DWORD dwIndex;
WCHAR *pwszInfo = NULL;
BOOL fFound = FALSE;
DWORD dwCSPFlag = SCARD_CTINFO_CSPLIST_NEXT;
LONG lInfo;
BOOL fStr = FALSE; //default to long
BOOL fFree = TRUE;
VARIANT varInfo;
ZeroMemory(&varInfo, sizeof(varInfo));
EnterCriticalSection(&m_cSection);
if (NULL == bstrCertTemplateName ||
0 == m_dwCTCount ||
NULL == m_rgCTInfo)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
goto InvalidParamErr;
}
//get the CT information
for (dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
{
if (0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
{
// found it
fFound = TRUE;
break;
}
}
if (!fFound)
{
//likely pass incorrect template name
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
goto NotFoundErr;
}
switch (lType)
{
case SCARD_CTINFO_KEYSPEC:
lInfo = m_rgCTInfo[dwIndex].dwKeySpec;
break;
case SCARD_CTINFO_KEYFLAGS:
lInfo = m_rgCTInfo[dwIndex].dwGenKeyFlags;
break;
case SCARD_CTINFO_EXT_OID:
hr = _getCertTemplateExtensionInfo(
m_rgCTInfo[dwIndex].pCertTypeExtensions,
lType,
&pwszInfo);
if (S_OK != hr)
{
goto _getCertTemplateExtensionInfoErr;
}
fStr = TRUE;
fFree = FALSE; //don't free cache
break;
case SCARD_CTINFO_EXT_MAJOR:
case SCARD_CTINFO_EXT_MINOR:
case SCARD_CTINFO_EXT_MINOR_FLAG:
hr = _getCertTemplateExtensionInfo(
m_rgCTInfo[dwIndex].pCertTypeExtensions,
lType,
&lInfo);
if (S_OK != hr)
{
goto _getCertTemplateExtensionInfoErr;
}
break;
case SCARD_CTINFO_CSPLIST_FIRST:
dwCSPFlag = SCARD_CTINFO_CSPLIST_FIRST;
//fall through
case SCARD_CTINFO_CSPLIST_NEXT:
hr = _getStrCertTemplateCSPList(dwIndex, dwCSPFlag, &pwszInfo);
if (S_OK != hr)
{
goto _getStrCertTemplateCSPListErr;
}
fStr = TRUE;
break;
case SCARD_CTINFO_SUBJECTFLAG:
lInfo = m_rgCTInfo[dwIndex].dwSubjectNameFlags;
break;
case SCARD_CTINFO_GENERALFLAGS:
lInfo = m_rgCTInfo[dwIndex].dwGeneralFlags;
break;
case SCARD_CTINFO_ENROLLMENTFLAGS:
lInfo = m_rgCTInfo[dwIndex].dwEnrollmentFlags;
break;
case SCARD_CTINFO_PRIVATEKEYFLAGS:
lInfo = m_rgCTInfo[dwIndex].dwPrivateKeyFlags;
break;
case SCARD_CTINFO_RA_SIGNATURES:
lInfo = m_rgCTInfo[dwIndex].dwRASignature;
break;
default:
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
goto InvalidParamErr;
}
if (fStr)
{
varInfo.vt = VT_BSTR;
varInfo.bstrVal = SysAllocString(pwszInfo);
if (NULL == varInfo.bstrVal)
{
hr = E_OUTOFMEMORY;
goto MemoryErr;
}
}
else
{
varInfo.vt = VT_I4;
varInfo.lVal = lInfo;
}
//return
*pvarCertTemplateInfo = varInfo;
hr = S_OK;
ErrorReturn:
LeaveCriticalSection(&m_cSection);
if (fFree && NULL != pwszInfo)
{
LocalFree(pwszInfo);
}
return hr;
TRACE_ERROR(InvalidParamErr)
TRACE_ERROR(NotFoundErr)
TRACE_ERROR(MemoryErr)
TRACE_ERROR(_getCertTemplateExtensionInfoErr)
TRACE_ERROR(_getStrCertTemplateCSPListErr)
}
STDMETHODIMP CSCrdEnr::getCACount
(/* [in] */ BSTR bstrCertTemplateName,
/* [retval][out] */ long *pdwCACount)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwIndex=0;
EnterCriticalSection(&m_cSection);
if(NULL == bstrCertTemplateName || NULL == pdwCACount)
goto InvalidArgErr;
*pdwCACount=0;
if(0 == m_dwCTCount || NULL == m_rgCTInfo)
goto InvalidArgErr;
//get the CT information
for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
break;
}
if(dwIndex == m_dwCTCount)
goto InvalidArgErr;
//we need to get the CA information for the newly selected cert type
if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
{
GetCAInfoFromCertType(NULL,
m_rgCTInfo[dwIndex].pwszCTName,
&(m_rgCTInfo[dwIndex].dwCACount),
&(m_rgCTInfo[dwIndex].rgCAInfo));
m_rgCTInfo[dwIndex].dwCAIndex=0;
m_rgCTInfo[dwIndex].fCAInfo=TRUE;
}
*pdwCACount = (long)m_rgCTInfo[dwIndex].dwCACount;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
STDMETHODIMP CSCrdEnr::getCAName
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName,
/* [retval][out] */ BSTR *pbstrCAName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwIndex=0;
LPWSTR pwszName=NULL;
SCrdEnroll_CT_INFO *pCTInfo=NULL;
EnterCriticalSection(&m_cSection);
if(NULL == bstrCertTemplateName || NULL == pbstrCAName)
goto InvalidArgErr;
*pbstrCAName=NULL;
if(0 == m_dwCTCount || NULL == m_rgCTInfo)
goto InvalidArgErr;
//get the CT information
for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
break;
}
if(dwIndex == m_dwCTCount)
goto InvalidArgErr;
//we need to get the CA information for the newly selected cert type
if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
{
GetCAInfoFromCertType(NULL,
m_rgCTInfo[dwIndex].pwszCTName,
&(m_rgCTInfo[dwIndex].dwCACount),
&(m_rgCTInfo[dwIndex].rgCAInfo));
m_rgCTInfo[dwIndex].dwCAIndex=0;
m_rgCTInfo[dwIndex].fCAInfo=TRUE;
}
pCTInfo=&(m_rgCTInfo[dwIndex]);
if(NULL == pCTInfo->rgCAInfo)
goto InvalidArgErr;
if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[pCTInfo->dwCAIndex]), &pwszName))
goto TraceErr;
if(NULL == (*pbstrCAName = SysAllocString(pwszName)))
goto MemoryErr;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwszName)
SCrdEnrollFree(pwszName);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(TraceErr);
}
STDMETHODIMP CSCrdEnr::setCAName
(/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName,
/* [in] */ BSTR bstrCAName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwIndex=0;
DWORD dwCAIndex=0;
LPWSTR pwszName=NULL;
SCrdEnroll_CT_INFO *pCTInfo=NULL;
EnterCriticalSection(&m_cSection);
if(NULL == bstrCertTemplateName || NULL == bstrCAName)
goto InvalidArgErr;
if(0 == m_dwCTCount || NULL == m_rgCTInfo)
goto InvalidArgErr;
//get the CT information
for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
break;
}
if(dwIndex == m_dwCTCount)
goto InvalidArgErr;
//we need to get the CA information for the newly selected cert type
if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
{
GetCAInfoFromCertType(NULL,
m_rgCTInfo[dwIndex].pwszCTName,
&(m_rgCTInfo[dwIndex].dwCACount),
&(m_rgCTInfo[dwIndex].rgCAInfo));
m_rgCTInfo[dwIndex].dwCAIndex=0;
m_rgCTInfo[dwIndex].fCAInfo=TRUE;
}
pCTInfo=&(m_rgCTInfo[dwIndex]);
if(NULL == pCTInfo->rgCAInfo)
goto InvalidArgErr;
//search for the CA specified in the input
for(dwCAIndex=0; dwCAIndex < pCTInfo->dwCACount; dwCAIndex++)
{
if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[dwCAIndex]), &pwszName))
continue;
if(0 == _wcsicmp(pwszName, bstrCAName))
break;
SCrdEnrollFree(pwszName);
pwszName=NULL;
}
if(dwCAIndex == pCTInfo->dwCACount)
goto InvalidArgErr;
//remember the selected CA by its index
pCTInfo->dwCAIndex = dwCAIndex;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwszName)
SCrdEnrollFree(pwszName);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
STDMETHODIMP CSCrdEnr::enumCAName
(/* [in] */ DWORD dwIndex,
/* [in] */ DWORD dwFlags,
/* [in] */ BSTR bstrCertTemplateName,
/* [retval][out] */ BSTR *pbstrCAName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwCTIndex=0;
LPWSTR pwszName=NULL;
SCrdEnroll_CT_INFO *pCTInfo=NULL;
EnterCriticalSection(&m_cSection);
if(NULL == bstrCertTemplateName || NULL == pbstrCAName)
goto InvalidArgErr;
*pbstrCAName=NULL;
if(0 == m_dwCTCount || NULL == m_rgCTInfo)
goto InvalidArgErr;
//get the CT information
for(dwCTIndex=0; dwCTIndex < m_dwCTCount; dwCTIndex++)
{
if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwCTIndex].pwszCTName))
break;
}
if(dwCTIndex == m_dwCTCount)
goto InvalidArgErr;
//we need to get the CA information for the newly selected cert type
if(FALSE == m_rgCTInfo[dwCTIndex].fCAInfo)
{
GetCAInfoFromCertType(NULL,
m_rgCTInfo[dwCTIndex].pwszCTName,
&(m_rgCTInfo[dwCTIndex].dwCACount),
&(m_rgCTInfo[dwCTIndex].rgCAInfo));
m_rgCTInfo[dwCTIndex].dwCAIndex=0;
m_rgCTInfo[dwCTIndex].fCAInfo=TRUE;
}
pCTInfo=&(m_rgCTInfo[dwCTIndex]);
//search for the CA specified in the input
if(dwIndex >= pCTInfo->dwCACount)
goto InvalidArgErr;
if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[dwIndex]), &pwszName))
goto TraceErr;
if(NULL == (*pbstrCAName = SysAllocString(pwszName)))
goto MemoryErr;
hr=S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwszName)
SCrdEnrollFree(pwszName);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(TraceErr);
}
STDMETHODIMP CSCrdEnr::getSigningCertificateName
(/* [in] */ DWORD dwFlags,
/* [retval][out] */ BSTR *pbstrSigningCertName)
{
HRESULT hr= E_FAIL;
DWORD errBefore= GetLastError();
DWORD dwChar=0;
LPWSTR pwsz=NULL;
CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
*pbstrSigningCertName=NULL;
EnterCriticalSection(&m_cSection);
if(NULL == m_pSigningCert)
goto InvalidArgErr;
if(0 == (SCARD_ENROLL_NO_DISPLAY_CERT & dwFlags))
{
//view the certificate
memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
CertViewStruct.pCertContext=m_pSigningCert;
CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE;
CryptUIDlgViewCertificate(&CertViewStruct, NULL);
}
dwChar=CertGetNameStringW(
m_pSigningCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0);
if ((dwChar != 0) && (NULL != (pwsz = (LPWSTR)SCrdEnrollAlloc(dwChar * sizeof(WCHAR)))))
{
CertGetNameStringW(
m_pSigningCert,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pwsz,
dwChar);
if( NULL == (*pbstrSigningCertName = SysAllocString(pwsz)))
goto MemoryErr;
}
hr= S_OK;
CommonReturn:
LeaveCriticalSection(&m_cSection);
if(pwsz)
SCrdEnrollFree(pwsz);
SetLastError(errBefore);
return hr;
ErrorReturn:
if(ERROR_SUCCESS == (errBefore = GetLastError()))
errBefore=E_UNEXPECTED;
hr = CodeToHR(errBefore);
goto CommonReturn;
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}