windows-nt/Source/XPSP1/NT/ds/security/services/ca/ocmsetup/config.cpp
2020-09-26 16:20:57 +08:00

1065 lines
31 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: config.cpp
//
// Contents: OC Manager component DLL for running the Certificate
// Server setup.
//
//--------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <string.h>
#include "csdisp.h"
#include "csprop.h"
#include "wizpage.h"
#include "certmsg.h"
#define __dwFILE__ __dwFILE_OCMSETUP_CONFIG_CPP__
WCHAR const g_szCertSrvDotTxt[] = L"certsrv.txt";
WCHAR const g_szCertSrvDotBak[] = L"certsrv.bak";
WCHAR const g_szSlashCertSrvDotTmp[] = L"\\certsrv.tmp";
#define wszXEnrollDllFileForVer L"CertSrv\\CertControl\\x86\\xenroll.dll"
#define wszScrdEnrlDllFileForVer L"CertSrv\\CertControl\\x86\\scrdenrl.dll"
//+-------------------------------------------------------------------------
//
// Function: GetBaseFileNameFromFullPath()
//
// Synopsis: Takes a string representing a path of the form
// "\foo\bar\shrd\lu\basefilename"
// and extracts the "basefilename" from the end.
//
// Effects: Modifies the pointer in the second argument;
// allocates memory.
//
// Arguments: [pszFullPath] -- Path to operate on
// [pszBaseFileName] -- Buffer to receive base name
//
// Returns: BOOL success/failure code.
//
// Requires: Assumes that pszBaseFileName is a pre-allocated buffer of
// size sufficient to hold the filename extracted from
// pszFullPath---NO ERROR CHECKING IS DONE ON THIS ARGUMENT;
// IN THE CURRENT CODE BUFFERS GIVEN TO THIS ARGUMENT ARE
// STATICALLY ALLOCATED OF SIZE MAX_PATH (OR EQUIVALENTLY
// STRBUF_SIZE).
//
// Modifies: [ppszBaseFileName]
//
// History: 10/25/96 JerryK Created
// 11/25/96 JerryK Code Cleanup
//
//--------------------------------------------------------------------------
BOOL
GetBaseFileNameFromFullPath(
IN const LPTSTR pszFullPath,
OUT LPTSTR pszBaseFileName)
{
LPTSTR pszBaseName;
BOOL fRetVal;
// Find the last '\' character in the full path string
if (NULL == (pszBaseName = _tcsrchr(pszFullPath,TEXT('\\'))))
{
// Didn't find a '\' character at all so point to start of string
pszBaseName = pszFullPath;
}
else
{
// Found the '\' character so move to point just past it
pszBaseName++;
}
// Copy the base file name into the result buffer
_tcscpy(pszBaseFileName,pszBaseName);
// Set up return value
fRetVal = TRUE;
return fRetVal;
}
HRESULT myStringToAnsiFile(HANDLE hFile, LPCSTR psz, DWORD cch)
{
DWORD dwWritten;
if (cch == -1)
cch = lstrlenA(psz);
if (!WriteFile(
hFile,
psz,
cch,
&dwWritten,
NULL))
return myHLastError();
CSASSERT(dwWritten == cch);
return S_OK;
}
HRESULT myStringToAnsiFile(HANDLE hFile, LPCWSTR pwsz, DWORD cch)
{
HRESULT hr;
LPSTR psz = NULL;
if (!ConvertWszToSz(&psz, pwsz, cch))
{
hr = myHLastError();
goto Ret;
}
hr = myStringToAnsiFile(hFile, psz, cch);
Ret:
if (psz)
LocalFree(psz);
return hr;
}
HRESULT myStringToAnsiFile(HANDLE hFile, CHAR ch)
{
return myStringToAnsiFile(hFile, &ch, 1);
}
HRESULT
WriteEscapedString(
HANDLE hConfigFile,
WCHAR const *pwszIn,
IN BOOL fEol)
{
BOOL fQuote = FALSE;
DWORD i;
HRESULT hr;
if (NULL == pwszIn)
{
hr = myStringToAnsiFile(hConfigFile, "\"\"", 2); // write ("")
_JumpIfError(hr, error, "myStringToAnsiFile");
}
else
{
// Quote strings that have double quotes, commas, '#' or white space,
// or that are empty.
fQuote = L'\0' != pwszIn[wcscspn(pwszIn, L"\",# \t")] || L'\0' == *pwszIn;
if (fQuote)
{
hr = myStringToAnsiFile(hConfigFile, '"');
_JumpIfError(hr, error, "myStringToAnsiFile");
}
while (TRUE)
{
// Find a L'\0' or L'"', and print the string UP TO that character:
i = wcscspn(pwszIn, L"\"");
hr = myStringToAnsiFile(hConfigFile, pwszIn, i);
_JumpIfError(hr, error, "myStringToAnsiFile");
// Point to the L'\0' or L'"', and stop at the end of the string.
pwszIn += i;
if (L'\0' == *pwszIn)
{
break;
}
// Skip the L'"', and print two of them to escape the embedded quote.
pwszIn++;
hr = myStringToAnsiFile(hConfigFile, "\"\"", 2); // write ("")
_JumpIfError(hr, error, "myStringToAnsiFile");
}
if (fQuote)
{
hr = myStringToAnsiFile(hConfigFile, '"');
_JumpIfError(hr, error, "myStringToAnsiFile");
}
}
hr = myStringToAnsiFile(hConfigFile, fEol ? "\r\n" : ", ", 2); // each insert string is 2 chars
_JumpIfError(hr, error, "myStringToAnsiFile");
error:
return hr;
}
HRESULT
WriteNewConfigEntry(
HANDLE hConfigFile,
IN PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
DWORD i;
WCHAR wszSelfSignFName[MAX_PATH];
WCHAR *pwszConfig = NULL;
CASERVERSETUPINFO *pServer = (pComp->CA).pServer;
hr = myFormConfigString(pComp->pwszServerName,
pServer->pwszSanitizedName,
&pwszConfig);
_JumpIfError(hr, error, "myFormConfigString");
// Yank out the base filenames for the exchange and self-signed certs
GetBaseFileNameFromFullPath(pServer->pwszCACertFile, wszSelfSignFName);
hr = WriteEscapedString(hConfigFile, pServer->pwszSanitizedName, FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
// org, ou, country, state
hr = WriteEscapedString(hConfigFile, L"", FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, L"", FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, L"", FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, L"", FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, L"", FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, pwszConfig, FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, L"", FALSE); // dummy wszExchangeFName
_JumpIfError(hr, error, "WriteEscapedString");
hr = WriteEscapedString(hConfigFile, wszSelfSignFName, FALSE);
_JumpIfError(hr, error, "WriteEscapedString");
// ca description
hr = WriteEscapedString(hConfigFile, L"", TRUE);
_JumpIfError(hr, error, "WriteEscapedString");
error:
if (NULL != pwszConfig)
{
LocalFree(pwszConfig);
}
return(hr);
}
WCHAR *apwszFieldNames[] = {
wszCONFIG_COMMONNAME,
wszCONFIG_ORGUNIT,
wszCONFIG_ORGANIZATION,
wszCONFIG_LOCALITY,
wszCONFIG_STATE,
wszCONFIG_COUNTRY,
#define FN_CONFIG 6 // Index into apwszFieldNames & apstrFieldNames
wszCONFIG_CONFIG,
wszCONFIG_EXCHANGECERTIFICATE,
#define FN_CERTNAME 8 // Index into apwszFieldNames & apstrFieldNames
wszCONFIG_SIGNATURECERTIFICATE,
#define FN_COMMENT 9 // Index into apwszFieldNames & apstrFieldNames
wszCONFIG_DESCRIPTION,
};
#define CSTRING (sizeof(apwszFieldNames)/sizeof(apwszFieldNames[0]))
BSTR apstrFieldNames[CSTRING];
HRESULT
CopyConfigEntry(
IN HANDLE hConfigFile,
IN BSTR const strConfig,
IN ICertConfig *pConfig)
{
HRESULT hr;
BSTR strFieldValue = NULL;
BSTR strComment = NULL;
BSTR strCertName = NULL;
DWORD i;
for (i = 0; i < CSTRING; i++)
{
CSASSERT(NULL != apstrFieldNames[i]);
hr = pConfig->GetField(apstrFieldNames[i], &strFieldValue);
_JumpIfErrorNotSpecific(
hr,
error,
"ICertConfig::GetField",
CERTSRV_E_PROPERTY_EMPTY);
hr = WriteEscapedString(hConfigFile, strFieldValue, ((CSTRING - 1) == i) );
_JumpIfError(hr, error, "WriteEscapedString");
switch (i)
{
case FN_CERTNAME:
strCertName = strFieldValue;
strFieldValue = NULL;
break;
case FN_COMMENT:
strComment = strFieldValue;
strFieldValue = NULL;
break;
}
}
hr = S_OK;
error:
if (NULL != strFieldValue)
{
SysFreeString(strFieldValue);
}
if (NULL != strComment)
{
SysFreeString(strComment);
}
if (NULL != strCertName)
{
SysFreeString(strCertName);
}
return(hr);
}
HRESULT
WriteFilteredConfigEntries(
IN HANDLE hConfigFile,
IN ICertConfig *pConfig,
IN PER_COMPONENT_DATA *pComp)
{
HRESULT hr = S_OK;
LONG Count;
LONG Index;
BSTR strConfig = NULL;
BSTR strFlags = NULL;
LONG lConfigFlags;
WCHAR wszConfigComputerName[MAX_COMPUTERNAME_LENGTH + 1];
WCHAR *pwsz;
WCHAR *pwszConfigServer = NULL;
DWORD cwcConfigServer;
DWORD cwc;
DWORD i;
BOOL fValidDigitString;
for (i = 0; i < CSTRING; i++)
{
if (!ConvertWszToBstr(&apstrFieldNames[i], apwszFieldNames[i], -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "ConvertWszToBstr");
}
}
hr = pConfig->Reset(0, &Count);
if (S_OK != hr)
{
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
hr = S_OK;
}
_JumpError2(hr, error, "Reset", S_FALSE);
}
while (Count-- > 0)
{
hr = pConfig->Next(&Index);
_JumpIfError(hr, error, "Next");
hr = pConfig->GetField(apstrFieldNames[FN_CONFIG], &strConfig);
_JumpIfError(hr, error, "GetField");
pwsz = wcschr(strConfig, L'\\');
if (NULL == pwsz)
{
cwc = wcslen(strConfig);
}
else
{
cwc = SAFE_SUBTRACT_POINTERS(pwsz, strConfig);
}
if (NULL == pwszConfigServer || cwc >= cwcConfigServer)
{
if (NULL != pwszConfigServer)
{
LocalFree(pwszConfigServer);
pwszConfigServer = NULL;
}
cwcConfigServer = cwc + 1;
if (2 * MAX_COMPUTERNAME_LENGTH > cwcConfigServer)
{
cwcConfigServer = 2 * MAX_COMPUTERNAME_LENGTH;
}
pwszConfigServer = (WCHAR *) LocalAlloc(
LMEM_FIXED,
cwcConfigServer * sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, pwszConfigServer);
}
CSASSERT(cwc < cwcConfigServer);
CopyMemory(pwszConfigServer, strConfig, cwc * sizeof(WCHAR));
pwszConfigServer[cwc] = L'\0';
hr = pConfig->GetField(wszCONFIG_FLAGS, &strFlags);
_JumpIfError(hr, error, "GetField");
lConfigFlags = myWtoI(strFlags, &fValidDigitString);
// write everything _but_ current server
if (0 != lstrcmpi(pwszConfigServer, pComp->pwszServerName) &&
0 != lstrcmpi(pwszConfigServer, pComp->pwszServerNameOld) &&
0 != (CAIF_SHAREDFOLDERENTRY & lConfigFlags) )
{
hr = CopyConfigEntry(
hConfigFile,
strConfig,
pConfig);
_JumpIfError(hr, error, "CopyConfigEntry");
}
}
error:
if (NULL != pwszConfigServer)
{
LocalFree(pwszConfigServer);
}
for (i = 0; i < CSTRING; i++)
{
if (NULL != apstrFieldNames[i])
{
SysFreeString(apstrFieldNames[i]);
apstrFieldNames[i] = NULL;
}
}
if (NULL != strConfig)
{
SysFreeString(strConfig);
}
if (NULL != strFlags)
{
SysFreeString(strFlags);
}
return(hr);
}
HRESULT
CertReplaceFile(
IN HINSTANCE hInstance,
IN BOOL fUnattended,
IN HWND hwnd,
IN WCHAR const *pwszpath,
IN WCHAR const *pwszFileNew,
IN WCHAR const *pwszFileBackup)
{
HRESULT hr;
WCHAR *pwsz;
WCHAR wszpathNew[MAX_PATH] = L"";
WCHAR wszpathBackup[MAX_PATH] = L"";
wcscpy(wszpathNew, pwszpath);
pwsz = wcsrchr(wszpathNew, L'\\');
CSASSERT(NULL != pwsz);
if (NULL == pwsz)
return E_INVALIDARG;
else
pwsz[1] = L'\0';
wcscpy(wszpathBackup, wszpathNew);
wcscat(wszpathNew, pwszFileNew);
wcscat(wszpathBackup, pwszFileBackup);
if (!DeleteFile(wszpathBackup))
{
hr = myHLastError();
_PrintErrorStr2(
hr,
"DeleteFile",
wszpathBackup,
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}
if (!MoveFile(wszpathNew, wszpathBackup))
{
hr = myHLastError();
_PrintErrorStr2(
hr,
"MoveFile",
wszpathNew,
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}
if (!MoveFile(pwszpath, wszpathNew))
{
hr = myHLastError();
_JumpErrorStr(hr, error, "MoveFile", pwszpath);
}
hr = S_OK;
error:
return(hr);
}
//--------------------------------------------------------------------
// Perform search and replace on the source string, using multiple
// replacee strings, and returns the result.
// rgrgwszReplacement is an array of arrays of two strings:
// rgrgwszReplacement[n][0] is the replacee,
// rgrgwszReplacement[n][1] is the replacment.
// No portion of any of the replacement strings is searched for a replacee string.
// Replacement strings may be NULL.
#define REPLACEE 0
#define REPLACEMENT 1
WCHAR * MultiStringReplace(const WCHAR * pwszSource, const WCHAR *(* rgrgpwszReplacements)[2] , unsigned int nReplacements) {
// precondition
CSASSERT(NULL!=pwszSource);
CSASSERT(nReplacements>0);
CSASSERT(NULL!=rgrgpwszReplacements);
// common variables
unsigned int nIndex;
BOOL bSubstFound;
unsigned int nChosenReplacement;
const WCHAR * pwchSubstStart;
const WCHAR * pwchSearchStart;
WCHAR * pwszTarget=NULL;
WCHAR * pwchTargetStart;
// first, calculate the length of the result string
unsigned int nFinalStringLen=wcslen(pwszSource)+1;
pwchSearchStart=pwszSource;
do {
// find the next substitution
bSubstFound=FALSE;
for (nIndex=0; nIndex<nReplacements; nIndex++) {
WCHAR * pwchTempSubstStart=wcsstr(pwchSearchStart, rgrgpwszReplacements[nIndex][REPLACEE]);
if (NULL==pwchTempSubstStart) {
// we didn't find this replacee in the target
// so ignore it
} else if (FALSE==bSubstFound) {
// this is the first one we found
pwchSubstStart=pwchTempSubstStart;
bSubstFound=TRUE;
nChosenReplacement=nIndex;
} else if (pwchSubstStart>pwchTempSubstStart) {
// this is one comes before the one we already found
pwchSubstStart=pwchTempSubstStart;
nChosenReplacement=nIndex;
} else {
// this is one comes after the one we already found
// so ignore it
}
} // <- end substitution finding loop
// if no substitution has been found, exit the loop
if (FALSE==bSubstFound) {
break;
}
// update the statistics
nFinalStringLen=nFinalStringLen
+ (NULL != rgrgpwszReplacements[nChosenReplacement][REPLACEMENT] ?
wcslen(rgrgpwszReplacements[nChosenReplacement][REPLACEMENT]) : 0)
-wcslen(rgrgpwszReplacements[nChosenReplacement][REPLACEE]);
pwchSearchStart=pwchSubstStart+wcslen(rgrgpwszReplacements[nChosenReplacement][REPLACEE]);
} while (TRUE); // <- end length-calculating loop
// allocate the new string
pwszTarget=(WCHAR *)LocalAlloc(LMEM_FIXED, nFinalStringLen*sizeof(WCHAR));
if (NULL==pwszTarget) {
_JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
}
// build the result
pwchTargetStart=pwszTarget;
pwchSearchStart=pwszSource;
do {
// find the next substitution
bSubstFound=FALSE;
for (nIndex=0; nIndex<nReplacements; nIndex++) {
WCHAR * pwchTempSubstStart=wcsstr(pwchSearchStart, rgrgpwszReplacements[nIndex][REPLACEE]);
if (NULL==pwchTempSubstStart) {
// we didn't find this replacee in the target
// so ignore it
} else if (FALSE==bSubstFound) {
// this is the first one we found
pwchSubstStart=pwchTempSubstStart;
bSubstFound=TRUE;
nChosenReplacement=nIndex;
} else if (pwchSubstStart>pwchTempSubstStart) {
// this is one comes before the one we already found
pwchSubstStart=pwchTempSubstStart;
nChosenReplacement=nIndex;
} else {
// this is one comes after the one we already found
// so ignore it
}
} // <- end substitution finding loop
// if no substitution has been found, exit the loop
if (FALSE==bSubstFound) {
break;
}
// copy the source up to the replacee
unsigned int nCopyLen=SAFE_SUBTRACT_POINTERS(pwchSubstStart, pwchSearchStart);
wcsncpy(pwchTargetStart, pwchSearchStart, nCopyLen);
pwchTargetStart+=nCopyLen;
if (NULL != rgrgpwszReplacements[nChosenReplacement][REPLACEMENT])
{
// copy the replacement
nCopyLen=wcslen(rgrgpwszReplacements[nChosenReplacement][REPLACEMENT]);
wcsncpy(pwchTargetStart, rgrgpwszReplacements[nChosenReplacement][REPLACEMENT], nCopyLen);
pwchTargetStart+=nCopyLen;
}
// skip over the replacee
pwchSearchStart=pwchSubstStart+wcslen(rgrgpwszReplacements[nChosenReplacement][REPLACEE]);
} while (TRUE); // <- end target string building loop
// finish copying whatever's left, which may be just '\0'.
wcscpy(pwchTargetStart, pwchSearchStart);
// postcondition
CSASSERT(wcslen(pwszTarget)+1==nFinalStringLen);
// all done
error:
return pwszTarget;
}
//--------------------------------------------------------------------
// Escapes any characters unsuitable for plain HTML (or VBScript)
static const WCHAR * gc_rgrgpwszHTMLSafe[4][2]={
{L"<", L"&lt;"}, {L">", L"&gt;"}, {L"\"", L"&quot;"}, {L"&", L"&amp;"}
};
WCHAR * MakeStringHTMLSafe(const WCHAR * pwszTarget) {
return MultiStringReplace(pwszTarget, gc_rgrgpwszHTMLSafe, ARRAYSIZE(gc_rgrgpwszHTMLSafe));
}
//--------------------------------------------------------------------
// Escapes any characters unsuitable for plain HTML (or VBScript)
static const WCHAR * gc_rgrgpwszVBScriptSafe[2][2]={
{L"\"", L"\"\""}, {L"%>", L"%\" & \">"}
};
WCHAR * MakeStringVBScriptSafe(const WCHAR * pwszTarget) {
return MultiStringReplace(pwszTarget, gc_rgrgpwszVBScriptSafe, ARRAYSIZE(gc_rgrgpwszVBScriptSafe));
}
//--------------------------------------------------------------------
// Perform search and replace on the source string and return the result
// No portion of the replacement string is searched for the replacee string.
// Simple adapter for MultiStringReplace
WCHAR * SingleStringReplace(const WCHAR * pwszSource, const WCHAR * pwszReplacee, const WCHAR * pwszReplacement) {
const WCHAR * rgrgpwszTemp[1][2]={{pwszReplacee, pwszReplacement}};
return MultiStringReplace(pwszSource, rgrgpwszTemp, ARRAYSIZE(rgrgpwszTemp));
}
//--------------------------------------------------------------------
// write a string to a file
// Mostly, this is a wrapper to do UNICODE->UTF8 conversion.
HRESULT WriteString(HANDLE hTarget, const WCHAR * pwszSource) {
// precondition
CSASSERT(NULL!=pwszSource);
CSASSERT(NULL!=hTarget && INVALID_HANDLE_VALUE!=hTarget);
// common variables
HRESULT hr=S_OK;
char * pszMbcsBuf=NULL;
// perform UNICODE->MBCS
// determine size of output buffer
DWORD dwBufByteSize=WideCharToMultiByte(CP_UTF8/*code page*/, 0/*flags*/, pwszSource,
-1/*null-terminated*/, NULL/*out-buf*/, 0/*size of out-buf, 0->calc*/,
NULL/*default char*/, NULL/*used default char*/);
if (0==dwBufByteSize) {
hr=myHLastError();
_JumpError(hr, error, "WideCharToMultiByte(calc)");
}
// allocate output buffer
pszMbcsBuf=(char *)LocalAlloc(LMEM_FIXED, dwBufByteSize);
_JumpIfOutOfMemory(hr, error, pszMbcsBuf);
// do the conversion
if (0==WideCharToMultiByte(CP_UTF8/*code page*/, 0/*flags*/, pwszSource,
-1/*null-terminated*/, pszMbcsBuf, dwBufByteSize,
NULL/*default char*/, NULL/*used default char*/)) {
hr=myHLastError();
_JumpError(hr, error, "WideCharToMultiByte(convert)");
}
// write to file and free the string
dwBufByteSize--; // minus one so we don't write the terminating null
DWORD dwBytesWritten;
if (FALSE==WriteFile(hTarget, pszMbcsBuf, dwBufByteSize, &dwBytesWritten, NULL /*overlapped*/)) {
hr=myHLastError();
_JumpError(hr, error, "WriteFile");
}
// all done
error:
if (NULL!=pszMbcsBuf) {
LocalFree(pszMbcsBuf);
}
return hr;
}
//--------------------------------------------------------------------
// return the version string for a file in the format for a web page (comma separated)
HRESULT
GetFileWebVersionString(
IN WCHAR const * pwszFileName,
OUT WCHAR ** ppwszVersion)
{
// precondition
CSASSERT(NULL!=pwszFileName);
CSASSERT(NULL!=ppwszVersion);
// common variables
HRESULT hr;
DWORD cbData;
DWORD dwIgnored;
UINT uLen;
VS_FIXEDFILEINFO * pvs;
WCHAR wszFileVersion[64];
int cch;
// variables that must be cleaned up
VOID * pvData=NULL;
// reset the output parameter
*ppwszVersion=NULL;
// determine the size of the memory block needed to store the version info
cbData=GetFileVersionInfoSize(const_cast<WCHAR *>(pwszFileName), &dwIgnored);
if (0==cbData) {
hr=myHLastError();
if (S_OK==hr) {
hr=HRESULT_FROM_WIN32(ERROR_RESOURCE_DATA_NOT_FOUND);
}
_JumpErrorStr(hr, error, "GetFileVersionInfoSize", pwszFileName);
}
// allocate the block
pvData=LocalAlloc(LMEM_FIXED, cbData);
_JumpIfOutOfMemory(hr, error, pvData);
// load the file version info
if (!GetFileVersionInfo(const_cast<WCHAR *>(pwszFileName), dwIgnored, cbData, pvData)) {
hr=myHLastError();
_JumpErrorStr(hr, error, "GetFileVersionInfo", pwszFileName);
}
// get a pointer to the root block
if (!VerQueryValue(pvData, L"\\", (VOID **) &pvs, &uLen)) {
hr=myHLastError();
_JumpError(hr, error, "VerQueryValue");
}
cch = wsprintf(wszFileVersion, L"%d,%d,%d,%d",
HIWORD(pvs->dwFileVersionMS),
LOWORD(pvs->dwFileVersionMS),
HIWORD(pvs->dwFileVersionLS),
LOWORD(pvs->dwFileVersionLS));
CSASSERT(cch < ARRAYSIZE(wszFileVersion));
*ppwszVersion = (WCHAR*)LocalAlloc(LMEM_FIXED,
(wcslen(wszFileVersion)+1) * sizeof(WCHAR));
if (NULL == *ppwszVersion)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
wcscpy(*ppwszVersion, wszFileVersion);
hr=S_OK;
error:
if (NULL != pvData) {
LocalFree(pvData);
}
return hr;
}
//--------------------------------------------------------------------
// create the .inc file that has the basic configuration data
HRESULT CreateCertWebDatIncPage(IN PER_COMPONENT_DATA *pComp, IN BOOL bIsServer)
{
// precondition
CSASSERT(NULL!=pComp);
// common variables
HRESULT hr=S_OK;
HANDLE hTarget=INVALID_HANDLE_VALUE;
const WCHAR * rgrgpwszSubst[12][2];
WCHAR wszTargetFileName[MAX_PATH];
wszTargetFileName[0] = L'\0';
// variables that must be cleaned up
WCHAR * pwszTempA=NULL;
WCHAR * pwszTempB=NULL;
WCHAR * pwszTempC=NULL;
WCHAR * pwszTempD=NULL;
WCHAR * pwszTempE=NULL;
ENUM_CATYPES CAType;
// create the target file name
wcscpy(wszTargetFileName, pComp->pwszSystem32);
wcscat(wszTargetFileName, L"CertSrv\\certdat.inc");
// get html lines from resource
// Note, we don't have to free these strings.
WCHAR const * pwszCWDat=myLoadResourceString(IDS_HTML_CERTWEBDAT);
if (NULL==pwszCWDat) {
hr=myHLastError();
_JumpError(hr, error, "myLoadResourceString");
}
// open the file
hTarget=CreateFileW(wszTargetFileName, GENERIC_WRITE, 0/*no sharing*/, NULL/*security*/,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL/*template*/);
if (INVALID_HANDLE_VALUE==hTarget) {
hr=myHLastError();
_JumpError(hr, error, "CreateFileW");
}
// prepare to write the file
// %0 - default company
// %1 - default OrgUnit
// %2 - default locality
// %3 - default state
// %4 - default country
// %5 - computer
// %6 - CA name (unsanitized, for config)
// %7 - server type
// %8 - opposite of %7
// %9 - XEnroll version
// %A - ScrdEnrl version
// %B - CA name (unsanitized, for display)
rgrgpwszSubst[0][REPLACEE]=L"%0";
rgrgpwszSubst[1][REPLACEE]=L"%1";
rgrgpwszSubst[2][REPLACEE]=L"%2";
rgrgpwszSubst[3][REPLACEE]=L"%3";
rgrgpwszSubst[4][REPLACEE]=L"%4";
rgrgpwszSubst[5][REPLACEE]=L"%5";
rgrgpwszSubst[6][REPLACEE]=L"%6";
rgrgpwszSubst[7][REPLACEE]=L"%7";
rgrgpwszSubst[8][REPLACEE]=L"%8";
rgrgpwszSubst[9][REPLACEE]=L"%9";
rgrgpwszSubst[10][REPLACEE]=L"%A";
rgrgpwszSubst[11][REPLACEE]=L"%B";
rgrgpwszSubst[0][REPLACEMENT]=L""; // company/org
rgrgpwszSubst[1][REPLACEMENT]=L""; // ou
rgrgpwszSubst[2][REPLACEMENT]=L""; // locality
rgrgpwszSubst[3][REPLACEMENT]=L""; // state
rgrgpwszSubst[4][REPLACEMENT]=L""; // country
if (FALSE==bIsServer) {
// This is a web-client only setup
CAWEBCLIENTSETUPINFO *pClient=pComp->CA.pClient;
// set the identity of the CA
rgrgpwszSubst[5][REPLACEMENT]=pClient->pwszWebCAMachine;
pwszTempE=MakeStringVBScriptSafe(pClient->pwszWebCAName);
_JumpIfOutOfMemory(hr, error, pwszTempE);
rgrgpwszSubst[6][REPLACEMENT]=pwszTempE;
pwszTempD=MakeStringHTMLSafe(pClient->pwszWebCAName);
_JumpIfOutOfMemory(hr, error, pwszTempD);
rgrgpwszSubst[11][REPLACEMENT]=pwszTempD;
CAType = pClient->WebCAType;
} else {
// This is a server + web-client setup
CASERVERSETUPINFO *pServer=pComp->CA.pServer;
// set the identity of the CA
rgrgpwszSubst[5][REPLACEMENT]=pComp->pwszServerName;
pwszTempE=MakeStringVBScriptSafe(pServer->pwszCACommonName);
_JumpIfOutOfMemory(hr, error, pwszTempE);
rgrgpwszSubst[6][REPLACEMENT]=pwszTempE;
pwszTempD=MakeStringHTMLSafe(pServer->pwszCACommonName);
_JumpIfOutOfMemory(hr, error, pwszTempD);
rgrgpwszSubst[11][REPLACEMENT]=pwszTempD;
CAType = pServer->CAType;
}
// set the CA type
if (IsStandaloneCA(CAType)) {
rgrgpwszSubst[7][REPLACEMENT]=L"StandAlone";
rgrgpwszSubst[8][REPLACEMENT]=L"Enterprise";
} else {
rgrgpwszSubst[7][REPLACEMENT]=L"Enterprise";
rgrgpwszSubst[8][REPLACEMENT]=L"StandAlone";
}
// %9 - XEnroll version
wcscpy(wszTargetFileName, pComp->pwszSystem32);
wcscat(wszTargetFileName, wszXEnrollDllFileForVer);
hr=GetFileWebVersionString(wszTargetFileName, &pwszTempB);
_JumpIfError(hr, error, "GetFileWebVersionString");
rgrgpwszSubst[9][REPLACEMENT]=pwszTempB;
// %A - ScrdEnrl version
wcscpy(wszTargetFileName, pComp->pwszSystem32);
wcscat(wszTargetFileName, wszScrdEnrlDllFileForVer);
hr=GetFileWebVersionString(wszTargetFileName, &pwszTempC);
_JumpIfError(hr, error, "GetFileWebVersionString");
rgrgpwszSubst[10][REPLACEMENT]=pwszTempC;
// do the replacements
pwszTempA=MultiStringReplace(pwszCWDat, rgrgpwszSubst, ARRAYSIZE(rgrgpwszSubst));
_JumpIfOutOfMemory(hr, error, pwszTempA);
// write the text
hr=WriteString(hTarget, pwszTempA);
_JumpIfError(hr, error, "WriteString");
// all done
error:
if (INVALID_HANDLE_VALUE!=hTarget) {
CloseHandle(hTarget);
}
if (NULL!=pwszTempA) {
LocalFree(pwszTempA);
}
if (NULL!=pwszTempB) {
LocalFree(pwszTempB);
}
if (NULL!=pwszTempC) {
LocalFree(pwszTempC);
}
if (NULL!=pwszTempD) {
LocalFree(pwszTempD);
}
if (NULL!=pwszTempE) {
LocalFree(pwszTempE);
}
return hr;
}
HRESULT
CreateConfigFiles(
WCHAR *pwszDirectoryPath,
PER_COMPONENT_DATA *pComp,
BOOL fRemove,
HWND hwnd)
{
WCHAR wszpathConfig[MAX_PATH];
WCHAR wszCACertFileName[MAX_PATH];
HANDLE hConfigFile;
DISPATCHINTERFACE di;
ICertConfig *pConfig = NULL;
BOOL fMustRelease = FALSE;
HRESULT hr = S_OK;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
hr = DispatchSetup(
DISPSETUP_COM,
CLSCTX_INPROC_SERVER,
wszCLASS_CERTCONFIG,
&CLSID_CCertConfig,
&IID_ICertConfig,
0, // cDispatch
NULL, // pDispatchTable
&di);
if (S_OK != hr)
{
pComp->iErrMsg = IDS_ERR_LOADICERTCONFIG;
_JumpError(hr, error, "DispatchSetup");
}
fMustRelease = TRUE;
pConfig = (ICertConfig *) di.pUnknown;
wcscpy(wszpathConfig, pwszDirectoryPath);
wcscat(wszpathConfig, g_szSlashCertSrvDotTmp);
hConfigFile = CreateFile(
wszpathConfig,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
0,
0);
if (INVALID_HANDLE_VALUE == hConfigFile)
{
hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
_JumpErrorStr2(
hr,
error,
"CreateFile",
wszpathConfig,
fRemove? hr : S_OK);
}
if (!fRemove)
{
// if installing, write our config entry first
hr = WriteNewConfigEntry(hConfigFile, pComp);
_PrintIfError(hr, "WriteNewConfigEntry");
}
if (S_OK == hr)
{
hr = WriteFilteredConfigEntries(
hConfigFile,
pConfig,
pComp);
_PrintIfError2(hr, "WriteFilteredConfigEntries", S_FALSE);
}
// must close here because the following call will move it
if (NULL != hConfigFile)
{
CloseHandle(hConfigFile);
}
hr = CertReplaceFile(pComp->hInstance,
pComp->fUnattended,
hwnd,
wszpathConfig,
g_szCertSrvDotTxt,
g_szCertSrvDotBak);
_JumpIfErrorStr(hr, error, "CertReplaceFile", g_szCertSrvDotTxt);
hr = S_OK;
error:
if (S_OK != hr && 0 == pComp->iErrMsg)
{
pComp->iErrMsg = IDS_ERR_WRITECONFIGFILE;
}
if (fMustRelease)
{
Config_Release(&di);
}
return(hr);
}