2623 lines
60 KiB
C++
2623 lines
60 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: reg.cpp
|
|
//
|
|
// Contents: Cert Server wrapper routines
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <sddl.h>
|
|
#include <assert.h>
|
|
|
|
#include "certacl.h"
|
|
#include "polreg.h"
|
|
|
|
|
|
HRESULT
|
|
myFormCertRegPath(
|
|
IN WCHAR const *pwszName1,
|
|
IN WCHAR const *pwszName2,
|
|
IN WCHAR const *pwszName3,
|
|
IN BOOL fConfigLevel, // from CertSrv if FALSE
|
|
OUT WCHAR **ppwszPath)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszPath = NULL;
|
|
DWORD len1;
|
|
DWORD len2;
|
|
DWORD len3;
|
|
|
|
len1 = NULL != pwszName1 ? wcslen(pwszName1) + 1 : 0;
|
|
len2 = 0 != len1 && NULL != pwszName2 ? wcslen(pwszName2) + 1 : 0;
|
|
len3 = 0 != len2 && NULL != pwszName3 ? wcslen(pwszName3) + 1 : 0;
|
|
|
|
pwszPath = (WCHAR*)LocalAlloc(
|
|
LMEM_FIXED | LMEM_ZEROINIT,
|
|
((fConfigLevel?
|
|
WSZARRAYSIZE(wszREGKEYCONFIGPATH) :
|
|
WSZARRAYSIZE(wszREGKEYCERTSVCPATH)) +
|
|
len1 +
|
|
len2 +
|
|
len3 +
|
|
1) * sizeof(WCHAR));
|
|
if (NULL == pwszPath)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
wcscpy(pwszPath, fConfigLevel? wszREGKEYCONFIGPATH : wszREGKEYCERTSVCPATH);
|
|
|
|
if (NULL != pwszName1)
|
|
{
|
|
wcscat(pwszPath, L"\\");
|
|
wcscat(pwszPath, pwszName1);
|
|
if (NULL != pwszName2)
|
|
{
|
|
wcscat(pwszPath, L"\\");
|
|
wcscat(pwszPath, pwszName2);
|
|
if (NULL != pwszName3)
|
|
{
|
|
wcscat(pwszPath, L"\\");
|
|
wcscat(pwszPath, pwszName3);
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppwszPath = pwszPath;
|
|
pwszPath = NULL;
|
|
|
|
hr = S_OK;
|
|
error:
|
|
if (NULL != pwszPath)
|
|
{
|
|
LocalFree(pwszPath);
|
|
}
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myDeleteCertRegValueEx(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN BOOL fAbsolutePath)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = NULL;
|
|
WCHAR *pwszTemp = NULL;
|
|
|
|
if (!fAbsolutePath)
|
|
{
|
|
hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, TRUE, &pwszTemp);
|
|
_JumpIfError(hr, error, "myFormCertRegPath");
|
|
}
|
|
else
|
|
{
|
|
CSASSERT(NULL == pwszName2 && NULL == pwszName3);
|
|
}
|
|
|
|
hr = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
fAbsolutePath ? pwszName1 : pwszTemp,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey);
|
|
_JumpIfError(hr, error, "RegOpenKeyEx");
|
|
|
|
hr = RegDeleteValue(hKey, pwszValueName);
|
|
if ((HRESULT) ERROR_FILE_NOT_FOUND != hr)
|
|
{
|
|
_JumpIfError(hr, error, "RegDeleteValue");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myDeleteCertRegValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName)
|
|
{
|
|
return myDeleteCertRegValueEx(pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
FALSE);
|
|
}
|
|
|
|
HRESULT
|
|
myDeleteCertRegKeyEx(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN BOOL fConfigLevel)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszTemp = NULL;
|
|
|
|
hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
|
|
_JumpIfError(hr, error, "myFormCertRegPath");
|
|
|
|
hr = RegDeleteKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
pwszTemp);
|
|
_JumpIfError(hr, error, "RegDeleteKey");
|
|
|
|
hr = S_OK;
|
|
error:
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myDeleteCertRegKey(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3)
|
|
{
|
|
return myDeleteCertRegKeyEx(pwszName1, pwszName2, pwszName3, TRUE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myCreateCertRegKeyEx(
|
|
IN BOOL fSetAcl,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = NULL;
|
|
DWORD dwDisposition;
|
|
WCHAR *pwszTemp = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, TRUE, &pwszTemp);
|
|
_JumpIfError(hr, error, "myFormCertRegPath");
|
|
|
|
hr = RegCreateKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
pwszTemp,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition);
|
|
_JumpIfError(hr, error, "RegCreateKeyEx");
|
|
|
|
if (fSetAcl)
|
|
{
|
|
// construct correct reg acl for the key if upgrade
|
|
hr = myGetSDFromTemplate(WSZ_DEFAULT_UPGRADE_SECURITY,
|
|
NULL,
|
|
&pSD);
|
|
if (S_OK == hr)
|
|
{
|
|
// set to correct acl
|
|
hr = RegSetKeySecurity(hKey,
|
|
DACL_SECURITY_INFORMATION,
|
|
pSD);
|
|
_PrintIfError(hr, "RegSetKeySecurity");
|
|
}
|
|
else
|
|
{
|
|
_PrintError(hr, "myGetSDFromTemplate");
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
error:
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
if (NULL != pSD)
|
|
{
|
|
LocalFree(pSD);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
HRESULT
|
|
myCreateCertRegKey(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3)
|
|
{
|
|
return myCreateCertRegKeyEx(FALSE, // not upgrade
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3);
|
|
}
|
|
|
|
HRESULT
|
|
mySetCertRegValueEx(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN BOOL fConfigLevel,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN DWORD const dwValueType,
|
|
IN BYTE const *pbData,
|
|
IN DWORD const cbData,
|
|
IN BOOL fAbsolutePath)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = NULL;
|
|
WCHAR *pwszTemp = NULL;
|
|
BOOL fFree = TRUE;
|
|
DWORD dwDisposition;
|
|
HKEY hBaseKey = NULL;
|
|
DWORD cbD = cbData;
|
|
|
|
if (!fAbsolutePath)
|
|
{
|
|
hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
|
|
_JumpIfError(hr, error, "myFormCertRegPath");
|
|
}
|
|
|
|
if (pwszMachine)
|
|
{
|
|
hr = RegConnectRegistry(
|
|
pwszMachine,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hBaseKey);
|
|
_JumpIfError(hr, error, "RegConnectRegistry");
|
|
}
|
|
else
|
|
hBaseKey = HKEY_LOCAL_MACHINE;
|
|
|
|
hr = RegCreateKeyEx(
|
|
hBaseKey,
|
|
fAbsolutePath ? pwszName1 : pwszTemp,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition);
|
|
_JumpIfError(hr, error, "RegCreateKeyEx");
|
|
|
|
if (NULL != pwszValueName)
|
|
{
|
|
if(NULL == pbData || 0 == cbData)
|
|
{
|
|
switch(dwValueType)
|
|
{
|
|
case REG_EXPAND_SZ:
|
|
case REG_SZ:
|
|
pbData = (BYTE*) L"";
|
|
cbD = sizeof (L"");
|
|
break;
|
|
case REG_MULTI_SZ:
|
|
pbData = (BYTE*) L"\0";
|
|
cbD = sizeof (L"\0");
|
|
break;
|
|
}
|
|
}
|
|
hr = RegSetValueEx(
|
|
hKey,
|
|
pwszValueName,
|
|
0,
|
|
dwValueType,
|
|
pbData,
|
|
cbD);
|
|
_JumpIfError(hr, error, "RegSetValueEx");
|
|
}
|
|
|
|
hr = S_OK;
|
|
error:
|
|
if ((NULL != hBaseKey) && (HKEY_LOCAL_MACHINE != hBaseKey))
|
|
{
|
|
RegCloseKey(hBaseKey);
|
|
}
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
HRESULT
|
|
mySetCertRegValue(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN DWORD const dwValueType,
|
|
IN BYTE const *pbData,
|
|
IN DWORD const cbData,
|
|
IN BOOL fAbsolutePath)
|
|
{
|
|
return mySetCertRegValueEx(pwszMachine,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
TRUE, //from Configuration
|
|
pwszValueName,
|
|
dwValueType,
|
|
pbData,
|
|
cbData,
|
|
fAbsolutePath);
|
|
}
|
|
|
|
HRESULT
|
|
myGetCertRegValueEx(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN BOOL fConfigLevel,
|
|
IN WCHAR const *pwszValueName,
|
|
OUT BYTE **ppbData,
|
|
OPTIONAL OUT DWORD *pcbData,
|
|
OPTIONAL OUT DWORD *pValueType)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKey = NULL;
|
|
WCHAR *pwszTemp = NULL;
|
|
DWORD dwDisposition;
|
|
DWORD dwType;
|
|
DWORD dwLen;
|
|
BYTE *pbData = NULL;
|
|
DWORD cbZero = 0;
|
|
HKEY hBaseKey = NULL;
|
|
|
|
*ppbData = NULL;
|
|
if (NULL != pcbData)
|
|
{
|
|
*pcbData = 0;
|
|
}
|
|
if (NULL != pValueType)
|
|
{
|
|
*pValueType = REG_NONE;
|
|
}
|
|
|
|
hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
|
|
_JumpIfError(hr, error, "myFormCertRegPath");
|
|
|
|
if (pwszMachine)
|
|
{
|
|
hr = RegConnectRegistry(
|
|
pwszMachine,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hBaseKey);
|
|
_JumpIfError(hr, error, "RegConnectRegistry");
|
|
}
|
|
else
|
|
hBaseKey = HKEY_LOCAL_MACHINE;
|
|
|
|
hr = RegOpenKeyEx(
|
|
hBaseKey,
|
|
pwszTemp,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
_JumpIfError2(hr, error, "RegOpenKeyEx", ERROR_FILE_NOT_FOUND);
|
|
|
|
while (TRUE)
|
|
{
|
|
hr = RegQueryValueEx(
|
|
hKey,
|
|
pwszValueName,
|
|
0,
|
|
&dwType,
|
|
pbData,
|
|
&dwLen);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"RegQueryValueEx",
|
|
pwszValueName,
|
|
ERROR_FILE_NOT_FOUND);
|
|
|
|
if (NULL != pbData)
|
|
{
|
|
ZeroMemory(&pbData[dwLen], cbZero);
|
|
break;
|
|
}
|
|
|
|
// Enforce WCHAR-aligned double null termination for malformed values.
|
|
// Some callers need to treat REG_SZ values as REG_MULTI_SZ.
|
|
|
|
if (REG_MULTI_SZ == dwType || REG_SZ == dwType)
|
|
{
|
|
cbZero = 2 * sizeof(WCHAR);
|
|
if (dwLen & (sizeof(WCHAR) - 1))
|
|
{
|
|
cbZero++;
|
|
}
|
|
}
|
|
pbData = (BYTE *) LocalAlloc(LMEM_FIXED, dwLen + cbZero);
|
|
if (NULL == pbData)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
}
|
|
if (NULL != pValueType)
|
|
{
|
|
*pValueType = dwType;
|
|
}
|
|
if (NULL != pcbData)
|
|
{
|
|
*pcbData = dwLen;
|
|
}
|
|
*ppbData = pbData;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if ((NULL != hBaseKey) && (hBaseKey != HKEY_LOCAL_MACHINE))
|
|
{
|
|
RegCloseKey(hBaseKey);
|
|
}
|
|
|
|
if (NULL != pwszTemp)
|
|
{
|
|
LocalFree(pwszTemp);
|
|
}
|
|
if (NULL != hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
HRESULT
|
|
myGetCertRegValue(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN WCHAR const *pwszValueName,
|
|
OUT BYTE **ppbData,
|
|
OPTIONAL OUT DWORD *pcbData,
|
|
OPTIONAL OUT DWORD *pValueType)
|
|
{
|
|
return myGetCertRegValueEx(pwszMachine,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
TRUE, //from Configuration
|
|
pwszValueName,
|
|
ppbData,
|
|
pcbData,
|
|
pValueType);
|
|
}
|
|
|
|
HRESULT
|
|
mySetCertRegMultiStrValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszzValue)
|
|
{
|
|
DWORD cwc = 0;
|
|
DWORD cwcT;
|
|
WCHAR const *pwc;
|
|
|
|
if (NULL != pwszzValue)
|
|
{
|
|
for (pwc = pwszzValue; L'\0' != *pwc; cwc += cwcT, pwc += cwcT)
|
|
{
|
|
cwcT = wcslen(pwc) + 1;
|
|
}
|
|
cwc++;
|
|
}
|
|
|
|
return(mySetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
REG_MULTI_SZ,
|
|
(BYTE const *) pwszzValue,
|
|
cwc * sizeof(WCHAR),
|
|
FALSE));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
mySetCertRegStrValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszValue)
|
|
{
|
|
DWORD cwc = 0;
|
|
|
|
if (NULL != pwszValue)
|
|
{
|
|
cwc = wcslen(pwszValue) + 1;
|
|
}
|
|
return mySetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
REG_SZ,
|
|
(BYTE const *) pwszValue,
|
|
cwc * sizeof(WCHAR),
|
|
FALSE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
mySetAbsRegMultiStrValue(
|
|
IN WCHAR const *pwszName,
|
|
IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszzValue)
|
|
{
|
|
DWORD cwc = 0;
|
|
DWORD cwcT;
|
|
WCHAR const *pwc;
|
|
|
|
if (NULL != pwszzValue)
|
|
{
|
|
for (pwc = pwszzValue; L'\0' != *pwc; cwc += cwcT, pwc += cwcT)
|
|
{
|
|
cwcT = wcslen(pwc) + 1;
|
|
}
|
|
cwc++;
|
|
}
|
|
return(mySetCertRegValue(
|
|
NULL,
|
|
pwszName,
|
|
NULL,
|
|
NULL,
|
|
pwszValueName,
|
|
REG_MULTI_SZ,
|
|
(BYTE const *) pwszzValue,
|
|
cwc * sizeof(WCHAR),
|
|
TRUE));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
mySetAbsRegStrValue(
|
|
IN WCHAR const *pwszName,
|
|
IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszValue)
|
|
{
|
|
DWORD cwc = 0;
|
|
|
|
if (NULL != pwszValue)
|
|
{
|
|
cwc = wcslen(pwszValue) + 1;
|
|
}
|
|
return mySetCertRegValue(
|
|
NULL,
|
|
pwszName,
|
|
NULL,
|
|
NULL,
|
|
pwszValueName,
|
|
REG_SZ,
|
|
(BYTE const *)pwszValue,
|
|
cwc*sizeof(WCHAR),
|
|
TRUE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
mySetCertRegDWValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN DWORD const dwValue)
|
|
{
|
|
return mySetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
REG_DWORD,
|
|
(BYTE const *)&dwValue,
|
|
sizeof(DWORD),
|
|
FALSE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetCertRegMultiStrValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
OUT WCHAR **ppwszzValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwType;
|
|
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
(BYTE **) ppwszzValue,
|
|
NULL,
|
|
&dwType);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegValue",
|
|
pwszValueName,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
if (REG_MULTI_SZ != dwType && REG_SZ != dwType)
|
|
{
|
|
LocalFree(*ppwszzValue);
|
|
*ppwszzValue = NULL;
|
|
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "not REG_SZ or REG_MULTI_SZ");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
myGetCertRegBinaryValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN WCHAR const *pwszValueName,
|
|
OUT BYTE **ppbValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwType;
|
|
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
ppbValue,
|
|
NULL,
|
|
&dwType);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegValue",
|
|
pwszName1,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
if (REG_BINARY != dwType)
|
|
{
|
|
LocalFree(*ppbValue);
|
|
*ppbValue = NULL;
|
|
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "not REG_BINARY");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
myGetCertRegStrValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN WCHAR const *pwszValueName,
|
|
OUT WCHAR **ppwszValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwType;
|
|
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
(BYTE **) ppwszValue,
|
|
NULL,
|
|
&dwType);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegValue",
|
|
pwszName1,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
if (REG_SZ != dwType)
|
|
{
|
|
LocalFree(*ppwszValue);
|
|
*ppwszValue = NULL;
|
|
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "not REG_SZ");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetCertRegDWValue(
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
IN WCHAR const *pwszValueName,
|
|
OUT DWORD *pdwValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD *pdw = NULL;
|
|
DWORD dwType;
|
|
|
|
*pdwValue = 0;
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
(BYTE **) &pdw,
|
|
NULL,
|
|
&dwType);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegValue",
|
|
pwszValueName,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
if (REG_DWORD != dwType)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpErrorStr(hr, error, "not REG_DWORD", pwszValueName);
|
|
}
|
|
*pdwValue = *pdw;
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pdw)
|
|
{
|
|
LocalFree(pdw);
|
|
}
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myCopyCertRegStrValue(
|
|
OPTIONAL IN WCHAR const *pwszSrcName1,
|
|
OPTIONAL IN WCHAR const *pwszSrcName2,
|
|
OPTIONAL IN WCHAR const *pwszSrcName3,
|
|
IN WCHAR const *pwszSrcValueName,
|
|
OPTIONAL IN WCHAR const *pwszDesName1,
|
|
OPTIONAL IN WCHAR const *pwszDesName2,
|
|
OPTIONAL IN WCHAR const *pwszDesName3,
|
|
OPTIONAL IN WCHAR const *pwszDesValueName,
|
|
IN BOOL fMultiStr)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszOrzzValue = NULL;
|
|
WCHAR const *pwszName = NULL != pwszDesValueName?
|
|
pwszDesValueName : pwszSrcValueName;
|
|
|
|
// get value from source
|
|
if (fMultiStr)
|
|
{
|
|
hr = myGetCertRegMultiStrValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName,
|
|
&pwszOrzzValue);
|
|
_JumpIfErrorStr(hr, error, "myGetCertRegMultiStrValue", pwszSrcValueName);
|
|
|
|
// set it to destination
|
|
hr = mySetCertRegMultiStrValue(
|
|
pwszDesName1,
|
|
pwszDesName2,
|
|
pwszDesName3,
|
|
pwszName,
|
|
pwszOrzzValue);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszName);
|
|
}
|
|
else
|
|
{
|
|
hr = myGetCertRegStrValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName,
|
|
&pwszOrzzValue);
|
|
_JumpIfErrorStr(hr, error, "myGetCertRegStrValue", pwszSrcValueName);
|
|
|
|
// set it to destination
|
|
hr = mySetCertRegStrValue(
|
|
pwszDesName1,
|
|
pwszDesName2,
|
|
pwszDesName3,
|
|
pwszName,
|
|
pwszOrzzValue);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszName);
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
if (NULL != pwszOrzzValue)
|
|
{
|
|
LocalFree(pwszOrzzValue);
|
|
}
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myMoveCertRegStrValue(
|
|
OPTIONAL IN WCHAR const *pwszSrcName1,
|
|
OPTIONAL IN WCHAR const *pwszSrcName2,
|
|
OPTIONAL IN WCHAR const *pwszSrcName3,
|
|
IN WCHAR const *pwszSrcValueName,
|
|
OPTIONAL IN WCHAR const *pwszDesName1,
|
|
OPTIONAL IN WCHAR const *pwszDesName2,
|
|
OPTIONAL IN WCHAR const *pwszDesName3,
|
|
OPTIONAL IN WCHAR const *pwszDesValueName,
|
|
IN BOOL fMultiStr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = myCopyCertRegStrValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName,
|
|
pwszDesName1,
|
|
pwszDesName2,
|
|
pwszDesName3,
|
|
pwszDesValueName,
|
|
fMultiStr);
|
|
_JumpIfErrorStr(hr, error, "myCopyCertRegStrValue", pwszSrcValueName);
|
|
|
|
hr = myDeleteCertRegValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName);
|
|
_PrintIfErrorStr(hr, "myDeleteCertRegValue", pwszSrcValueName);
|
|
hr = S_OK;
|
|
|
|
error:
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
myMoveOrCopyCertRegStrValue(
|
|
OPTIONAL IN WCHAR const *pwszSrcName1,
|
|
OPTIONAL IN WCHAR const *pwszSrcName2,
|
|
OPTIONAL IN WCHAR const *pwszSrcName3,
|
|
IN WCHAR const *pwszSrcValueName,
|
|
OPTIONAL IN WCHAR const *pwszDesName1,
|
|
OPTIONAL IN WCHAR const *pwszDesName2,
|
|
OPTIONAL IN WCHAR const *pwszDesName3,
|
|
OPTIONAL IN WCHAR const *pwszDesValueName,
|
|
IN BOOL fMultiStr,
|
|
IN BOOL fMove)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (fMove)
|
|
{
|
|
hr = myMoveCertRegStrValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName,
|
|
pwszDesName1,
|
|
pwszDesName2,
|
|
pwszDesName3,
|
|
pwszDesValueName,
|
|
fMultiStr);
|
|
}
|
|
else
|
|
{
|
|
hr = myCopyCertRegStrValue(
|
|
pwszSrcName1,
|
|
pwszSrcName2,
|
|
pwszSrcName3,
|
|
pwszSrcValueName,
|
|
pwszDesName1,
|
|
pwszDesName2,
|
|
pwszDesName3,
|
|
pwszDesValueName,
|
|
fMultiStr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Description: it does the same thing as mySetCertRegStrValue but it takes
|
|
// upgrade flag, if upgrade and entry exists, do nothing
|
|
HRESULT
|
|
mySetCertRegStrValueEx(
|
|
IN BOOL fUpgrade,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszValue)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszDummy = NULL;
|
|
|
|
if (fUpgrade)
|
|
{
|
|
// see if it exists
|
|
hr = myGetCertRegStrValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
&pwszDummy);
|
|
if (S_OK == hr)
|
|
{
|
|
if (NULL != pwszDummy && L'\0' != pwszDummy[0])
|
|
{
|
|
goto error; // keep existing entry
|
|
}
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpErrorStr(hr, error, "myGetCertRegStrValue", pwszValueName);
|
|
}
|
|
}
|
|
// cases: 1) not upgrade
|
|
// 2) upgrade but no existing entry
|
|
// 3) upgrade, existing but empty reg string
|
|
hr = mySetCertRegStrValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
pwszValue);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszValueName);
|
|
|
|
error:
|
|
if (NULL != pwszDummy)
|
|
{
|
|
LocalFree(pwszDummy);
|
|
}
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
// calculate multi string character length including double zero terminators
|
|
DWORD
|
|
myWCSZZLength(
|
|
IN WCHAR const *pwszz)
|
|
{
|
|
DWORD len = 0;
|
|
WCHAR const *pwsz = pwszz;
|
|
|
|
if (NULL != pwszz)
|
|
{
|
|
// point to the end of pwszz
|
|
for (; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
|
|
{
|
|
}
|
|
|
|
len = SAFE_SUBTRACT_POINTERS(pwsz, pwszz) + 1;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
// merge two multi strings into one
|
|
// ignore redundant strings
|
|
HRESULT
|
|
myMergeMultiStrings(
|
|
IN WCHAR const *pwszzStr1,
|
|
IN WCHAR const *pwszzStr2,
|
|
OUT WCHAR **ppwszzStr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DWORD dwStr1 = myWCSZZLength(pwszzStr1);
|
|
DWORD dwStr2 = 0;
|
|
DWORD i = 0;
|
|
DWORD dwCount = 0;
|
|
|
|
WCHAR const *pwsz1;
|
|
WCHAR const *pwsz2;
|
|
WCHAR *pwsz;
|
|
BOOL *pfRedundant = NULL;
|
|
WCHAR *pwszzMerge = NULL;
|
|
|
|
// init
|
|
*ppwszzStr = NULL;
|
|
|
|
//calculate string count
|
|
for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
|
|
{
|
|
++dwCount;
|
|
}
|
|
if (0 == dwCount)
|
|
{
|
|
//no merge needed
|
|
goto only_str1;
|
|
}
|
|
pfRedundant = (BOOL*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,
|
|
dwCount * sizeof(BOOL));
|
|
if (NULL == pfRedundant)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
//calculate size
|
|
for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
|
|
{
|
|
++i;
|
|
for (pwsz1 = pwszzStr1; L'\0' != *pwsz1; pwsz1 += wcslen(pwsz1) + 1)
|
|
{
|
|
if (0 == lstrcmpi(pwsz2, pwsz1))
|
|
{
|
|
//pwsz2 exists in pwszzStr1, dont take it
|
|
// cache information
|
|
pfRedundant[i - 1] = TRUE;
|
|
break; //for pwsz1
|
|
}
|
|
}
|
|
//if get here, no-existing
|
|
dwStr2 += wcslen(pwsz2) + 1;
|
|
}
|
|
|
|
only_str1:
|
|
pwszzMerge = (WCHAR*)LocalAlloc(LMEM_FIXED,
|
|
(dwStr1 + dwStr2) * sizeof(WCHAR));
|
|
if (NULL == pwszzMerge)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
// copy existing
|
|
CopyMemory(pwszzMerge,
|
|
pwszzStr1,
|
|
(dwStr1 - 1) * sizeof(WCHAR));
|
|
|
|
if (0 < dwCount)
|
|
{
|
|
// merge begins
|
|
i = 0;
|
|
// point to end at 2nd z
|
|
pwsz = pwszzMerge + dwStr1 - 1;
|
|
for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
|
|
{
|
|
if (!pfRedundant[i])
|
|
{
|
|
wcscpy(pwsz, pwsz2);
|
|
pwsz += wcslen(pwsz) + 1;
|
|
}
|
|
++i;
|
|
}
|
|
// zz
|
|
*pwsz = L'\0';
|
|
}
|
|
|
|
*ppwszzStr = pwszzMerge;
|
|
pwszzMerge = NULL;
|
|
|
|
hr = S_OK;
|
|
error:
|
|
if (NULL != pfRedundant)
|
|
{
|
|
LocalFree(pfRedundant);
|
|
}
|
|
if (NULL != pwszzMerge)
|
|
{
|
|
LocalFree(pwszzMerge);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// append one multi_sz to another
|
|
HRESULT
|
|
myAppendMultiStrings(
|
|
IN WCHAR const *pwszzStr1,
|
|
IN WCHAR const *pwszzStr2,
|
|
OUT WCHAR **ppwszzStr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DWORD dwStr1 = myWCSZZLength(pwszzStr1);
|
|
DWORD dwStr2 = myWCSZZLength(pwszzStr2);
|
|
|
|
// init
|
|
*ppwszzStr = NULL;
|
|
|
|
WCHAR *pwszzMerge = (WCHAR*)LocalAlloc(LMEM_FIXED,
|
|
(dwStr1 + dwStr2 - 1) * sizeof(WCHAR));
|
|
if (NULL == pwszzMerge)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
// copy existing
|
|
CopyMemory(pwszzMerge,
|
|
pwszzStr1,
|
|
(dwStr1 - 1) * sizeof(WCHAR));
|
|
// append second
|
|
CopyMemory(pwszzMerge + dwStr1 - 1,
|
|
pwszzStr2,
|
|
dwStr2 * sizeof(WCHAR));
|
|
*ppwszzStr = pwszzMerge;
|
|
|
|
hr = S_OK;
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
// Description: it does the same thing as mySetCertRegMultiStrValue but it takes
|
|
// upgrade|append flag, if upgrade and entry exists, do nothing
|
|
// if upgrade & append, merge existing entry with in-pwszz
|
|
HRESULT
|
|
mySetCertRegMultiStrValueEx(
|
|
IN DWORD dwFlags, //CSREG_UPGRADE|CSREG_APPEND|CSREG_REPLACE|CSREG_MERGE
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN WCHAR const *pwszzValue)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszzExisting = NULL;
|
|
WCHAR const *pwszzFinal = pwszzValue; //default
|
|
WCHAR *pwszzMerge = NULL;
|
|
|
|
if (0x0 == (CSREG_REPLACE & dwFlags) &&
|
|
(CSREG_UPGRADE & dwFlags) )
|
|
{
|
|
// to see if it exist
|
|
hr = myGetCertRegMultiStrValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
&pwszzExisting);
|
|
if (S_OK == hr)
|
|
{
|
|
if (NULL != pwszzExisting)
|
|
{
|
|
if (0x0 == (CSREG_APPEND & dwFlags) &&
|
|
0x0 == (CSREG_MERGE & dwFlags) )
|
|
{
|
|
goto error; // keep existing entry
|
|
}
|
|
else if (0x0 != (CSREG_MERGE & dwFlags))
|
|
{
|
|
hr = myMergeMultiStrings(
|
|
pwszzExisting,
|
|
pwszzValue,
|
|
&pwszzMerge);
|
|
_JumpIfError(hr, error, "myMergeMultiStrings");
|
|
pwszzFinal = pwszzMerge;
|
|
}
|
|
else if (0x0 != (CSREG_APPEND & dwFlags))
|
|
{
|
|
hr = myAppendMultiStrings(
|
|
pwszzExisting,
|
|
pwszzValue,
|
|
&pwszzMerge);
|
|
_JumpIfError(hr, error, "myAppendMultiStrings");
|
|
pwszzFinal = pwszzMerge;
|
|
}
|
|
}
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpErrorStr(hr, error, "myGetCertRegMultiStrValue", pwszValueName);
|
|
}
|
|
}
|
|
hr = mySetCertRegMultiStrValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
pwszzFinal);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszValueName);
|
|
|
|
error:
|
|
if (NULL != pwszzExisting)
|
|
{
|
|
LocalFree(pwszzExisting);
|
|
}
|
|
if (NULL != pwszzMerge)
|
|
{
|
|
LocalFree(pwszzMerge);
|
|
}
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
// Description: it does the same thing as mySetCertRegDWValue but it takes
|
|
// upgrade flag, if upgrade and entry exists, do nothing
|
|
HRESULT
|
|
mySetCertRegDWValueEx(
|
|
IN BOOL fUpgrade,
|
|
OPTIONAL IN WCHAR const *pwszName1,
|
|
OPTIONAL IN WCHAR const *pwszName2,
|
|
OPTIONAL IN WCHAR const *pwszName3,
|
|
OPTIONAL IN WCHAR const *pwszValueName,
|
|
IN DWORD const dwValue)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwDummy;
|
|
|
|
if (fUpgrade)
|
|
{
|
|
// to see if it exist
|
|
hr = myGetCertRegDWValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
&dwDummy);
|
|
if (S_OK == hr)
|
|
{
|
|
goto error; // keep existing entry
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpErrorStr(hr, error, "myGetCertRegDWValue", pwszValueName);
|
|
}
|
|
}
|
|
hr = mySetCertRegDWValue(
|
|
pwszName1,
|
|
pwszName2,
|
|
pwszName3,
|
|
pwszValueName,
|
|
dwValue);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegDWValue", pwszValueName);
|
|
|
|
error:
|
|
CSASSERT(S_OK == hr || FAILED(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
WCHAR const *
|
|
wszRegCertChoice(
|
|
IN DWORD dwRegHashChoice)
|
|
{
|
|
WCHAR const *pwsz;
|
|
|
|
switch (dwRegHashChoice)
|
|
{
|
|
case CSRH_CASIGCERT:
|
|
pwsz = wszREGCACERTHASH;
|
|
break;
|
|
|
|
case CSRH_CAXCHGCERT:
|
|
pwsz = wszREGCAXCHGCERTHASH;
|
|
break;
|
|
|
|
case CSRH_CAKRACERT:
|
|
pwsz = wszREGKRACERTHASH;
|
|
break;
|
|
|
|
default:
|
|
CSASSERT("dwRegHashChoice");
|
|
pwsz = L"";
|
|
break;
|
|
}
|
|
return(pwsz);
|
|
}
|
|
|
|
|
|
WCHAR const g_wszNoHash[] = L"-";
|
|
|
|
|
|
HRESULT myShrinkCARegHash(
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN DWORD dwRegHashChoice,
|
|
IN DWORD Index)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD i;
|
|
DWORD dwType;
|
|
DWORD count;
|
|
WCHAR *pwszzOld = NULL;
|
|
WCHAR *pwchr = NULL; // no free
|
|
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
(BYTE **) &pwszzOld,
|
|
&i, // ignore &cb
|
|
&dwType);
|
|
_JumpIfErrorStr(hr, error, "myGetCertRegValue", wszRegCertChoice(dwRegHashChoice));
|
|
|
|
for (count = 0, pwchr = pwszzOld;
|
|
count < Index && L'\0' != *pwchr;
|
|
count++, pwchr += wcslen(pwchr) + 1)
|
|
NULL;
|
|
|
|
// valid only if shrinking the list
|
|
if(L'\0' == *pwchr)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "new hash count should be smaller than current count");
|
|
}
|
|
|
|
*pwchr = L'\0';
|
|
|
|
hr = mySetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
REG_MULTI_SZ,
|
|
(BYTE const *) pwszzOld,
|
|
(SAFE_SUBTRACT_POINTERS(pwchr, pwszzOld) + 1) * sizeof(WCHAR),
|
|
FALSE);
|
|
_JumpIfError(hr, error, "mySetCertRegValue");
|
|
|
|
error:
|
|
if(pwszzOld)
|
|
LocalFree(pwszzOld);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
mySetCARegHash(
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN DWORD dwRegHashChoice,
|
|
IN DWORD Index,
|
|
IN CERT_CONTEXT const *pCert)
|
|
{
|
|
HRESULT hr;
|
|
BSTR strHash = NULL;
|
|
BYTE abHash[CBMAX_CRYPT_HASH_LEN];
|
|
DWORD cbHash;
|
|
WCHAR *pwszzOld = NULL;
|
|
WCHAR *pwszzNew = NULL;
|
|
DWORD cOld;
|
|
DWORD i;
|
|
DWORD cNew;
|
|
DWORD cwcNew;
|
|
WCHAR const **apwsz = NULL;
|
|
DWORD dwType;
|
|
WCHAR *pwc;
|
|
|
|
if (NULL == pwszSanitizedCAName)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "empty ca name");
|
|
}
|
|
|
|
cbHash = sizeof(abHash);
|
|
if (!CertGetCertificateContextProperty(
|
|
pCert,
|
|
CERT_HASH_PROP_ID,
|
|
abHash,
|
|
&cbHash))
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertGetCertificateContextProperty");
|
|
}
|
|
|
|
hr = MultiByteIntegerToBstr(TRUE, cbHash, abHash, &strHash);
|
|
_JumpIfError(hr, error, "MultiByteIntegerToBstr");
|
|
|
|
cOld = 0;
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
(BYTE **) &pwszzOld,
|
|
&i, // ignore &cb
|
|
&dwType);
|
|
_PrintIfError2(hr, "myGetCertRegValue", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
if (S_OK == hr && REG_MULTI_SZ == dwType)
|
|
{
|
|
for (pwc = pwszzOld; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
|
|
{
|
|
cOld++;
|
|
}
|
|
}
|
|
|
|
cNew = max(Index + 1, cOld);
|
|
apwsz = (WCHAR const **) LocalAlloc(LMEM_FIXED, cNew * sizeof(*apwsz));
|
|
if (NULL == apwsz)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
i = 0;
|
|
if (0 != cOld)
|
|
{
|
|
for (pwc = pwszzOld; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
|
|
{
|
|
DBGPRINT((DBG_SS_CERTLIBI, "Old CARegHash[%u] = \"%ws\"\n", i, pwc));
|
|
apwsz[i++] = pwc;
|
|
}
|
|
CSASSERT(i == cOld);
|
|
}
|
|
while (i < Index)
|
|
{
|
|
DBGPRINT((DBG_SS_CERTLIBI, "CARegHash[%u] Unused\n", i));
|
|
apwsz[i++] = g_wszNoHash;
|
|
}
|
|
if (Index < cOld)
|
|
{
|
|
DBGPRINT((
|
|
DBG_SS_CERTLIBI,
|
|
"Replacing CARegHash[%u] = \"%ws\"\n",
|
|
Index,
|
|
apwsz[Index]));
|
|
}
|
|
DBGPRINT((
|
|
DBG_SS_CERTLIBI,
|
|
"Adding CARegHash[%u] = \"%ws\"\n",
|
|
Index,
|
|
strHash));
|
|
apwsz[Index] = strHash;
|
|
|
|
cwcNew = 1; // wszz double termination
|
|
for (i = 0; i < cNew; i++)
|
|
{
|
|
cwcNew += wcslen(apwsz[i]) + 1;
|
|
}
|
|
|
|
pwszzNew = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcNew * sizeof(WCHAR));
|
|
if (NULL == pwszzNew)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
|
|
pwc = pwszzNew;
|
|
for (i = 0; i < cNew; i++)
|
|
{
|
|
wcscpy(pwc, apwsz[i]);
|
|
DBGPRINT((DBG_SS_CERTLIBI, "New CARegHash[%u] = \"%ws\"\n", i, pwc));
|
|
pwc += wcslen(pwc) + 1;
|
|
}
|
|
*pwc = L'\0';
|
|
|
|
CSASSERT(&pwszzNew[cwcNew - 1] == pwc);
|
|
|
|
hr = mySetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
REG_MULTI_SZ,
|
|
(BYTE const *) pwszzNew,
|
|
cwcNew * sizeof(WCHAR),
|
|
FALSE);
|
|
_JumpIfError(hr, error, "mySetCertRegValue");
|
|
|
|
error:
|
|
if (NULL != apwsz)
|
|
{
|
|
LocalFree(apwsz);
|
|
}
|
|
if (NULL != pwszzOld)
|
|
{
|
|
LocalFree(pwszzOld);
|
|
}
|
|
if (NULL != pwszzNew)
|
|
{
|
|
LocalFree(pwszzNew);
|
|
}
|
|
if (NULL != strHash)
|
|
{
|
|
SysFreeString(strHash);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetCARegHash(
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN DWORD dwRegHashChoice,
|
|
IN DWORD Index,
|
|
OUT BYTE **ppbHash,
|
|
OUT DWORD *pcbHash)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszz = NULL;
|
|
DWORD cb;
|
|
DWORD dwType;
|
|
WCHAR *pwc;
|
|
DWORD i;
|
|
|
|
*ppbHash = NULL;
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
(BYTE **) &pwszz,
|
|
&cb,
|
|
&dwType);
|
|
_JumpIfError(hr, error, "myGetCertRegValue");
|
|
|
|
if (REG_MULTI_SZ != dwType)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpError(hr, error, "dwType");
|
|
}
|
|
pwc = pwszz;
|
|
for (i = 0; i < Index; i++)
|
|
{
|
|
if (L'\0' == *pwc)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
_JumpError(hr, error, "Index too large");
|
|
}
|
|
pwc += wcslen(pwc) + 1;
|
|
}
|
|
if (0 == lstrcmp(g_wszNoHash, pwc))
|
|
{
|
|
hr = S_FALSE;
|
|
_JumpError2(hr, error, "Unused hash", S_FALSE);
|
|
}
|
|
hr = WszToMultiByteInteger(TRUE, pwc, pcbHash, ppbHash);
|
|
_JumpIfError(hr, error, "WszToMultiByteInteger");
|
|
|
|
error:
|
|
if (NULL != pwszz)
|
|
{
|
|
LocalFree(pwszz);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetCARegHashCount(
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN DWORD dwRegHashChoice,
|
|
OUT DWORD *pCount)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszz = NULL;
|
|
DWORD cb;
|
|
DWORD dwType;
|
|
WCHAR *pwc;
|
|
DWORD Count = 0;
|
|
|
|
hr = myGetCertRegValue(
|
|
NULL,
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszRegCertChoice(dwRegHashChoice),
|
|
(BYTE **) &pwszz,
|
|
&cb,
|
|
&dwType);
|
|
if (S_OK == hr)
|
|
{
|
|
if (REG_MULTI_SZ == dwType)
|
|
{
|
|
for (pwc = pwszz; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
|
|
{
|
|
Count++;
|
|
}
|
|
}
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
|
|
{
|
|
_JumpError(hr, error, "myGetCertRegValue");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
*pCount = Count;
|
|
if (NULL != pwszz)
|
|
{
|
|
LocalFree(pwszz);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myFindCACertByHash(
|
|
IN HCERTSTORE hStore,
|
|
IN BYTE const *pbHash,
|
|
IN DWORD cbHash,
|
|
OUT OPTIONAL DWORD *pdwNameId,
|
|
CERT_CONTEXT const **ppCACert)
|
|
{
|
|
HRESULT hr;
|
|
CRYPT_DATA_BLOB Hash;
|
|
|
|
CSASSERT(
|
|
NULL != hStore &&
|
|
NULL != pbHash &&
|
|
NULL != ppCACert);
|
|
|
|
*ppCACert = NULL;
|
|
Hash.pbData = const_cast<BYTE *>(pbHash);
|
|
Hash.cbData = cbHash;
|
|
|
|
*ppCACert = CertFindCertificateInStore(
|
|
hStore,
|
|
X509_ASN_ENCODING,
|
|
0,
|
|
CERT_FIND_HASH,
|
|
&Hash,
|
|
NULL);
|
|
if (NULL == *ppCACert)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "CertFindCertificateInStore");
|
|
}
|
|
|
|
if (NULL != pdwNameId)
|
|
{
|
|
*pdwNameId = MAXDWORD;
|
|
hr = myGetNameId(*ppCACert, pdwNameId);
|
|
_PrintIfError(hr, "myGetNameId");
|
|
}
|
|
hr = S_OK;
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myFindCACertByHashIndex(
|
|
IN HCERTSTORE hStore,
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN DWORD dwRegHashChoice,
|
|
IN DWORD Index,
|
|
OPTIONAL OUT DWORD *pdwNameId,
|
|
CERT_CONTEXT const **ppCACert)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbHash;
|
|
BYTE *pbHash = NULL;
|
|
|
|
CSASSERT(NULL != hStore && NULL != ppCACert);
|
|
|
|
if (NULL != pdwNameId)
|
|
{
|
|
*pdwNameId = MAXDWORD;
|
|
}
|
|
*ppCACert = NULL;
|
|
|
|
hr = myGetCARegHash(
|
|
pwszSanitizedCAName,
|
|
dwRegHashChoice,
|
|
Index,
|
|
&pbHash,
|
|
&cbHash);
|
|
_JumpIfError2(hr, error, "myGetCARegHash", S_FALSE);
|
|
|
|
hr = myFindCACertByHash(hStore, pbHash, cbHash, pdwNameId, ppCACert);
|
|
_JumpIfError(hr, error, "myFindCACertByHash");
|
|
|
|
error:
|
|
if (NULL != pbHash)
|
|
{
|
|
LocalFree(pbHash);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetSetupStatus(
|
|
OPTIONAL IN WCHAR const *pwszSanitizedCAName,
|
|
OUT DWORD *pdwStatus)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = myGetCertRegDWValue(
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszREGSETUPSTATUS,
|
|
pdwStatus);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegDWValue",
|
|
wszREGSETUPSTATUS,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
DBGPRINT((DBG_SS_CERTLIBI, "GetSetupStatus(%ws) --> %x\n", pwszSanitizedCAName, *pdwStatus));
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SetSetupStatus(
|
|
OPTIONAL IN WCHAR const *pwszSanitizedCAName,
|
|
IN const DWORD dwFlag,
|
|
IN const BOOL fSetBit)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwCurrentStatus;
|
|
DWORD dwStatus = dwFlag;
|
|
|
|
hr = myGetCertRegDWValue(
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszREGSETUPSTATUS,
|
|
&dwCurrentStatus);
|
|
_PrintIfError2(
|
|
hr,
|
|
"myGetCertRegDWValue",
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
// check to if there is existing status
|
|
if (S_OK == hr || 0xFFFFFFFF == dwStatus)
|
|
{
|
|
// existing status, set according to dwFlag
|
|
|
|
if (fSetBit)
|
|
{
|
|
// set corresponding bit
|
|
dwStatus = dwCurrentStatus | dwStatus;
|
|
}
|
|
else
|
|
{
|
|
// unset corresponding
|
|
dwStatus = dwCurrentStatus & ~dwStatus;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// entry doesn't exist, if fSetBit, keep dwStatus=dwFlag
|
|
if (!fSetBit)
|
|
{
|
|
// otherwise set all 0
|
|
dwStatus = 0x0;
|
|
}
|
|
}
|
|
hr = mySetCertRegDWValue(
|
|
pwszSanitizedCAName,
|
|
NULL,
|
|
NULL,
|
|
wszREGSETUPSTATUS,
|
|
dwStatus);
|
|
_JumpIfError(hr, error, "mySetCertRegDWValue");
|
|
|
|
DBGPRINT((DBG_SS_CERTLIBI, "SetSetupStatus(%ws, %x)\n", pwszSanitizedCAName, dwStatus));
|
|
|
|
error:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetActiveManageModule(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN BOOL fPolicyModule,
|
|
IN DWORD Index,
|
|
OUT LPOLESTR *ppwszProgIdManageModule, // CoTaskMem*
|
|
OUT CLSID *pclsidManageModule)
|
|
{
|
|
DWORD dw;
|
|
PBYTE pb = NULL;
|
|
DWORD dwType, cb = 0;
|
|
|
|
LPWSTR pszTmp;
|
|
DWORD cbClassName;
|
|
LPOLESTR lpszProgID = NULL;
|
|
LPWSTR szClassName = NULL;
|
|
|
|
if (NULL != *ppwszProgIdManageModule)
|
|
{
|
|
CoTaskMemFree(*ppwszProgIdManageModule);
|
|
*ppwszProgIdManageModule = NULL;
|
|
}
|
|
|
|
dw = myGetActiveModule(
|
|
pwszMachine,
|
|
pwszSanitizedCAName,
|
|
fPolicyModule,
|
|
Index,
|
|
&lpszProgID,
|
|
NULL);
|
|
if (S_OK != dw)
|
|
goto error;
|
|
|
|
{
|
|
// terminate class name at first '.'
|
|
LPWSTR pAddTermination = wcschr(lpszProgID, L'.');
|
|
|
|
if (NULL != pAddTermination)
|
|
{
|
|
pAddTermination[0] = L'\0';
|
|
}
|
|
}
|
|
|
|
cbClassName = (wcslen(lpszProgID) + 1) * sizeof(WCHAR);
|
|
cbClassName += (fPolicyModule) ? sizeof(wszCERTMANAGEPOLICY_POSTFIX) : sizeof(wszCERTMANAGEEXIT_POSTFIX);
|
|
|
|
szClassName = (LPWSTR) CoTaskMemAlloc(cbClassName);
|
|
if (NULL == szClassName)
|
|
goto error;
|
|
|
|
wcscpy(szClassName, lpszProgID);
|
|
wcscat(szClassName, fPolicyModule? wszCERTMANAGEPOLICY_POSTFIX : wszCERTMANAGEEXIT_POSTFIX);
|
|
|
|
// Now we have class module name, cvt to clsid
|
|
dw = CLSIDFromProgID(szClassName, pclsidManageModule);
|
|
if (S_OK != dw)
|
|
goto error; // clsid not found?
|
|
|
|
error:
|
|
if (pb)
|
|
LocalFree(pb);
|
|
|
|
// intermediate ProgId
|
|
if (lpszProgID)
|
|
CoTaskMemFree(lpszProgID);
|
|
|
|
*ppwszProgIdManageModule = szClassName;
|
|
|
|
return dw;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetActiveModule(
|
|
OPTIONAL IN WCHAR const *pwszMachine,
|
|
IN WCHAR const *pwszSanitizedCAName,
|
|
IN BOOL fPolicyModule,
|
|
IN DWORD Index,
|
|
OPTIONAL OUT LPOLESTR *ppwszProgIdModule, // CoTaskMem*
|
|
OPTIONAL OUT CLSID *pclsidModule)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszzValue = NULL;
|
|
WCHAR *pwsz;
|
|
DWORD dwType;
|
|
DWORD cb = 0;
|
|
LPWSTR pwszModuleSubkey = NULL;
|
|
DWORD chModule;
|
|
|
|
chModule = wcslen(pwszSanitizedCAName) + 1 + 1; // (L'\\' + trailing L'\0');
|
|
chModule += fPolicyModule?
|
|
WSZARRAYSIZE(wszREGKEYPOLICYMODULES) :
|
|
WSZARRAYSIZE(wszREGKEYEXITMODULES);
|
|
|
|
pwszModuleSubkey = (LPWSTR) LocalAlloc(
|
|
LMEM_FIXED,
|
|
chModule * sizeof(WCHAR));
|
|
if (NULL == pwszModuleSubkey)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(pwszModuleSubkey, pwszSanitizedCAName);
|
|
wcscat(pwszModuleSubkey, L"\\");
|
|
wcscat(
|
|
pwszModuleSubkey,
|
|
fPolicyModule? wszREGKEYPOLICYMODULES : wszREGKEYEXITMODULES);
|
|
|
|
// grab entry under CA with the active module ProgID
|
|
hr = myGetCertRegValue(
|
|
pwszMachine,
|
|
pwszModuleSubkey,
|
|
NULL,
|
|
NULL,
|
|
wszREGACTIVE,
|
|
(BYTE **) &pwszzValue,
|
|
&cb,
|
|
&dwType);
|
|
_JumpIfError(hr, error, "myGetCertRegValue");
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
|
|
|
|
// might or might not have an active entry
|
|
if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
|
|
{
|
|
_JumpError(hr, error, "Bad active entry type");
|
|
}
|
|
if (0 == cb || NULL == pwszzValue)
|
|
{
|
|
_JumpError(hr, error, "No active entry");
|
|
}
|
|
if (0 != Index && (REG_SZ == dwType || fPolicyModule))
|
|
{
|
|
_JumpError(hr, error, "only one policy module or REG_SZ entry");
|
|
}
|
|
|
|
pwsz = pwszzValue;
|
|
|
|
if (REG_MULTI_SZ == dwType)
|
|
{
|
|
// look for Index'th entry
|
|
for ( ; 0 != Index; pwsz += wcslen(pwsz) + 1, Index--)
|
|
{
|
|
if (L'\0' == *pwsz)
|
|
{
|
|
_JumpError(hr, error, "No more active entries");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Verify nth entry exists
|
|
if (L'\0' == *pwsz)
|
|
{
|
|
_JumpError(hr, error, "No active entries");
|
|
}
|
|
|
|
if (NULL != pclsidModule)
|
|
{
|
|
hr = CLSIDFromProgID(pwsz, pclsidModule);
|
|
_JumpIfError(hr, error, "CLSIDFromProgID");
|
|
}
|
|
|
|
if (NULL != ppwszProgIdModule)
|
|
{
|
|
*ppwszProgIdModule = (LPOLESTR) CoTaskMemAlloc(
|
|
(wcslen(pwsz) + 1) * sizeof(WCHAR));
|
|
if (NULL == *ppwszProgIdModule)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "CoTaskMemAlloc");
|
|
}
|
|
wcscpy(*ppwszProgIdModule, pwsz);
|
|
}
|
|
hr = S_OK; // not reset after ERROR_MOD_NOT_FOUND in all cases
|
|
|
|
error:
|
|
if (NULL != pwszModuleSubkey)
|
|
{
|
|
LocalFree(pwszModuleSubkey);
|
|
}
|
|
if (NULL != pwszzValue)
|
|
{
|
|
LocalFree(pwszzValue);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsPrefix(
|
|
WCHAR const *pwszPrefix,
|
|
WCHAR const *pwszString,
|
|
DWORD cwcPrefix)
|
|
{
|
|
return(
|
|
0 == _wcsnicmp(pwszPrefix, pwszString, cwcPrefix) &&
|
|
(L'\\' == pwszString[cwcPrefix] ||
|
|
L'\0' == pwszString[cwcPrefix]));
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
// Function: myRegOpenRelativeKey
|
|
//
|
|
// Synopsis: Compute CA-relative, Policy-relative or Exit-relative registry
|
|
// path, and retrieve the value, type, and parent registry key.
|
|
//
|
|
// IN params:
|
|
//
|
|
// pwszConfig is the config string of the CA:
|
|
// if NULL, the local machine's first active CA is used.
|
|
// if a server name (no \CAName is present), the specified machine's
|
|
// first active CA is used.
|
|
//
|
|
// pwszRegName can specify any of the following the targets:
|
|
// Passed String: ValueName Relative Key Opened:
|
|
// ------------- ------------------------------
|
|
// "ValueName" Configuration key
|
|
// "CA[\ValueName]" CAName key
|
|
// "policy[\ValueName]" CAName\PolicyModules\<ActivePolicy>
|
|
// "policy\ModuleProgId[\ValueName]" CAName\PolicyModules\ModuleProgId
|
|
// "exit[\ValueName]" CAName\ExitModules\<ActiveExit>
|
|
// "exit\ModuleProgId[\ValueName]" CAName\ExitModules\ModuleProgId
|
|
// "Template[\ValueName]" Template
|
|
//
|
|
//
|
|
// RORKF_FULLPATH specifies whether the path returned is relative from HKLM or
|
|
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration.
|
|
//
|
|
// RORKF_CREATESUBKEYS will allow subkeys to be created if necessary and the
|
|
// returned hkey opened for WRITE access
|
|
//
|
|
// On successful execution:
|
|
//
|
|
// *ppwszPath will contain a LocalAlloc'd registry path relative to
|
|
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration.
|
|
//
|
|
// *ppwszName will contain a LocalAlloc'd registry value name string relative to
|
|
// the returned parent key. If NULL, pwszRegName specifies a key, not a value.
|
|
//
|
|
// *phkey contains the opened reg key, if phkey non-NULL. Caller is responsible
|
|
// for freeing this key.
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
myRegOpenRelativeKey(
|
|
OPTIONAL IN WCHAR const *pwszConfig,
|
|
IN WCHAR const *pwszRegName,
|
|
IN DWORD Flags, // RORKF_*
|
|
OUT WCHAR **ppwszPath,
|
|
OUT OPTIONAL WCHAR **ppwszName,
|
|
OUT OPTIONAL HKEY *phkey)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR awc[MAX_PATH];
|
|
WCHAR awc2[MAX_PATH];
|
|
HKEY hkeyRoot = HKEY_LOCAL_MACHINE;
|
|
HKEY hkeyConfig = NULL;
|
|
HKEY hkeyMod = NULL;
|
|
HKEY hkeyRequested = NULL;
|
|
WCHAR *pwszMachine = NULL;
|
|
WCHAR const *pwszModules = NULL;
|
|
WCHAR const *pwszName;
|
|
WCHAR const *pwsz;
|
|
DWORD dwType;
|
|
DWORD cb;
|
|
DWORD cwc;
|
|
DWORD i;
|
|
BOOL fTemplateCache;
|
|
DWORD dwDisposition;
|
|
|
|
// Parameter checking
|
|
|
|
if (NULL != phkey)
|
|
{
|
|
*phkey = NULL;
|
|
}
|
|
if (NULL != ppwszName)
|
|
{
|
|
*ppwszName = NULL;
|
|
}
|
|
if (NULL == ppwszPath)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, error, "ppwszPath not optional");
|
|
}
|
|
*ppwszPath = NULL;
|
|
|
|
fTemplateCache = IsPrefix(L"Template", pwszRegName, 8);
|
|
if (fTemplateCache && (RORKF_USERKEY & Flags))
|
|
{
|
|
hkeyRoot = HKEY_CURRENT_USER;
|
|
}
|
|
|
|
// take care of remote machine access
|
|
|
|
if (NULL != pwszConfig)
|
|
{
|
|
BOOL fLocal;
|
|
|
|
hr = myIsConfigLocal(pwszConfig, &pwszMachine, &fLocal);
|
|
_JumpIfError(hr, error, "myIsConfigLocal");
|
|
|
|
if (!fLocal)
|
|
{
|
|
hr = RegConnectRegistry(pwszMachine, hkeyRoot, &hkeyRoot);
|
|
_JumpIfError(hr, error, "RegConnectRegistry");
|
|
}
|
|
}
|
|
|
|
if (!fTemplateCache)
|
|
{
|
|
hr = RegOpenKeyEx(
|
|
hkeyRoot,
|
|
wszREGKEYCONFIGPATH,
|
|
0,
|
|
(RORKF_CREATESUBKEYS & Flags)? KEY_ALL_ACCESS : KEY_READ,
|
|
&hkeyConfig);
|
|
_JumpIfError(hr, error, "RegOpenKey(config)");
|
|
}
|
|
|
|
// value or key\value passed in under pwszRegName?
|
|
|
|
pwsz = wcschr(pwszRegName, L'\\');
|
|
if (NULL == pwsz &&
|
|
!IsPrefix(L"CA", pwszRegName, 2) &&
|
|
!IsPrefix(L"Policy", pwszRegName, 6) &&
|
|
!IsPrefix(L"Exit", pwszRegName, 4) &&
|
|
!IsPrefix(L"Restore", pwszRegName, 7) &&
|
|
!fTemplateCache)
|
|
{
|
|
// Operate on registry value under the Configuration registry key
|
|
|
|
pwszName = pwszRegName;
|
|
|
|
// this is the final key we'll open
|
|
|
|
hkeyRequested = hkeyConfig;
|
|
hkeyConfig = NULL;
|
|
awc[0] = L'\0';
|
|
}
|
|
else if (fTemplateCache)
|
|
{
|
|
pwszName = &pwszRegName[8];
|
|
wcscpy(awc, wszCERTTYPECACHE);
|
|
}
|
|
else
|
|
{
|
|
//printf("RegName = '%ws'\n", pwszRegName);
|
|
// load config of the active CA
|
|
|
|
cb = sizeof(awc);
|
|
hr = RegQueryValueEx(
|
|
hkeyConfig,
|
|
wszREGACTIVE,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) awc,
|
|
&cb);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx", wszREGACTIVE);
|
|
|
|
if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx TYPE", wszREGACTIVE);
|
|
}
|
|
|
|
//printf("Active CA = '%ws'\n", awc);
|
|
|
|
// operate on key\value
|
|
|
|
// first, subdivide into policymodules\exitmodules subkey
|
|
|
|
if (IsPrefix(L"CA", pwszRegName, 2))
|
|
{
|
|
// Operate on registry value under the Active CA registry key
|
|
|
|
pwszName = &pwszRegName[2];
|
|
}
|
|
else if (IsPrefix(L"Policy", pwszRegName, 6))
|
|
{
|
|
// Operate on registry value under a Policy Module registry key
|
|
|
|
pwszModules = wszREGKEYPOLICYMODULES;
|
|
pwszName = &pwszRegName[6];
|
|
}
|
|
else if (IsPrefix(L"Exit", pwszRegName, 4))
|
|
{
|
|
// Operate on registry value under an Exit Module registry key
|
|
|
|
pwszModules = wszREGKEYEXITMODULES;
|
|
pwszName = &pwszRegName[4];
|
|
}
|
|
else if (IsPrefix(L"Restore", pwszRegName, 7))
|
|
{
|
|
// Operate on registry value under Restore registry key
|
|
|
|
pwszName = &pwszRegName[7];
|
|
wcscpy(awc, wszREGKEYRESTOREINPROGRESS);
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_JumpError(hr, error, "pwszRegName: no subkey description");
|
|
}
|
|
|
|
// expand module ProgId if necessary: get active ProgId
|
|
|
|
if (NULL != pwszModules) // if a policy or exit module
|
|
{
|
|
wcscat(awc, L"\\");
|
|
wcscat(awc, pwszModules);
|
|
}
|
|
|
|
//printf("CA|restore|policy|exit key = '%ws'\n", awc);
|
|
|
|
if (NULL != ppwszName) // if a registry value expected
|
|
{
|
|
// Find active policy/exit module's ProgId
|
|
hr = RegOpenKeyEx(
|
|
hkeyConfig,
|
|
awc,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyMod);
|
|
_JumpIfErrorStr(hr, error, "RegOpenKey", awc);
|
|
|
|
if (NULL != pwszModules) // if a policy or exit module
|
|
{
|
|
cb = sizeof(awc2);
|
|
hr = RegQueryValueEx(
|
|
hkeyMod,
|
|
wszREGACTIVE,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) awc2,
|
|
&cb);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx", wszREGACTIVE);
|
|
|
|
if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
_JumpIfErrorStr(hr, error, "RegQueryValueEx Active Module", awc);
|
|
}
|
|
|
|
//printf("Active Module = '%ws'\n", awc2);
|
|
|
|
wcscat(awc, L"\\");
|
|
wcscat(awc, awc2);
|
|
}
|
|
}
|
|
else // else a registry key name is expected
|
|
{
|
|
// key\value: ProgId was passed in
|
|
// concatenate key name (including the \\ prefix) onto end of awc
|
|
|
|
if (NULL != pwsz)
|
|
{
|
|
CSASSERT(L'\\' == *pwsz);
|
|
wcscat(awc, pwsz);
|
|
}
|
|
}
|
|
} // end if (operate on key/value or value)
|
|
|
|
if (NULL == hkeyRequested)
|
|
{
|
|
//printf("Creating key = '%ws'\n", awc);
|
|
|
|
// open this key
|
|
hr = RegCreateKeyEx(
|
|
NULL != hkeyConfig? hkeyConfig : hkeyRoot,
|
|
awc,
|
|
0,
|
|
NULL,
|
|
0,
|
|
(RORKF_CREATESUBKEYS & Flags)? KEY_ALL_ACCESS : KEY_READ,
|
|
NULL,
|
|
&hkeyRequested,
|
|
&dwDisposition);
|
|
_JumpIfErrorStr(hr, error, "RegCreateKeyEx(parent)", awc);
|
|
|
|
} // end if (operate on key/value or value)
|
|
|
|
if (L'\\' == *pwszName)
|
|
{
|
|
pwszName++;
|
|
}
|
|
if (NULL != ppwszName && L'\0' != *pwszName)
|
|
{
|
|
// Look for case-ignore matching registry value name, & use the value's
|
|
// correct upper/lower case spelling if an existing registry value:
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
cwc = ARRAYSIZE(awc2);
|
|
hr = RegEnumValue(hkeyRequested, i, awc2, &cwc, NULL, NULL, NULL, NULL);
|
|
if (S_OK != hr)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
if (0 == lstrcmpi(awc2, pwszName))
|
|
{
|
|
pwszName = awc2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
cb = (wcslen(awc) + 1) * sizeof(WCHAR);
|
|
if (!fTemplateCache && (RORKF_FULLPATH & Flags))
|
|
{
|
|
cb += WSZARRAYSIZE(wszREGKEYCONFIGPATH_BS) * sizeof(WCHAR);
|
|
}
|
|
|
|
*ppwszPath = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
|
|
if (NULL == *ppwszPath)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
(*ppwszPath)[0] = L'\0';
|
|
if (!fTemplateCache && (RORKF_FULLPATH & Flags))
|
|
{
|
|
wcscpy(*ppwszPath, wszREGKEYCONFIGPATH_BS);
|
|
}
|
|
wcscat(*ppwszPath, awc);
|
|
CSASSERT((wcslen(*ppwszPath) + 1) * sizeof(WCHAR) == cb);
|
|
if (L'\0' == awc[0] && L'\\' == (*ppwszPath)[cb / sizeof(WCHAR) - 2])
|
|
{
|
|
(*ppwszPath)[cb / sizeof(WCHAR) - 2] = L'\0';
|
|
}
|
|
|
|
if (NULL != ppwszName)
|
|
{
|
|
*ppwszName = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(wcslen(pwszName) + 1) * sizeof(WCHAR));
|
|
if (NULL == *ppwszName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(*ppwszName, pwszName);
|
|
}
|
|
if (NULL != phkey)
|
|
{
|
|
*phkey = hkeyRequested;
|
|
hkeyRequested = NULL;
|
|
}
|
|
|
|
//printf("key path = '%ws'\n", *ppwszPath);
|
|
//if (NULL != ppwszName) printf("value name = '%ws'\n", *ppwszName);
|
|
|
|
error:
|
|
if (HKEY_LOCAL_MACHINE != hkeyRoot && HKEY_CURRENT_USER != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
if (NULL != hkeyConfig)
|
|
{
|
|
RegCloseKey(hkeyConfig);
|
|
}
|
|
if (NULL != hkeyMod)
|
|
{
|
|
RegCloseKey(hkeyMod);
|
|
}
|
|
if (NULL != hkeyRequested)
|
|
{
|
|
RegCloseKey(hkeyRequested);
|
|
}
|
|
if (NULL != pwszMachine)
|
|
{
|
|
LocalFree(pwszMachine);
|
|
}
|
|
if (S_OK != hr)
|
|
{
|
|
if (NULL != ppwszPath && NULL != *ppwszPath)
|
|
{
|
|
LocalFree(*ppwszPath);
|
|
*ppwszPath = NULL;
|
|
}
|
|
if (NULL != ppwszName && NULL != *ppwszName)
|
|
{
|
|
LocalFree(*ppwszName);
|
|
*ppwszName = NULL;
|
|
}
|
|
}
|
|
return(myHError(hr));
|
|
}
|
|
|
|
|
|
#define wszTEMPLATE wszFCSAPARM_SERVERDNSNAME L"_" wszFCSAPARM_SANITIZEDCANAME
|
|
#define cwcTEMPLATE WSZARRAYSIZE(wszTEMPLATE)
|
|
|
|
HRESULT
|
|
mySetCARegFileNameTemplate(
|
|
IN WCHAR const *pwszRegValueName,
|
|
IN WCHAR const *pwszServerName,
|
|
IN WCHAR const *pwszSanitizedName,
|
|
IN WCHAR const *pwszFileName)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszMatch = NULL;
|
|
WCHAR *pwszMatchIn;
|
|
WCHAR const *pwszBase;
|
|
WCHAR const *pwszExt;
|
|
DWORD cwcPath;
|
|
DWORD cwcBase;
|
|
DWORD cwcMatch;
|
|
DWORD cwcT;
|
|
WCHAR *pwszT = NULL;
|
|
WCHAR *pwszT2;
|
|
|
|
pwszBase = wcsrchr(pwszFileName, L'\\');
|
|
if (NULL == pwszBase)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
|
_JumpErrorStr(hr, error, "bad path", pwszFileName);
|
|
}
|
|
pwszBase++;
|
|
cwcPath = SAFE_SUBTRACT_POINTERS(pwszBase, pwszFileName);
|
|
pwszExt = wcsrchr(pwszBase, L'.');
|
|
if (NULL == pwszExt)
|
|
{
|
|
pwszExt = &pwszBase[wcslen(pwszBase)];
|
|
}
|
|
cwcBase = SAFE_SUBTRACT_POINTERS(pwszExt, pwszBase);
|
|
|
|
do
|
|
{
|
|
cwcMatch = wcslen(pwszServerName) + 1 + wcslen(pwszSanitizedName);
|
|
if (cwcBase != cwcMatch)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Allocate space for both strings at once:
|
|
|
|
pwszMatch = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
2 * (cwcMatch + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszMatch)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
wcscpy(pwszMatch, pwszServerName);
|
|
wcscat(pwszMatch, L"_");
|
|
wcscat(pwszMatch, pwszSanitizedName);
|
|
|
|
pwszMatchIn = &pwszMatch[cwcMatch + 1];
|
|
CopyMemory(pwszMatchIn, pwszBase, cwcMatch * sizeof(WCHAR));
|
|
pwszMatchIn[cwcMatch] = L'\0';
|
|
|
|
if (0 == lstrcmpi(pwszMatch, pwszMatchIn))
|
|
{
|
|
pwszBase = wszTEMPLATE;
|
|
cwcBase = cwcTEMPLATE;
|
|
}
|
|
} while (FALSE);
|
|
|
|
cwcT = cwcPath +
|
|
cwcBase +
|
|
WSZARRAYSIZE(wszFCSAPARM_CERTFILENAMESUFFIX) +
|
|
wcslen(pwszExt);
|
|
|
|
pwszT = (WCHAR *) LocalAlloc(
|
|
LMEM_FIXED,
|
|
(cwcT + 1) * sizeof(WCHAR));
|
|
if (NULL == pwszT)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, error, "LocalAlloc");
|
|
}
|
|
pwszT2 = pwszT;
|
|
|
|
CopyMemory(pwszT2, pwszFileName, cwcPath * sizeof(WCHAR));
|
|
pwszT2 += cwcPath;
|
|
|
|
CopyMemory(pwszT2, pwszBase, cwcBase * sizeof(WCHAR));
|
|
pwszT2 += cwcBase;
|
|
|
|
wcscpy(pwszT2, wszFCSAPARM_CERTFILENAMESUFFIX);
|
|
wcscat(pwszT2, pwszExt);
|
|
|
|
hr = mySetCertRegStrValue(
|
|
pwszSanitizedName,
|
|
NULL,
|
|
NULL,
|
|
pwszRegValueName,
|
|
pwszT);
|
|
_JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszRegValueName);
|
|
|
|
error:
|
|
if (NULL != pwszMatch)
|
|
{
|
|
LocalFree(pwszMatch);
|
|
}
|
|
if (NULL != pwszT)
|
|
{
|
|
LocalFree(pwszT);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
myGetCARegFileNameTemplate(
|
|
IN WCHAR const *pwszRegValueName,
|
|
IN WCHAR const *pwszServerName,
|
|
IN WCHAR const *pwszSanitizedName,
|
|
IN DWORD iCert,
|
|
IN DWORD iCRL,
|
|
OUT WCHAR **ppwszFileName)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR *pwszT = NULL;
|
|
|
|
*ppwszFileName = NULL;
|
|
|
|
hr = myGetCertRegStrValue(
|
|
pwszSanitizedName,
|
|
NULL,
|
|
NULL,
|
|
pwszRegValueName,
|
|
&pwszT);
|
|
_JumpIfErrorStr2(
|
|
hr,
|
|
error,
|
|
"myGetCertRegStrValue",
|
|
pwszRegValueName,
|
|
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
|
|
hr = myFormatCertsrvStringArray(
|
|
FALSE, // fURL
|
|
pwszServerName, // pwszServerName_p1_2
|
|
pwszSanitizedName, // pwszSanitizedName_p3_7
|
|
iCert, // iCert_p4
|
|
L"", // pwszDomainDN_p5
|
|
L"", // pwszConfigDN_p6
|
|
iCRL, // iCRL_p8
|
|
FALSE, // fDeltaCRL_p9
|
|
FALSE, // fDSAttrib_p10_11
|
|
1, // cStrings
|
|
(LPCWSTR *) &pwszT, // apwszStringsIn
|
|
ppwszFileName); // apwszStringsOut
|
|
_JumpIfError(hr, error, "myFormatCertsrvStringArray");
|
|
|
|
error:
|
|
if (NULL != pwszT)
|
|
{
|
|
LocalFree(pwszT);
|
|
}
|
|
return(hr);
|
|
}
|