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.
 
 
 
 
 
 

2045 lines
44 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2001
//
// File: cainfo.cpp
//
// Contents:
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <certca.h>
#include <cainfop.h>
#include <polreg.h>
#include <cainfoc.h>
#include <certtype.h>
#include "certacl.h"
#include "accctrl.h"
#include <winldap.h>
#define __dwFILE__ __dwFILE_CERTCLIB_CAINFO_CPP__
typedef struct _CA_DEFAULT_PROVIDER {
DWORD dwFlags;
LPWSTR wszName;
} CA_DEFAULT_PROVIDER;
CA_DEFAULT_PROVIDER g_DefaultProviders[] =
{
{0, MS_DEF_PROV_W},
{0, MS_ENHANCED_PROV_W},
{0, MS_DEF_RSA_SIG_PROV_W},
{0, MS_DEF_RSA_SCHANNEL_PROV_W},
{0, MS_DEF_DSS_PROV_W},
{0, MS_DEF_DSS_DH_PROV_W},
{0, MS_ENH_DSS_DH_PROV_W},
{0, MS_DEF_DH_SCHANNEL_PROV_W},
{0, MS_SCARD_PROV_W}
};
DWORD g_cDefaultProviders = sizeof(g_DefaultProviders)/sizeof(g_DefaultProviders[0]);
LPCWSTR
CAGetDN(
IN HCAINFO hCAInfo
)
{
CSASSERT(hCAInfo);
return ((CCAInfo*)hCAInfo)->GetDN();
}
HRESULT
CAFindByName(
IN LPCWSTR wszCAName,
IN LPCWSTR wszScope,
IN DWORD fFlags,
OUT HCAINFO * phCAInfo
)
{
HRESULT hr = S_OK;
WCHAR *wszQueryBase = L"(cn=";
WCHAR *wszQuery = NULL;
DWORD cQuery;
if((wszCAName == NULL) || (phCAInfo == NULL))
{
return E_POINTER;
}
// Generate Query
cQuery = wcslen(wszQueryBase) + wcslen(wszCAName) + 2; // 2 for ending paren and null
wszQuery = (WCHAR *)LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*cQuery);
if(wszQuery == NULL)
{
hr = E_OUTOFMEMORY;
goto error;
}
wcscpy(wszQuery, wszQueryBase);
wcscat(wszQuery, wszCAName);
wcscat(wszQuery, L")");
if(fFlags & CA_FLAG_SCOPE_DNS)
{
hr = CCAInfo::FindDnsDomain(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
else
{
hr = CCAInfo::Find(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
if((hr == S_OK) &&
(*phCAInfo == NULL))
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
error:
if(wszQuery)
{
LocalFree(wszQuery);
}
return hr;
}
HRESULT
CAFindByCertType(
IN LPCWSTR wszCertType,
IN LPCWSTR wszScope,
IN DWORD fFlags,
OUT HCAINFO * phCAInfo
)
{
HRESULT hr = S_OK;
WCHAR *wszQueryBase = L"(" CA_PROP_CERT_TYPES L"=";
WCHAR *wszQuery = NULL;
DWORD cQuery;
if((wszCertType == NULL) || (phCAInfo == NULL))
{
return E_POINTER;
}
// Generate Query
cQuery = wcslen(wszQueryBase) + wcslen(wszCertType) + 2; // 2 for ending paren and null
wszQuery = (WCHAR *)LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*cQuery);
if(wszQuery == NULL)
{
hr = E_OUTOFMEMORY;
goto error;
}
wcscpy(wszQuery, wszQueryBase);
wcscat(wszQuery, wszCertType);
wcscat(wszQuery, L")");
if(fFlags & CA_FLAG_SCOPE_DNS)
{
hr = CCAInfo::FindDnsDomain(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
else
{
hr = CCAInfo::Find(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
if(*phCAInfo == NULL)
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
error:
if(wszQuery)
{
LocalFree(wszQuery);
}
return hr;
}
HRESULT
CAFindByIssuerDN(
IN CERT_NAME_BLOB const * pIssuerDN,
IN LPCWSTR wszScope,
IN DWORD fFlags,
OUT HCAINFO * phCAInfo
)
{
HRESULT hr = S_OK;
WCHAR *wszQueryBase = wszLPAREN L"cACertificateDN=";
WCHAR *wszQuery = NULL;
WCHAR *wszNameStr = NULL;
DWORD cQuery;
if((pIssuerDN == NULL) || (phCAInfo == NULL))
{
return E_POINTER;
}
// Generate Query
// Convert the CAPI2 name to a string
hr = myCertNameToStr(
X509_ASN_ENCODING,
pIssuerDN,
CERT_X500_NAME_STR |
CERT_NAME_STR_REVERSE_FLAG |
CERT_NAME_STR_NO_QUOTING_FLAG,
&wszNameStr);
_JumpIfError(hr, error, "myCertNameToStr");
// Now quote that string with double quotes
// two for ending paren and null, two for the double quotes
cQuery = wcslen(wszQueryBase) + wcslen(wszNameStr) + 4;
wszQuery = (WCHAR *)LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*cQuery);
if(wszQuery == NULL)
{
hr = E_OUTOFMEMORY;
goto error;
}
wcscpy(wszQuery, wszQueryBase);
//wcscat(wszQuery, L"\"");
wcscat(wszQuery, wszNameStr);
//wcscat(wszQuery, L"\"" wszRPAREN);
wcscat(wszQuery, wszRPAREN);
CSASSERT(cQuery - 1 == wcslen(wszQuery));
if(fFlags & CA_FLAG_SCOPE_DNS)
{
hr = CCAInfo::FindDnsDomain(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
else
{
hr = CCAInfo::Find(wszQuery, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
error:
if(wszNameStr)
{
LocalFree(wszNameStr);
}
if(wszQuery)
{
LocalFree(wszQuery);
}
return hr;
}
HRESULT
CAEnumFirstCA(
IN LPCWSTR wszScope,
IN DWORD fFlags,
OUT HCAINFO * phCAInfo
)
{
HRESULT hr = S_OK;
if(fFlags & CA_FLAG_SCOPE_DNS)
{
hr = CCAInfo::FindDnsDomain(NULL, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
else
{
hr = CCAInfo::Find(NULL, wszScope, fFlags, (CCAInfo **)phCAInfo);
}
if (S_OK != hr)
{
if (HRESULT_FROM_WIN32(ERROR_NETWORK_UNREACHABLE) != hr &&
HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD) != hr)
{
_PrintError3(
hr,
"FindDnsDomain/Find",
HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED),
HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN));
}
goto error;
}
error:
return(hr);
}
HRESULT
CAEnumNextCA(
IN HCAINFO hPrevCA,
OUT HCAINFO * phCAInfo
)
{
CCAInfo *pInfo;
if(hPrevCA == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hPrevCA;
return pInfo->Next((CCAInfo **)phCAInfo);
}
HRESULT
CACreateNewCA(
IN LPCWSTR wszCAName,
IN LPCWSTR wszScope,
IN DWORD fFlags,
OUT HCAINFO * phCAInfo
)
{
HRESULT hr = S_OK;
if((wszCAName == NULL) || (phCAInfo == NULL))
{
return E_POINTER;
}
// Generate Query
if(CA_FLAG_SCOPE_DNS & fFlags)
{
hr = CCAInfo::CreateDnsDomain(wszCAName, wszScope, (CCAInfo **)phCAInfo);
}
else
{
hr = CCAInfo::Create(wszCAName, wszScope, (CCAInfo **)phCAInfo);
}
return hr;
}
HRESULT
CAUpdateCA(
IN HCAINFO hCAInfo
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->Update();
}
HRESULT
CADeleteCA(
IN HCAINFO hCAInfo
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->Delete();
}
DWORD
CACountCAs(IN HCAINFO hCAInfo)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return 0;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->Count();
}
HRESULT
CACloseCA(IN HCAINFO hCAInfo)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->Release();
}
HRESULT
CAGetCAProperty(
IN HCAINFO hCAInfo,
IN LPCWSTR wszPropertyName,
OUT LPWSTR ** pawszPropertyValue)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->GetProperty(wszPropertyName, pawszPropertyValue);
}
HRESULT
CAFreeCAProperty(
IN HCAINFO hCAInfo,
IN LPWSTR * awszPropertyValue
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->FreeProperty(awszPropertyValue);
}
HRESULT
CASetCAProperty(
IN HCAINFO hCAInfo,
IN LPCWSTR wszPropertyName,
IN LPWSTR * awszPropertyValue)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->SetProperty(wszPropertyName, awszPropertyValue);
}
HRESULT
CAGetCAFlags(
IN HCAINFO hCAInfo,
OUT DWORD * pdwFlags
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
if(pdwFlags == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
*pdwFlags = pInfo->GetFlags();
return S_OK;
}
HRESULT
CASetCAFlags(
IN HCAINFO hCAInfo,
IN DWORD dwFlags
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
pInfo->SetFlags(dwFlags);
return S_OK;
}
HRESULT
CAGetCACertificate(
IN HCAINFO hCAInfo,
OUT PCCERT_CONTEXT *ppCert)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->GetCertificate(ppCert);
}
HRESULT
CASetCACertificate(
IN HCAINFO hCAInfo,
IN PCCERT_CONTEXT pCert)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->SetCertificate(pCert);
}
HRESULT
CAGetCAExpiration(
HCAINFO hCAInfo,
DWORD * pdwExpiration,
DWORD * pdwUnits
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->GetExpiration(pdwExpiration, pdwUnits);
}
HRESULT
CASetCAExpiration(
HCAINFO hCAInfo,
DWORD dwExpiration,
DWORD dwUnits
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->SetExpiration(dwExpiration, dwUnits);
}
HRESULT
CASetCASecurity(
IN HCAINFO hCAInfo,
IN PSECURITY_DESCRIPTOR pSD
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->SetSecurity( pSD );
}
HRESULT
CAGetCASecurity(
IN HCAINFO hCAInfo,
OUT PSECURITY_DESCRIPTOR * ppSD
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->GetSecurity( ppSD ) ;
}
CERTCLIAPI
HRESULT
WINAPI
CAAccessCheck(
IN HCAINFO hCAInfo,
IN HANDLE ClientToken
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->AccessCheck(ClientToken,CERTTYPE_ACCESS_CHECK_ENROLL);
}
CERTCLIAPI
HRESULT
WINAPI
CAAccessCheckEx(
IN HCAINFO hCAInfo,
IN HANDLE ClientToken,
IN DWORD dwOption
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->AccessCheck(ClientToken,dwOption);
}
HRESULT
CAEnumCertTypesForCAEx(
IN HCAINFO hCAInfo,
IN LPCWSTR wszScope,
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
if(dwFlags & CA_FLAG_ENUM_ALL_TYPES)
{
return CCertTypeInfo::Enum(wszScope,
dwFlags,
(CCertTypeInfo **)phCertType);
}
return pInfo->EnumSupportedCertTypesEx(wszScope,
dwFlags,
(CCertTypeInfo **)phCertType);
}
HRESULT
CAEnumCertTypesForCA(
IN HCAINFO hCAInfo,
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
return CAEnumCertTypesForCAEx(hCAInfo,
NULL,
dwFlags,
phCertType);
}
HRESULT
CAAddCACertificateType(
HCAINFO hCAInfo,
HCERTTYPE hCertType
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->AddCertType((CCertTypeInfo *)hCertType);
}
HRESULT
CARemoveCACertificateType(
HCAINFO hCAInfo,
HCERTTYPE hCertType
)
{
CCAInfo *pInfo;
if(hCAInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCAInfo *)hCAInfo;
return pInfo->RemoveCertType((CCertTypeInfo *)hCertType);
}
//
// Certificate Type API's
//
HRESULT
CAEnumCertTypes(
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
HRESULT hr;
hr = CCertTypeInfo::Enum(NULL,
dwFlags,
(CCertTypeInfo **)phCertType);
return hr;
}
HRESULT
CAEnumCertTypesEx(
IN LPCWSTR wszScope,
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
HRESULT hr;
hr = CCertTypeInfo::Enum(wszScope,
dwFlags,
(CCertTypeInfo **)phCertType);
return hr;
}
HRESULT
CAFindCertTypeByName(
IN LPCWSTR wszCertType,
IN HCAINFO hCAInfo,
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
HRESULT hr = S_OK;
LPCWSTR awszTypes[2];
if((wszCertType == NULL) || (phCertType == NULL))
{
return E_POINTER;
}
awszTypes[0] = wszCertType;
awszTypes[1] = NULL;
hr = CCertTypeInfo::FindByNames(awszTypes,
((CT_FLAG_SCOPE_IS_LDAP_HANDLE & dwFlags)?(LPWSTR)hCAInfo:NULL),
dwFlags,
(CCertTypeInfo **)phCertType);
if((hr == S_OK) && (*phCertType == NULL))
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
return hr;
}
HRESULT
CACreateCertType(
IN LPCWSTR wszCertType,
IN LPCWSTR wszScope,
IN DWORD, // fFlags
OUT HCERTTYPE * phCertType
)
{
HRESULT hr = S_OK;
if((wszCertType == NULL) || (phCertType == NULL))
{
return E_POINTER;
}
hr = CCertTypeInfo::Create(wszCertType, wszScope, (CCertTypeInfo **)phCertType);
return hr;
}
HRESULT
CAUpdateCertType(
IN HCERTTYPE hCertType
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->Update();
}
HRESULT
CADeleteCertType(
IN HCERTTYPE hCertType
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->Delete();
}
//--------------------------------------------------------------------
//
// CertTypeRetrieveClientToken
//
//--------------------------------------------------------------------
BOOL CertTypeRetrieveClientToken(HANDLE *phToken)
{
HRESULT hr = S_OK;
HANDLE hHandle = NULL;
HANDLE hClientToken = NULL;
hHandle = GetCurrentThread();
if (NULL == hHandle)
{
hr = myHLastError();
}
else
{
if (!OpenThreadToken(hHandle,
TOKEN_QUERY,
TRUE, // open as self
&hClientToken))
{
hr = myHLastError();
CloseHandle(hHandle);
hHandle = NULL;
}
}
if(hr != S_OK)
{
hHandle = GetCurrentProcess();
if (NULL == hHandle)
{
hr = myHLastError();
}
else
{
HANDLE hProcessToken = NULL;
hr = S_OK;
if (!OpenProcessToken(hHandle,
TOKEN_DUPLICATE,
&hProcessToken))
{
hr = myHLastError();
CloseHandle(hHandle);
hHandle = NULL;
}
else
{
if(!DuplicateToken(hProcessToken,
SecurityImpersonation,
&hClientToken))
{
hr = myHLastError();
CloseHandle(hHandle);
hHandle = NULL;
}
CloseHandle(hProcessToken);
}
}
}
if(S_OK == hr)
*phToken = hClientToken;
if(hHandle)
CloseHandle(hHandle);
return (S_OK == hr);
}
HRESULT
CACloneCertType(
IN HCERTTYPE hCertType,
IN LPCWSTR wszCertType,
IN LPCWSTR wszFriendlyName,
IN LPVOID pvldap,
IN DWORD dwFlags,
OUT HCERTTYPE * phCertType
)
{
HRESULT hr=E_INVALIDARG;
DWORD dwFindCT=CT_FLAG_NO_CACHE_LOOKUP | CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES;
LPWSTR awszProp[2];
DWORD dwEnrollmentFlag=0;
DWORD dwSubjectNameFlag=0;
DWORD dwGeneralFlag=0;
DWORD dwSubjectRequirement=CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH |
CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME |
CT_FLAG_SUBJECT_REQUIRE_EMAIL |
CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN;
DWORD dwTokenUserSize=0;
DWORD dwAbsSDSize=0;
DWORD dwDaclSize=0;
DWORD dwSaclSize=0;
DWORD dwOwnerSize=0;
DWORD dwPriGrpSize=0;
DWORD dwRelSDSize=0;
ACL_SIZE_INFORMATION aclsizeinfo;
DWORD dwNewAclSize=0;
ACE_HEADER *pFirstAce=NULL;
PACL pAcl=NULL;
BOOL bAclPresent=FALSE;
BOOL bDefaultAcl=FALSE;
DWORD nIndex=0;
BOOL fAddAce=TRUE;
DWORD dwCount=0;
HANDLE hToken=NULL;
TOKEN_USER *pTokenUser=NULL;
PSECURITY_DESCRIPTOR pSID=NULL;
PSECURITY_DESCRIPTOR pAbsSD=NULL;
ACL * pAbsDacl=NULL;
ACL * pAbsSacl=NULL;
SID * pAbsOwner=NULL;
SID * pAbsPriGrp=NULL;
PSECURITY_DESCRIPTOR pNewSD=NULL;
LPWSTR * awszCN=NULL;
HCERTTYPE hNewCertType=NULL;
ACL *pNewDacl=NULL;
DWORD *pdwIndex=NULL;
if((NULL==hCertType) || (NULL==wszCertType) || (NULL==phCertType))
goto error;
*phCertType=NULL;
if(pvldap)
dwFindCT |= CT_FLAG_SCOPE_IS_LDAP_HANDLE;
//make sure the new name does not exit
if(S_OK == CAFindCertTypeByName(
wszCertType,
(HCAINFO)pvldap,
dwFindCT,
&hNewCertType))
{
hr=CRYPT_E_EXISTS;
goto error;
}
//get a new cert type handle
if(S_OK != (hr = CAGetCertTypePropertyEx(hCertType,
CERTTYPE_PROP_CN,
&awszCN)))
goto error;
if((NULL==awszCN) || (NULL==awszCN[0]))
{
hr=HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
goto error;
}
if(S_OK != (hr = CAFindCertTypeByName(
(LPCWSTR)awszCN[0],
(HCAINFO)pvldap,
dwFindCT,
&hNewCertType)))
goto error;
if(NULL==hNewCertType)
{
hr=HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
goto error;
}
//clone by setting the CN
awszProp[0]=(LPWSTR)wszCertType;
awszProp[1]=NULL;
if(S_OK != (hr=CASetCertTypePropertyEx(
hNewCertType,
CERTTYPE_PROP_CN,
awszProp)))
goto error;
//set the friendly name
if(wszFriendlyName)
{
awszProp[0]=(LPWSTR)wszFriendlyName;
awszProp[1]=NULL;
if(S_OK != (hr=CASetCertTypePropertyEx(
hNewCertType,
CERTTYPE_PROP_FRIENDLY_NAME,
awszProp)))
goto error;
}
//turn off autoenrollment bit
if(0 == (CT_CLONE_KEEP_AUTOENROLLMENT_SETTING & dwFlags))
{
if(S_OK != (hr=CAGetCertTypeFlagsEx(
hNewCertType,
CERTTYPE_ENROLLMENT_FLAG,
&dwEnrollmentFlag)))
goto error;
dwEnrollmentFlag &= (~CT_FLAG_AUTO_ENROLLMENT);
if(S_OK != (hr=CASetCertTypeFlagsEx(
hNewCertType,
CERTTYPE_ENROLLMENT_FLAG,
dwEnrollmentFlag)))
goto error;
}
//turn off the subject name requirement for machien template
if(0 == (CT_CLONE_KEEP_SUBJECT_NAME_SETTING & dwFlags))
{
if(S_OK != (hr=CAGetCertTypeFlagsEx(
hNewCertType,
CERTTYPE_GENERAL_FLAG,
&dwGeneralFlag)))
goto error;
if(CT_FLAG_MACHINE_TYPE & dwGeneralFlag)
{
if(S_OK != (hr=CAGetCertTypeFlagsEx(
hNewCertType,
CERTTYPE_SUBJECT_NAME_FLAG,
&dwSubjectNameFlag)))
goto error;
dwSubjectNameFlag &= (~dwSubjectRequirement);
if(S_OK != (hr=CASetCertTypeFlagsEx(
hNewCertType,
CERTTYPE_SUBJECT_NAME_FLAG,
dwSubjectNameFlag)))
goto error;
}
}
//get the client token
if(!CertTypeRetrieveClientToken(&hToken))
{
hr = myHLastError();
goto error;
}
//get the client sid
dwTokenUserSize=0;
if(!GetTokenInformation(
hToken, // handle to access token
TokenUser, // token type
NULL, // buffer
0, // size of buffer
&dwTokenUserSize)) // required buffer size
{
if (ERROR_INSUFFICIENT_BUFFER!=GetLastError())
{
hr = myHLastError();
goto error;
}
}
if(NULL==(pTokenUser=(TOKEN_USER *)LocalAlloc(LPTR, dwTokenUserSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
if(!GetTokenInformation(
hToken, // handle to access token
TokenUser, // token type
pTokenUser, // buffer
dwTokenUserSize, // size of buffer
&dwTokenUserSize)) // required buffer size
{
hr = myHLastError();
goto error;
}
//update the ACLs of the template to have the caller as the owner
//of the ACL
if(S_OK != (hr=CACertTypeGetSecurity(
hNewCertType,
&pSID)))
goto error;
//we will delete all ACCESS_DENIED ACEs for the caller
// get the (D)ACL from the security descriptor
if (!GetSecurityDescriptorDacl(pSID, &bAclPresent, &pAcl, &bDefaultAcl))
{
hr = myHLastError();
_JumpError(hr, error, "GetSecurityDescriptorDacl");
}
if(FALSE == bAclPresent)
{
hr=HRESULT_FROM_WIN32(ERROR_INVALID_SECURITY_DESCR);
_JumpError(hr, error, "IsValidSecurityDescriptor");
}
// NULL acl -> allow all access
if (NULL != pAcl)
{
// find out how many ACEs
memset(&aclsizeinfo, 0, sizeof(aclsizeinfo));
if (!GetAclInformation(pAcl, &aclsizeinfo, sizeof(aclsizeinfo), AclSizeInformation))
{
hr = myHLastError();
_JumpError(hr, error, "GetAclInformation");
}
pdwIndex=(DWORD *)LocalAlloc(LPTR, sizeof(DWORD) * (aclsizeinfo.AceCount));
if(NULL==pdwIndex)
{
hr=E_OUTOFMEMORY;
goto error;
}
memset(pdwIndex, 0, sizeof(DWORD) * (aclsizeinfo.AceCount));
dwCount=0;
for (nIndex=0; nIndex < aclsizeinfo.AceCount; nIndex++)
{
ACE_HEADER * pAceHeader=NULL;
ACCESS_ALLOWED_ACE * pAccessAce=NULL;
PSID pSid=NULL;
if (!GetAce(pAcl, nIndex, (void**)&pAceHeader))
{
hr = myHLastError();
_JumpError(hr, error, "GetAce");
}
// find the sid for this ACE
if ((ACCESS_ALLOWED_ACE_TYPE != pAceHeader->AceType) && (ACCESS_DENIED_ACE_TYPE != pAceHeader->AceType))
{
// we are only interested in ace types
continue;
}
// note that ACCESS_ALLOWED_ACE and ACCESS_DENIED_ACE are the same structurally.
pAccessAce=(ACCESS_ALLOWED_ACE *)pAceHeader;
pSid=((BYTE *)&(pAccessAce->SidStart));
// make sure this is the sid we are looking for
if (!EqualSid(pSid, (pTokenUser->User).Sid))
{
continue;
}
if(ACCESS_ALLOWED_ACE_TYPE == pAceHeader->AceType)
{
//change it to allowed for everything
fAddAce=FALSE;
pAceHeader->AceType=ACCESS_ALLOWED_ACE_TYPE;
pAccessAce->Mask=(pAccessAce->Mask) | (ACTRL_CERTSRV_MANAGE_LESS_CONTROL_ACCESS);
}
else
{
//delete the denied ace
if(ACCESS_DENIED_ACE_TYPE == pAceHeader->AceType)
{
pdwIndex[dwCount]=nIndex;
dwCount++;
}
}
}
if(!MakeAbsoluteSD(pSID, NULL, &dwAbsSDSize, NULL, &dwDaclSize, NULL, &dwSaclSize, NULL, &dwOwnerSize, NULL, &dwPriGrpSize))
{
if (ERROR_INSUFFICIENT_BUFFER!=GetLastError())
{
hr = myHLastError();
goto error;
}
}
// allocate memory
if(NULL==(pAbsSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwAbsSDSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
if(NULL==(pAbsDacl=(ACL * )LocalAlloc(LPTR, dwDaclSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
if(NULL==(pAbsSacl=(ACL * )LocalAlloc(LPTR, dwSaclSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
if(NULL==(pAbsOwner=(SID *)LocalAlloc(LPTR, dwOwnerSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
if(NULL==(pAbsPriGrp=(SID *)LocalAlloc(LPTR, dwPriGrpSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
// copy the SD to the memory buffers
if(!MakeAbsoluteSD(pSID, pAbsSD, &dwAbsSDSize, pAbsDacl, &dwDaclSize, pAbsSacl, &dwSaclSize, pAbsOwner, &dwOwnerSize, pAbsPriGrp, &dwPriGrpSize))
{
hr = myHLastError();
goto error;
}
// get the current size info for the dacl
memset(&aclsizeinfo, 0, sizeof(aclsizeinfo));
if(!GetAclInformation(pAbsDacl, &aclsizeinfo, sizeof(aclsizeinfo), AclSizeInformation))
{
hr = myHLastError();
_JumpError(hr, error, "GetAclInformation");
}
// figure out the new size
dwNewAclSize=aclsizeinfo.AclBytesInUse
+sizeof(ACCESS_ALLOWED_ACE)
-sizeof(DWORD) //ACCESS_ALLOWED_ACE::SidStart
+GetLengthSid((pTokenUser->User).Sid);
// allocate memory
pNewDacl=(ACL *)LocalAlloc(LPTR, dwNewAclSize);
if(NULL == pNewDacl)
{
hr=E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
// init the header
if(!InitializeAcl(pNewDacl, dwNewAclSize, ACL_REVISION_DS))
{
hr = myHLastError();
_JumpError(hr, error, "InitializeAcl");
}
// find the first ace in the dacl
if(!GetAce(pAbsDacl, 0, (void **)&pFirstAce))
{
hr = myHLastError();
_JumpError(hr, error, "GetAce");
}
// add all the old aces
if(!AddAce(pNewDacl, ACL_REVISION_DS, 0, pFirstAce, aclsizeinfo.AclBytesInUse-sizeof(ACL)))
{
hr = myHLastError();
_JumpError(hr, error, "AddAce");
}
//delete ACEs
for(nIndex=0; nIndex < dwCount; nIndex++)
{
//the ACEs in pNewDacl is repacked after each deletion.
//the pdwIndex[] has to be adjusted
if(!DeleteAce(pNewDacl, (pdwIndex[nIndex]-nIndex)))
{
hr = myHLastError();
_JumpError(hr, error, "DeleteAce");
}
}
// add the new ace for caller to allow FULL control other than DS_CONTROL
if(TRUE == fAddAce)
{
if(!AddAccessAllowedAce(pNewDacl, ACL_REVISION_DS, ACTRL_CERTSRV_MANAGE_LESS_CONTROL_ACCESS, (pTokenUser->User).Sid))
{
hr = myHLastError();
_JumpError(hr, error, "AddAccessDeniedAce");
}
}
// stick the new dacl in the sd
if(!SetSecurityDescriptorDacl(pAbsSD, TRUE, pNewDacl, FALSE))
{
hr = myHLastError();
_JumpError(hr, error, "SetSecurityDescriptorDacl");
}
// set the owner of the security descriptor as the caller
if(!SetSecurityDescriptorOwner(
pAbsSD, // SD
(pTokenUser->User).Sid, // SID for owner
FALSE)) // flag for default
{
hr = myHLastError();
goto error;
}
//convert the absolute SD to its relative form
if(!MakeSelfRelativeSD(pAbsSD, NULL, &dwRelSDSize))
{
if (ERROR_INSUFFICIENT_BUFFER!=GetLastError())
{
hr = myHLastError();
goto error;
}
}
// allocate memory
if(NULL==(pNewSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwRelSDSize)))
{
hr=E_OUTOFMEMORY;
goto error;
}
// copy the SD to the new memory buffer
if (!MakeSelfRelativeSD(pAbsSD, pNewSD, &dwRelSDSize))
{
hr = myHLastError();
goto error;
}
//set the relative SID
if(S_OK != (hr=CACertTypeSetSecurity(
hNewCertType,
pNewSD)))
goto error;
}
*phCertType=hNewCertType;
hNewCertType=NULL;
hr=S_OK;
error:
if(pdwIndex)
LocalFree(pdwIndex);
if (pNewDacl)
LocalFree(pNewDacl);
if(hToken)
CloseHandle(hToken);
if(pTokenUser)
LocalFree(pTokenUser);
if(pSID)
LocalFree(pSID);
if (NULL!=pAbsSD)
LocalFree(pAbsSD);
if (NULL!=pAbsDacl)
LocalFree(pAbsDacl);
if (NULL!=pAbsSacl)
LocalFree(pAbsSacl);
if (NULL!=pAbsOwner)
LocalFree(pAbsOwner);
if (NULL!=pAbsPriGrp)
LocalFree(pAbsPriGrp);
if (NULL!=pNewSD)
LocalFree(pNewSD);
if(awszCN)
CAFreeCertTypeProperty(hCertType, awszCN);
if(hNewCertType)
CACloseCertType(hNewCertType);
return hr;
}
HRESULT
CAEnumNextCertType(
IN HCERTTYPE hPrevCertType,
OUT HCERTTYPE * phCertTypeInfo
)
{
CCertTypeInfo *pInfo;
if(hPrevCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hPrevCertType;
return pInfo->Next((CCertTypeInfo **)phCertTypeInfo);
}
DWORD
CACountCertTypes(IN HCERTTYPE hCertType)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return 0;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->Count();
}
HRESULT
CACloseCertType(IN HCERTTYPE hCertTypeInfo)
{
CCertTypeInfo *pInfo;
if(hCertTypeInfo == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertTypeInfo;
return pInfo->Release();
}
HRESULT
CAGetCertTypeProperty(
IN HCERTTYPE hCertType,
IN LPCWSTR wszPropertyName,
OUT LPWSTR ** pawszPropertyValue)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->GetProperty(wszPropertyName, pawszPropertyValue);
}
HRESULT
CAGetCertTypePropertyEx(
IN HCERTTYPE hCertType,
IN LPCWSTR wszPropertyName,
OUT LPVOID pPropertyValue)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->GetPropertyEx(wszPropertyName, pPropertyValue);
}
HRESULT
CASetCertTypeProperty(
IN HCERTTYPE hCertType,
IN LPCWSTR wszPropertyName,
IN LPWSTR * awszPropertyValue)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetProperty(wszPropertyName, awszPropertyValue) ;
}
HRESULT
CASetCertTypePropertyEx(
IN HCERTTYPE hCertType,
IN LPCWSTR wszPropertyName,
IN LPVOID pPropertyValue)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetPropertyEx(wszPropertyName, pPropertyValue) ;
}
HRESULT
CAFreeCertTypeProperty(
IN HCERTTYPE hCertType,
LPWSTR * awszPropertyValue
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->FreeProperty(awszPropertyValue) ;
}
HRESULT
CAGetCertTypeExtensions(
IN HCERTTYPE hCertType,
OUT PCERT_EXTENSIONS * ppCertExtensions
)
{
return CAGetCertTypeExtensionsEx(hCertType, 0, NULL, ppCertExtensions);
}
HRESULT
CAGetCertTypeExtensionsEx(
IN HCERTTYPE hCertType,
IN DWORD dwFlags,
IN LPVOID, // pParam
OUT PCERT_EXTENSIONS * ppCertExtensions
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->GetExtensions(dwFlags, ppCertExtensions);
}
HRESULT
CAFreeCertTypeExtensions(
IN HCERTTYPE, // hCertType
IN PCERT_EXTENSIONS pCertExtensions
)
{
//should alreays free via LocalFree since CryptUIWizCertRequest freed
//it via LocalFree
if(pCertExtensions)
{
LocalFree(pCertExtensions);
}
return S_OK;
#if 0
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->FreeExtensions(pCertExtensions) ;
#endif
}
HRESULT
CASetCertTypeExtension(
IN HCERTTYPE hCertType,
IN LPCWSTR wszExtensionName,
IN DWORD dwFlags,
IN LPVOID pExtension
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetExtension(wszExtensionName, pExtension, dwFlags);
}
HRESULT
CAGetCertTypeFlags(
IN HCERTTYPE hCertType,
OUT DWORD * pdwFlags
)
{
return CAGetCertTypeFlagsEx(hCertType, CERTTYPE_GENERAL_FLAG, pdwFlags);
}
HRESULT
CAGetCertTypeFlagsEx(
IN HCERTTYPE hCertType,
IN DWORD dwOption,
OUT DWORD * pdwFlags
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
if(pdwFlags == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
*pdwFlags = pInfo->GetFlags(dwOption);
return S_OK;
}
HRESULT
CASetCertTypeFlags(
IN HCERTTYPE hCertType,
IN DWORD dwFlags
)
{
return CASetCertTypeFlagsEx(hCertType, CERTTYPE_GENERAL_FLAG, dwFlags);
}
HRESULT
CASetCertTypeFlagsEx(
IN HCERTTYPE hCertType,
IN DWORD dwOption,
IN DWORD dwFlags
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetFlags(dwOption, dwFlags);
}
HRESULT
CAGetCertTypeKeySpec(
IN HCERTTYPE hCertType,
OUT DWORD * pdwKeySpec
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
if(pdwKeySpec == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
*pdwKeySpec = pInfo->GetKeySpec();
return S_OK;
}
HRESULT
CASetCertTypeKeySpec(
IN HCERTTYPE hCertType,
IN DWORD dwKeySpec
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
pInfo->SetKeySpec(dwKeySpec);
return S_OK;
}
HRESULT
CAGetCertTypeExpiration(
IN HCERTTYPE hCertType,
OUT OPTIONAL FILETIME * pftExpiration,
OUT OPTIONAL FILETIME * pftOverlap
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->GetExpiration(pftExpiration, pftOverlap);
}
HRESULT
CASetCertTypeExpiration(
IN HCERTTYPE hCertType,
IN OPTIONAL FILETIME * pftExpiration,
IN OPTIONAL FILETIME * pftOverlap
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetExpiration(pftExpiration, pftOverlap);
}
HRESULT
CACertTypeSetSecurity(
IN HCERTTYPE hCertType,
IN PSECURITY_DESCRIPTOR pSD
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->SetSecurity( pSD );
}
HRESULT
CACertTypeGetSecurity(
IN HCERTTYPE hCertType,
OUT PSECURITY_DESCRIPTOR * ppSD
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->GetSecurity( ppSD ) ;
}
HRESULT
CACertTypeAccessCheck(
IN HCERTTYPE hCertType,
IN HANDLE ClientToken
)
{
return CACertTypeAccessCheckEx(hCertType, ClientToken, CERTTYPE_ACCESS_CHECK_ENROLL);
}
CERTCLIAPI
HRESULT
WINAPI
CACertTypeAccessCheckEx(
IN HCERTTYPE hCertType,
IN HANDLE ClientToken,
IN DWORD dwOption
)
{
CCertTypeInfo *pInfo;
if(hCertType == NULL)
{
return E_POINTER;
}
pInfo = (CCertTypeInfo *)hCertType;
return pInfo->AccessCheck(ClientToken, dwOption);
}
CERTCLIAPI
HRESULT
WINAPI
CAInstallDefaultCertType(
IN DWORD // dwFlags
)
{
return CCertTypeInfo::InstallDefaultTypes();
}
CERTCLIAPI
BOOL
WINAPI
CAIsCertTypeCurrent(
IN DWORD, // dwFlags
IN LPWSTR wszCertType
)
{
BOOL fCurrent=FALSE;
HRESULT hr=E_FAIL;
DWORD dwCT=0;
DWORD dwDefault=0;
DWORD dwCount=0;
BOOL fFound=FALSE;
DWORD dwFound=0;
DWORD dwVersion=0;
CCertTypeInfo *pInfo=NULL;
HCERTTYPE hNewCertType=NULL;
HCERTTYPE hCurCertType=NULL;
LPWSTR *awszCertTypeName=NULL;
//get all the templates on the directory
hr = CAEnumCertTypesEx(
NULL,
CT_ENUM_USER_TYPES | CT_ENUM_MACHINE_TYPES | CT_FLAG_NO_CACHE_LOOKUP,
&hCurCertType);
if((S_OK != hr) || (NULL==hCurCertType))
goto error;
dwCount = CACountCertTypes(hCurCertType);
if(0 == dwCount)
goto error;
//enumrating all templates on the directory
for(dwCT = 0; dwCT < dwCount; dwCT++ )
{
if(awszCertTypeName)
{
CAFreeCertTypeProperty(hCurCertType, awszCertTypeName);
awszCertTypeName=NULL;
}
//check if we have a new certificate template
if(dwCT > 0)
{
hr = CAEnumNextCertType(hCurCertType, &hNewCertType);
if((S_OK != hr) || (NULL == hNewCertType))
{
break;
}
CACloseCertType(hCurCertType);
hCurCertType=hNewCertType;
}
//get the template name
hr = CAGetCertTypePropertyEx(
hCurCertType,
CERTTYPE_PROP_DN,
&awszCertTypeName);
if((S_OK != hr) ||
(NULL == awszCertTypeName) ||
(NULL == awszCertTypeName[0])
)
{
goto error;
}
//for all templates requested, verify against the default list
if((NULL == wszCertType) || (0 == mylstrcmpiL(awszCertTypeName[0], wszCertType)))
{
if(wszCertType)
fFound=TRUE;
for(dwDefault=0; dwDefault < g_cDefaultCertTypes; dwDefault++)
{
if(0==mylstrcmpiL(awszCertTypeName[0], g_aDefaultCertTypes[dwDefault].wszName))
{
break;
}
}
//match the default name list
if(dwDefault < g_cDefaultCertTypes)
{
hr=CAGetCertTypePropertyEx(
hCurCertType,
CERTTYPE_PROP_REVISION,
&dwVersion);
if(S_OK != hr)
goto error;
if (dwVersion < g_aDefaultCertTypes[dwDefault].dwRevision)
goto error;
pInfo = (CCertTypeInfo *)hCurCertType;
if(!(pInfo->IsValidSecurityOwner()))
goto error;
//mark that we found a good default template
dwFound++;
}
}
}
//all requested template has to be checked
if(wszCertType)
{
if(FALSE == fFound)
goto error;
}
else
{
if(dwFound != g_cDefaultCertTypes)
goto error;
}
fCurrent=TRUE;
error:
if(awszCertTypeName)
{
if(hCurCertType)
{
CAFreeCertTypeProperty(hCurCertType, awszCertTypeName);
}
}
if(hCurCertType)
{
CACloseCertType(hCurCertType);
}
return fCurrent;
}
HANDLE
myEnterCriticalPolicySection(
IN BOOL bMachine)
{
HANDLE hPolicy = NULL;
HRESULT hr = S_OK;
// ?CriticalPolicySection calls are delay loaded. Protect with try/except
__try
{
hPolicy = EnterCriticalPolicySection(bMachine); // Delayload wrapped
}
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
{
}
// (S_OK == hr) does not mean EnterCriticalPolicySection succeeded.
// It just means no exception was raised.
if (myIsDelayLoadHResult(hr))
{
hPolicy = (HANDLE) (ULONG_PTR) (bMachine? 37 : 49);
hr = S_OK;
}
return(hPolicy);
}
BOOL
myLeaveCriticalPolicySection(
IN HANDLE hSection)
{
HRESULT hr = S_OK;
BOOL fOk = FALSE;
// ?CriticalPolicySection calls are delay loaded. Protect with try/except
__try
{
fOk = LeaveCriticalPolicySection(hSection); // Delayload wrapped
}
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
{
}
// (S_OK == hr) does not mean LeaveCriticalPolicySection succeeded.
// It just means no exception was raised.
if (myIsDelayLoadHResult(hr))
{
fOk = (HANDLE) (ULONG_PTR) 37 == hSection ||
(HANDLE) (ULONG_PTR) 49 == hSection;
hr = S_OK;
}
return(fOk);
}