//+------------------------------------------------------------------------- // // 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 #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" #define wszScrdW2KDllFileForVer L"CertSrv\\CertControl\\w2k\\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"); } for (;;) { // 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; 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 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 *pwsz; WCHAR *pwszConfigServer = NULL; DWORD cwcConfigServer; DWORD cwc; DWORD i; BOOL fValidDigitString; BSTR strConfigFlags = NULL; 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); } strConfigFlags = SysAllocString(wszCONFIG_FLAGS); if (NULL == strConfigFlags) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "SysAllocString"); } cwcConfigServer = 0; 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(strConfigFlags, &strFlags); _JumpIfError(hr, error, "GetField"); lConfigFlags = myWtoI(strFlags, &fValidDigitString); // write everything _but_ current server if (0 != mylstrcmpiL(pwszConfigServer, pComp->pwszServerName) && 0 != mylstrcmpiL(pwszConfigServer, pComp->pwszServerNameOld) && 0 != (CAIF_SHAREDFOLDERENTRY & lConfigFlags) ) { hr = CopyConfigEntry(hConfigFile, 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 != strConfigFlags) { SysFreeString(strConfigFlags); } if (NULL != strConfig) { SysFreeString(strConfig); } if (NULL != strFlags) { SysFreeString(strFlags); } return(hr); } HRESULT CertReplaceFile( IN WCHAR const *pwszpath, IN WCHAR const *pwszFileNew, IN WCHAR const *pwszFileBackup) { HRESULT hr; WCHAR *pwsz; WCHAR wszpathNew[MAX_PATH]; WCHAR wszpathBackup[MAX_PATH]; if (wcslen(pwszpath) >= ARRAYSIZE(wszpathNew)) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); _JumpErrorStr(hr, error, "wszpathNew", pwszpath); } wcscpy(wszpathNew, pwszpath); pwsz = wcsrchr(wszpathNew, L'\\'); if (NULL == pwsz) { hr = E_INVALIDARG; _JumpError(hr, error, "pwsz"); } pwsz[1] = L'\0'; if (wcslen(wszpathNew) + wcslen(pwszFileBackup) >= ARRAYSIZE(wszpathBackup)) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); _JumpErrorStr(hr, error, "wszpathBackup", wszpathNew); } wcscpy(wszpathBackup, wszpathNew); wcscat(wszpathBackup, pwszFileBackup); if (wcslen(wszpathNew) + wcslen(pwszFileNew) >= ARRAYSIZE(wszpathNew)) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); _JumpErrorStr(hr, error, "wszpathBackup", wszpathNew); } wcscat(wszpathNew, pwszFileNew); 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; pwchSubstStart = NULL; nChosenReplacement = 0; for (;;) { // find the next substitution bSubstFound=FALSE; for (nIndex=0; nIndexpwchTempSubstStart) { // 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]); } // <- 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; nChosenReplacement = 0; for (;;) { // find the next substitution bSubstFound=FALSE; for (nIndex=0; nIndexpwchTempSubstStart) { // 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]); } // <- 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"<"}, {L">", L">"}, {L"\"", L"""}, {L"&", L"&"} }; 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(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(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[13][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; WCHAR * pwszTempF=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) // %C - W2K ScrdEnrl version 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[12][REPLACEE]=L"%C"; 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; // %C - W2K ScrdEnrl version wcscpy(wszTargetFileName, pComp->pwszSystem32); wcscat(wszTargetFileName, wszScrdW2KDllFileForVer); hr=GetFileWebVersionString(wszTargetFileName, &pwszTempF); _JumpIfError(hr, error, "GetFileWebVersionString"); rgrgpwszSubst[12][REPLACEMENT]=pwszTempF; // 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); } if (NULL!=pwszTempF) { LocalFree(pwszTempF); } return hr; } HRESULT CreateConfigFiles( WCHAR *pwszDirectoryPath, PER_COMPONENT_DATA *pComp, BOOL fRemove) { WCHAR wszpathConfig[MAX_PATH]; HANDLE hConfigFile; DISPATCHINTERFACE di; ICertConfig *pConfig = NULL; BOOL fMustRelease = FALSE; HRESULT hr = S_OK; 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; if (wcslen(pwszDirectoryPath) + wcslen(g_szSlashCertSrvDotTmp) >= ARRAYSIZE(wszpathConfig)) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); _JumpErrorStr(hr, error, "wszpathConfig", pwszDirectoryPath); } 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( 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); }