889 lines
21 KiB
C++
889 lines
21 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
//
|
|
// File: misc.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <stdafx.h>
|
|
|
|
// sddl.h requires this value to be at least
|
|
// 0x0500. Bump it up if necessary. NOTE: This
|
|
// 'bump' comes after all other H files that may
|
|
// be sensitive to this value.
|
|
#if(_WIN32_WINNT < 0x500)
|
|
#undef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0500
|
|
#endif
|
|
|
|
#include <sddl.h>
|
|
#include <shlobj.h>
|
|
#include <dsclient.h>
|
|
#include <dsgetdc.h>
|
|
#include <lm.h>
|
|
#include <lmapibuf.h>
|
|
#include <objsel.h>
|
|
|
|
CLIPFORMAT g_cfDsObjectPicker = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
|
|
|
|
|
|
// returns (if cstr.IsEmpty()) ? NULL : cstr)
|
|
LPCWSTR GetNullMachineName(CString* pcstr)
|
|
{
|
|
LPCWSTR szMachine = (pcstr->IsEmpty()) ? NULL : (LPCWSTR)*pcstr;
|
|
return szMachine;
|
|
}
|
|
|
|
BOOL StringFromDurationUnit(DWORD dwExpirationUnits, CString* pcstr, BOOL fLocalized)
|
|
{
|
|
if (NULL == pcstr)
|
|
return FALSE;
|
|
|
|
UINT uiRsc = 0;
|
|
|
|
switch (dwExpirationUnits)
|
|
{
|
|
case(ENUM_PERIOD_YEARS):
|
|
if (fLocalized)
|
|
uiRsc = IDS_PERIOD_YEARS;
|
|
else
|
|
*pcstr = wszPERIODYEARS;
|
|
break;
|
|
case(ENUM_PERIOD_MONTHS):
|
|
if (fLocalized)
|
|
uiRsc = IDS_PERIOD_MONTHS;
|
|
else
|
|
*pcstr = wszPERIODMONTHS;
|
|
break;
|
|
case(ENUM_PERIOD_WEEKS):
|
|
if (fLocalized)
|
|
uiRsc = IDS_PERIOD_WEEKS;
|
|
else
|
|
*pcstr = wszPERIODWEEKS;
|
|
break;
|
|
case(ENUM_PERIOD_DAYS):
|
|
if (fLocalized)
|
|
uiRsc = IDS_PERIOD_DAYS;
|
|
else
|
|
*pcstr = wszPERIODDAYS;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (uiRsc)
|
|
pcstr->LoadString(uiRsc);
|
|
|
|
return !pcstr->IsEmpty();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// fxns to load/save cstrings to a streams
|
|
STDMETHODIMP CStringLoad(CString& cstr, IStream *pStm)
|
|
{
|
|
ASSERT(pStm);
|
|
HRESULT hr;
|
|
|
|
DWORD cbSize=0;
|
|
ULONG nBytesRead;
|
|
|
|
// get cbSize (bytes)
|
|
hr = pStm->Read(&cbSize, sizeof(cbSize), &nBytesRead);
|
|
ASSERT(SUCCEEDED(hr) && (nBytesRead == sizeof(cbSize)) );
|
|
|
|
if (FAILED(hr))
|
|
return E_FAIL;
|
|
|
|
// get string
|
|
hr = pStm->Read(cstr.GetBuffer(cbSize), cbSize, &nBytesRead);
|
|
ASSERT(SUCCEEDED(hr) && (nBytesRead == cbSize));
|
|
|
|
cstr.ReleaseBuffer();
|
|
|
|
return SUCCEEDED(hr) ? S_OK : E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP CStringSave(CString& cstr, IStream *pStm, BOOL fClearDirty)
|
|
{
|
|
// Write the string
|
|
DWORD cbSize = (cstr.GetLength()+1)*sizeof(WCHAR);
|
|
ULONG nBytesWritten;
|
|
HRESULT hr;
|
|
|
|
// write size in bytes
|
|
hr = pStm->Write(&cbSize, sizeof(cbSize), &nBytesWritten);
|
|
ASSERT(SUCCEEDED(hr) && (nBytesWritten == sizeof(cbSize)) );
|
|
|
|
if (FAILED(hr))
|
|
return STG_E_CANTSAVE;
|
|
|
|
// write string
|
|
hr = pStm->Write((LPCWSTR)cstr, cbSize, &nBytesWritten);
|
|
ASSERT(SUCCEEDED(hr) && (nBytesWritten == cbSize));
|
|
|
|
// Verify that the write operation succeeded
|
|
return SUCCEEDED(hr) ? S_OK : STG_E_CANTSAVE;
|
|
}
|
|
|
|
LPSTR AllocAndCopyStr(LPCSTR psz)
|
|
{
|
|
LPSTR pszReturn;
|
|
|
|
pszReturn = (LPSTR) new(BYTE[strlen(psz)+1]);
|
|
if(pszReturn)
|
|
{
|
|
strcpy(pszReturn, psz);
|
|
}
|
|
return pszReturn;
|
|
}
|
|
|
|
|
|
LPWSTR AllocAndCopyStr(LPCWSTR pwsz)
|
|
{
|
|
LPWSTR pwszReturn;
|
|
|
|
pwszReturn = (LPWSTR) new(WCHAR[wcslen(pwsz)+1]);
|
|
if(pwszReturn)
|
|
{
|
|
wcscpy(pwszReturn, pwsz);
|
|
}
|
|
return pwszReturn;
|
|
}
|
|
|
|
LPWSTR BuildErrorMessage(DWORD dwErr)
|
|
{
|
|
LPWSTR lpMsgBuf = NULL;
|
|
FormatMessageW(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
dwErr,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPWSTR) &lpMsgBuf,
|
|
0,
|
|
NULL );
|
|
return lpMsgBuf;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// given an error code and a console pointer, will pop error dlg
|
|
void DisplayGenericCertSrvError(LPCONSOLE2 pConsole, DWORD dwErr)
|
|
{
|
|
ASSERT(pConsole);
|
|
LPWSTR lpMsgBuf = BuildErrorMessage(dwErr);
|
|
|
|
|
|
if(lpMsgBuf)
|
|
{
|
|
// ...
|
|
// Display the string.
|
|
pConsole->MessageBoxW(lpMsgBuf, L"Certificate Services Error", MB_OK | MB_ICONINFORMATION, NULL);
|
|
|
|
// Free the buffer.
|
|
LocalFree( lpMsgBuf );
|
|
}
|
|
}
|
|
// returns localized, stringized time
|
|
BOOL FileTimeToLocalTimeString(FILETIME* pftGMT, LPWSTR* ppszTmp)
|
|
{
|
|
FILETIME ftLocal;
|
|
if (FileTimeToLocalFileTime(pftGMT, &ftLocal))
|
|
{
|
|
SYSTEMTIME sysLocal;
|
|
if (FileTimeToSystemTime(
|
|
&ftLocal,
|
|
&sysLocal))
|
|
{
|
|
WCHAR rgTmpDate[128], rgTmpTime[128];
|
|
DWORD dwLen;
|
|
dwLen = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &sysLocal,
|
|
NULL, rgTmpDate, ARRAYLEN(rgTmpDate));
|
|
|
|
dwLen += GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &sysLocal,
|
|
NULL, rgTmpTime, ARRAYLEN(rgTmpTime));
|
|
|
|
dwLen += sizeof(L" ");
|
|
|
|
*ppszTmp = new WCHAR[dwLen];
|
|
if(*ppszTmp == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
wcscpy(*ppszTmp, rgTmpDate);
|
|
wcscat(*ppszTmp, L" ");
|
|
wcscat(*ppszTmp, rgTmpTime);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void MyErrorBox(HWND hwndParent, UINT nIDText, UINT nIDCaption, DWORD dwErrorCode)
|
|
{
|
|
CString cstrTitle, cstrFormatText, cstrFullText;
|
|
cstrTitle.LoadString(nIDCaption);
|
|
cstrFormatText.LoadString(nIDText);
|
|
|
|
WCHAR const *pwszError = NULL;
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
pwszError = myGetErrorMessageText(dwErrorCode, TRUE);
|
|
|
|
cstrFullText.Format(cstrFormatText, pwszError);
|
|
|
|
// Free the buffer
|
|
if (NULL != pwszError)
|
|
{
|
|
LocalFree(const_cast<WCHAR *>(pwszError));
|
|
}
|
|
}
|
|
|
|
::MessageBoxW(hwndParent, cstrFullText, cstrTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
|
|
|
|
BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
|
|
{
|
|
PCCRYPT_OID_INFO pOIDInfo;
|
|
|
|
pOIDInfo = CryptFindOIDInfo(
|
|
CRYPT_OID_INFO_OID_KEY,
|
|
pszObjId,
|
|
0);
|
|
|
|
if (pOIDInfo != NULL)
|
|
{
|
|
if (wcslen(pOIDInfo->pwszName)+1 <= stringSize)
|
|
{
|
|
wcscpy(string, pOIDInfo->pwszName);
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL MyGetEnhancedKeyUsages(HCERTTYPE hCertType, CString **aszUsages, DWORD *cUsages, BOOL *pfCritical, BOOL fGetOIDSNotNames)
|
|
{
|
|
PCERT_EXTENSIONS pCertExtensions;
|
|
CERT_ENHKEY_USAGE *pehku;
|
|
DWORD cb = 0;
|
|
WCHAR OIDName[256];
|
|
unsigned int i;
|
|
LPWSTR pwszOID;
|
|
HRESULT hr;
|
|
|
|
CSASSERT(cUsages);
|
|
|
|
if(aszUsages)
|
|
*aszUsages = NULL;
|
|
|
|
hr = CAGetCertTypeExtensions(hCertType, &pCertExtensions);
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
i = 0;
|
|
while ((i<pCertExtensions->cExtension) &&
|
|
(strcmp(pCertExtensions->rgExtension[i].pszObjId, szOID_ENHANCED_KEY_USAGE) != 0))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if (i >= pCertExtensions->cExtension)
|
|
{
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pfCritical != NULL)
|
|
{
|
|
*pfCritical = pCertExtensions->rgExtension[i].fCritical;
|
|
}
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ENHANCED_KEY_USAGE,
|
|
pCertExtensions->rgExtension[i].Value.pbData,
|
|
pCertExtensions->rgExtension[i].Value.cbData,
|
|
0,
|
|
NULL,
|
|
&cb);
|
|
|
|
if (NULL == (pehku = (CERT_ENHKEY_USAGE *) new(BYTE[cb])))
|
|
{
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return FALSE;
|
|
}
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_ENHANCED_KEY_USAGE,
|
|
pCertExtensions->rgExtension[i].Value.pbData,
|
|
pCertExtensions->rgExtension[i].Value.cbData,
|
|
0,
|
|
pehku,
|
|
&cb);
|
|
|
|
if(!aszUsages)
|
|
{
|
|
// only retrieving the usage count
|
|
*cUsages = pehku->cUsageIdentifier;
|
|
}
|
|
else
|
|
{
|
|
// retrieving usage strings, count better match
|
|
CSASSERT(*cUsages == pehku->cUsageIdentifier);
|
|
|
|
for (i=0; i<pehku->cUsageIdentifier; i++)
|
|
{
|
|
if (fGetOIDSNotNames)
|
|
{
|
|
pwszOID = MyMkWStr(pehku->rgpszUsageIdentifier[i]);
|
|
aszUsages[i]= new CString(pwszOID);
|
|
delete(pwszOID);
|
|
if(aszUsages[i] == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
MyGetOIDInfo(OIDName, sizeof(OIDName)/sizeof(WCHAR), pehku->rgpszUsageIdentifier[i]);
|
|
aszUsages[i]= new CString(OIDName);
|
|
if(aszUsages[i] == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete[](pehku);
|
|
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL GetIntendedUsagesString(HCERTTYPE hCertType, CString *pUsageString)
|
|
{
|
|
CString **aszUsages = NULL;
|
|
DWORD cNumUsages = 0;
|
|
unsigned int i;
|
|
|
|
if(!MyGetEnhancedKeyUsages(hCertType, NULL, &cNumUsages, NULL, FALSE))
|
|
return FALSE;
|
|
|
|
if(0==cNumUsages)
|
|
{
|
|
*pUsageString = "";
|
|
return TRUE;
|
|
}
|
|
|
|
aszUsages = new CString*[cNumUsages];
|
|
if(!aszUsages)
|
|
return FALSE;
|
|
|
|
if(!MyGetEnhancedKeyUsages(hCertType, aszUsages, &cNumUsages, NULL, FALSE))
|
|
{
|
|
delete[] aszUsages;
|
|
return FALSE;
|
|
}
|
|
|
|
*pUsageString = "";
|
|
|
|
for (i=0; i<cNumUsages; i++)
|
|
{
|
|
if (i != 0)
|
|
{
|
|
*pUsageString += ", ";
|
|
}
|
|
*pUsageString += *(aszUsages[i]);
|
|
|
|
delete(aszUsages[i]);
|
|
}
|
|
|
|
delete[] aszUsages;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL MyGetKeyUsages(HCERTTYPE hCertType, CRYPT_BIT_BLOB **ppBitBlob, BOOL *pfPublicKeyUsageCritical)
|
|
{
|
|
PCERT_EXTENSIONS pCertExtensions;
|
|
DWORD cb = 0;
|
|
unsigned int i;
|
|
|
|
HRESULT hr;
|
|
hr = CAGetCertTypeExtensions(hCertType, &pCertExtensions);
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
i = 0;
|
|
while ((i<pCertExtensions->cExtension) && (strcmp(pCertExtensions->rgExtension[i].pszObjId, szOID_KEY_USAGE) != 0))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if (i >= pCertExtensions->cExtension)
|
|
{
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pfPublicKeyUsageCritical != NULL)
|
|
{
|
|
*pfPublicKeyUsageCritical = pCertExtensions->rgExtension[i].fCritical;
|
|
}
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_KEY_USAGE,
|
|
pCertExtensions->rgExtension[i].Value.pbData,
|
|
pCertExtensions->rgExtension[i].Value.cbData,
|
|
0,
|
|
NULL,
|
|
&cb);
|
|
|
|
if (NULL == (*ppBitBlob = (CRYPT_BIT_BLOB *) new(BYTE[cb])))
|
|
{
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return FALSE;
|
|
}
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_KEY_USAGE,
|
|
pCertExtensions->rgExtension[i].Value.pbData,
|
|
pCertExtensions->rgExtension[i].Value.cbData,
|
|
0,
|
|
*ppBitBlob,
|
|
&cb);
|
|
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MyGetBasicConstraintInfo(HCERTTYPE hCertType, BOOL *pfCA, BOOL *pfPathLenConstraint, DWORD *pdwPathLenConstraint)
|
|
{
|
|
PCERT_EXTENSIONS pCertExtensions;
|
|
DWORD cb = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
|
|
unsigned int i;
|
|
CERT_BASIC_CONSTRAINTS2_INFO basicConstraintsInfo;
|
|
|
|
HRESULT hr;
|
|
hr = CAGetCertTypeExtensions(hCertType, &pCertExtensions);
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
i = 0;
|
|
while ((i<pCertExtensions->cExtension) && (strcmp(pCertExtensions->rgExtension[i].pszObjId, szOID_BASIC_CONSTRAINTS2) != 0))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
if (i >= pCertExtensions->cExtension)
|
|
{
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return FALSE;
|
|
}
|
|
|
|
CryptDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_BASIC_CONSTRAINTS2,
|
|
pCertExtensions->rgExtension[i].Value.pbData,
|
|
pCertExtensions->rgExtension[i].Value.cbData,
|
|
0,
|
|
&basicConstraintsInfo,
|
|
&cb);
|
|
|
|
*pfCA = basicConstraintsInfo.fCA;
|
|
*pfPathLenConstraint = basicConstraintsInfo.fPathLenConstraint;
|
|
*pdwPathLenConstraint = basicConstraintsInfo.dwPathLenConstraint;
|
|
|
|
CAFreeCertTypeExtensions(hCertType, pCertExtensions);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LPSTR MyMkMBStr(LPCWSTR pwsz)
|
|
{
|
|
int cb;
|
|
LPSTR psz;
|
|
|
|
if (pwsz == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cb = WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pwsz,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (NULL == (psz = (LPSTR) new BYTE[cb]))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cb = WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pwsz,
|
|
-1,
|
|
psz,
|
|
cb,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (cb==0)
|
|
{
|
|
delete [] psz;
|
|
return NULL;
|
|
}
|
|
return(psz);
|
|
}
|
|
|
|
LPWSTR MyMkWStr(LPCSTR psz)
|
|
{
|
|
int cWChars;
|
|
LPWSTR pwsz;
|
|
|
|
if (psz == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cWChars = MultiByteToWideChar(
|
|
0,
|
|
0,
|
|
psz,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
|
|
if (NULL == (pwsz = (LPWSTR) new BYTE[cWChars * sizeof(WCHAR)] ))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cWChars = MultiByteToWideChar(
|
|
0,
|
|
0,
|
|
psz,
|
|
-1,
|
|
pwsz,
|
|
cWChars);
|
|
|
|
if (cWChars == 0)
|
|
{
|
|
delete [] pwsz;
|
|
return NULL;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
BOOL IsCerttypeEditingAllowed()
|
|
{
|
|
DWORD lResult;
|
|
HKEY hKey = NULL;
|
|
DWORD dwType;
|
|
DWORD dwEnabled = 0;
|
|
DWORD cbEnabled = sizeof(dwEnabled);
|
|
lResult = RegOpenKeyEx (HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\Cryptography\\CertificateTemplateCache",
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
lResult = RegQueryValueEx(hKey,
|
|
REGSZ_ENABLE_CERTTYPE_EDITING,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)&dwEnabled,
|
|
&cbEnabled);
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
if(dwType != REG_DWORD)
|
|
{
|
|
dwEnabled = 0;
|
|
}
|
|
}
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
return (dwEnabled != 0);
|
|
}
|
|
|
|
HRESULT RetrieveCATemplateListFromCA(
|
|
HCAINFO hCAInfo,
|
|
CTemplateList& list)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR *ppwszDNSName = NULL;
|
|
LPWSTR *ppwszAuthority = NULL;
|
|
ICertAdminD2 *pAdminD2 = NULL;
|
|
DWORD dwServerVersion = 2;
|
|
CERTTRANSBLOB ctbSD;
|
|
|
|
ZeroMemory(&ctbSD, sizeof(CERTTRANSBLOB));
|
|
|
|
hr = CAGetCAProperty(hCAInfo, CA_PROP_DNSNAME, &ppwszDNSName);
|
|
_JumpIfError(hr, error, "CAGetCAProperty CA_PROP_DNSNAME");
|
|
|
|
hr = CAGetCAProperty(hCAInfo, CA_PROP_NAME, &ppwszAuthority);
|
|
_JumpIfError(hr, error, "CAGetCAProperty CA_PROP_DNSNAME");
|
|
|
|
ASSERT(ppwszDNSName[0]);
|
|
|
|
hr = myOpenAdminDComConnection(
|
|
ppwszDNSName[0],
|
|
NULL,
|
|
NULL,
|
|
&dwServerVersion,
|
|
&pAdminD2);
|
|
_JumpIfError(hr, error, "myOpenAdminDComConnection");
|
|
|
|
if (2 > dwServerVersion)
|
|
{
|
|
hr = RPC_E_VERSION_MISMATCH;
|
|
_JumpError(hr, error, "old server");
|
|
}
|
|
|
|
CSASSERT(ppwszAuthority[0]);
|
|
|
|
hr = pAdminD2->GetCAProperty(
|
|
ppwszAuthority[0],
|
|
CR_PROP_TEMPLATES,
|
|
0,
|
|
PROPTYPE_STRING,
|
|
&ctbSD);
|
|
_JumpIfErrorStr(hr, error, "ICertAdminD2::GetCAProperty CR_PROP_TEMPLATES",
|
|
ppwszDNSName[0]);
|
|
|
|
hr = list.Unmarshal(ctbSD.pb, ctbSD.cb);
|
|
_JumpIfError(hr, error, "CTemplateList::Unmarshal");
|
|
|
|
error:
|
|
if(ppwszDNSName)
|
|
CAFreeCAProperty(hCAInfo, ppwszDNSName);
|
|
|
|
if(ppwszAuthority)
|
|
CAFreeCAProperty(hCAInfo, ppwszAuthority);
|
|
|
|
if(pAdminD2)
|
|
pAdminD2->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT RetrieveCATemplateListFromDS(
|
|
HCAINFO hCAInfo,
|
|
CTemplateList& list)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCERTTYPE hCertTypeNext, hCertTypePrev;
|
|
|
|
hr = CAEnumCertTypesForCA(
|
|
hCAInfo,
|
|
CT_ENUM_MACHINE_TYPES |
|
|
CT_ENUM_USER_TYPES |
|
|
CT_FLAG_NO_CACHE_LOOKUP,
|
|
&hCertTypeNext);
|
|
_JumpIfError(hr, error, "CAEnumCertTypesForCA");
|
|
|
|
while (hCertTypeNext != NULL)
|
|
{
|
|
hr = list.AddTemplateInfo(hCertTypeNext);
|
|
_JumpIfError(hr, error, "CTemplateList::AddTemplate");
|
|
|
|
hCertTypePrev = hCertTypeNext;
|
|
hr = CAEnumNextCertType(hCertTypePrev, &hCertTypeNext);
|
|
_JumpIfError(hr, error, "CAEnumNextCertType");
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT RetrieveCATemplateList(
|
|
HCAINFO hCAInfo,
|
|
CTemplateList& list)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = RetrieveCATemplateListFromCA(hCAInfo, list);
|
|
if(S_OK != hr)
|
|
{
|
|
// if failed to retrieve from the CA for any reason, try
|
|
// fetching from DS
|
|
|
|
hr = RetrieveCATemplateListFromDS(hCAInfo, list);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT UpdateCATemplateListToDS(
|
|
HCAINFO hCAInfo,
|
|
const CTemplateList& list)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CAUpdateCA(hCAInfo);
|
|
_JumpIfError(hr, error, "CAUpdateCA");
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT UpdateCATemplateListToCA(
|
|
HCAINFO hCAInfo,
|
|
const CTemplateList& list)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR *ppwszDNSName = NULL;
|
|
LPWSTR *ppwszAuthority = NULL;
|
|
ICertAdminD2 *pAdminD2 = NULL;
|
|
DWORD dwServerVersion = 2;
|
|
CERTTRANSBLOB ctbSD;
|
|
|
|
ZeroMemory(&ctbSD, sizeof(CERTTRANSBLOB));
|
|
|
|
hr = CAGetCAProperty(hCAInfo, CA_PROP_DNSNAME, &ppwszDNSName);
|
|
_JumpIfError(hr, error, "CAGetCAProperty CA_PROP_DNSNAME");
|
|
|
|
hr = CAGetCAProperty(hCAInfo, CA_PROP_NAME, &ppwszAuthority);
|
|
_JumpIfError(hr, error, "CAGetCAProperty CA_PROP_DNSNAME");
|
|
|
|
ASSERT(ppwszDNSName[0]);
|
|
|
|
hr = myOpenAdminDComConnection(
|
|
ppwszDNSName[0],
|
|
NULL,
|
|
NULL,
|
|
&dwServerVersion,
|
|
&pAdminD2);
|
|
_JumpIfError(hr, error, "myOpenAdminDComConnection");
|
|
|
|
if (2 > dwServerVersion)
|
|
{
|
|
hr = RPC_E_VERSION_MISMATCH;
|
|
_JumpError(hr, error, "old server");
|
|
}
|
|
|
|
CSASSERT(ppwszAuthority[0]);
|
|
|
|
hr = list.Marshal(ctbSD.pb, ctbSD.cb);
|
|
_JumpIfError(hr, error, "CTemplateList::Marshal");
|
|
|
|
CSASSERT(S_OK==list.ValidateMarshalBuffer(ctbSD.pb, ctbSD.cb));
|
|
|
|
hr = pAdminD2->SetCAProperty(
|
|
ppwszAuthority[0],
|
|
CR_PROP_TEMPLATES,
|
|
0,
|
|
PROPTYPE_STRING,
|
|
&ctbSD);
|
|
_JumpIfErrorStr(hr, error, "ICertAdminD2::SetCAProperty CR_PROP_TEMPLATES",
|
|
ppwszDNSName[0]);
|
|
|
|
error:
|
|
if(ppwszDNSName)
|
|
CAFreeCAProperty(hCAInfo, ppwszDNSName);
|
|
|
|
if(ppwszAuthority)
|
|
CAFreeCAProperty(hCAInfo, ppwszAuthority);
|
|
|
|
if(pAdminD2)
|
|
pAdminD2->Release();
|
|
|
|
if(ctbSD.pb)
|
|
MIDL_user_free(ctbSD.pb);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT UpdateCATemplateList(
|
|
HCAINFO hCAInfo,
|
|
const CTemplateList& list)
|
|
{
|
|
HRESULT hr = UpdateCATemplateListToCA(hCAInfo, list);
|
|
if(S_OK != hr)
|
|
{
|
|
// if failed to update through the CA for any reason, try
|
|
// writing directly to DS
|
|
|
|
hr = UpdateCATemplateListToDS(hCAInfo, list);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT AddToCATemplateList(
|
|
HCAINFO hCAInfo,
|
|
CTemplateList& list,
|
|
HCERTTYPE hCertType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
hr = CAAddCACertificateType(hCAInfo, hCertType);
|
|
_JumpIfError(hr, error, "CAAddCACertificateType");
|
|
|
|
hr = list.AddTemplateInfo(hCertType);
|
|
_JumpIfError(hr, error, "CTemplateList::AddTemplateInfo HCERTTYPE");
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT RemoveFromCATemplateList(
|
|
HCAINFO hCAInfo,
|
|
CTemplateList& list,
|
|
HCERTTYPE hCertType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CARemoveCACertificateType(hCAInfo, hCertType);
|
|
_JumpIfError(hr, error, "CARemoveCACertificateType");
|
|
|
|
hr = list.RemoveTemplateInfo(hCertType);
|
|
_JumpIfError(hr, error, "CTemplateList::RemoveTemplateInfo HCERTTYPE");
|
|
|
|
error:
|
|
return hr;
|
|
|
|
} |