Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7259 lines
204 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: wizpage.cpp
//
// Contents: Wizard page construction and presentation functions to be used
// by the OCM driver code.
//
// History: 04/16/97 JerryK Fixed/Changed/Unmangled
// 0/8/97 XTan major structure change
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
// ** System Includes **
#include <prsht.h>
#include <commdlg.h>
#include <sddl.h>
// ** Application Includes **
#include "cryptui.h"
#include "csdisp.h"
#include "csprop.h"
#include "cspenum.h"
#include "usecert.h"
#include "wizpage.h"
#include "cscsp.h"
#include "clibres.h"
#include "certmsg.h"
#include "websetup.h"
#include "dssetup.h"
#include "setupids.h"
#include "tfc.h"
#include "certacl.h"
//defines
#define __dwFILE__ __dwFILE_OCMSETUP_WIZPAGE_CPP__
#define dwWIZDISABLE (DWORD) -2
#define dwWIZBACK (DWORD) -1
#define dwWIZACTIVE 0
#define dwWIZNEXT 1
#define C_CSPHASNOKEYMINMAX (DWORD) -1
#define MAX_KEYLENGTHEDIT 128
#define MAX_KEYLENGTHDIGIT 5
#define wszOLDCASTOREPREFIX L"CA_"
#define _ReturnIfWizError(hr) \
{ \
if (S_OK != (hr)) \
{ \
CSILOG((hr), IDS_LOG_WIZ_PAGE_ERROR, NULL, NULL, NULL); \
_PrintError(hr, "CertSrv Wizard error"); \
return TRUE; \
} \
}
#define _GetCompDataOrReturnIfError(pComp, hDlg) \
(PER_COMPONENT_DATA*)GetWindowLongPtr((hDlg), DWLP_USER); \
if (NULL == (pComp) || S_OK != (pComp)->hrContinue) \
{ \
return TRUE; \
}
#define _GetCompDataOrReturn(pComp, hDlg) \
(PER_COMPONENT_DATA*)GetWindowLongPtr((hDlg), DWLP_USER); \
if (NULL == (pComp)) \
{ \
return TRUE; \
}
#define _DisableWizDisplayIfError(pComp, hDlg) \
if (S_OK != (pComp)->hrContinue) \
{ \
CSILOG((pComp)->hrContinue, IDS_LOG_DISABLE_WIZ_PAGE, NULL, NULL, NULL); \
SetWindowLongPtr((hDlg), DWLP_MSGRESULT, -1); \
}
//--------------------------------------------------------------------
struct FAKEPROGRESSINFO {
HANDLE hStopEvent;
CRITICAL_SECTION csTimeSync;
BOOL fCSInit;
DWORD dwSecsRemaining;
HWND hwndProgBar;
};
struct KEYGENPROGRESSINFO {
HWND hDlg; // wizard page window
PER_COMPONENT_DATA * pComp; // setup data
};
KEYGENPROGRESSINFO g_KeyGenInfo = {
NULL, //hDlg
NULL, //pComp
};
BOOL g_fAllowUnicodeStrEncoding = FALSE;
// ** Prototypes/Forward Declarations **
LRESULT CALLBACK
IdInfoNameEditFilterHook(HWND, UINT, WPARAM, LPARAM);
INT_PTR
DefaultPageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
__inline VOID
SetEditFocusAndSelect(
IN HWND hwnd,
IN DWORD indexStart,
IN DWORD indexEnd)
{
SetFocus(hwnd);
SendMessage(hwnd, EM_SETSEL, indexStart, indexEnd);
}
// fix for 160324 - NT4->Whistler upgrade:
// cannot reinstall CA w/ same cert as instructions tell us to do
//
// Upgrade NT4->Whistler is not supported but old CA key and cert can be reused
// But NT4 used to install CA certs in a separate store (CA_MACHINENAME) so we
// need to move the cert to root store so it can be validated.
HRESULT CopyNT4CACertToRootStore(CASERVERSETUPINFO *pServer)
{
HRESULT hr;
WCHAR wszOldCAStore[MAX_PATH];
HCERTSTORE hOldStore = NULL;
HCERTSTORE hRootStore = NULL;
CERT_RDN_ATTR rdnAttr = { szOID_COMMON_NAME, CERT_RDN_ANY_TYPE,};
CERT_RDN rdn = { 1, &rdnAttr };
DWORD cCA = 0;
CERT_CONTEXT const *pCACert;
CERT_CONTEXT const *pCACertKeep = NULL; // needn't free
CERT_CONTEXT const **ppCACertKeep = NULL;
CRYPT_KEY_PROV_INFO keyProvInfo;
DWORD *pIndex = NULL;
DWORD i = 0;
ZeroMemory(&keyProvInfo, sizeof(keyProvInfo));
// form old ca store name
// !!! NT4 uses different sanitize, how do we build it correctly?
wcscpy(wszOldCAStore, wszOLDCASTOREPREFIX);
wcscat(wszOldCAStore, pServer->pwszSanitizedName);
// open old CA store
hOldStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
X509_ASN_ENCODING,
NULL, // hProv
CERT_STORE_OPEN_EXISTING_FLAG |
CERT_STORE_READONLY_FLAG |
CERT_SYSTEM_STORE_LOCAL_MACHINE,
wszOldCAStore);
if (NULL == hOldStore)
{
hr = myHLastError();
_JumpError(hr, error, "CertOpenStore");
}
// find CA cert, old ca common name always same as ca name
rdnAttr.Value.pbData = (BYTE *) pServer->pwszCACommonName;
rdnAttr.Value.cbData = 0;
pCACert = NULL;
do
{
pCACert = CertFindCertificateInStore(
hOldStore,
X509_ASN_ENCODING,
CERT_UNICODE_IS_RDN_ATTRS_FLAG |
CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG,
CERT_FIND_SUBJECT_ATTR,
&rdn,
pCACert);
if (NULL != pCACert)
{
// find one
if (NULL == ppCACertKeep)
{
ppCACertKeep = (CERT_CONTEXT const **)LocalAlloc(LMEM_FIXED,
(cCA + 1) * sizeof(CERT_CONTEXT const *));
_JumpIfOutOfMemory(hr, error, ppCACertKeep);
}
else
{
CERT_CONTEXT const ** ppTemp;
ppTemp = (CERT_CONTEXT const **)LocalReAlloc(
ppCACertKeep,
(cCA + 1) * sizeof(CERT_CONTEXT const *),
LMEM_MOVEABLE);
_JumpIfOutOfMemory(hr, error, ppTemp);
ppCACertKeep = ppTemp;
}
// keep current
ppCACertKeep[cCA] = CertDuplicateCertificateContext(pCACert);
if (NULL == ppCACertKeep[cCA])
{
hr = myHLastError();
_JumpError(hr, error, "CertDuplicateCertificate");
}
++cCA;
}
} while (NULL != pCACert);
if (1 > cCA)
{
// no ca cert
hr = E_INVALIDARG;
_JumpError(hr, error, "no ca cert");
}
// assume 1st one
pCACertKeep = ppCACertKeep[0];
if (1 < cCA)
{
DWORD cCA2 = cCA;
BOOL fMatch;
// have multi ca certs with the same cn
// because sp4 doesn't reg ca serial # so need to decide which one
// once the correct one is found, reg its serial #
// build an index
pIndex = (DWORD*)LocalAlloc(LMEM_FIXED, cCA * sizeof(DWORD));
_JumpIfOutOfMemory(hr, error, pIndex);
i = 0;
for (pIndex[i] = i; i < cCA; ++i);
// try to compare with public key
// in case ca cert doesn't have kpi which is the case for v10
// so try base rsa
hr = csiFillKeyProvInfo(
pServer->pwszSanitizedName,
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
TRUE, // always machine keyset
&keyProvInfo);
if (S_OK == hr)
{
cCA2 = 0;
for (i = 0; i < cCA; ++i)
{
hr = myVerifyPublicKey(
ppCACertKeep[i],
FALSE,
&keyProvInfo,
NULL,
&fMatch);
if (S_OK != hr)
{
continue;
}
if (fMatch)
{
// found one match with current public key from container
pIndex[cCA2] = i;
++cCA2;
}
}
}
// compare all ca certs and pick one has most recent NotAfter
pCACertKeep = ppCACertKeep[pIndex[0]];
for (i = 1; i < cCA2; ++i)
{
if (0 < CompareFileTime(
&ppCACertKeep[pIndex[i]]->pCertInfo->NotAfter,
&pCACertKeep->pCertInfo->NotAfter))
{
// update
pCACertKeep = ppCACertKeep[pIndex[i]];
}
}
}
// if get here, must find ca cert
CSASSERT(NULL != pCACertKeep);
// add cert to root store
hRootStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY_W,
X509_ASN_ENCODING,
NULL, // hProv
CERT_SYSTEM_STORE_LOCAL_MACHINE,
wszROOT_CERTSTORE);
if (NULL == hRootStore)
{
hr = myHLastError();
_JumpError(hr, error, "CertOpenStore");
}
if(!CertAddCertificateContextToStore(
hRootStore,
pCACertKeep,
CERT_STORE_ADD_NEW,
NULL))
{
hr = myHLastError();
_JumpError(hr, error, "CertAddCertificateContextToStore");
}
hr = S_OK;
error:
csiFreeKeyProvInfo(&keyProvInfo);
for (i = 0; i < cCA; ++i)
{
CertFreeCertificateContext(ppCACertKeep[i]);
}
if (NULL != hOldStore)
{
CertCloseStore(hOldStore, CERT_CLOSE_STORE_CHECK_FLAG);
}
if (NULL != hRootStore)
{
CertCloseStore(hRootStore, CERT_CLOSE_STORE_CHECK_FLAG);
}
return hr;
}
//--------------------------------------------------------------------
// Clear the key container name to indicate that we must generate a new key.
void
ClearKeyContainerName(CASERVERSETUPINFO *pServer)
{
if (NULL!=pServer->pwszKeyContainerName) {
// Delete the key container if this is a new one
if (pServer->fDeletableNewKey) {
// Delete the key container. Ignore any errors.
HCRYPTPROV hProv=NULL;
myCertSrvCryptAcquireContext(
&hProv,
pServer->pwszKeyContainerName,
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
CRYPT_DELETEKEYSET,
pServer->pCSPInfo->fMachineKeyset);
if (NULL!=hProv) {
CryptReleaseContext(hProv, 0);
}
pServer->fDeletableNewKey=FALSE;
}
// Clear the key container name, to indicate that we must generate a new key.
LocalFree(pServer->pwszKeyContainerName);
LocalFree(pServer->pwszDesanitizedKeyContainerName);
pServer->pwszKeyContainerName=NULL;
pServer->pwszDesanitizedKeyContainerName=NULL;
// if we were using an existing cert, we are not anymore
ClearExistingCertToUse(pServer);
} else {
// if there was no key, there couldn't be a existing cert.
CSASSERT(NULL==pServer->pccExistingCert);
// key container name is already clear
}
}
//--------------------------------------------------------------------
// Set both the real key container name and the display key container name
HRESULT
SetKeyContainerName(
CASERVERSETUPINFO *pServer,
const WCHAR * pwszKeyContainerName)
{
HRESULT hr;
// get rid of any previous names
ClearKeyContainerName(pServer);
// set the real key container name
pServer->pwszKeyContainerName = (WCHAR *) LocalAlloc(
LMEM_FIXED,
sizeof(WCHAR) * (wcslen(pwszKeyContainerName) + 1));
_JumpIfOutOfMemory(hr, error, pServer->pwszKeyContainerName);
wcscpy(pServer->pwszKeyContainerName, pwszKeyContainerName);
// set the display key container name
hr = myRevertSanitizeName(
pServer->pwszKeyContainerName,
&pServer->pwszDesanitizedKeyContainerName);
_JumpIfError(hr, error, "myRevertSanitizeName");
// Must validate the key again when the selected key changes
pServer->fValidatedHashAndKey = FALSE;
CSILOG(
hr,
IDS_ILOG_KEYCONTAINERNAME,
pServer->pwszKeyContainerName,
pServer->pwszDesanitizedKeyContainerName,
NULL);
error:
return hr;
}
HRESULT
UpdateDomainAndUserName(
IN HWND hwnd,
IN OUT PER_COMPONENT_DATA *pComp);
BOOL
CertConfirmCancel(
HWND hwnd,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CSASSERT(NULL != pComp);
if (!(*pComp->HelperRoutines.ConfirmCancelRoutine)(hwnd))
{
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}
hr = CancelCertsrvInstallation(hwnd, pComp);
_PrintIfError(hr, "CancelCertsrvInstallation");
return FALSE;
}
HRESULT
StartWizardPageEditControls(
IN HWND hDlg,
IN OUT PAGESTRINGS *pPageStrings)
{
HRESULT hr;
for ( ; NULL != pPageStrings->ppwszString; pPageStrings++)
{
SendMessage(
GetDlgItem(hDlg, pPageStrings->idControl),
WM_SETTEXT,
0,
(LPARAM) *pPageStrings->ppwszString);
}
hr = S_OK;
//error:
return hr;
}
HRESULT
FinishWizardPageEditControls(
IN HWND hDlg,
IN OUT PAGESTRINGS *pPageStrings)
{
HRESULT hr;
for ( ; NULL != pPageStrings->ppwszString; pPageStrings++)
{
WCHAR *pwszString = NULL;
hr = myUIGetWindowText(
GetDlgItem(hDlg, pPageStrings->idControl),
&pwszString);
_JumpIfError(hr, error, "myUIGetWindowText");
if (NULL != *pPageStrings->ppwszString)
{
// free old one
LocalFree(*pPageStrings->ppwszString);
*pPageStrings->ppwszString = NULL;
}
*pPageStrings->ppwszString = pwszString;
CSILOG(S_OK, pPageStrings->idLog, pwszString, NULL, NULL);
}
hr = S_OK;
error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizPageSetTextLimits
//
// Synopsis: Sets text input limits for the text controls of a dlg page.
//-------------------------------------------------------------------------
HRESULT
WizPageSetTextLimits(
HWND hDlg,
IN OUT PAGESTRINGS *pPageStrings)
{
HRESULT hr;
for ( ; NULL != pPageStrings->ppwszString; pPageStrings++)
{
SendDlgItemMessage(
hDlg,
pPageStrings->idControl,
EM_SETLIMITTEXT,
(WPARAM) pPageStrings->cchMax,
(LPARAM) 0);
}
hr = S_OK;
//error:
return hr;
}
// check optional or mac length in edit field
// if any invalid, focus on the edit field, select all
HRESULT
ValidateTextField(
HINSTANCE hInstance,
BOOL fUnattended,
HWND hDlg,
LPTSTR pszTestString,
DWORD nUBValue,
int nMsgBoxNullStringErrID,
int nMsgBoxLenStringErrID,
int nControlID)
{
HRESULT hr = E_INVALIDARG;
HWND hwndCtrl = NULL;
BOOL fIsEmpty;
fIsEmpty = (NULL == pszTestString) || (L'\0' == pszTestString[0]);
if (fIsEmpty)
{
if (0 != nMsgBoxNullStringErrID) // non optional
{
// edit field can't be empty
CertWarningMessageBox(
hInstance,
fUnattended,
hDlg,
nMsgBoxNullStringErrID,
0,
NULL);
if (!fUnattended)
{
hwndCtrl = GetDlgItem(hDlg, nControlID); // Get offending ctrl
}
goto error;
}
goto done;
}
// the following may not be necessary because edit field set to max limit
#pragma prefast(disable:11, "PREfast bug 648")
if (wcslen(pszTestString) > nUBValue) // Make sure it's not too long
#pragma prefast(enable:11, "re-enable")
{
CertWarningMessageBox(
hInstance,
fUnattended,
hDlg,
nMsgBoxLenStringErrID,
0,
NULL);
if (!fUnattended)
{
hwndCtrl = GetDlgItem(hDlg, nControlID);
}
goto error;
}
done:
hr = S_OK;
error:
if (!fUnattended && NULL != hwndCtrl)
{
SetEditFocusAndSelect(hwndCtrl, 0, MAXDWORD);
}
return hr;
}
HRESULT
WizardPageValidation(
IN HINSTANCE hInstance,
IN BOOL fUnattended,
IN HWND hDlg,
IN PAGESTRINGS *pPageStrings)
{
HRESULT hr;
for ( ; NULL != pPageStrings->ppwszString; pPageStrings++)
{
hr = ValidateTextField(
hInstance,
fUnattended,
hDlg,
*pPageStrings->ppwszString,
pPageStrings->cchMax,
pPageStrings->idMsgBoxNullString,
pPageStrings->idMsgBoxLenString,
pPageStrings->idControl);
_JumpIfError(hr, error, "invalid edit field");
}
hr = S_OK;
error:
return hr;
}
#define KEYGEN_GENERATE_KEY 60 // estimated seconds to gen key
#define KEYGEN_PROTECT_KEY 60 // estimated seconds to acl key
#define KEYGEN_TEST_HASH 2 // estimated seconds to acl key
//--------------------------------------------------------------------
// Fake progress by incrementing a progress bar every second
DWORD WINAPI
KeyGenFakeProgressThread(
LPVOID lpParameter)
{
FAKEPROGRESSINFO * pFakeProgressInfo=(FAKEPROGRESSINFO *)lpParameter;
// Wait for the stop signal for 1 second.
while (WAIT_TIMEOUT==WaitForSingleObject(pFakeProgressInfo->hStopEvent, 1000)) {
// See if we can send another tick to the progress bar
if(pFakeProgressInfo->fCSInit)
{
EnterCriticalSection(&pFakeProgressInfo->csTimeSync);
if (pFakeProgressInfo->dwSecsRemaining>0) {
// move one step (one second)
SendMessage(pFakeProgressInfo->hwndProgBar, PBM_DELTAPOS, 1, 0);
pFakeProgressInfo->dwSecsRemaining--;
}
LeaveCriticalSection(&pFakeProgressInfo->csTimeSync);
}
}
// We were signaled, so stop.
return 0; // return value ignored
}
//--------------------------------------------------------------------
// Generate a new key and test the hash algorithm
DWORD WINAPI
GenerateKeyThread(
LPVOID lpParameter)
{
HRESULT hr = S_OK;
WCHAR * pwszMsg;
FAKEPROGRESSINFO fpi;
KEYGENPROGRESSINFO * pKeyGenInfo=(KEYGENPROGRESSINFO *)lpParameter;
PER_COMPONENT_DATA * pComp=pKeyGenInfo->pComp;
CASERVERSETUPINFO * pServer=pComp->CA.pServer;
HWND hwndProgBar=GetDlgItem(pKeyGenInfo->hDlg, IDC_KEYGEN_PROGRESS);
HWND hwndText=GetDlgItem(pKeyGenInfo->hDlg, IDC_KEYGEN_PROGRESS_TEXT);
int iErrMsg=0; // error msg id
const WCHAR * pwszErrMsgData = L"";
BOOL fEnableKeyCounting;
// variables that must be cleaned up
fpi.hStopEvent=NULL;
HANDLE hFakeProgressThread=NULL;
HCRYPTPROV hProv=NULL;
fpi.fCSInit = FALSE;
__try
{
InitializeCriticalSection(&fpi.csTimeSync);
fpi.fCSInit = TRUE;
}
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
{
}
_JumpIfError(hr, error, "InitializeCriticalSection");
// STEP 0:
// initialize the fake-progress thread
// set up the structure for the fake-progress thread
fpi.hStopEvent=CreateEvent(
NULL, // security
FALSE, // manual reset?
FALSE, // signaled?
NULL); // name
if (NULL==fpi.hStopEvent) {
hr = myHLastError();
_JumpError(hr, error, "CreateEvent");
}
fpi.hwndProgBar=hwndProgBar;
fpi.dwSecsRemaining=0; // Initially, the thread has no work to do.
// start the fake-progress thread
DWORD dwThreadID; // ignored
hFakeProgressThread=CreateThread(
NULL, // security
0, // stack
KeyGenFakeProgressThread,
(void *)&fpi,
0, // flags
&dwThreadID);
if (NULL==hFakeProgressThread) {
hr = myHLastError();
_JumpError(hr, error, "CreateThread");
}
if (NULL==pServer->pwszKeyContainerName) {
// STEP 1:
// Generate a key
// set the status
hr = myLoadRCString(pComp->hInstance, IDS_KEYGEN_GENERATING, &pwszMsg);
_JumpIfError(hr, error, "myLoadRCString");
SetWindowText(hwndText, pwszMsg);
LocalFree(pwszMsg);
SendMessage(hwndProgBar, PBM_SETPOS, (WPARAM)0, 0);
if(fpi.fCSInit)
{
EnterCriticalSection(&fpi.csTimeSync);
fpi.dwSecsRemaining = KEYGEN_GENERATE_KEY;
LeaveCriticalSection(&fpi.csTimeSync);
}
hr = myInfGetEnableKeyCounting(
pComp->hinfCAPolicy,
&fEnableKeyCounting);
if (S_OK != hr)
{
fEnableKeyCounting = FALSE;
}
// generate key
hr = csiGenerateKeysOnly(
pServer->pwszSanitizedName,
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
pServer->pCSPInfo->fMachineKeyset,
pServer->dwKeyLength,
pComp->fUnattended,
fEnableKeyCounting,
&hProv,
&iErrMsg);
if (S_OK != hr)
{
pwszErrMsgData=pServer->pwszSanitizedName;
pServer->fKeyGenFailed = TRUE;
_JumpError(hr, error, "csiGenerateKeysOnly");
}
pServer->fKeyGenFailed = FALSE;
// now set this as the existing key
SetKeyContainerName(pServer, pServer->pwszSanitizedName);
pServer->fDeletableNewKey=TRUE;
// STEP 2:
// Set the ACLs
// set the status
hr = myLoadRCString(pComp->hInstance, IDS_KEYGEN_PROTECTING, &pwszMsg);
_JumpIfError(hr, error, "myLoadRCString");
SetWindowText(hwndText, pwszMsg);
LocalFree(pwszMsg);
if(fpi.fCSInit)
{
EnterCriticalSection(&fpi.csTimeSync);
SendMessage(hwndProgBar, PBM_SETPOS, (WPARAM)KEYGEN_GENERATE_KEY, 0);
fpi.dwSecsRemaining=KEYGEN_PROTECT_KEY;
LeaveCriticalSection(&fpi.csTimeSync);
}
// set the ACLs
hr = csiSetKeyContainerSecurity(hProv);
if (S_OK!=hr) {
iErrMsg=IDS_ERR_KEYSECURITY;
pwszErrMsgData=pServer->pwszKeyContainerName;
_JumpError(hr, error, "csiSetKeyContainerSecurity");
}
} // <- end if (NULL==pServer->pwszKeyContainerName)
if (FALSE==pServer->fValidatedHashAndKey) {
// STEP 3:
// Test the hash algorithm and key set
// set the status
hr = myLoadRCString(pComp->hInstance, IDS_KEYGEN_TESTINGHASHANDKEY, &pwszMsg);
_JumpIfError(hr, error, "myLoadRCString");
SetWindowText(hwndText, pwszMsg);
LocalFree(pwszMsg);
if(fpi.fCSInit)
{
EnterCriticalSection(&fpi.csTimeSync);
SendMessage(hwndProgBar, PBM_SETPOS, (WPARAM)KEYGEN_GENERATE_KEY+KEYGEN_PROTECT_KEY, 0);
fpi.dwSecsRemaining=KEYGEN_TEST_HASH;
LeaveCriticalSection(&fpi.csTimeSync);
}
// test the hash and keyset
hr = myValidateSigningKey(
pServer->pwszKeyContainerName,
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
FALSE, // fCryptSilent
pServer->pCSPInfo->fMachineKeyset,
TRUE, // fForceSignatureTest
NULL, // pcc
NULL, // pPublicKeyInfo
pServer->pHashInfo->idAlg,
NULL, // pfSigningTestAttempted
NULL); // phProv
if (S_OK!=hr) {
if (NTE_BAD_KEY_STATE==hr || //all the errors with KEY in them
NTE_NO_KEY==hr ||
NTE_BAD_PUBLIC_KEY==hr ||
NTE_BAD_KEYSET==hr ||
NTE_KEYSET_NOT_DEF==hr ||
NTE_KEYSET_ENTRY_BAD==hr ||
NTE_BAD_KEYSET_PARAM==hr) {
// Bad keyset (eg, not AT_SIGNATURE) - force user to pick another
iErrMsg=IDS_KEY_INVALID;
pwszErrMsgData=pServer->pwszKeyContainerName;
} else {
// Bad hash algorithm - force user to pick another
iErrMsg=IDS_ERR_INVALIDHASH;
pwszErrMsgData=pServer->pHashInfo->pwszName;
}
_JumpError(hr, error, "myValidateSigningKey");
}
// mark this hash as validated
pServer->fValidatedHashAndKey=TRUE;
}
// STEP 3:
// Go to the next page
// set the status, so the user sees the bar go all the way.
if(fpi.fCSInit)
{
EnterCriticalSection(&fpi.csTimeSync);
SendMessage(hwndProgBar, PBM_SETPOS, (WPARAM)KEYGEN_GENERATE_KEY+KEYGEN_PROTECT_KEY+KEYGEN_TEST_HASH, 0);
fpi.dwSecsRemaining=0;
LeaveCriticalSection(&fpi.csTimeSync);
}
error:
// clean up after the false-progress thread
if (NULL!=hFakeProgressThread) {
CSASSERT(NULL!=fpi.hStopEvent);
// tell the progress thread to stop
if (FALSE==SetEvent(fpi.hStopEvent)) {
_PrintError(myHLastError(), "SetEvent");
} else {
// wait for it to stop
WaitForSingleObject(hFakeProgressThread, INFINITE);
}
CloseHandle(hFakeProgressThread);
}
if(fpi.fCSInit)
{
DeleteCriticalSection(&fpi.csTimeSync);
}
if (NULL!=fpi.hStopEvent) {
CloseHandle(fpi.hStopEvent);
}
if (NULL!=hProv) {
CryptReleaseContext(hProv, 0);
}
// show an error message if we need to
if (0!=iErrMsg) {
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
pKeyGenInfo->hDlg,
iErrMsg,
hr,
pwszErrMsgData);
}
pServer->LastWiz=ENUM_WIZ_KEYGEN;
if (S_OK==hr) {
// go to next page
PropSheet_PressButton(GetParent(pKeyGenInfo->hDlg), PSBTN_NEXT);
} else {
// go back
PropSheet_PressButton(GetParent(pKeyGenInfo->hDlg), PSBTN_BACK);
}
return 0; // return value ignored
}
//--------------------------------------------------------------------
// Start the KeyGen wizard page
HRESULT
HandleKeyGenWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp,
KEYGENPROGRESSINFO *pKeyGenInfo)
{
HRESULT hr = S_OK;
// Suppress this wizard page if
// we are going backwards, or
// we've already seen an error, or
// we are not installing the server,
// or the key exists and the hash has been checked.
if (ENUM_WIZ_STORE == pComp->CA.pServer->LastWiz ||
!(IS_SERVER_INSTALL & pComp->dwInstallStatus) ||
(NULL != pComp->CA.pServer->pwszKeyContainerName &&
pComp->CA.pServer->fValidatedHashAndKey)) {
// skip/disable page
CSILOGDWORD(IDS_KEYGEN_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
}
else
{
// set progress bar parameters: range, step, and position
// set them now so the user will never see a full bar if this is the second visit.
HWND hwndProgBar=GetDlgItem(hDlg, IDC_KEYGEN_PROGRESS);
SendMessage(hwndProgBar, PBM_SETRANGE, 0,
MAKELPARAM(0, KEYGEN_GENERATE_KEY+KEYGEN_PROTECT_KEY+KEYGEN_TEST_HASH));
SendMessage(hwndProgBar, PBM_SETSTEP, (WPARAM)1, 0);
SendMessage(hwndProgBar, PBM_SETPOS, (WPARAM)0, 0);
// init info for keygen thread
pKeyGenInfo->hDlg=hDlg;
pKeyGenInfo->pComp=pComp;
// start the key gen thread
DWORD dwThreadID; // ignored
HANDLE hKeyGenThread=CreateThread(
NULL, // security
0, // stack
GenerateKeyThread,
(void *)pKeyGenInfo,
0, // flags
&dwThreadID);
if (NULL==hKeyGenThread) {
hr = myHLastError();
_JumpError(hr, error, "CreateThread");
}
CloseHandle(hKeyGenThread);
}
error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizKeyGenPageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for keygen wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizKeyGenPageDlgProc(
HWND hDlg,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_KEYGEN_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), 0);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue=HandleKeyGenWizActive(hDlg, pComp, &g_KeyGenInfo);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_KEYGEN_TITLE, dwWIZBACK);
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_KEYGEN_TITLE, dwWIZNEXT);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
HRESULT
ValidateESERestrictions(
IN WCHAR const *pwszDirectory)
{
HRESULT hr;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileA = INVALID_HANDLE_VALUE;
WCHAR *pwszPath = NULL;
char *pszPath = NULL;
WCHAR *pwsz;
char *psz;
DWORD cwcbs;
DWORD cchbs;
hr = myBuildPathAndExt(pwszDirectory, L"certocm.tmp", NULL, &pwszPath);
_JumpIfError(hr, error, "myBuildPathAndExt");
if (!ConvertWszToSz(&pszPath, pwszPath, -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "ConvertWszToSz")
}
pwsz = pwszPath;
cwcbs = 0;
for (;;)
{
pwsz = wcschr(pwsz, L'\\');
if (NULL == pwsz)
{
break;
}
pwsz++;
cwcbs++;
}
psz = pszPath;
cchbs = 0;
for (;;)
{
psz = strchr(psz, '\\');
if (NULL == psz)
{
break;
}
psz++;
cchbs++;
}
if (cchbs != cwcbs)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "backslash count")
}
hFile = CreateFile(
pwszPath,
GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // security
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL); // template
if (INVALID_HANDLE_VALUE == hFile)
{
hr = myHLastError();
_JumpErrorStr(hr, error, "CreateFile", pwszPath);
}
hFileA = CreateFileA(
pszPath,
GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL); // template
if (INVALID_HANDLE_VALUE == hFileA)
{
hr = myHLastError();
_JumpErrorStr(hr, error, pszPath, L"CreateFileA");
}
CSASSERT(S_OK == hr);
error:
if (INVALID_HANDLE_VALUE != hFileA)
{
CloseHandle(hFileA); // close before below delete
}
if (NULL != pszPath)
{
LocalFree(pszPath);
}
if (NULL != pwszPath)
{
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile); // close before delete
DeleteFile(pwszPath);
}
LocalFree(pwszPath);
}
return(hr);
}
//+-------------------------------------------------------------------------
// Function: check if a database edit field
//--------------------------------------------------------------------------
BOOL
ValidateAndCreateDirField(
HINSTANCE hInstance,
BOOL fUnattended,
HWND hDlg,
WCHAR *pwszDirectory,
BOOL fDefaultDir,
int iMsgNotFullPath,
BOOL *pfExist,
BOOL *pfIsUNC)
{
BOOL fRet = FALSE;
DWORD dwPathFlag = 0;
HRESULT hr;
*pfExist = TRUE;
// check edit field
if (!myIsFullPath(pwszDirectory, &dwPathFlag))
{
CertWarningMessageBox(
hInstance,
fUnattended,
hDlg,
iMsgNotFullPath,
0,
pwszDirectory);
goto error;
}
// set the UNC check
*pfIsUNC = (dwPathFlag == UNC_PATH);
if (MAX_PATH - 1 < wcslen(pwszDirectory))
{
WCHAR wszMsg[256 + MAX_PATH];
WCHAR *pwszFormat = NULL;
hr = myLoadRCString(hInstance,
IDS_STORELOC_PATHTOOLONG,
&pwszFormat);
_JumpIfError(hr, error, "myLoadRCString");
swprintf(wszMsg, pwszFormat, pwszDirectory, MAX_PATH-1);
CertWarningMessageBox(
hInstance,
fUnattended,
hDlg,
0,
0,
wszMsg);
LocalFree(pwszFormat);
goto error;
}
if (DE_DIREXISTS != DirExists(pwszDirectory))
{
if (*pfIsUNC)
{
CertWarningMessageBox(
hInstance,
fUnattended,
hDlg,
IDS_STORELOC_UNCMUSTEXIST,
0,
pwszDirectory);
goto error;
}
else
{
if (!fDefaultDir)
{
// confirm and create outside
*pfExist = FALSE;
goto done;
}
// try to create default dir
hr = myCreateNestedDirectories(pwszDirectory);
_JumpIfError(hr, error, "myCreateNestedDirectories");
}
}
done:
fRet = TRUE;
error:
return fRet;
}
//+---------------------------------------------------------------------------
// Description: set MS Base CSP as default csp otherwise 1st one
//----------------------------------------------------------------------------
HRESULT
DetermineDefaultCSP(CASERVERSETUPINFO *pServer)
{
HRESULT hr;
CSP_INFO *pCSPInfo = NULL;
// select 1st if no MSBase
pServer->pCSPInfo = pServer->pCSPInfoList;
if (NULL == pServer->pDefaultCSPInfo)
{
goto done;
}
// check all csps
pCSPInfo = pServer->pCSPInfoList;
while (NULL != pCSPInfo)
{
if (NULL != pCSPInfo->pwszProvName)
{
if (0 == mylstrcmpiL(pCSPInfo->pwszProvName,
pServer->pDefaultCSPInfo->pwszProvName) &&
pCSPInfo->dwProvType == pServer->pDefaultCSPInfo->dwProvType)
{
// change to default
pServer->pCSPInfo = pCSPInfo;
break;
}
}
pCSPInfo = pCSPInfo->next;
}
done:
hr = S_OK;
//error:
return hr;
}
//+---------------------------------------------------------------------------
// Description: set SHA as default hash alg. otherwise 1st one
//----------------------------------------------------------------------------
HRESULT
DetermineDefaultHash(CASERVERSETUPINFO *pServer)
{
CSP_HASH *pHashInfo = NULL;
HRESULT hr;
if ((NULL == pServer) || (NULL == pServer->pCSPInfo))
return E_POINTER;
// select 1st if no default match
pServer->pHashInfo = pServer->pCSPInfo->pHashList;
// search list
pHashInfo = pServer->pCSPInfo->pHashList;
while (NULL != pHashInfo)
{
if (pHashInfo->idAlg == pServer->pDefaultHashInfo->idAlg)
{
//change to default
pServer->pHashInfo = pHashInfo;
break;
}
pHashInfo = pHashInfo->next;
}
// Must validate the hash again when the selected hash changes
pServer->fValidatedHashAndKey = FALSE;
hr = S_OK;
//error:
return hr;
}
HRESULT
UpdateCADescription(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
int ids;
WCHAR *pwszDesc = NULL;
HRESULT hr;
ids = 0;
switch (pComp->CA.pServer->CAType)
{
case ENUM_STANDALONE_ROOTCA:
ids = IDS_CATYPE_DES_STANDALONE_ROOTCA;
break;
case ENUM_STANDALONE_SUBCA:
ids = IDS_CATYPE_DES_STANDALONE_SUBCA;
break;
case ENUM_ENTERPRISE_ROOTCA:
ids = IDS_CATYPE_DES_ENTERPRISE_ROOTCA;
break;
case ENUM_ENTERPRISE_SUBCA:
ids = IDS_CATYPE_DES_ENTERPRISE_SUBCA;
break;
}
// load description from resource
hr = myLoadRCString(pComp->hInstance, ids, &pwszDesc);
_JumpIfError(hr, error, "myLoadRCString");
// change text
SetWindowText(GetDlgItem(hDlg, IDC_CATYPE_CA_DESCRIPTION), pwszDesc);
hr = S_OK;
error:
if (NULL != pwszDesc)
{
LocalFree(pwszDesc);
}
return hr;
}
HRESULT
InitCATypeWizControls(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
int idc;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
EnableWindow(GetDlgItem(hDlg, IDC_CATYPE_ENT_ROOT_CA), pServer->fUseDS);
EnableWindow(GetDlgItem(hDlg, IDC_CATYPE_ENT_SUB_CA), pServer->fUseDS);
ShowWindow(GetDlgItem(hDlg, IDC_CATYPE_DESCRIPTION_ENTERPRISE),
!pServer->fUseDS);
EnableWindow(GetDlgItem(hDlg, IDC_CATYPE_STAND_ROOT_CA), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_CATYPE_STAND_SUB_CA), TRUE);
if (pServer->fUseDS)
{
if (ENUM_ENTERPRISE_SUBCA == pServer->CAType)
{
idc = IDC_CATYPE_ENT_SUB_CA;
}
else
{
idc = IDC_CATYPE_ENT_ROOT_CA;
}
}
else
{
idc = IDC_CATYPE_STAND_ROOT_CA;
}
SendMessage(GetDlgItem(hDlg, idc), BM_CLICK, (WPARAM)0, (LPARAM)0);
hr = UpdateCADescription(hDlg, pComp);
_JumpIfError(hr, error, "UpdateCADescription");
error:
return hr;
}
BOOL
IsRadioControlChecked(HWND hwnd)
{
BOOL checked = FALSE;
if (BST_CHECKED == SendMessage(hwnd, BM_GETCHECK, (WPARAM)0, (LPARAM)0))
{
checked = TRUE;
}
return checked;
}
HRESULT
HandleAdvanceChange(CASERVERSETUPINFO *pServer)
{
HRESULT hr;
if (!pServer->fAdvance)
{
// if not advance, clear all advance flags
pServer->fPreserveDB = FALSE;
ClearExistingCertToUse(pServer);
}
hr = S_OK;
//error:
return hr;
}
HRESULT
HandleCATypeChange(
IN HWND hDlg,
IN PER_COMPONENT_DATA *pComp,
IN ENUM_CATYPES eNewType)
{
HRESULT hr;
BOOL bCertOK;
CASERVERSETUPINFO * pServer=pComp->CA.pServer;
pServer->CAType = eNewType;
pServer->dwKeyLength = IsRootCA(pServer->CAType)?
CA_DEFAULT_KEY_LENGTH_ROOT:
CA_DEFAULT_KEY_LENGTH_SUB;
hr = UpdateCADescription(hDlg, pComp);
_JumpIfError(hr, error, "UpdateCADescription");
// make sure that if we are using an existing cert, we didn't make it invalid.
if (NULL!=pServer->pccExistingCert) {
hr = IsCertSelfSignedForCAType(pServer, pServer->pccExistingCert, &bCertOK);
_JumpIfError(hr, error, "UpdateCADescription");
if (FALSE==bCertOK) {
// can't use this cert with this CA type.
ClearExistingCertToUse(pServer);
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
HandleCATypeWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
// first of all, get install status
hr = UpdateSubComponentInstallStatus(wszCERTSRVSECTION, wszSERVERSECTION, pComp);
_JumpIfError(hr, error, "UpdateSubComponentInstallStatus");
hr = UpdateSubComponentInstallStatus(wszCERTSRVSECTION, wszCLIENTSECTION, pComp);
_JumpIfError(hr, error, "UpdateSubComponentInstallStatus");
// Suppress this wizard page if
// we've already seen an error, or
// we are not installing the server.
if (!(IS_SERVER_INSTALL & pComp->dwInstallStatus) )
{
// disable page
CSILOGDWORD(IDS_CATYPE_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
done:
hr = S_OK;
error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizCATypePageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for CA Type wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizCATypePageDlgProc(
HWND hDlg,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
static fDisplayed = false;
switch (iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitCATypeWizControls(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
CSILOGDWORD(IDS_ENTERPRISE_UNAVAIL_REASON,
pComp->CA.pServer->EnterpriseUnavailReason);
break;
case WM_SHOWWINDOW:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
if(!fDisplayed &&
ENUM_ENTERPRISE_UNAVAIL_REASON_OLD_DS_VERSION ==
pComp->CA.pServer->EnterpriseUnavailReason)
{
fDisplayed = true;
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_OLD_DS_VERSION,
0,
NULL);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CATYPE_STAND_ROOT_CA:
if (IsRadioControlChecked((HWND)lParam))
{
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleCATypeChange(hDlg,
pComp, ENUM_STANDALONE_ROOTCA);
_ReturnIfWizError(pComp->hrContinue);
}
break;
case IDC_CATYPE_STAND_SUB_CA:
if (IsRadioControlChecked((HWND)lParam))
{
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleCATypeChange(hDlg,
pComp, ENUM_STANDALONE_SUBCA);
_ReturnIfWizError(pComp->hrContinue);
}
break;
case IDC_CATYPE_ENT_ROOT_CA:
if (IsRadioControlChecked((HWND)lParam))
{
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleCATypeChange(hDlg,
pComp, ENUM_ENTERPRISE_ROOTCA);
_ReturnIfWizError(pComp->hrContinue);
}
break;
case IDC_CATYPE_ENT_SUB_CA:
if (IsRadioControlChecked((HWND)lParam))
{
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleCATypeChange(hDlg,
pComp, ENUM_ENTERPRISE_SUBCA);
_ReturnIfWizError(pComp->hrContinue);
}
break;
case IDC_CATYPE_CHECK_ADVANCE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->fAdvance = !pComp->CA.pServer->fAdvance;
pComp->hrContinue = HandleAdvanceChange(pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_CATYPE_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleCATypeWizActive(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_CATYPE_TITLE, dwWIZBACK);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->LastWiz = ENUM_WIZ_CATYPE;
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_CATYPE_TITLE, dwWIZNEXT);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->LastWiz = ENUM_WIZ_CATYPE;
CSILOGDWORD(IDS_LOG_CATYPE, pComp->CA.pServer->CAType);
pComp->hrContinue = InitNameFields(pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
//+---------------------------------------------------------------------------
// Description: display existing keys from list
//----------------------------------------------------------------------------
HRESULT
ShowExistingKey(
IN HWND hDlg,
KEY_LIST *pKeyList)
{
HRESULT hr;
KEY_LIST *pKey = pKeyList;
HWND hKeyList = GetDlgItem(hDlg, IDC_ADVANCE_KEYLIST);
LRESULT nItem;
LRESULT lr;
WCHAR *pwszDeSanitize = NULL;
while (NULL != pKey)
{
if (NULL != pKey->pwszName)
{
if (NULL != pwszDeSanitize)
{
LocalFree(pwszDeSanitize);
pwszDeSanitize = NULL;
}
hr = myRevertSanitizeName(pKey->pwszName, &pwszDeSanitize);
_JumpIfError(hr, error, "myRevertSanitizeName");
nItem = (INT)SendMessage(
hKeyList,
LB_ADDSTRING,
(WPARAM) 0,
(LPARAM) pwszDeSanitize);
if (LB_ERR == nItem)
{
hr = myHLastError();
_JumpError(hr, error, "SendMessage");
}
lr = (INT)SendMessage(
hKeyList,
LB_SETITEMDATA,
(WPARAM) nItem,
(LPARAM) pKey->pwszName);
if (LB_ERR == lr)
{
hr = myHLastError();
_JumpError(hr, error, "SendMessage");
}
}
pKey = pKey->next;
}
if (NULL != pKeyList)
{
// choose the 1st one as default
lr = (INT)SendMessage(hKeyList, LB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);
if (LB_ERR == lr)
{
hr = myHLastError();
_JumpError(hr, error, "SendMessage");
}
}
hr = S_OK;
error:
if (NULL != pwszDeSanitize)
{
LocalFree(pwszDeSanitize);
}
return hr;
}
//+---------------------------------------------------------------------------
// Description: hilight an item by matched data
//----------------------------------------------------------------------------
HRESULT
HilightItemInList(HWND hDlg, int id, VOID const *pData, BOOL fString)
{
HWND hListCtrl = GetDlgItem(hDlg, id);
LRESULT iItem;
LRESULT count;
VOID *pItemData;
HRESULT hr = NTE_NOT_FOUND;
// find item
if (fString)
{
iItem = (INT)SendMessage(
hListCtrl,
LB_FINDSTRING,
(WPARAM) 0,
(LPARAM) pData);
if (LB_ERR == iItem)
{
_JumpError(hr, error, "SendMessage");
}
hr = S_OK;
}
else
{
count = (INT)SendMessage(hListCtrl, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
for (iItem = 0; iItem < count; ++iItem)
{
pItemData = (VOID*)SendMessage(hListCtrl, LB_GETITEMDATA,
(WPARAM)iItem, (LPARAM)0);
if (pItemData == pData)
{
hr = S_OK;
break;
}
}
}
if (S_OK != hr)
{
_JumpError(hr, error, "not found");
}
// hilight it
SendMessage(hListCtrl, LB_SETCURSEL, (WPARAM)iItem, (LPARAM)0);
hr = S_OK;
error:
return hr;
}
HRESULT
ShowAllCSP(
HWND hDlg,
CSP_INFO *pCSPInfo)
{
HWND hCSPList = GetDlgItem(hDlg, IDC_ADVANCE_CSPLIST);
LRESULT nItem;
// list all of csps
while (pCSPInfo)
{
if (pCSPInfo->pwszProvName)
{
nItem = (INT)SendMessage(hCSPList, LB_ADDSTRING,
(WPARAM)0, (LPARAM)pCSPInfo->pwszProvName);
SendMessage(hCSPList, LB_SETITEMDATA,
(WPARAM)nItem, (LPARAM)pCSPInfo);
}
pCSPInfo = pCSPInfo->next;
}
return S_OK;
}
HRESULT
ShowAllHash(
HWND hDlg,
CSP_HASH *pHashInfo)
{
HWND hHashList = GetDlgItem(hDlg, IDC_ADVANCE_HASHLIST);
LRESULT nItem;
// remove hash of previous csp from list
while (SendMessage(hHashList, LB_GETCOUNT,
(WPARAM)0, (LPARAM)0))
{
SendMessage(hHashList, LB_DELETESTRING,
(WPARAM)0, (LPARAM)0);
}
// list all hash
while (NULL != pHashInfo)
{
if (NULL != pHashInfo->pwszName)
{
nItem = (INT)SendMessage(hHashList, LB_ADDSTRING,
(WPARAM)0, (LPARAM)pHashInfo->pwszName);
SendMessage(hHashList, LB_SETITEMDATA,
(WPARAM)nItem, (LPARAM)pHashInfo);
}
pHashInfo = pHashInfo->next;
}
return S_OK;
}
//--------------------------------------------------------------------
HRESULT
UpdateUseCertCheckbox(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
BOOL bUsingExistingCert;
if (NULL==pServer->pccExistingCert) {
bUsingExistingCert=FALSE;
} else {
bUsingExistingCert=TRUE;
}
// check "use cert" control
SendMessage(GetDlgItem(hDlg, IDC_ADVANCE_USECERTCHECK),
BM_SETCHECK,
(WPARAM)(bUsingExistingCert?BST_CHECKED:BST_UNCHECKED),
(LPARAM)0);
// enable the "View Cert" button if necessary
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_VIEWCERT), bUsingExistingCert);
// we will match the hash alg used by the cert, if possible
hr = HilightItemInList(hDlg, IDC_ADVANCE_HASHLIST,
pServer->pHashInfo, FALSE);
_JumpIfError(hr, error, "HilightItemInList");
error:
return hr;
}
HRESULT
FindCertificateByKeyWithWaitCursor(
IN CASERVERSETUPINFO *pServer,
OUT CERT_CONTEXT const **ppccCert)
{
HRESULT hr;
HCURSOR hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = FindCertificateByKey(pServer, ppccCert);
SetCursor(hPrevCur);
_JumpIfError(hr, error, "FindCertificateByKey");
error:
return(hr);
}
//--------------------------------------------------------------------
// handle the "Use existing Cert" checkbox
HRESULT
HandleUseCertCheckboxChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
CERT_CONTEXT const * pccCert;
if(pServer->pwszFullCADN)
{
LocalFree(pServer->pwszFullCADN);
pServer->pwszFullCADN = NULL;
}
// is the checkbox checked or unchecked?
if (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ADVANCE_USECERTCHECK)) {
// checkbox was just checked, so we previously were not using an existing cert
CSASSERT(NULL==pServer->pccExistingCert);
// Find the existing cert for this key
hr = FindCertificateByKeyWithWaitCursor(pServer, &pccCert);
_JumpIfError(hr, error, "FindCertificateByKeyWithWaitCursor");
// use it
hr = SetExistingCertToUse(pServer, pccCert);
_JumpIfError(hr, error, "SetExistingCertToUse");
} else {
// checkbox was just unchecked, so we previously were using an existing cert.
CSASSERT(NULL!=pServer->pccExistingCert);
// stop using the cert
ClearExistingCertToUse(pServer);
}
hr = UpdateUseCertCheckbox(hDlg, pServer);
_JumpIfError(hr, error, "UpdateUseCertCheckbox");
error:
return hr;
}
//----------------------------------------------------------------------------
// Hilight the current key - don't use HilightItemInList because we
// must use string-compare on the data portion, and HilightItemInList does not
// support this.
HRESULT
HilightKeyInList(HWND hDlg, CASERVERSETUPINFO * pServer)
{
HWND hListCtrl=GetDlgItem(hDlg, IDC_ADVANCE_KEYLIST);
LRESULT nIndex;
LRESULT nTotNames;
WCHAR * pwszKeyContainerName;
HRESULT hr = NTE_NOT_FOUND;
nTotNames=(INT)SendMessage(hListCtrl, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
for (nIndex=0; nIndex<nTotNames; nIndex++) {
pwszKeyContainerName=(WCHAR *)SendMessage(hListCtrl, LB_GETITEMDATA, (WPARAM)nIndex, (LPARAM)0);
if (0==wcscmp(pwszKeyContainerName, pServer->pwszKeyContainerName)) {
SendMessage(hListCtrl, LB_SETCURSEL, (WPARAM)nIndex, (LPARAM)0);
hr = S_OK;
break;
}
}
if (S_OK != hr)
{
// can lead to dead wiz pages
CSILOG(
hr,
IDS_LOG_KEY_NOT_FOUND_IN_LIST,
pServer->pwszKeyContainerName,
NULL,
NULL);
_PrintErrorStr(hr, "not found", pServer->pwszKeyContainerName);
}
hr = S_OK;
//error:
return hr;
}
//--------------------------------------------------------------------
HRESULT
UpdateKeySelection(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
BOOL bAvailableExistingCert = FALSE;
CERT_CONTEXT const * pccCert;
// if we have an existing key, make sure it is the one hilighted
// in the list and check for coresponding certs.
if (NULL!=pServer->pwszKeyContainerName) {
// hilight key
hr = HilightKeyInList(hDlg, pServer);
_JumpIfError(hr, error, "HilightKeyInList");
if (NULL!=pServer->pccExistingCert) {
// we are using an existing cert, so it better exist!
bAvailableExistingCert = TRUE;
} else {
// see if there is an existing cert for this key
hr = FindCertificateByKeyWithWaitCursor(pServer, &pccCert);
if (S_OK==hr) {
CertFreeCertificateContext(pccCert);
bAvailableExistingCert = TRUE;
} else {
// only other return is 'not found'
CSASSERT(CRYPT_E_NOT_FOUND==hr);
}
}
} else {
// no key selected, can't have an existing cert
}
// enable/disable reuse cert...
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_USECERTCHECK), bAvailableExistingCert);
hr = UpdateUseCertCheckbox(hDlg, pServer);
_JumpIfError(hr, error, "UpdateUseCertCheckbox");
error:
return hr;
}
//--------------------------------------------------------------------
HRESULT
UpdateUseKeyCheckbox(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
BOOL bReuseKey;
if (NULL==pServer->pwszKeyContainerName) {
// we are creating a new key
bReuseKey=FALSE;
} else {
// we are using an existing key
bReuseKey=TRUE;
}
// check/uncheck the checkbox depending upon whether we are reusing a key
SendDlgItemMessage(hDlg,
IDC_ADVANCE_USEKEYCHECK,
BM_SETCHECK,
(WPARAM)(bReuseKey?BST_CHECKED:BST_UNCHECKED),
(LPARAM)0);
// enable the key list if we are reusing a key
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_KEYLIST), bReuseKey);
// disable the key length box if we are reusing a key
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH), !bReuseKey);
hr = UpdateKeySelection(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeySelection");
error:
return hr;
}
//+---------------------------------------------------------------------------
// Description: update hash alg. list if csp selection changes
//----------------------------------------------------------------------------
HRESULT
UpdateHashList(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
// load new hash list
hr = ShowAllHash(hDlg, pServer->pCSPInfo->pHashList);
_JumpIfError(hr, error, "ShowAllHash");
hr = HilightItemInList(hDlg, IDC_ADVANCE_HASHLIST,
pServer->pHashInfo, FALSE);
_JumpIfError(hr, error, "HilightItemInList");
hr = S_OK;
error:
return hr;
}
//+---------------------------------------------------------------------------
// Description: update key list if csp selection changes
//----------------------------------------------------------------------------
HRESULT
UpdateKeyList(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
HWND hKeyList;
HCURSOR hPrevCur;
// remove keys of previous csp from list
hKeyList = GetDlgItem(hDlg, IDC_ADVANCE_KEYLIST);
while (SendMessage(hKeyList, LB_GETCOUNT, (WPARAM) 0, (LPARAM) 0))
{
SendMessage(hKeyList, LB_DELETESTRING, (WPARAM) 0, (LPARAM) 0);
}
// update key list with new CSP
if (NULL != pServer->pKeyList)
{
csiFreeKeyList(pServer->pKeyList);
}
hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = csiGetKeyList(
pServer->pCSPInfo->dwProvType,
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->fMachineKeyset,
TRUE, // fSilent
&pServer->pKeyList);
SetCursor(hPrevCur);
if (S_OK != hr)
{
_PrintError(hr, "csiGetKeyList");
// don't fail setup if only no key update
//goto done;
}
// show keys
if (NULL != pServer->pKeyList)
{
hr = ShowExistingKey(hDlg, pServer->pKeyList);
_JumpIfError(hr, error, "ShowExistingKey");
}
if (NULL == pServer->pKeyList) {
// no existing key for the csp, so disable "use existing key" checkbox
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_USEKEYCHECK), FALSE);
CSASSERT(NULL==pServer->pwszKeyContainerName);
} else {
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_USEKEYCHECK), TRUE);
}
hr = UpdateUseKeyCheckbox(hDlg, pServer);
_JumpIfError(hr, error, "UpdateUseKeyCheckbox");
//done:
hr = S_OK;
error:
return(hr);
}
DWORD g_adwKeyLengths[] =
{
512,
1024,
2048,
4096,
};
DWORD g_adwKeyLengthsSmall[] =
{
128,
256,
512,
1024,
};
HRESULT
AddPredefinedKeyLength
(
HWND hwnd,
DWORD dwKeyLength)
{
HRESULT hr;
WCHAR wszKeyLength[MAX_KEYLENGTHDIGIT + 1];
WCHAR const *pwszKeyLength;
LRESULT nIndex;
CSASSERT(0 != dwKeyLength);
wsprintf(wszKeyLength, L"%u", dwKeyLength);
pwszKeyLength = wszKeyLength;
nIndex = (INT)SendMessage(hwnd, CB_ADDSTRING, (WPARAM)0, (LPARAM)pwszKeyLength);
if (CB_ERR == nIndex)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_ADDSTRING)");
}
SendMessage(hwnd, CB_SETITEMDATA, (WPARAM)nIndex, (LPARAM)dwKeyLength);
hr = S_OK;
error:
return hr;
}
HRESULT
ShowAllKeyLength(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
HWND hwndCtrl = GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH);
WCHAR wszKeyLength[MAX_KEYLENGTHDIGIT + 1];
DWORD *pdw;
DWORD *pdwEnd;
// remove existing key length list
while (SendMessage(hwndCtrl, CB_GETCOUNT, (WPARAM) 0, (LPARAM) 0))
{
SendMessage(hwndCtrl, CB_DELETESTRING, (WPARAM) 0, (LPARAM) 0);
}
CSASSERT(0 != pServer->dwKeyLength);
if(pServer->dwKeyLength > pServer->dwKeyLenMax)
{
pServer->dwKeyLength=pServer->dwKeyLenMax;
}
wsprintf(wszKeyLength, L"%u", pServer->dwKeyLength);
SetWindowText(hwndCtrl, wszKeyLength);
pdw = g_adwKeyLengths;
pdwEnd = &g_adwKeyLengths[ARRAYSIZE(g_adwKeyLengths)];
if (C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMin &&
C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMax &&
g_adwKeyLengthsSmall[ARRAYSIZE(g_adwKeyLengthsSmall) - 1] >=
pServer->dwKeyLenMax)
{
pdw = g_adwKeyLengthsSmall;
pdwEnd = &g_adwKeyLengthsSmall[ARRAYSIZE(g_adwKeyLengthsSmall)];
}
// show new key length list
for ( ; pdw < pdwEnd; pdw++)
{
if (0 == *pdw ||
((C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMin &&
*pdw >= pServer->dwKeyLenMin) &&
(C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMax &&
*pdw <= pServer->dwKeyLenMax)) )
{
hr = AddPredefinedKeyLength(hwndCtrl, *pdw);
_JumpIfError(hr, error, "AddPredefinedKeyLength");
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
UpdateKeyLengthMinMax(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
HCRYPTPROV hProv = NULL;
CSP_INFO *pCSPInfo = pServer->pCSPInfo;
PROV_ENUMALGS_EX paramData;
DWORD cbData;
DWORD dwFlags;
// default that csp doesn't support PP_ENUMALGS_EX
pServer->dwKeyLenMin = C_CSPHASNOKEYMINMAX;
pServer->dwKeyLenMax = C_CSPHASNOKEYMINMAX;
// determine the min and max key length for selected csp
if (!myCertSrvCryptAcquireContext(
&hProv,
NULL,
pCSPInfo->pwszProvName,
pCSPInfo->dwProvType,
CRYPT_VERIFYCONTEXT,
FALSE))
{
hr = myHLastError();
if (NULL != hProv)
{
hProv = NULL;
_PrintError(hr, "CSP returns a non-null handle");
}
_JumpErrorStr(hr, error, "myCertSrvCryptAcquireContext", pCSPInfo->pwszProvName);
}
dwFlags = CRYPT_FIRST;
for (;;)
{
cbData = sizeof(paramData);
if (!CryptGetProvParam(
hProv,
PP_ENUMALGS_EX,
(BYTE *) &paramData,
&cbData,
dwFlags))
{
hr = myHLastError();
if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
{
// out of for loop
break;
}
_JumpError(hr, error, "CryptGetProvParam");
}
if (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(paramData.aiAlgid))
{
pServer->dwKeyLenMin = paramData.dwMinLen;
pServer->dwKeyLenMax = paramData.dwMaxLen;
break;
}
dwFlags = 0;
}
error:
hr = ShowAllKeyLength(hDlg, pServer);
_PrintIfError(hr, "ShowAllKeyLength");
if (NULL != hProv)
{
CryptReleaseContext(hProv, 0);
}
return(S_OK);
}
HRESULT
InitializeKeyLengthControl(HWND hDlg)
{
HWND hwndCtrl = GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH);
// set digit length
SendMessage(
hwndCtrl,
CB_LIMITTEXT,
(WPARAM) MAX_KEYLENGTHDIGIT,
(LPARAM) 0);
return S_OK;
}
//--------------------------------------------------------------------
HRESULT
HandleKeySelectionChange(
HWND hDlg,
CASERVERSETUPINFO *pServer,
BOOL fUpdate)
{
HRESULT hr;
HWND hKeyList = GetDlgItem(hDlg, IDC_ADVANCE_KEYLIST);
WCHAR * pwszKeyContainerName;
CERT_CONTEXT const * pccCert;
LRESULT nItem = (INT)SendMessage(
hKeyList,
LB_GETCURSEL,
(WPARAM) 0,
(LPARAM) 0);
CSASSERT(LB_ERR!=nItem);
pwszKeyContainerName = (WCHAR *) SendMessage(
hKeyList,
LB_GETITEMDATA,
(WPARAM) nItem,
(LPARAM) 0);
CSASSERT(NULL!=pwszKeyContainerName);
// Only change is this is a different selection
if (NULL==pServer->pwszKeyContainerName ||
0!=wcscmp(pwszKeyContainerName, pServer->pwszKeyContainerName)) {
// Set the container name to match what the user picked.
BOOL fKeyListChange=pServer->fDeletableNewKey;
hr = SetKeyContainerName(pServer, pwszKeyContainerName);
_JumpIfError(hr, error, "SetKeyContainerName");
// see if there is an existing cert for this key
hr = FindCertificateByKeyWithWaitCursor(pServer, &pccCert);
if (S_OK==hr) {
// Yes there is. By default, use it.
hr = SetExistingCertToUse(pServer, pccCert);
_JumpIfError(hr, error, "SetExistingCertToUse");
} else {
// only other return is 'not found'
CSASSERT(CRYPT_E_NOT_FOUND==hr);
}
// check to see if our caller wants us to update.
// our caller may want to do the update himself.
if (fUpdate) {
// perform the minimum necessary update
if (fKeyListChange) {
hr = UpdateKeyList(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeyList");
} else {
hr = UpdateKeySelection(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeySelection");
}
}
}
hr = S_OK;
error:
return hr;
}
//--------------------------------------------------------------------
// handle the "Use existing Key" checkbox
HRESULT
HandleUseKeyCheckboxChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
static bool fNT4CertCopiedAlready = false;
if(pServer->pwszFullCADN)
{
LocalFree(pServer->pwszFullCADN);
pServer->pwszFullCADN = NULL;
}
if(pServer->pwszCACommonName)
{
LocalFree(pServer->pwszCACommonName);
pServer->pwszCACommonName = NULL;
}
if(pServer->pwszDNSuffix)
{
LocalFree(pServer->pwszDNSuffix);
pServer->pwszDNSuffix = NULL;
}
// is the checkbox checked or unchecked?
if (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ADVANCE_USEKEYCHECK)) {
// checkbox was just checked, so we previously did not have a chosen key.
CSASSERT(NULL==pServer->pwszKeyContainerName);
hr = HandleKeySelectionChange(hDlg, pServer, FALSE); // don't update, because we need to update too.
_JumpIfError(hr, error, "HandleKeySelectionChange");
hr = UpdateUseKeyCheckbox(hDlg, pServer);
_JumpIfError(hr, error, "UpdateUseKeyCheckbox");
} else {
// checkbox was just unchecked, so we previously had a chosen key..
CSASSERT(NULL!=pServer->pwszKeyContainerName);
BOOL fKeyListChange=pServer->fDeletableNewKey;
ClearKeyContainerName(pServer);
// perform the minimum necessary update
if (fKeyListChange) {
hr = UpdateKeyList(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeyList");
} else {
hr = UpdateUseKeyCheckbox(hDlg, pServer);
_JumpIfError(hr, error, "UpdateUseKeyCheckbox");
}
hr = InitNameFields(pServer);
_JumpIfError(hr, error, "InitNameFields");
}
error:
return hr;
}
//--------------------------------------------------------------------
HRESULT
UpdateCSPSelection(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
bool fInteractiveOff;
if (NULL == pServer->pCSPInfo)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL pCSPInfo");
}
// hilight current CSP
hr = HilightItemInList(hDlg,
IDC_ADVANCE_CSPLIST,
pServer->pCSPInfo->pwszProvName,
TRUE);
_JumpIfError(hr, error, "HilightItemInList");
hr = UpdateHashList(hDlg, pServer);
_JumpIfError(hr, error, "UpdateHashList");
hr = UpdateKeyLengthMinMax(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeyLengthMinMax");
hr = UpdateKeyList(hDlg, pServer);
_JumpIfError(hr, error, "UpdateKeyList");
// Update "interact with desktop" flag. For default CSP
// we turn it off, otherwise turn it on.
CSASSERT(pServer->pCSPInfo &&
pServer->pDefaultCSPInfo&&
pServer->pCSPInfo->pwszProvName &&
pServer->pDefaultCSPInfo->pwszProvName);
fInteractiveOff =
(0 == mylstrcmpiL(pServer->pCSPInfo->pwszProvName,
pServer->pDefaultCSPInfo->pwszProvName) &&
(pServer->pCSPInfo->dwProvType == pServer->pDefaultCSPInfo->dwProvType));
SendMessage(
GetDlgItem(hDlg, IDC_ADVANCE_INTERACTIVECHECK),
BM_SETCHECK,
(WPARAM)(fInteractiveOff?BST_UNCHECKED:BST_CHECKED),
(LPARAM)0);
if(fInteractiveOff)
{
WCHAR wszKeyLength[MAX_KEYLENGTHDIGIT + 1];
wsprintf(wszKeyLength, L"%u",
IsRootCA(pServer->CAType)?
CA_DEFAULT_KEY_LENGTH_ROOT:
CA_DEFAULT_KEY_LENGTH_SUB);
SetWindowText(
GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH),
wszKeyLength);
}
hr = S_OK;
error:
return hr;
}
//--------------------------------------------------------------------
HRESULT
HandleCSPSelectionChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr = S_OK;
HWND hCSPList;
LRESULT nItem;
CSP_INFO * pCSPInfo;
// get current csp
hCSPList = GetDlgItem(hDlg, IDC_ADVANCE_CSPLIST);
nItem = (INT)SendMessage(hCSPList, LB_GETCURSEL,
(WPARAM)0, (LPARAM)0);
pCSPInfo = (CSP_INFO *)SendMessage(hCSPList,
LB_GETITEMDATA, (WPARAM)nItem, (LPARAM)0);
// only change if this is a different selection
if (pCSPInfo->dwProvType!=pServer->pCSPInfo->dwProvType ||
0!=wcscmp(pCSPInfo->pwszProvName, pServer->pCSPInfo->pwszProvName)) {
// Must create a new key if the CSP changes
ClearKeyContainerName(pServer);
pServer->pCSPInfo=pCSPInfo;
hr = DetermineDefaultHash(pServer);
_JumpIfError(hr, error, "DetermineDefaultHash");
hr = UpdateCSPSelection(hDlg, pServer);
_JumpIfError(hr, error, "UpdateCSPSelection");
}
error:
return hr;
}
// Update cascade:
//
// UpdateCSPSelection
// |-UpdateHashList
// |-UpdateKeyLengthMinMax
// \-UpdateKeyList
// \-UpdateUseKeyCheckbox
// \-UpdateKeySelection
// \-UpdateUseCertCheckbox
HRESULT
InitAdvanceWizPageControls(
HWND hDlg)
{
HRESULT hr;
EnableWindow(GetDlgItem(hDlg, IDC_ADVANCE_INTERACTIVECHECK), TRUE);
hr = S_OK;
//error:
return hr;
}
HRESULT
HandleHashSelectionChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
HWND hHashList = GetDlgItem(hDlg, IDC_ADVANCE_HASHLIST);
LRESULT nItem = (INT)SendMessage(
hHashList,
LB_GETCURSEL,
(WPARAM) 0,
(LPARAM) 0);
pServer->pHashInfo = (CSP_HASH*)SendMessage(
hHashList,
LB_GETITEMDATA,
(WPARAM) nItem,
(LPARAM) 0);
// Must validate the hash again when the selected hash changes
pServer->fValidatedHashAndKey = FALSE;
hr = S_OK;
//error:
return hr;
}
HRESULT
HandleKeyLengthSelectionChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
HWND hwndCtrl = GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH);
LRESULT nItem = (INT)SendMessage(hwndCtrl, CB_GETCURSEL,
(WPARAM)0, (LPARAM)0);
pServer->dwKeyLength = (DWORD)SendMessage(hwndCtrl,
CB_GETITEMDATA,
(WPARAM)nItem, (LPARAM)0);
// If key length chenges, we must not have created a key yet.
CSASSERT(NULL==pServer->pwszKeyContainerName);
hr = S_OK;
//error:
return hr;
}
// remove any non-numeric chars except default string
HRESULT
HandleKeyLengthEditChange(
HWND hwndComboBox)
{
HRESULT hr;
WCHAR wszKeyLength[MAX_KEYLENGTHEDIT];
int index = 0; // index for new #
int posi = 0; // current position
wszKeyLength[0] = L'\0'; // PREFIX says initialize
GetWindowText(hwndComboBox, wszKeyLength, ARRAYSIZE(wszKeyLength));
// remove non-numeric chars
while (L'\0' != wszKeyLength[posi])
{
if (iswdigit(wszKeyLength[posi]))
{
// take digit
wszKeyLength[index] = wszKeyLength[posi];
++index;
}
++posi;
}
if (index != posi)
{
// null terminator
wszKeyLength[index] = L'\0';
// update
SetWindowText(hwndComboBox, wszKeyLength);
// point to end
SendMessage(hwndComboBox, CB_SETEDITSEL, (WPARAM)0,
MAKELPARAM((index), (index)) );
}
hr = S_OK;
//error:
return hr;
}
HRESULT
HandleImportPFXButton(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
hr = ImportPFXAndUpdateCSPInfo(hDlg, pComp);
_PrintIfError(hr, "ImportPFXAndUpdateCSPInfo");
// ignore error and force update anyway.
hr = UpdateCSPSelection(hDlg, pServer);
_JumpIfError(hr, error, "UpdateCSPSelection");
hr = S_OK;
error:
return hr;
}
HRESULT
HandleAdvanceWizNext(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
WCHAR wszKeyLength[MAX_KEYLENGTHEDIT] = L"";
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
HWND hwndCtrl = GetDlgItem(hDlg, IDC_ADVANCE_KEY_LENGTH);
BOOL fDontNext = FALSE;
WCHAR wszKeyRange[2*MAX_KEYLENGTHDIGIT + 5]; //"(xxxx, xxxx)" format
WCHAR *pwszKeyRange = NULL; //don't free just a pointer
int dwKeyLength;
int idMsg;
BOOL fValidDigitString;
if (NULL == pServer->pwszKeyContainerName)
{
if(!GetWindowText(hwndCtrl, wszKeyLength, ARRAYSIZE(wszKeyLength)))
{
hr = myHLastError();
_JumpError(hr, error, "GetWindowText");
}
dwKeyLength = myWtoI(wszKeyLength, &fValidDigitString);
idMsg = 0;
if (0 > dwKeyLength)
{
idMsg = IDS_ADVANCE_NEGATIVEKEYLENGTH;
fDontNext = TRUE;
}
else if (!fValidDigitString)
{
idMsg = IDS_ADVANCE_INVALIDKEYLENGTH;
fDontNext = TRUE;
}
else if ( (C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMin &&
(DWORD)dwKeyLength < pServer->dwKeyLenMin) ||
(C_CSPHASNOKEYMINMAX != pServer->dwKeyLenMax &&
(DWORD)dwKeyLength > pServer->dwKeyLenMax) )
{
swprintf(wszKeyRange, L"(%ld, %ld)",
pServer->dwKeyLenMin, pServer->dwKeyLenMax);
pwszKeyRange = wszKeyRange;
idMsg = IDS_ADVANCE_KEYLENGTHOUTOFRANGE;
fDontNext = TRUE;
}
if (fDontNext)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
idMsg,
0,
pwszKeyRange);
SetEditFocusAndSelect(hwndCtrl, 0, MAXDWORD);
goto done;
}
// take the length
pServer->dwKeyLength = dwKeyLength;
}
else
{
// use existing key
if (NULL==pServer->pccExistingCert)
{
// If reusing a key but not a cert, make the common name match the key name
if (NULL != pServer->pwszCACommonName)
{
// free old
LocalFree(pServer->pwszCACommonName);
pServer->pwszCACommonName = NULL;
}
pServer->pwszCACommonName = (WCHAR*) LocalAlloc(LPTR,
(wcslen(pServer->pwszDesanitizedKeyContainerName) + 1) * sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, pServer->pwszCACommonName);
wcscpy(pServer->pwszCACommonName, pServer->pwszDesanitizedKeyContainerName);
hr = InitNameFields(pServer);
_JumpIfError(hr, error, "InitNameFields");
} else {
// If reusing a cert, make all the ID fields match the cert
// use idinfo from signing cert
hr = DetermineExistingCAIdInfo(pServer, NULL);
if (S_OK != hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_ANALYSIS_CA,
hr,
NULL);
_PrintError(hr, "DetermineExistingCAIdInfo");
fDontNext = TRUE;
goto done;
}
}
}
// get "interactive service" check box state
pServer->fInteractiveService =
(BST_CHECKED ==
SendMessage(GetDlgItem(hDlg, IDC_ADVANCE_INTERACTIVECHECK),
BM_GETCHECK, (WPARAM)0, (LPARAM)0))?
TRUE:FALSE;
// update hash oid
if (NULL != pServer->pszAlgId)
{
// free old
LocalFree(pServer->pszAlgId);
}
hr = myGetSigningOID(
NULL, // hProv
pServer->pCSPInfo->pwszProvName,
pServer->pCSPInfo->dwProvType,
pServer->pHashInfo->idAlg,
&(pServer->pszAlgId));
if (S_OK != hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_UNSUPPORTEDHASH,
hr,
NULL);
fDontNext = TRUE;
goto done;
}
done:
if (fDontNext)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // forbid
}
else
{
pServer->LastWiz = ENUM_WIZ_ADVANCE;
}
hr = S_OK;
error:
return hr;
}
HRESULT
HandleAdvanceWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
// Suppress this wizard page if
// we've already seen an error, or
// the advanced option was not selected, or
// we are not installing the server.
if (!pServer->fAdvance ||
!(IS_SERVER_INSTALL & pComp->dwInstallStatus) )
{
// disable page
CSILOGDWORD(IDS_ADVANCE_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
if (NULL == pServer->pCSPInfoList)
{
// construct CSP info list
HCURSOR hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = GetCSPInfoList(&pServer->pCSPInfoList);
SetCursor(hPrevCur);
_JumpIfError(hr, error, "GetCSPInfoList");
// show all csps
hr = ShowAllCSP(hDlg, pServer->pCSPInfoList);
_JumpIfError(hr, error, "ShowAllCSP");
// determine default csp
hr = DetermineDefaultCSP(pServer);
_JumpIfError(hr, error, "DetermineDefaultCSP");
hr = DetermineDefaultHash(pServer);
_JumpIfError(hr, error, "DetermineDefaultHash");
hr = InitializeKeyLengthControl(hDlg);
_JumpIfError(hr, error, "InitializeKeyLengthControl");
}
hr = UpdateCSPSelection(hDlg, pServer);
_JumpIfError(hr, error, "UpdateCSPSelection");
done:
hr = S_OK;
error:
return hr;
}
HRESULT
HandleViewCertButton(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CRYPTUI_VIEWCERTIFICATE_STRUCTW viewCert;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
CSASSERT(NULL!=pServer->pwszKeyContainerName &&
NULL!=pServer->pccExistingCert);
ZeroMemory(&viewCert, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW));
viewCert.hwndParent = hDlg;
viewCert.dwSize = sizeof(viewCert);
viewCert.pCertContext = CertDuplicateCertificateContext(pServer->pccExistingCert);
if (NULL == viewCert.pCertContext)
{
hr = myHLastError();
_JumpError(hr, error, "CertDuplicateCertificateContext");
}
// viewCert.rghStores = &pServer->hMyStore;
// viewCert.cStores = 1;
viewCert.dwFlags = CRYPTUI_DONT_OPEN_STORES;
if (!CryptUIDlgViewCertificateW(&viewCert, NULL))
{
hr = myHLastError();
_PrintError(hr, "CryptUIDlgViewCertificate");
}
hr = S_OK;
error:
if (NULL != viewCert.pCertContext)
{
CertFreeCertificateContext(viewCert.pCertContext);
}
return hr;
}
//+------------------------------------------------------------------------
//
// Function: WizAdvancedPageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for advanced configuration OCM wizard.
//
// Arguments: [hDlg]
// [iMsg]
// [wParam]
// [lParam] ... the usual.
//
// Returns: BOOL dlg proc result.
//
//-------------------------------------------------------------------------
INT_PTR
WizAdvancedPageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
switch (iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitAdvanceWizPageControls(hDlg);
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_ADVANCE_CSPLIST:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleCSPSelectionChange(hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
break;
}
break;
case IDC_ADVANCE_HASHLIST:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleHashSelectionChange(hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
}
break;
case IDC_ADVANCE_KEYLIST:
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleKeySelectionChange(hDlg,
pComp->CA.pServer, TRUE);
_ReturnIfWizError(pComp->hrContinue);
break;
}
break;
case IDC_ADVANCE_USEKEYCHECK:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleUseKeyCheckboxChange(hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_ADVANCE_USECERTCHECK:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleUseCertCheckboxChange(hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_ADVANCE_KEY_LENGTH:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleKeyLengthSelectionChange(hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
case CBN_EDITCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleKeyLengthEditChange(
(HWND)lParam);
_ReturnIfWizError(pComp->hrContinue);
break;
}
break;
case IDC_ADVANCE_IMPORT:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleImportPFXButton(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_ADVANCE_VIEWCERT:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleViewCertButton(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR*) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_ADVANCE_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleAdvanceWizActive(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_ADVANCE_TITLE, dwWIZBACK);
break;
case PSN_WIZNEXT:
DWORD fReuseCert;
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
fReuseCert = NULL != pComp->CA.pServer->pccExistingCert;
CSILOG(
S_OK,
IDS_LOG_KEYNAME,
pComp->CA.pServer->pwszKeyContainerName,
pComp->CA.pServer->pwszDesanitizedKeyContainerName,
&fReuseCert);
CSILOGDWORD(IDS_ADVANCE_TITLE, dwWIZNEXT);
pComp->hrContinue = HandleAdvanceWizNext(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
HRESULT
EnableSharedFolderControls(HWND hDlg, BOOL fUseSharedFolder)
{
EnableWindow(GetDlgItem(hDlg, IDC_STORE_EDIT_SHAREDFOLDER), fUseSharedFolder);
EnableWindow(GetDlgItem(hDlg, IDC_STORE_SHAREDBROWSE), fUseSharedFolder);
if (fUseSharedFolder)
{
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_STORE_EDIT_SHAREDFOLDER), 0, MAXDWORD);
}
return S_OK;
}
HRESULT
StorePageValidation(
HWND hDlg,
PER_COMPONENT_DATA *pComp,
BOOL *pfDontNext)
{
HRESULT hr;
UINT uiFocus = 0;
WCHAR *pwszDefaultDBDir = NULL;
WCHAR *pwszDefaultSF = NULL;
LPWSTR pwszPrompt = NULL;
LPWSTR pwszComputerName = NULL;
BOOL fExistSF = TRUE;
BOOL fExistDB = TRUE;
BOOL fExistLog = TRUE;
BOOL fDefaultDir;
BOOL fIsUNC;
BOOL fIsSharedFolderUNC;
WCHAR wszNotExistingDir[3 * MAX_PATH];
BOOL fUseSharedFolder;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
*pfDontNext = FALSE;
// get shared folder check state
if (pComp->fUnattended)
{
CSASSERT(NULL != pServer->pwszSharedFolder);
fUseSharedFolder = TRUE; // unattended always use shared folder
}
else
{
fUseSharedFolder = (BST_CHECKED == SendMessage(
GetDlgItem(hDlg, IDC_STORE_USE_SHAREDFOLDER),
BM_GETCHECK, 0, 0));
}
fIsSharedFolderUNC = FALSE;
if (NULL != pServer->pwszSharedFolder)
{
fDefaultDir = TRUE;
hr = GetDefaultSharedFolder(&pwszDefaultSF);
_JumpIfError(hr, error, "GetDefaultSharedFolder");
// make sure case insensitive
if (0 != mylstrcmpiL(pwszDefaultSF, pServer->pwszSharedFolder))
{
fDefaultDir = FALSE;
}
if (!ValidateAndCreateDirField(
pComp->hInstance,
pComp->fUnattended,
hDlg,
pServer->pwszSharedFolder,
fDefaultDir,
IDS_WRN_STORELOC_SHAREDFOLDER_FULLPATH,
&fExistSF,
&fIsSharedFolderUNC))
{
uiFocus = IDC_STORE_EDIT_SHAREDFOLDER;
*pfDontNext = TRUE;
goto done;
}
}
else if (fUseSharedFolder)
{
// the case to enforce shared folder but edit field is empty
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_STORELOC_SHAREDFOLDER_FULLPATH,
0,
L"");
uiFocus = IDC_STORE_EDIT_SHAREDFOLDER;
*pfDontNext = TRUE;
goto done;
}
fDefaultDir = TRUE;
hr = GetDefaultDBDirectory(pComp, &pwszDefaultDBDir);
_JumpIfError(hr, error, "GetDefaultDBDirectory");
// make sure case insensitive
if (0 != mylstrcmpiL(pwszDefaultDBDir, pServer->pwszDBDirectory))
{
fDefaultDir = FALSE;
}
if (!ValidateAndCreateDirField(
pComp->hInstance,
pComp->fUnattended,
hDlg,
pServer->pwszDBDirectory,
fDefaultDir,
IDS_WRN_STORELOC_DB_FULLPATH,
&fExistDB,
&fIsUNC))
{
uiFocus = IDC_STORE_EDIT_DB;
*pfDontNext = TRUE;
goto done;
}
fDefaultDir = TRUE;
// remember default log dir is the same as db
if (0 != mylstrcmpiL(pwszDefaultDBDir, pServer->pwszLogDirectory))
{
fDefaultDir = FALSE;
}
if (!ValidateAndCreateDirField(
pComp->hInstance,
pComp->fUnattended,
hDlg,
pServer->pwszLogDirectory,
fDefaultDir,
IDS_WRN_STORELOC_LOG_FULLPATH,
&fExistLog,
&fIsUNC))
{
uiFocus = IDC_STORE_EDIT_LOG;
*pfDontNext = TRUE;
goto done;
}
wszNotExistingDir[0] = '\0'; // empty string
if (!fExistSF)
{
wcscat(wszNotExistingDir, pServer->pwszSharedFolder);
}
if (!fExistDB)
{
if ('\0' != wszNotExistingDir[0])
{
wcscat(wszNotExistingDir, L"\n");
}
wcscat(wszNotExistingDir, pServer->pwszDBDirectory);
}
if (!fExistLog)
{
if ('\0' != wszNotExistingDir[0])
{
wcscat(wszNotExistingDir, L"\n");
}
wcscat(wszNotExistingDir, pServer->pwszLogDirectory);
}
if ('\0' != wszNotExistingDir[0])
{
// skip confirm in unattended mode
if (!pComp->fUnattended)
{
// confirm all here
if (IDYES != CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ASK_CREATE_DIRECTORY,
0,
MB_YESNO |
MB_ICONWARNING |
CMB_NOERRFROMSYS,
wszNotExistingDir) )
{
if (!fExistSF)
{
uiFocus = IDC_STORE_EDIT_SHAREDFOLDER;
}
else if (!fExistDB)
{
uiFocus = IDC_STORE_EDIT_DB;
}
else if (!fExistLog)
{
uiFocus = IDC_STORE_EDIT_LOG;
}
*pfDontNext = TRUE;
goto done;
}
}
if (!fExistSF)
{
hr = myCreateNestedDirectories(pServer->pwszSharedFolder);
if (S_OK != hr)
{
CertWarningMessageBox(pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_CREATE_DIR,
hr,
pServer->pwszSharedFolder);
uiFocus = IDC_STORE_EDIT_SHAREDFOLDER;
*pfDontNext = TRUE;
goto done;
}
}
if (!fExistDB)
{
hr = myCreateNestedDirectories(pServer->pwszDBDirectory);
if (S_OK != hr)
{
CertWarningMessageBox(pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_CREATE_DIR,
hr,
pServer->pwszDBDirectory);
uiFocus = IDC_STORE_EDIT_DB;
*pfDontNext = TRUE;
goto done;
}
}
if (!fExistLog)
{
hr = myCreateNestedDirectories(pServer->pwszLogDirectory);
if (S_OK != hr)
{
CertWarningMessageBox(pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_ERR_CREATE_DIR,
hr,
pServer->pwszLogDirectory);
uiFocus = IDC_STORE_EDIT_LOG;
*pfDontNext = TRUE;
goto done;
}
}
}
hr = SetFolderDacl(
pServer->pwszDBDirectory,
WSZ_DEFAULT_DB_DIR_SECURITY);
_JumpIfErrorStr(hr, error, "SetFolderDacl", pServer->pwszDBDirectory);
hr = SetFolderDacl(
pServer->pwszLogDirectory,
WSZ_DEFAULT_LOG_DIR_SECURITY);
_JumpIfErrorStr(hr, error, "SetFolderDacl", pServer->pwszLogDirectory);
hr = ValidateESERestrictions(pServer->pwszDBDirectory);
if (S_OK != hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_DBSPECIALCHARACTERS,
hr,
pServer->pwszDBDirectory);
uiFocus = IDC_STORE_EDIT_DB;
*pfDontNext = TRUE;
goto done;
}
hr = ValidateESERestrictions(pServer->pwszLogDirectory);
if (S_OK != hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_DBSPECIALCHARACTERS,
hr,
pServer->pwszLogDirectory);
uiFocus = IDC_STORE_EDIT_LOG;
*pfDontNext = TRUE;
goto done;
}
CSASSERT(!*pfDontNext);
// directory creation done; now analyze for UNC, sharepath
if (NULL != pServer->pwszSharedFolder)
{
// if not UNC, prompt to change to UNC
if (!fIsSharedFolderUNC)
{
#define UNCPATH_TEMPLATE L"\\\\%ws\\" wszCERTCONFIGSHARENAME
hr = myAddShare(
wszCERTCONFIGSHARENAME,
myLoadResourceString(IDS_CERTCONFIG_FOLDERDESCR),
pServer->pwszSharedFolder,
TRUE, // overwrite
NULL);
_JumpIfError(hr, done, "myAddShare");
// get the local machine name
WCHAR wszUNCPath[MAX_PATH + ARRAYSIZE(UNCPATH_TEMPLATE)]; // "machine" + UNCPATH_TEMPLATE
hr = myGetMachineDnsName(&pwszComputerName);
_JumpIfError(hr, done, "myGetMachineDnsName");
// create UNC path
swprintf(wszUNCPath, UNCPATH_TEMPLATE, pwszComputerName);
// only convert to UNC if this thing is shared
LocalFree(pServer->pwszSharedFolder);
pServer->pwszSharedFolder = (LPWSTR)LocalAlloc(LMEM_FIXED,
WSZ_BYTECOUNT(wszUNCPath));
_JumpIfOutOfMemory(hr, error, pServer->pwszSharedFolder);
wcscpy(pServer->pwszSharedFolder, wszUNCPath);
} // else, user typed in an already-shared UNC path
}
done:
hr = S_OK;
error:
if (NULL != pwszDefaultDBDir)
LocalFree(pwszDefaultDBDir);
if (NULL != pwszDefaultSF)
LocalFree(pwszDefaultSF);
if (NULL != pwszPrompt)
LocalFree(pwszPrompt);
if (NULL != pwszComputerName)
LocalFree(pwszComputerName);
if (!pComp->fUnattended && uiFocus != 0 && *pfDontNext)
{
SetEditFocusAndSelect(GetDlgItem(hDlg, uiFocus), 0, MAXDWORD);
}
return hr;
}
HRESULT
StoreDBShareValidation(
IN HWND hDlg,
IN PER_COMPONENT_DATA *pComp,
IN WCHAR const *pwszDir,
IN BOOL fDB, //db dir vs. log dir
OUT BOOL *pfDontNext)
{
HRESULT hr;
WCHAR *pwszDefaultLogDir = NULL;
BOOL fDefaultLogPath;
WCHAR *pwszFileInUse = NULL;
BOOL fFilesExist;
static BOOL s_fOverwriteDB = FALSE;
static BOOL s_fOverwriteLog = FALSE;
BOOL *pfOverwrite = fDB ? &s_fOverwriteDB : &s_fOverwriteLog;
// init
*pfDontNext = FALSE;
// get default log path which is the same as db
hr = GetDefaultDBDirectory(pComp, &pwszDefaultLogDir);
_JumpIfError(hr, error, "GetDefaultDBDirectory");
fDefaultLogPath = (0 == mylstrcmpiL(pwszDir, pwszDefaultLogDir));
hr = myDoDBFilesExistInDir(pwszDir, &fFilesExist, &pwszFileInUse);
_JumpIfError(hr, error, "myDoDBFilesExistInDir");
if (NULL != pwszFileInUse)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_DBFILEINUSE,
0,
pwszFileInUse);
*pfDontNext = TRUE;
goto done;
}
if (!pComp->CA.pServer->fPreserveDB &&
fFilesExist &&
!*pfOverwrite &&
!fDefaultLogPath)
{
// log file exists in non-default dir
if (IDYES != CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_STORELOC_EXISTINGDB,
0,
MB_YESNO |
MB_DEFBUTTON2 |
MB_ICONWARNING |
CMB_NOERRFROMSYS,
pwszDir))
{
*pfDontNext = TRUE;
goto done;
}
// warn only once
*pfOverwrite = TRUE;
}
done:
if (*pfDontNext)
{
// set focus
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_STORE_EDIT_LOG), 0, MAXDWORD);
}
hr = S_OK;
error:
if (NULL != pwszFileInUse)
{
LocalFree(pwszFileInUse);
}
if (NULL != pwszDefaultLogDir)
{
LocalFree(pwszDefaultLogDir);
}
return hr;
}
HRESULT
FinishDirectoryBrowse(
HWND hDlg,
int idEdit)
{
HRESULT hr = S_FALSE;
WCHAR dirInitName[MAX_PATH] = L"";
WCHAR dirName[MAX_PATH] = L"";
if(!GetWindowText(GetDlgItem(hDlg, idEdit), dirInitName, MAX_PATH))
{
hr = myHLastError();
if(S_OK != hr)
{
return hr;
}
}
if (BrowseForDirectory(
GetParent(hDlg),
dirInitName,
dirName,
MAX_PATH,
NULL))
{
SetDlgItemText(hDlg, idEdit, dirName);
hr = S_OK;
}
return hr;
}
HRESULT
HookStorePageStrings(
PAGESTRINGS *pPageString,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
for ( ; 0 != pPageString->idControl; pPageString++)
{
switch (pPageString->idControl)
{
case IDC_STORE_EDIT_SHAREDFOLDER:
pPageString->ppwszString = &(pServer->pwszSharedFolder);
break;
case IDC_STORE_EDIT_DB:
pPageString->ppwszString = &(pServer->pwszDBDirectory);
break;
case IDC_STORE_EDIT_LOG:
pPageString->ppwszString = &(pServer->pwszLogDirectory);
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error");
break;
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
InitStoreWizControls(
HWND hDlg,
PAGESTRINGS *pPageString,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
// now make page strings complete
hr = HookStorePageStrings(pPageString, pServer);
_JumpIfError(hr, error, "HookStorePageStrings");
SendDlgItemMessage(hDlg,
IDC_STORE_USE_SHAREDFOLDER,
BM_SETCHECK,
(WPARAM)((NULL != pServer->pwszSharedFolder) ?
BST_CHECKED : BST_UNCHECKED),
(LPARAM)0);
if (!pServer->fUseDS && (NULL != pServer->pwszSharedFolder))
{
// no DS, disable shared folder check to force it
EnableWindow(GetDlgItem(hDlg, IDC_STORE_USE_SHAREDFOLDER), FALSE);
}
hr = StartWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "StartWizardPageEditControls");
hr = S_OK;
error:
return hr;
}
HRESULT
HandlePreservingDB(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
HWND hwndSF = GetDlgItem(hDlg, IDC_STORE_EDIT_SHAREDFOLDER);
HWND hwndDB = GetDlgItem(hDlg, IDC_STORE_EDIT_DB);
HWND hwndLog = GetDlgItem(hDlg, IDC_STORE_EDIT_LOG);
BOOL fEnable = TRUE;
BOOL fEnableSharedFolder = TRUE;
WCHAR *pwszExistingSharedFolder = NULL;
WCHAR *pwszExistingDBDirectory = NULL;
WCHAR *pwszExistingLogDirectory = NULL;
if (pServer->fPreserveDB)
{
if (!pServer->fUNCPathNotFound)
{
// get shared folder path
hr = myGetCertRegStrValue(NULL, NULL, NULL,
wszREGDIRECTORY, &pwszExistingSharedFolder);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
// optional value
hr = S_OK;
pwszExistingSharedFolder = NULL;
}
_JumpIfError(hr, error, "myGetCertRegStrValue");
fEnableSharedFolder = FALSE;
}
else
{
pwszExistingSharedFolder = pServer->pwszSharedFolder;
}
// get existing db path
hr = myGetCertRegStrValue(NULL, NULL, NULL,
wszREGDBDIRECTORY, &pwszExistingDBDirectory);
_JumpIfError(hr, error, "myGetCertRegStrValue");
hr = myGetCertRegStrValue(NULL, NULL, NULL,
wszREGDBLOGDIRECTORY, &pwszExistingLogDirectory);
_JumpIfError(hr, error, "myGetCertRegStrValue");
// fill edit fields
SetWindowText(hwndSF, pwszExistingSharedFolder);
SetWindowText(hwndDB, pwszExistingDBDirectory);
SetWindowText(hwndLog, pwszExistingLogDirectory);
// disable them
fEnable = FALSE;
}
EnableWindow(hwndSF, fEnableSharedFolder);
EnableWindow(hwndDB, fEnable);
EnableWindow(hwndLog, fEnable);
hr = S_OK;
error:
if (NULL != pwszExistingSharedFolder &&
pwszExistingSharedFolder != pServer->pwszSharedFolder)
{
LocalFree(pwszExistingSharedFolder);
}
if (NULL != pwszExistingDBDirectory)
{
LocalFree(pwszExistingDBDirectory);
}
if (NULL != pwszExistingLogDirectory)
{
LocalFree(pwszExistingLogDirectory);
}
return hr;
}
HRESULT
HandleStoreWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
HWND hwndDB;
BOOL fEnableKeepDB = FALSE;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
// Suppress this wizard page if
// we've already seen an error, or
// we are not installing the server.
if (!(IS_SERVER_INSTALL & pComp->dwInstallStatus) )
{
// disable page
CSILOGDWORD(IDS_STORE_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
CSASSERT(NULL != pServer->pwszKeyContainerName);
hwndDB = GetDlgItem(hDlg, IDC_STORE_KEEPDB);
if (NULL != pServer->pccExistingCert)
{
// determine existing db status
hr = myDoDBFilesExist(
pServer->pwszSanitizedName,
&fEnableKeepDB,
NULL);
_JumpIfError(hr, error, "myDoDBFilesExist");
}
else
{
// can't use db
pServer->fPreserveDB = FALSE;
SendMessage(hwndDB, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
HandlePreservingDB(hDlg, pComp);
}
// enable/disable the control
EnableSharedFolderControls(hDlg, NULL != pServer->pwszSharedFolder);
EnableWindow(hwndDB, fEnableKeepDB);
done:
hr = S_OK;
error:
return hr;
}
HRESULT
HandleStoreWizNextOrBack(
HWND hDlg,
PAGESTRINGS *pPageString,
PER_COMPONENT_DATA *pComp,
int iWizBN)
{
HRESULT hr;
WCHAR *pwszFile = NULL;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
BOOL fDontNext = FALSE;
BOOL fGoBack = FALSE;
BOOL fUseSharedFolder;
HCURSOR hPrevCur;
hr = FinishWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "FinishWizardPageEditControls");
if (PSN_WIZBACK == iWizBN)
{
goto done;
}
// make sure at least one way to publish ca
CSASSERT(NULL != pServer->pwszSharedFolder || pComp->CA.pServer->fUseDS);
// get shared folder check state
fUseSharedFolder = (BST_CHECKED == SendMessage(
GetDlgItem(hDlg, IDC_STORE_USE_SHAREDFOLDER),
BM_GETCHECK, 0, 0));
if (!fUseSharedFolder && NULL != pServer->pwszSharedFolder)
{
//don't collect shared folder from edit control
LocalFree(pServer->pwszSharedFolder);
pServer->pwszSharedFolder = NULL;
}
hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = StorePageValidation(hDlg, pComp, &fDontNext);
SetCursor(hPrevCur);
_JumpIfError(hr, error, "StorePageValidation");
if (fDontNext)
{
goto done;
}
// validate existing db sharing here
hr = StoreDBShareValidation(
hDlg,
pComp,
pComp->CA.pServer->pwszDBDirectory,
TRUE, //db dir
&fDontNext);
_JumpIfError(hr, error, "StoreDBShareValidation");
if (fDontNext)
{
goto done;
}
if (0 != mylstrcmpiL(
pComp->CA.pServer->pwszDBDirectory,
pComp->CA.pServer->pwszLogDirectory))
{
hr = StoreDBShareValidation(
hDlg,
pComp,
pComp->CA.pServer->pwszLogDirectory,
FALSE, //log dir
&fDontNext);
_JumpIfError(hr, error, "StoreDBShareValidation");
if (fDontNext)
{
goto done;
}
}
hr = myBuildPathAndExt(
pComp->CA.pServer->pwszDBDirectory,
pServer->pwszSanitizedName,
wszDBFILENAMEEXT,
&pwszFile);
_JumpIfError(hr, error, "myBuildPathAndExt");
// make sure path fits
if (MAX_PATH <= wcslen(pwszFile))
{
// pop up warning
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PATH_TOO_LONG_CANAME,
S_OK,
pwszFile);
// make it go back
fGoBack = TRUE;
fDontNext = TRUE;
goto done;
}
LocalFree(pwszFile);
pwszFile = NULL;
hr = myBuildPathAndExt(
pComp->CA.pServer->pwszLogDirectory,
TEXT(szDBBASENAMEPARM) L"00000",
wszLOGFILENAMEEXT,
&pwszFile);
_JumpIfError(hr, error, "myBuildPathAndExt");
// make sure path fits
if (MAX_PATH <= wcslen(pwszFile))
{
// pop up warning
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PATH_TOO_LONG_DIRECTORY,
S_OK,
pwszFile);
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_STORE_EDIT_LOG), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
LocalFree(pwszFile);
pwszFile = NULL;
hr = csiBuildCACertFileName(
pComp->hInstance,
hDlg,
pComp->fUnattended,
pServer->pwszSharedFolder,
pServer->pwszSanitizedName,
L".crt",
0, // CANAMEIDTOICERT(pServer->dwCertNameId),
&pwszFile);
_JumpIfError(hr, error, "csiBuildCACertFileName");
// make sure path fit
if (MAX_PATH <= wcslen(pwszFile) + cwcSUFFIXMAX)
{
// pop up warning
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PATH_TOO_LONG_CANAME,
S_OK,
pwszFile);
// make it go back
fGoBack = TRUE;
fDontNext = TRUE;
goto done;
}
if (NULL != pServer->pwszCACertFile)
{
// free old one
LocalFree(pServer->pwszCACertFile);
}
pServer->pwszCACertFile = pwszFile;
pwszFile = NULL;
if (IsRootCA(pServer->CAType))
{
hPrevCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = StartAndStopService(pComp->hInstance,
pComp->fUnattended,
hDlg,
wszW3SVCNAME,
TRUE,
TRUE, // confirmation
IDS_STOP_W3SVC,
&g_fW3SvcRunning);
SetCursor(hPrevCur);
if (S_OK != hr)
{
if (E_ABORT == hr)
{
fDontNext = TRUE;
goto done;
}
_JumpError(hr, error, "StartAndStopService");
}
}
done:
if (fDontNext)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // forbid
if (fGoBack)
{
PropSheet_PressButton(GetParent(hDlg), PSBTN_BACK);
pServer->LastWiz = ENUM_WIZ_STORE;
}
}
else
{
// continue to next
pServer->LastWiz = ENUM_WIZ_STORE;
}
hr = S_OK;
error:
if (NULL != pwszFile)
{
LocalFree(pwszFile);
}
return hr;
}
HRESULT
HandleUseSharedFolder(
IN HWND hDlg,
IN OUT PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
// get shared folder check state
BOOL fUseSharedFolder = (BST_CHECKED == SendMessage(
GetDlgItem(hDlg, IDC_STORE_USE_SHAREDFOLDER),
BM_GETCHECK, 0, 0));
if (!fUseSharedFolder && !pComp->CA.pServer->fUseDS)
{
// must check at least one, force unchange
fUseSharedFolder = TRUE;
SendDlgItemMessage(hDlg, IDC_STORE_USE_SHAREDFOLDER,
BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
}
hr = EnableSharedFolderControls(hDlg, fUseSharedFolder);
// _JumpIfError(hr, error, "EnableSharedFolderControls");
_PrintIfError(hr, "EnableSharedFolderControls");
// hr = S_OK;
//error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizStorePageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for storage location
//-------------------------------------------------------------------------
INT_PTR
WizStorePageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
// keep scope of following array inside
static PAGESTRINGS saStoreString[] =
{
{
IDC_STORE_EDIT_SHAREDFOLDER,
IDS_LOG_SHAREDFOLDER,
0,
0,
MAX_PATH,
NULL,
},
{
IDC_STORE_EDIT_DB,
IDS_LOG_DBDIR,
0,
0,
MAX_PATH,
NULL,
},
{
IDC_STORE_EDIT_LOG,
IDS_LOG_DBLOGDIR,
0,
0,
MAX_PATH,
NULL,
},
// you need to add code in HookStoreStrings if adding more...
{
0,
0,
0,
0,
0,
NULL,
}
};
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitStoreWizControls(hDlg, saStoreString, pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_STORE_USE_SHAREDFOLDER:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleUseSharedFolder(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_STORE_KEEPDB:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->fPreserveDB = !pComp->CA.pServer->fPreserveDB;
pComp->hrContinue = HandlePreservingDB(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_STORE_SHAREDBROWSE:
FinishDirectoryBrowse(hDlg, IDC_STORE_EDIT_SHAREDFOLDER);
break;
case IDC_STORE_DBBROWSE:
FinishDirectoryBrowse(hDlg, IDC_STORE_EDIT_DB);
break;
case IDC_STORE_LOGBROWSE:
FinishDirectoryBrowse(hDlg, IDC_STORE_EDIT_LOG);
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_STORE_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleStoreWizActive(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_STORE_TITLE, dwWIZBACK);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleStoreWizNextOrBack(hDlg,
saStoreString, pComp, PSN_WIZBACK);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_STORE_TITLE, dwWIZNEXT);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleStoreWizNextOrBack(hDlg,
saStoreString, pComp, PSN_WIZNEXT);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
HRESULT
EnableCARequestControls(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
// Online req
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_CANAME),
!pServer->fSaveRequestAsFile);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_COMPUTERNAME),
!pServer->fSaveRequestAsFile);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_CA_BROWSE),
!pServer->fSaveRequestAsFile && pServer->fCAsExist);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_CNLABEL),
!pServer->fSaveRequestAsFile);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_PCALABEL),
!pServer->fSaveRequestAsFile);
// File req
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_FILE),
pServer->fSaveRequestAsFile);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_FILE_BROWSE),
pServer->fSaveRequestAsFile);
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_FILELABEL),
pServer->fSaveRequestAsFile);
if (pServer->fSaveRequestAsFile)
{
SetFocus(GetDlgItem(hDlg, IDC_CAREQUEST_FILE));
}
else
{
SetFocus(GetDlgItem(hDlg, IDC_CAREQUEST_CANAME));
}
hr = S_OK;
//error:
return hr;
}
HRESULT
BuildRequestFileName(
IN WCHAR const *pwszCACertFile,
OUT WCHAR **ppwszRequestFile)
{
#define wszREQEXT L".req"
HRESULT hr;
WCHAR const *pwszStart;
WCHAR const *pwszEnd;
WCHAR *pwszRequestFile = NULL;
CSASSERT(NULL != pwszCACertFile);
// derive request file name
pwszStart = pwszCACertFile;
pwszEnd = wcsrchr(pwszStart, L'.');
if (pwszEnd == NULL)
{
// set to end of entire string -- no '.' found
pwszEnd = &pwszStart[wcslen(pwszStart)];
}
pwszRequestFile = (WCHAR*)LocalAlloc(LMEM_FIXED,
(SAFE_SUBTRACT_POINTERS(pwszEnd, pwszStart) +
wcslen(wszREQEXT) + 1) * sizeof(WCHAR));
_JumpIfOutOfMemory(hr, error, pwszRequestFile);
CopyMemory(pwszRequestFile, pwszStart,
SAFE_SUBTRACT_POINTERS(pwszEnd, pwszStart) * sizeof(WCHAR));
wcscpy(pwszRequestFile + SAFE_SUBTRACT_POINTERS(pwszEnd, pwszStart), wszREQEXT);
// return
*ppwszRequestFile = pwszRequestFile;
pwszRequestFile = NULL;
hr = S_OK;
error:
if (NULL != pwszRequestFile)
{
LocalFree(pwszRequestFile);
}
return hr;
}
HRESULT
StartCARequestPage(
HWND hDlg,
PAGESTRINGS *pPageString,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
if (NULL == pServer->pwszRequestFile)
{
hr = BuildRequestFileName(
pServer->pwszCACertFile,
&pServer->pwszRequestFile);
_JumpIfError(hr, error, "BuildRequestFileName");
}
hr = StartWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "StartWizardPageEditControls");
hr = S_OK;
error:
return hr;
}
HRESULT
GetRequestFileName(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
WCHAR *pwszFileIn = NULL;
WCHAR *pwszFileOut = NULL;
HWND hCtrl = GetDlgItem(hDlg, IDC_CAREQUEST_FILE);
hr = myUIGetWindowText(hCtrl, &pwszFileIn);
_JumpIfError(hr, error, "myUIGetWindowText");
hr = myGetSaveFileName(
hDlg,
pComp->hInstance,
IDS_REQUEST_SAVE_TITLE,
IDS_REQUEST_FILE_FILTER,
IDS_REQUEST_FILE_DEFEXT,
OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
pwszFileIn,
&pwszFileOut);
_JumpIfError(hr, error, "myGetSaveFileName");
if (NULL != pwszFileOut)
{
SetWindowText(hCtrl, pwszFileOut);
}
hr = S_OK;
error:
if (NULL != pwszFileOut)
{
LocalFree(pwszFileOut);
}
if (NULL != pwszFileIn)
{
LocalFree(pwszFileIn);
}
return hr;
}
HRESULT
HookCARequestPageStrings(
PAGESTRINGS *pPageString,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
for ( ; 0 != pPageString->idControl; pPageString++)
{
switch (pPageString->idControl)
{
case IDC_CAREQUEST_CANAME:
pPageString->ppwszString = &(pServer->pwszParentCAName);
break;
case IDC_CAREQUEST_COMPUTERNAME:
pPageString->ppwszString = &(pServer->pwszParentCAMachine);
break;
case IDC_CAREQUEST_FILE:
pPageString->ppwszString = &(pServer->pwszRequestFile);
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error");
break;
}
}
hr = S_OK;
error:
return hr;
}
CERTSRVUICASELECTION g_CARequestUICASelection =
{ NULL, NULL, NULL, NULL, NULL, ENUM_UNKNOWN_CA, false, true };
HRESULT
InitCARequestWizControls(
HWND hDlg,
PAGESTRINGS *pSubmitPageString,
PAGESTRINGS *pFilePageString,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
// now make page strings complete
hr = HookCARequestPageStrings(pSubmitPageString, pServer);
_JumpIfError(hr, error, "HookCARequestPageStrings");
hr = HookCARequestPageStrings(pFilePageString, pServer);
_JumpIfError(hr, error, "HookCARequestPageStrings");
if (!(SETUPOP_STANDALONE & pComp->Flags))
{
// nt base setup
// disable online submit
EnableWindow(GetDlgItem(hDlg, IDC_CAREQUEST_SUBMITTOCA), FALSE);
SendMessage(GetDlgItem(hDlg, IDC_CAREQUEST_SUBMITTOCA),
BM_SETCHECK,
(WPARAM) BST_UNCHECKED,
(LPARAM) 0);
// only save as file
pServer->fSaveRequestAsFile = TRUE;
SendMessage(GetDlgItem(hDlg, IDC_CAREQUEST_SAVETOFILE),
BM_SETCHECK,
(WPARAM) BST_CHECKED,
(LPARAM) 0);
}
else
{
// set online submit as default
pServer->fSaveRequestAsFile = FALSE;
SendMessage(GetDlgItem(hDlg, IDC_CAREQUEST_SUBMITTOCA),
BM_CLICK,
(WPARAM) 0,
(LPARAM) 0);
hr = myInitUICASelectionControls(
&g_CARequestUICASelection,
pComp->hInstance,
hDlg,
GetDlgItem(hDlg, IDC_CAREQUEST_CA_BROWSE),
GetDlgItem(hDlg, IDC_CAREQUEST_COMPUTERNAME),
GetDlgItem(hDlg, IDC_CAREQUEST_CANAME),
csiIsAnyDSCAAvailable(),
&pServer->fCAsExist);
_JumpIfError(hr, error, "myInitUICASelectionControls");
}
hr = S_OK;
error:
return hr;
}
HRESULT
HandleCARequestWizActive(
HWND hDlg,
PAGESTRINGS *pPageString,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CRYPTUI_CA_CONTEXT const *pCAContext = NULL;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
BOOL fMatchAll = IsEverythingMatched(pServer);
// Suppress this wizard page if
// we've already seen an error, or
// we are not installing the server, or
// we are not installing a subordinate, or
// the advanced page already selected a matching key and cert
if (!(IS_SERVER_INSTALL & pComp->dwInstallStatus) ||
IsRootCA(pServer->CAType) ||
fMatchAll)
{
// disable page
CSILOGDWORD(IDS_CAREQUEST_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
EnableCARequestControls(hDlg, pComp);
hr = StartCARequestPage(hDlg, pPageString, pServer);
_JumpIfError(hr, error, "StartCARequestPage");
done:
hr = S_OK;
error:
if (NULL != pCAContext)
{
CryptUIDlgFreeCAContext(pCAContext);
}
return hr;
}
HRESULT
ConvertEditControlFullFilePath(
HWND hEdtCtrl)
{
HRESULT hr;
WCHAR *pwszPath = NULL;
WCHAR wszFullPath[MAX_PATH];
WCHAR *pwszNotUsed;
DWORD dwSize = 0;
hr = myUIGetWindowText(hEdtCtrl, &pwszPath);
_JumpIfError(hr, error, "myUIGetWindowText");
if (NULL == pwszPath)
{
// empty path, done
goto done;
}
dwSize = GetFullPathName(pwszPath,
ARRAYSIZE(wszFullPath),
wszFullPath,
&pwszNotUsed);
CSASSERT(ARRAYSIZE(wszFullPath) > dwSize);
if (0 == dwSize)
{
hr = myHLastError();
_JumpError(hr, error, "GetFullPathName");
}
// get full path, set it back to edit control
SetWindowText(hEdtCtrl, wszFullPath);
done:
hr = S_OK;
error:
if (NULL != pwszPath)
{
LocalFree(pwszPath);
}
return hr;
}
HRESULT
HandleCARequestWizNextOrBack(
HWND hDlg,
PAGESTRINGS *pPageString,
PER_COMPONENT_DATA *pComp,
int iWizBN)
{
HRESULT hr;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
BOOL fDontNext = FALSE;
BOOL fValid;
if (pServer->fSaveRequestAsFile)
{
// convert request file to full path
hr = ConvertEditControlFullFilePath(
GetDlgItem(hDlg, IDC_CAREQUEST_FILE));
_JumpIfError(hr, error, "ConvertEditControlFullFilePath");
CSASSERT(pServer->pwszSanitizedName);
CSASSERT(pServer->pwszKeyContainerName);
hr = mySetCertRegStrValue(
pServer->pwszSanitizedName,
NULL,
NULL,
wszREGREQUESTKEYCONTAINER,
pServer->pwszKeyContainerName);
_JumpIfErrorStr(hr, error, "mySetCertRegStrValue", wszREGREQUESTKEYCONTAINER);
}
hr = FinishWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "FinishWizardPageEditControls");
if (PSN_WIZBACK == iWizBN)
{
goto done;
}
if (!pServer->fSaveRequestAsFile && NULL==pServer->pccExistingCert)
{
// online case
hr = myUICASelectionValidation(&g_CARequestUICASelection, &fValid);
_JumpIfError(hr, error, "myUICASelectionValidation");
if (!fValid)
{
fDontNext = TRUE;
goto done;
}
}
hr = WizardPageValidation(pComp->hInstance, pComp->fUnattended,
hDlg, pPageString);
if (S_OK != hr)
{
fDontNext = TRUE;
goto done;
}
if (pServer->fSaveRequestAsFile)
{
// validate dir path existance of the request file
WCHAR *pwszLastSlash = wcsrchr(pServer->pwszRequestFile, L'\\');
CSASSERT(NULL != pwszLastSlash);
if (NULL != pwszLastSlash)
{
// make request file path into a dir path
pwszLastSlash[0] = L'\0';
if (DE_DIREXISTS != DirExists(pServer->pwszRequestFile) ||
L'\0' == pwszLastSlash[1])
{
// bring request file path back
pwszLastSlash[0] = L'\\';
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_CAREQUEST_REQUESTFILEPATH_MUSTEXIST,
0,
pServer->pwszRequestFile);
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_CAREQUEST_FILE), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
// bring request file path back
pwszLastSlash[0] = L'\\';
}
// Fail if a directory with the same name already exists
if(DE_DIREXISTS == DirExists(pServer->pwszRequestFile))
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_CAREQUEST_REQUESTFILEPATH_DIREXISTS,
0,
pServer->pwszRequestFile);
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_CAREQUEST_FILE), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
}
hr = StartAndStopService(pComp->hInstance,
pComp->fUnattended,
hDlg,
wszW3SVCNAME,
TRUE,
TRUE,
IDS_STOP_W3SVC,
&g_fW3SvcRunning);
if (S_OK != hr)
{
if (E_ABORT == hr)
{
fDontNext = TRUE;
goto done;
}
_JumpError(hr, error, "StartAndStopService");
}
done:
if (fDontNext)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // forbid
}
else
{
pServer->LastWiz = ENUM_WIZ_REQUEST;
}
hr = S_OK;
error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizCARequestPageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for CA Request wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizCARequestPageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PAGESTRINGS *pPageString;
PER_COMPONENT_DATA *pComp = NULL;
static BOOL s_fComputerChange = FALSE;
// keep the following in local scope
static PAGESTRINGS saCARequestSubmit[] =
{
{
IDC_CAREQUEST_COMPUTERNAME,
IDS_LOG_COMPUTER,
IDS_COMPUTERNULLSTRERR,
IDS_COMPUTERLENSTRERR,
MAX_PATH,
NULL,
},
{
IDC_CAREQUEST_CANAME,
IDS_LOG_CANAME,
IDS_CANULLSTRERR,
IDS_CALENSTRERR,
cchCOMMONNAMEMAX,
NULL,
},
// add more code in HookCARequestPageStrings if you add
{
0,
0,
0,
0,
0,
NULL
}
};
static PAGESTRINGS saCARequestFile[] =
{
{
IDC_CAREQUEST_FILE,
IDS_LOG_REQUESTFILE,
IDS_REQUESTFILENULLSTRERR,
IDS_REQUESTFILELENSTRERR,
MAX_PATH,
NULL,
},
// add more code in HookCARequestPageStrings if you add
{
0,
0,
0,
0,
0,
NULL,
}
};
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitCARequestWizControls(hDlg,
saCARequestSubmit,
saCARequestFile,
pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CAREQUEST_SAVETOFILE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->fSaveRequestAsFile = TRUE;
pComp->hrContinue = EnableCARequestControls(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CAREQUEST_SUBMITTOCA:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->CA.pServer->fSaveRequestAsFile = FALSE;
pComp->hrContinue = EnableCARequestControls(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CAREQUEST_CA_BROWSE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = myUICAHandleCABrowseButton(
&g_CARequestUICASelection,
csiIsAnyDSCAAvailable(),
IDS_CA_PICKER_TITLE,
IDS_CA_PICKER_PROMPT,
NULL);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CAREQUEST_FILE_BROWSE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = GetRequestFileName(hDlg, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CAREQUEST_CANAME:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = myUICAHandleCAListDropdown(
(int)HIWORD(wParam), // notification
&g_CARequestUICASelection,
&s_fComputerChange);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CAREQUEST_COMPUTERNAME:
switch ((int)HIWORD(wParam))
{
case EN_CHANGE: // edit changed
s_fComputerChange = TRUE;
break;
}
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_CAREQUEST_TITLE, dwWIZACTIVE);
pComp = _GetCompDataOrReturn(pComp, hDlg);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleCARequestWizActive(hDlg,
saCARequestFile, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_CAREQUEST_TITLE, dwWIZBACK);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pPageString = saCARequestSubmit;
if (pComp->CA.pServer->fSaveRequestAsFile)
{
pPageString = saCARequestFile;
}
pComp->hrContinue = HandleCARequestWizNextOrBack(hDlg,
pPageString, pComp, PSN_WIZBACK);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_CAREQUEST_TITLE, dwWIZNEXT);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pPageString = saCARequestSubmit;
if (pComp->CA.pServer->fSaveRequestAsFile)
{
pPageString = saCARequestFile;
}
pComp->hrContinue = HandleCARequestWizNextOrBack(hDlg,
pPageString, pComp, PSN_WIZNEXT);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
HRESULT
HookClientPageStrings(
PAGESTRINGS *pPageString,
CAWEBCLIENTSETUPINFO *pClient)
{
HRESULT hr;
for ( ; 0 != pPageString->idControl; pPageString++)
{
switch (pPageString->idControl)
{
case IDC_CLIENT_COMPUTERNAME:
pPageString->ppwszString = &(pClient->pwszWebCAMachine);
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error");
break;
}
}
hr = S_OK;
error:
return hr;
}
CERTSRVUICASELECTION g_WebClientUICASelection =
{ NULL, NULL, NULL, NULL, NULL, ENUM_UNKNOWN_CA, true, false };
HRESULT
InitClientWizControls(
HWND hDlg,
PAGESTRINGS *pPageString,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
BOOL fCAsExist;
CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
hr = HookClientPageStrings(pPageString, pClient);
_JumpIfError(hr, error, "HookClientPageStrings");
hr = WizPageSetTextLimits(hDlg, pPageString);
_JumpIfError(hr, error, "WizPageSetTextLimits");
pClient->fUseDS = FALSE;
if (IsDSAvailable(NULL))
{
pClient->fUseDS = csiIsAnyDSCAAvailable();
}
hr = myInitUICASelectionControls(
&g_WebClientUICASelection,
pComp->hInstance,
hDlg,
GetDlgItem(hDlg, IDC_CLIENT_BROWSECNFG),
GetDlgItem(hDlg, IDC_CLIENT_COMPUTERNAME),
GetDlgItem(hDlg, IDC_CLIENT_CANAME),
pClient->fUseDS,
&fCAsExist);
_JumpIfError(hr, error, "myInitUICASelectionControls");
hr = S_OK;
error:
return hr;
}
HRESULT
GetCAConfigInfo(
PER_COMPONENT_DATA *pComp)
{
HRESULT hr = S_OK;
CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
// free old shared folder always
if (NULL != pClient->pwszSharedFolder)
{
// free old
LocalFree(pClient->pwszSharedFolder);
pClient->pwszSharedFolder = NULL;
}
hr = myUICAHandleCABrowseButton(
&g_WebClientUICASelection,
pClient->fUseDS,
IDS_CONFIG_PICKER_TITLE,
IDS_CONFIG_PICKER_PROMPT,
&pClient->pwszSharedFolder);
_JumpIfError(hr, error, "myUICAHandleCABrowseButton");
error:
return hr;
}
HRESULT
HandleClientWizNextOrBack(
HWND hDlg,
PAGESTRINGS *pPageString,
PER_COMPONENT_DATA *pComp,
int iWizBN)
{
HRESULT hr;
CAWEBCLIENTSETUPINFO *pClient = pComp->CA.pClient;
BOOL fDontNext = FALSE;
WCHAR *pwszCAName = NULL;
WCHAR *pwszSanitizedCAName;
BOOL fValid;
BOOL fCoInit = FALSE;
hr = FinishWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "FinishWizardPageEditControls");
if (PSN_WIZBACK == iWizBN)
{
goto done;
}
hr = myUICASelectionValidation(&g_WebClientUICASelection, &fValid);
_JumpIfError(hr, error, "myUICASelectionValidation");
if (!fValid)
{
fDontNext = TRUE;
goto done;
}
// at this point, g_WebClientUICASelection.CAType is guaranteed to be filled in
hr = WizardPageValidation(pComp->hInstance, pComp->fUnattended,
hDlg, pPageString);
if (S_OK != hr)
{
fDontNext = TRUE;
goto done;
}
hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_CLIENT_CANAME), &pwszCAName);
_JumpIfError(hr, error, "myUIGetWindowText");
CSASSERT(NULL != pwszCAName);
if (NULL != pClient->pwszWebCAName)
{
// free old one
LocalFree(pClient->pwszWebCAName);
}
pClient->pwszWebCAName = pwszCAName;
pwszCAName = NULL;
hr = mySanitizeName(pClient->pwszWebCAName, &pwszSanitizedCAName);
_JumpIfError(hr, error, "mySanitizeName");
if (NULL != pClient->pwszSanitizedWebCAName)
{
// free old one
LocalFree(pClient->pwszSanitizedWebCAName);
}
pClient->pwszSanitizedWebCAName = pwszSanitizedCAName;
// pClient->WebCAType = pCAInfo->CAType;
pClient->WebCAType = g_WebClientUICASelection.CAType;
hr = StartAndStopService(pComp->hInstance,
pComp->fUnattended,
hDlg,
wszW3SVCNAME,
TRUE,
TRUE,
IDS_STOP_W3SVC,
&g_fW3SvcRunning);
if (S_OK != hr)
{
if (E_ABORT == hr)
{
fDontNext = TRUE;
goto done;
}
_JumpError(hr, error, "StartAndStopService");
}
done:
hr = S_OK;
error:
if (fCoInit)
{
CoUninitialize();
}
if (fDontNext)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // forbid
}
if (NULL != pwszCAName)
{
LocalFree(pwszCAName);
}
// if (NULL != pCAInfo)
{
// LocalFree(pCAInfo);
}
return hr;
}
HRESULT
HandleClientWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp,
PAGESTRINGS *pPageString)
{
HRESULT hr;
// Suppress this wizard page if
// we've already seen an error, or
// the server is or will be installed, or
// the client isn't or won't be installed, or
// ther will be no change in client and server install states.
if ((IS_SERVER_ENABLED & pComp->dwInstallStatus) ||
!(IS_CLIENT_ENABLED & pComp->dwInstallStatus) ||
!((IS_CLIENT_CHANGE | IS_SERVER_CHANGE) & pComp->dwInstallStatus))
{
// disable page
CSILOGDWORD(IDS_CLIENT_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
// load id info
hr = StartWizardPageEditControls(hDlg, pPageString);
_JumpIfError(hr, error, "StartWizardPageEditControls");
done:
hr = S_OK;
error:
return hr;
}
//+------------------------------------------------------------------------
// Function: WizClientPageDlgProc(. . . .)
//
// Synopsis: Dialog procedure for CA Client wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizClientPageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
static BOOL s_fComputerChange = FALSE;
static PAGESTRINGS saClientPageString[] =
{
{
IDC_CLIENT_COMPUTERNAME,
IDS_LOG_COMPUTER,
IDS_CLIENT_NOCOMPUTER,
IDS_COMPUTERLENSTRERR,
MAX_PATH,
NULL,
},
// you need to add code in HookClientPageStrings if adding more...
{
0,
0,
0,
0,
0,
NULL
}
};
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitClientWizControls(hDlg,
saClientPageString, pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_CLIENT_BROWSECNFG:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = GetCAConfigInfo(pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CLIENT_CANAME:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = myUICAHandleCAListDropdown(
(int)HIWORD(wParam),
&g_WebClientUICASelection,
&s_fComputerChange);
_ReturnIfWizError(pComp->hrContinue);
break;
case IDC_CLIENT_COMPUTERNAME:
switch ((int)HIWORD(wParam))
{
case EN_CHANGE: // edit change
s_fComputerChange = TRUE;
break;
}
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_CLIENT_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleClientWizActive(hDlg, pComp, saClientPageString);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_CLIENT_TITLE, dwWIZBACK);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
// enable back
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 0);
pComp->hrContinue = HandleClientWizNextOrBack(hDlg,
saClientPageString, pComp, PSN_WIZBACK);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_CLIENT_TITLE, dwWIZNEXT);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleClientWizNextOrBack(hDlg,
saClientPageString, pComp, PSN_WIZNEXT);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
static CFont s_cBigBoldFont;
static BOOL s_fBigBoldFont;
BOOL ocmWiz97SetupFonts(HWND hwnd)
{
BOOL bReturn = FALSE;
//
// Create the fonts we need based on the dialog font
//
NONCLIENTMETRICS ncm = {0};
ncm.cbSize = sizeof (ncm);
SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
LOGFONT BigBoldLogFont = ncm.lfMessageFont;
//
// Create Big Bold Font and Bold Font
//
BigBoldLogFont.lfWeight = FW_BOLD;
WCHAR largeFontSizeString[24];
INT largeFontSize;
//
// Load size and name from resources, since these may change
// from locale to locale based on the size of the system font, etc.
//
if ( !::LoadString (g_hInstance, IDS_LARGEFONTNAME,
BigBoldLogFont.lfFaceName, LF_FACESIZE) )
{
CSASSERT(CSExpr(FALSE));
lstrcpy(BigBoldLogFont.lfFaceName, L"MS Shell Dlg");
}
if ( ::LoadStringW (g_hInstance, IDS_LARGEFONTSIZE,
largeFontSizeString, ARRAYSIZE(largeFontSizeString)) )
{
largeFontSize = wcstoul (largeFontSizeString, NULL, 10);
}
else
{
CSASSERT(CSExpr(FALSE));
largeFontSize = 12;
}
HDC hdc = GetDC(hwnd);
if (hdc)
{
BigBoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc, LOGPIXELSY) * largeFontSize / 72);
BOOL bBigBold = s_cBigBoldFont.CreateFontIndirect (&BigBoldLogFont);
ReleaseDC(hwnd, hdc);
if ( bBigBold )
bReturn = TRUE;
}
return bReturn;
}
HFONT ocmWiz97GetBigBoldFont(HWND hwnd)
{
if (FALSE == s_fBigBoldFont)
{
if (!ocmWiz97SetupFonts(hwnd))
return NULL;
s_fBigBoldFont = TRUE;
}
return s_cBigBoldFont;
}
//+------------------------------------------------------------------------
// Function: WizWelcomePageDlgProc(. . . .)
//
// Synopsis: Dialog procedure welcome wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizWelcomePageDlgProc(
HWND hDlg,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
HFONT hf;
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)((PROPSHEETPAGE*)lParam)->lParam;
// set wizard 97 fonts
hf = ocmWiz97GetBigBoldFont(hDlg);
if (NULL != hf)
SendMessage(GetDlgItem(hDlg, IDC_TEXT_BIGBOLD), WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE, 0));
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_SETACTIVE:
// disable back button
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
//+------------------------------------------------------------------------
// Function: WizFinalPageDlgProc(. . . .)
//
// Synopsis: Dialog procedure final wiz-page
//-------------------------------------------------------------------------
INT_PTR
WizFinalPageDlgProc(
HWND hDlg,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
HFONT hf;
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)((PROPSHEETPAGE*)lParam)->lParam;
hf = ocmWiz97GetBigBoldFont(hDlg);
if (NULL != hf)
SendMessage(GetDlgItem(hDlg,IDC_TEXT_BIGBOLD), WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE, 0));
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_SETACTIVE:
// enable finish button
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
pComp = _GetCompDataOrReturn(pComp, hDlg);
// always display final wiz page
if (S_OK != pComp->hrContinue)
{
WCHAR *pwszFail = NULL;
HRESULT hr2 = myLoadRCString(
pComp->hInstance,
IDS_FINAL_ERROR_TEXT,
&pwszFail);
if (S_OK == hr2)
{
SetWindowText(GetDlgItem(hDlg, IDC_FINAL_STATUS),
pwszFail);
LocalFree(pwszFail);
}
else
{
// well, use hard code string
SetWindowText(GetDlgItem(hDlg, IDC_FINAL_STATUS),
L"Certificate Services Installation failed");
_PrintError(hr2, "myLoadRCString");
}
}
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
// Map table for dialog template resource IDs and dialog proc pointers
WIZPAGERESENTRY aWizPageResources[] =
{
IDD_WIZCATYPEPAGE, WizCATypePageDlgProc,
IDS_CATYPE_TITLE, IDS_CATYPE_SUBTITLE,
IDD_WIZADVANCEDPAGE, WizAdvancedPageDlgProc,
IDS_ADVANCE_TITLE, IDS_ADVANCE_SUBTITLE,
IDD_WIZIDINFOPAGE, WizIdInfoPageDlgProc,
IDS_IDINFO_TITLE, IDS_IDINFO_SUBTITLE,
IDD_WIZKEYGENPAGE, WizKeyGenPageDlgProc,
IDS_KEYGEN_TITLE, IDS_KEYGEN_SUBTITLE,
IDD_WIZSTOREPAGE, WizStorePageDlgProc,
IDS_STORE_TITLE, IDS_STORE_SUBTITLE,
IDD_WIZCAREQUESTPAGE, WizCARequestPageDlgProc,
IDS_CAREQUEST_TITLE, IDS_CAREQUEST_SUBTITLE,
IDD_WIZCLIENTPAGE, WizClientPageDlgProc,
IDS_CLIENT_TITLE, IDS_CLIENT_SUBTITLE,
};
#define NUM_SERVERWIZPAGES sizeof(aWizPageResources)/sizeof(WIZPAGERESENTRY)
HRESULT
CreateCertsrvWizPage(
IN PER_COMPONENT_DATA *pComp,
IN int idTitle,
IN int idSubTitle,
IN int idDlgResource,
IN DLGPROC fnDlgProc,
IN BOOL fWelcomeFinal,
OUT HPROPSHEETPAGE *phPage)
{
HRESULT hr;
PROPSHEETPAGE Page;
WCHAR *pwszTitle = NULL;
WCHAR *pwszSubTitle = NULL;
// init
ZeroMemory(&Page, sizeof(PROPSHEETPAGE));
// construct page info
// Set titles
Page.dwFlags = PSP_DEFAULT | PSP_HASHELP;
if (fWelcomeFinal)
Page.dwFlags |= PSP_HIDEHEADER;
if (-1 != idTitle)
{
hr = myLoadRCString(pComp->hInstance,
idTitle,
&pwszTitle);
_JumpIfError(hr, error, "Internal Error");
Page.pszHeaderTitle = pwszTitle;
Page.dwFlags |= PSP_USEHEADERTITLE;
}
if (-1 != idSubTitle)
{
hr = myLoadRCString(pComp->hInstance,
idSubTitle,
&pwszSubTitle);
_JumpIfError(hr, error, "Internal Error");
Page.pszHeaderSubTitle = pwszSubTitle;
Page.dwFlags |= PSP_USEHEADERSUBTITLE;
}
// Set the basic property sheet data
Page.dwSize = sizeof(PROPSHEETPAGE); // + sizeof(MYWIZPAGE);
// Set up module and resource dependent data
Page.hInstance = pComp->hInstance;
Page.pszTemplate = MAKEINTRESOURCE(idDlgResource);
Page.pfnDlgProc = fnDlgProc;
Page.pfnCallback = NULL;
Page.pcRefParent = NULL;
Page.pszIcon = NULL;
Page.pszTitle = NULL;
Page.lParam = (LPARAM)pComp; // pass this to wizpage handlers
// Create the page
*phPage = CreatePropertySheetPage(&Page);
_JumpIfOutOfMemory(hr, error, *phPage);
hr = S_OK;
error:
if (NULL != pwszTitle)
{
LocalFree(pwszTitle);
}
if (NULL != pwszSubTitle)
{
LocalFree(pwszSubTitle);
}
return hr;
}
//+------------------------------------------------------------------------
//
// Function: DoPageRequest(. . . .)
//
// Synopsis: Handler for the OC_REQUEST_PAGES notification.
//
// Effects: Ponies up the pages for the OCM driven wizard to display.
//
// Arguments: [ComponentId] ID String for the component.
// [WhichOnes] Type specifier for requested pages.
// [SetupPages] Structure to receive page handles.
//
// Returns: DWORD count of pages returned or -1 (MAXDWORD) in case of
// failure; in this case SetLastError() will provide extended
// error information.
//
// History: 04/16/97 JerryK Unmangled
// 08/97 XTan major structure change
//
//-------------------------------------------------------------------------
DWORD
DoPageRequest(
IN PER_COMPONENT_DATA *pComp,
IN WIZPAGERESENTRY *pWizPageResources,
IN DWORD dwWizPageNum,
IN WizardPagesType WhichOnes,
IN OUT PSETUP_REQUEST_PAGES SetupPages)
{
DWORD dwPageNum = MAXDWORD;
HRESULT hr;
DWORD i;
if (pComp->fUnattended)
{
// don't create wiz page if unattended
return 0;
}
// handle welcome page
if (pComp->fPostBase && WizPagesWelcome == WhichOnes)
{
if (1 > SetupPages->MaxPages)
{
// ask ocm allocate enough pages
return 1; // only welcome, 1 page
}
hr = CreateCertsrvWizPage(
pComp,
IDS_WELCOME_TITLE, // title,
-1, // no sub-title
IDD_WIZWELCOMEPAGE,
WizWelcomePageDlgProc,
TRUE,
&SetupPages->Pages[0]);
_JumpIfError(hr, error, "CreateCertsrvWizPage");
return 1; // create 1 page
}
// handle final page
if (pComp->fPostBase && WizPagesFinal == WhichOnes)
{
if (1 > SetupPages->MaxPages)
{
// ask ocm allocate enough pages
return 1; // only final, 1 page
}
hr = CreateCertsrvWizPage(
pComp,
IDS_FINAL_TITLE, // title,
-1, // no sub-title
IDD_WIZFINALPAGE,
WizFinalPageDlgProc,
TRUE,
&SetupPages->Pages[0]);
_JumpIfError(hr, error, "CreateCertsrvWizPage");
return 1; // create 1 page
}
// from now on, we should only handle post net wiz pages
if (WizPagesPostnet != WhichOnes)
{
// ignore all others except postnet pages
return 0;
}
if (dwWizPageNum > SetupPages->MaxPages)
{
// OCM didn't allocate enough for pages, return # and ask more
return dwWizPageNum;
}
// Create the property sheet pages for the wizard
for (i = 0; i < dwWizPageNum; i++)
{
hr = CreateCertsrvWizPage(
pComp,
pWizPageResources[i].idTitle, // title,
pWizPageResources[i].idSubTitle, // sub-title
pWizPageResources[i].idResource,
pWizPageResources[i].fnDlgProc,
FALSE,
&SetupPages->Pages[i]);
_JumpIfError(hr, error, "CreateCertsrvWizPage");
}
dwPageNum = dwWizPageNum;
error:
return dwPageNum;
}
DWORD
myDoPageRequest(
IN PER_COMPONENT_DATA *pComp,
IN WizardPagesType WhichOnes,
IN OUT PSETUP_REQUEST_PAGES SetupPages)
{
pComp->CA.pServer->LastWiz = ENUM_WIZ_UNKNOWN;
return DoPageRequest(pComp,
aWizPageResources,
NUM_SERVERWIZPAGES,
WhichOnes,
SetupPages);
}
//+-------------------------------------------------------------------------
//
// Function: DirExists()
//
// Synopsis: Determines whether or not a directory already exists.
//
// Arguments: [pszTestFileName] -- Name of directory to test for.
//
// Returns: FALSE -- Directory doesn't exist
// DE_DIREXISTS -- Directory exists
// DE_NAMEINUSE -- Name in use by non-directory entity
//
// History: 10/23/96 JerryK Created
//
//--------------------------------------------------------------------------
int
DirExists(LPTSTR pszTestFileName)
{
DWORD dwFileAttrs;
int nRetVal;
// Get file attributes
dwFileAttrs = GetFileAttributes(pszTestFileName);
if (0xFFFFFFFF == dwFileAttrs) // Error code from GetFileAttributes
{
nRetVal = FALSE; // Couldn't open file
}
else if (dwFileAttrs & FILE_ATTRIBUTE_DIRECTORY)
{
nRetVal = DE_DIREXISTS; // Directory already exists
}
else
{
nRetVal = DE_NAMEINUSE; // Name in use by non-directory entity
}
return nRetVal;
}
BOOL
IsEverythingMatched(CASERVERSETUPINFO *pServer)
{
return pServer->fAdvance &&
(NULL!=pServer->pwszKeyContainerName) &&
NULL!=pServer->pccExistingCert;
}
//====================================================================
//
// CA info code
//
//
//====================================================================
WNDPROC g_pfnValidityWndProcs;
WNDPROC g_pfnIdInfoWndProcs;
HRESULT
GetValidityEditCount(
HWND hDlg,
DWORD *pdwPeriodCount)
{
HRESULT hr;
WCHAR *pwszPeriodCount = NULL;
BOOL fValidDigitString;
// init to 0
*pdwPeriodCount = 0;
hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT),
&pwszPeriodCount);
_JumpIfError(hr, error, "myUIGetWindowText");
if (NULL != pwszPeriodCount)
{
*pdwPeriodCount = myWtoI(pwszPeriodCount, &fValidDigitString);
}
hr = S_OK;
error:
if (NULL != pwszPeriodCount)
{
LocalFree(pwszPeriodCount);
}
return hr;
}
HRESULT
UpdateExpirationDate(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
WCHAR *pwszExpiration = NULL;
hr = GetValidityEditCount(hDlg, &pServer->dwValidityPeriodCount);
_JumpIfError(hr, error, "GetValidityEditCount");
if (0 < pServer->dwValidityPeriodCount)
{
if(!pServer->pccExistingCert)
{
GetSystemTimeAsFileTime(&pServer->NotBefore);
pServer->NotAfter = pServer->NotBefore;
myMakeExprDateTime(
&pServer->NotAfter,
pServer->dwValidityPeriodCount,
pServer->enumValidityPeriod);
}
hr = myGMTFileTimeToWszLocalTime(
&pServer->NotAfter,
FALSE,
&pwszExpiration);
_JumpIfError(hr, error, "myGMTFileTimeToWszLocalTime");
if (!SetWindowText(GetDlgItem(hDlg, IDC_IDINFO_EXPIRATION),
pwszExpiration))
{
hr = myHLastError();
_JumpError(hr, error, "SetWindowText");
}
}
hr = S_OK;
error:
if (NULL != pwszExpiration)
{
LocalFree(pwszExpiration);
}
return hr;
}
HRESULT
AddValidityString(
IN HINSTANCE hInstance,
const HWND hList,
const int ids,
ENUM_PERIOD enumValidityPeriod)
{
HRESULT hr;
WCHAR *pwsz = NULL;
LRESULT nIndex;
hr = myLoadRCString(hInstance, ids, &pwsz);
_JumpIfError(hr, error, "myLoadRCString");
// add string
nIndex = (INT)SendMessage(hList, CB_ADDSTRING, (WPARAM)0, (LPARAM)pwsz);
if (CB_ERR == nIndex)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_ADDSTRING)");
}
// set data
nIndex = (INT)SendMessage(hList, CB_SETITEMDATA, (WPARAM)nIndex, (LPARAM)enumValidityPeriod);
if (CB_ERR == nIndex)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_ADDSTRING)");
}
hr = S_OK;
error:
if (NULL != pwsz)
{
LocalFree(pwsz);
}
return hr;
}
HRESULT
SelectValidityString(
PER_COMPONENT_DATA *pComp,
HWND hList,
ENUM_PERIOD enumValidityPeriod)
{
HRESULT hr;
WCHAR *pwsz = NULL;
LRESULT nIndex;
LRESULT lr;
int id;
switch (enumValidityPeriod)
{
case ENUM_PERIOD_YEARS:
id = IDS_VALIDITY_YEAR;
break;
case ENUM_PERIOD_MONTHS:
id = IDS_VALIDITY_MONTH;
break;
case ENUM_PERIOD_WEEKS:
id = IDS_VALIDITY_WEEK;
break;
case ENUM_PERIOD_DAYS:
id = IDS_VALIDITY_DAY;
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Invalid validity period enum");
break;
}
hr = myLoadRCString(pComp->hInstance, id, &pwsz);
_JumpIfError(hr, error, "myLoadRCString");
nIndex = (INT)SendMessage(hList, CB_FINDSTRING, (WPARAM)0, (LPARAM)pwsz);
if (CB_ERR == nIndex)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_FINDSTRING)");
}
lr = (INT)SendMessage(hList, CB_SETCURSEL, (WPARAM)nIndex, (LPARAM)0);
if (CB_ERR == lr)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_FINDSTRING)");
}
lr = (INT)SendMessage(hList, CB_GETITEMDATA, (WPARAM)nIndex, (LPARAM)0);
if (CB_ERR == lr)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "SendMessage(CB_FINDSTRING)");
}
pComp->CA.pServer->enumValidityPeriod = (ENUM_PERIOD)lr;
hr = S_OK;
error:
if (pwsz)
LocalFree(pwsz);
return hr;
}
HRESULT
DetermineKeyExistence(
CSP_INFO *pCSPInfo,
WCHAR *pwszKeyName)
{
HRESULT hr;
HCRYPTPROV hProv = NULL;
if (!myCertSrvCryptAcquireContext(
&hProv,
pwszKeyName,
pCSPInfo->pwszProvName,
pCSPInfo->dwProvType,
CRYPT_SILENT,
TRUE))
{
hr = myHLastError();
goto error;
}
hr = S_OK;
error:
if (NULL != hProv)
{
CryptReleaseContext(hProv, 0);
}
return hr;
}
LRESULT CALLBACK
ValidityEditFilterHook(
HWND hwnd,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
BOOL fUpdate = FALSE;
LRESULT lr;
CASERVERSETUPINFO *pServer = (CASERVERSETUPINFO*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch(iMsg)
{
case WM_CHAR:
fUpdate = TRUE;
if (!iswdigit((TCHAR) wParam))
{
if (VK_BACK != (int)wParam)
{
// ignore the key
MessageBeep(0xFFFFFFFF);
return 0;
}
}
break;
case WM_KEYDOWN:
if (VK_DELETE == (int)wParam)
{
// validity is changed
fUpdate = TRUE;
}
break;
}
lr = CallWindowProc(
g_pfnValidityWndProcs,
hwnd,
iMsg,
wParam,
lParam);
if (fUpdate)
{
UpdateExpirationDate(GetParent(hwnd), pServer);
}
return lr;
}
HRESULT MakeNullStringEmpty(LPWSTR *ppwszStr)
{
if(!*ppwszStr)
return myDupString(L"", ppwszStr);
return S_OK;
}
HRESULT
HideAndShowMachineDNControls(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
hr = MakeNullStringEmpty(&pServer->pwszFullCADN);
_JumpIfError(hr, error, "MakeNullStringEmpty");
hr = MakeNullStringEmpty(&pServer->pwszCACommonName);
_JumpIfError(hr, error, "MakeNullStringEmpty");
hr = MakeNullStringEmpty(&pServer->pwszDNSuffix);
_JumpIfError(hr, error, "MakeNullStringEmpty");
SetDlgItemText(hDlg, IDC_IDINFO_NAMEEDIT, pServer->pwszCACommonName);
SetDlgItemText(hDlg, IDC_IDINFO_DNSUFFIXEDIT, pServer->pwszDNSuffix);
SetDlgItemText(hDlg, IDC_IDINFO_NAMEPREVIEW, pServer->pwszFullCADN);
// name preview is never editable
// EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_NAMEPREVIEW), FALSE);
SendDlgItemMessage(hDlg, IDC_IDINFO_NAMEPREVIEW, EM_SETREADONLY, TRUE, 0);
// if we're in reuse cert mode, we can't edit the DNs
if (NULL != pServer->pccExistingCert)
{
// EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), FALSE);
// EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_DNSUFFIXEDIT), FALSE);
SendDlgItemMessage(hDlg, IDC_IDINFO_NAMEEDIT, EM_SETREADONLY, TRUE, 0);
SendDlgItemMessage(hDlg, IDC_IDINFO_DNSUFFIXEDIT, EM_SETREADONLY, TRUE, 0);
}
else
{
// set the defaults again
// and re-enable everything else
// EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), TRUE);
// EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_DNSUFFIXEDIT), TRUE);
SendDlgItemMessage(hDlg, IDC_IDINFO_NAMEEDIT, EM_SETREADONLY, FALSE, 0);
SendDlgItemMessage(hDlg, IDC_IDINFO_DNSUFFIXEDIT, EM_SETREADONLY, FALSE, 0);
// SendDlgItemMessage(hDlg, IDC_IDINFO_NAMEPREVIEW, EM_SETREADONLY, FALSE, 0);
}
hr = S_OK;
error:
return hr;
}
HRESULT InitNameFields(CASERVERSETUPINFO *pServer)
{
HRESULT hr = S_OK;
CAutoLPWSTR pwsz;
const WCHAR *pwszFirstDCComponent = L"";
if(pServer->pccExistingCert)
{
}
else
{
if(!pServer->pwszCACommonName)
{
// avoid null name
hr = myDupString(L"", &pServer->pwszCACommonName);
_JumpIfError(hr, error, "myDupString");
}
hr = myGetComputerObjectName(NameFullyQualifiedDN, &pwsz);
_PrintIfError(hr, "myGetComputerObjectName");
if (S_OK == hr && pwsz != NULL)
{
pwszFirstDCComponent = wcsstr(pwsz, L"DC=");
}
if(pServer->pwszDNSuffix)
{
LocalFree(pServer->pwszDNSuffix);
pServer->pwszDNSuffix = NULL;
}
if(!pwszFirstDCComponent)
{
pwszFirstDCComponent = L"";
}
hr = myDupString(pwszFirstDCComponent, &pServer->pwszDNSuffix);
_JumpIfError(hr, error, "myDupString");
if(pServer->pwszFullCADN)
{
LocalFree(pServer->pwszFullCADN);
pServer->pwszFullCADN = NULL;
}
hr = BuildFullDN(
pServer->pwszCACommonName,
pwszFirstDCComponent,
&pServer->pwszFullCADN);
_JumpIfError(hr, error, "BuildFullDN");
}
error:
return hr;
}
// Builds full DN "CN=CAName,DistinguishedName" where CAName and DistinguishedName
// could be empty or NULL;
HRESULT BuildFullDN(
OPTIONAL LPCWSTR pcwszCAName,
OPTIONAL LPCWSTR pcwszDNSuffix,
LPWSTR* ppwszFullDN)
{
HRESULT hr = S_OK;
DWORD cBytes = 4; // 4 chars for leading "CN=" plus null terminator
CSASSERT(ppwszFullDN);
if(!EmptyString(pcwszCAName))
cBytes += wcslen(pcwszCAName);
if(!EmptyString(pcwszDNSuffix))
cBytes += wcslen(pcwszDNSuffix)+1; // comma
cBytes *= sizeof(WCHAR);
*ppwszFullDN = (LPWSTR) LocalAlloc(LMEM_FIXED, cBytes);
_JumpIfAllocFailed(*ppwszFullDN, error);
wcscpy(*ppwszFullDN, L"CN=");
if(!EmptyString(pcwszCAName))
{
wcscat(*ppwszFullDN, pcwszCAName);
}
if(!EmptyString(pcwszDNSuffix))
{
wcscat(*ppwszFullDN, L",");
wcscat(*ppwszFullDN, pcwszDNSuffix);
}
error:
return hr;
}
HRESULT
EnableValidityControls(HWND hDlg, BOOL fEnabled)
{
EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_COMBO_VALIDITYSTRING), fEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT), fEnabled);
return S_OK;
}
HRESULT
HideAndShowValidityControls(
HWND hDlg,
ENUM_CATYPES CAType)
{
// default to root ca
int showValidity = SW_SHOW;
int showHelp = SW_HIDE;
BOOL fEnableLabel = TRUE;
if (IsSubordinateCA(CAType))
{
showValidity = SW_HIDE;
showHelp = SW_SHOW;
fEnableLabel = FALSE;
}
ShowWindow(GetDlgItem(hDlg, IDC_IDINFO_DETERMINEDBYPCA), showHelp);
ShowWindow(GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT), showValidity);
ShowWindow(GetDlgItem(hDlg, IDC_IDINFO_COMBO_VALIDITYSTRING), showValidity);
ShowWindow(GetDlgItem(hDlg, IDC_IDINFO_EXPIRATION_LABEL), showValidity);
ShowWindow(GetDlgItem(hDlg, IDC_IDINFO_EXPIRATION), showValidity);
EnableWindow(GetDlgItem(hDlg, IDC_IDINFO_VPLABEL), fEnableLabel);
return S_OK;
}
HRESULT
InitValidityControls(
HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
HWND hwndCtrl = GetDlgItem(hDlg, IDC_IDINFO_COMBO_VALIDITYSTRING);
WCHAR *pwsz = NULL;
// load validity help text
hr = myLoadRCString(pComp->hInstance, IDS_IDINFO_DETERMINEDBYPCA, &pwsz);
_JumpIfError(hr, error, "LoadString");
if (!SetWindowText(GetDlgItem(hDlg, IDC_IDINFO_DETERMINEDBYPCA), pwsz))
{
hr = myHLastError();
_JumpError(hr, error, "SetWindowText");
}
// load validity period strings
hr = AddValidityString(pComp->hInstance, hwndCtrl, IDS_VALIDITY_YEAR,
ENUM_PERIOD_YEARS);
_JumpIfError(hr, error, "AddValidityString");
hr = AddValidityString(pComp->hInstance, hwndCtrl, IDS_VALIDITY_MONTH,
ENUM_PERIOD_MONTHS);
_JumpIfError(hr, error, "AddValidityString");
hr = AddValidityString(pComp->hInstance, hwndCtrl, IDS_VALIDITY_WEEK,
ENUM_PERIOD_WEEKS);
_JumpIfError(hr, error, "AddValidityString");
hr = AddValidityString(pComp->hInstance, hwndCtrl, IDS_VALIDITY_DAY,
ENUM_PERIOD_DAYS);
_JumpIfError(hr, error, "AddValidityString");
hr = S_OK;
error:
if (NULL != pwsz)
{
LocalFree(pwsz);
}
return hr;
}
HRESULT
EnableMatchedCertIdInfoEditFields(HWND hDlg, BOOL fEnable)
{
HRESULT hr;
EnableValidityControls(hDlg, fEnable);
hr = S_OK;
//error:
return hr;
}
HRESULT
WizIdInfoPageSetHooks(HWND hDlg, PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
CSASSERT (NULL != pComp);
// CA Name filter proc
g_pfnIdInfoWndProcs =
(WNDPROC) SetWindowLongPtr(
GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT),
GWLP_WNDPROC,
(LPARAM)IdInfoNameEditFilterHook);
if (0 == g_pfnIdInfoWndProcs)
{
hr = myHLastError();
_JumpError(hr, error, "SetWindowLongPtr");
}
SetLastError(0);
if (0 == SetWindowLongPtr(
GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT),
GWLP_USERDATA,
(LPARAM)pComp->CA.pServer))
{
hr = myHLastError(); // might return S_OK
_JumpIfError(hr, error, "SetWindowLongPtr USERDATA");
}
hr = S_OK;
error:
return hr;
}
HRESULT
HandleValidityStringChange(
HWND hDlg,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
LRESULT nItem;
LRESULT lr;
HWND hwndCtrl = GetDlgItem(hDlg, IDC_IDINFO_COMBO_VALIDITYSTRING);
if (NULL == hwndCtrl)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal Error");
}
nItem = (INT)SendMessage(hwndCtrl, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
if (CB_ERR == nItem)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal Error");
}
lr = (INT)SendMessage(hwndCtrl, CB_GETITEMDATA, (WPARAM)nItem, (LPARAM)0);
if (CB_ERR == nItem)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal Error");
}
pServer->enumValidityPeriod = (ENUM_PERIOD)lr;
hr = UpdateExpirationDate(hDlg, pServer);
_JumpIfError(hr, error, "UpdateExpirationDate");
hr = S_OK;
error:
return hr;
}
HRESULT
HookIdInfoPageStrings(
PAGESTRINGS *pPageString,
CASERVERSETUPINFO *pServer)
{
HRESULT hr;
for ( ; 0 != pPageString->idControl; pPageString++)
{
switch (pPageString->idControl)
{
case IDC_IDINFO_NAMEEDIT:
pPageString->ppwszString = &(pServer->pwszCACommonName);
break;
case IDC_IDINFO_EDIT_VALIDITYCOUNT:
pPageString->ppwszString = &(pServer->pwszValidityPeriodCount);
break;
default:
hr = E_INVALIDARG;
_JumpError(hr, error, "Internal error");
break;
}
}
hr = S_OK;
error:
return hr;
}
HRESULT
InitIdInfoWizControls(
HWND hDlg,
PAGESTRINGS *pIdPageString,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr;
HWND hwndCtrl;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
// now make page strings complete
hr = HookIdInfoPageStrings(pIdPageString, pServer);
_JumpIfError(hr, error, "HookIdInfoPageStrings");
hr = WizPageSetTextLimits(hDlg, pIdPageString);
_JumpIfError(hr, error, "WizPageSetTextLimits");
hr = WizIdInfoPageSetHooks(hDlg, pComp);
_JumpIfError(hr, error, "WizIdInfoPageSetHooks");
hr = InitValidityControls(hDlg, pComp);
_JumpIfError(hr, error, "InitValidityControls");
if (!IsSubordinateCA(pServer->CAType))
{
hwndCtrl = GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT);
g_pfnValidityWndProcs = (WNDPROC)SetWindowLongPtr(hwndCtrl,
GWLP_WNDPROC, (LPARAM)ValidityEditFilterHook);
if (NULL == g_pfnValidityWndProcs)
{
hr = myHLastError();
_JumpError(hr, error, "SetWindowLongPtr");
}
// pass data
SetWindowLongPtr(hwndCtrl, GWLP_USERDATA, (ULONG_PTR)pServer);
}
hr = S_OK;
error:
return hr;
}
HRESULT
UpdateValidityMaxDigits(
BOOL fMatchAll,
PAGESTRINGS *pIdPageString)
{
HRESULT hr;
for (; 0 != pIdPageString; pIdPageString++)
{
if (IDC_IDINFO_EDIT_VALIDITYCOUNT == pIdPageString->idControl)
{
pIdPageString->cchMax = fMatchAll? UB_VALIDITY_ANY : UB_VALIDITY;
break;
}
}
hr = S_OK;
//error:
return hr;
}
HRESULT
HandleIdInfoWizActive(
HWND hDlg,
PER_COMPONENT_DATA *pComp,
PAGESTRINGS *pIdPageString)
{
HRESULT hr;
WCHAR wszValidity[cwcDWORDSPRINTF];
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
ENUM_PERIOD enumValidityPeriod = pServer->enumValidityPeriod;
BOOL fMatchAll;
// Suppress this wizard page if
// we've already seen an error, or
// we are not installing the server.
if (!(IS_SERVER_INSTALL & pComp->dwInstallStatus) )
{
// disable page
CSILOGDWORD(IDS_IDINFO_TITLE, dwWIZDISABLE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
goto done;
}
if (ENUM_WIZ_STORE == pServer->LastWiz)
{
// if back from ca request, reset
g_fAllowUnicodeStrEncoding = FALSE;
}
if (pServer->fAdvance &&
ENUM_WIZ_KEYGEN == pServer->LastWiz &&
(pServer->fKeyGenFailed || pServer->fValidatedHashAndKey) )
{
// key gen failed and go back
PropSheet_PressButton(GetParent(hDlg), PSBTN_BACK);
}
if (!pServer->fAdvance && ENUM_WIZ_CATYPE == pServer->LastWiz)
{
hr = LoadDefaultAdvanceAttributes(pServer);
_JumpIfError(hr, error, "LoadDefaultAdvanceAttributes");
}
hr = HideAndShowValidityControls(hDlg, pServer->CAType);
_JumpIfError(hr, error, "HideAndShowValidityControls");
hr = HideAndShowMachineDNControls(hDlg, pServer);
_JumpIfError(hr, error, "HideAndShowMachineDNControls");
// load id info
hr = StartWizardPageEditControls(hDlg, pIdPageString);
_JumpIfError(hr, error, "StartWizardPageEditControls");
hr = EnableMatchedCertIdInfoEditFields(hDlg, TRUE);
_JumpIfError(hr, error, "EnableMatchedCertIdInfoEditFields");
// default
wsprintf(wszValidity, L"%u", pServer->dwValidityPeriodCount);
fMatchAll = IsEverythingMatched(pServer);
if (fMatchAll)
{
enumValidityPeriod = ENUM_PERIOD_DAYS;
wsprintf(wszValidity, L"%u", pServer->lExistingValidity);
hr = EnableMatchedCertIdInfoEditFields(hDlg, FALSE);
_JumpIfError(hr, error, "EnableMatchedCertIdInfoEditFields");
}
// update validity period string
hr = SelectValidityString(
pComp,
GetDlgItem(hDlg, IDC_IDINFO_COMBO_VALIDITYSTRING),
enumValidityPeriod);
_JumpIfError(hr, error, "SelectValidityString");
// update validity
SetWindowText(GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT), wszValidity);
hr = UpdateExpirationDate(hDlg, pServer);
_JumpIfError(hr, error, "UpdateExpirationDate");
// update validity digits max for validation
hr = UpdateValidityMaxDigits(fMatchAll, pIdPageString);
_JumpIfError(hr, error, "UpdateValidityMaxDigits");
EnableValidityControls(hDlg, !IsSubordinateCA(pServer->CAType) && !fMatchAll);
done:
hr = S_OK;
error:
return hr;
}
// check server RDN info, warning any invalid or
// or confirm from users once if any unicode string encoding
BOOL
IsAnyInvalidRDN(
OPTIONAL HWND hDlg,
PER_COMPONENT_DATA *pComp)
{
HRESULT hr = S_OK;
BOOL fInvalidRDN = TRUE;
BYTE *pbEncodedName = NULL;
DWORD cbEncodedName;
CERT_NAME_INFO *pbDecodedNameInfo = NULL;
DWORD cbDecodedNameInfo;
CERT_NAME_INFO *pNameInfo = NULL;
DWORD *pIndexRDN = NULL;
DWORD *pIndexAttr = NULL;
DWORD dwUnicodeCount;
WCHAR *pwszAllStrings = NULL;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
DWORD indexRDN;
DWORD indexAttr;
LPCWSTR pszErrorPtr = NULL;
// don't bother calling with CERT_NAME_STR_REVERSE_FLAG, we're just throwing this encoding away
hr = myCertStrToName(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pServer->pwszDNSuffix,
CERT_X500_NAME_STR | CERT_NAME_STR_COMMA_FLAG,
NULL,
&pbEncodedName,
&cbEncodedName,
&pszErrorPtr);
if(S_OK != hr)
{
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_IDINFO_INVALIDDN,
0,
NULL);
int nStartIndex = 0;
int nEndIndex = wcslen(pServer->pwszDNSuffix);
if(pszErrorPtr)
{
nStartIndex = SAFE_SUBTRACT_POINTERS(pszErrorPtr,pServer->pwszDNSuffix);
const WCHAR *pwszNextComma = wcsstr(pszErrorPtr, L",");
if(pwszNextComma)
{
nEndIndex = SAFE_SUBTRACT_POINTERS(pwszNextComma,pServer->pwszDNSuffix+1);
}
}
SetEditFocusAndSelect(
GetDlgItem(hDlg, IDC_IDINFO_DNSUFFIXEDIT),
nStartIndex,
nEndIndex);
}
_JumpIfError(hr, error, "myCertStrToName");
LocalFree(pbEncodedName);
pbEncodedName = NULL;
hr = AddCNAndEncode(
pServer->pwszCACommonName,
pServer->pwszDNSuffix,
&pbEncodedName,
&cbEncodedName);
_JumpIfError(hr, error, "AddCNAndEncode");
// call CryptDecodeObject to get pbDecodedNameInfo
// if hit here, check if any unicode string encoding
if (!g_fAllowUnicodeStrEncoding && !pComp->fUnattended)
{
// decode to nameinfo
if (!myDecodeName(
X509_ASN_ENCODING,
X509_UNICODE_NAME,
pbEncodedName,
cbEncodedName,
CERTLIB_USE_LOCALALLOC,
&pbDecodedNameInfo,
&cbDecodedNameInfo))
{
hr = myHLastError();
_JumpError(hr, error, "myDecodeName");
}
// calculate attributes total in RDN
dwUnicodeCount = 0;
for (indexRDN = 0; indexRDN < pbDecodedNameInfo->cRDN; ++indexRDN)
{
dwUnicodeCount += pbDecodedNameInfo->rgRDN[indexRDN].cRDNAttr;
}
// allocate & init index
// sure allocate max for possible all unicode strings
pIndexRDN = (DWORD*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
dwUnicodeCount * sizeof(DWORD));
_JumpIfOutOfMemory(hr, error, pIndexRDN);
pIndexAttr = (DWORD*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
dwUnicodeCount * sizeof(DWORD));
_JumpIfOutOfMemory(hr, error, pIndexAttr);
dwUnicodeCount = 0; // reset count
for (indexRDN = 0; indexRDN < pbDecodedNameInfo->cRDN; ++indexRDN)
{
DWORD cRDNAttr = pbDecodedNameInfo->rgRDN[indexRDN].cRDNAttr;
CERT_RDN_ATTR *rgRDNAttr = pbDecodedNameInfo->rgRDN[indexRDN].rgRDNAttr;
// for each RDN
for (indexAttr = 0; indexAttr < cRDNAttr; indexAttr++)
{
// for each attr, check unicode string
switch (rgRDNAttr[indexAttr].dwValueType)
{
case CERT_RDN_UTF8_STRING:
case CERT_RDN_UNICODE_STRING:
// there is a unicode or UTF8 string, save index
pIndexRDN[dwUnicodeCount] = indexRDN;
pIndexAttr[dwUnicodeCount] = indexAttr;
// set count
++dwUnicodeCount;
break;
}
}
}
if (0 == dwUnicodeCount)
{
// no unicode string encoding
goto done;
}
// calculate size of all unicode strings for display
DWORD dwLen = 0;
for (indexAttr = 0; indexAttr < dwUnicodeCount; ++indexAttr)
{
dwLen += (wcslen((WCHAR*)pbDecodedNameInfo->rgRDN[pIndexRDN[indexAttr]].rgRDNAttr[pIndexAttr[indexAttr]].Value.pbData) + 3 ) * sizeof(WCHAR);
}
pwszAllStrings = (WCHAR*)LocalAlloc(LMEM_FIXED, dwLen);
_JumpIfOutOfMemory(hr, error, pwszAllStrings);
// form all strings for display
for (indexAttr = 0; indexAttr < dwUnicodeCount; ++indexAttr)
{
if (0 == indexAttr)
{
wcscpy(pwszAllStrings, (WCHAR*)
pbDecodedNameInfo->rgRDN[pIndexRDN[indexAttr]].rgRDNAttr[pIndexAttr[indexAttr]].Value.pbData);
}
else
{
wcscat(pwszAllStrings, (WCHAR*)
pbDecodedNameInfo->rgRDN[pIndexRDN[indexAttr]].rgRDNAttr[pIndexAttr[indexAttr]].Value.pbData);
}
if (dwUnicodeCount - 1 > indexAttr)
{
// add comma + new line
wcscat(pwszAllStrings, L",\n");
}
}
// ok, ready to put out a warning
if (IDYES == CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_UNICODESTRINGENCODING,
0,
MB_YESNO |
MB_ICONWARNING |
CMB_NOERRFROMSYS,
NULL)) //pwszAllStrings))
{
// warning only once
g_fAllowUnicodeStrEncoding = TRUE;
goto done;
}
goto error;
}
done:
fInvalidRDN = FALSE;
error:
if (NULL != pIndexRDN)
{
LocalFree(pIndexRDN);
}
if (NULL != pIndexAttr)
{
LocalFree(pIndexAttr);
}
if (NULL != pwszAllStrings)
{
LocalFree(pwszAllStrings);
}
if (NULL != pbEncodedName)
{
LocalFree(pbEncodedName);
}
if (NULL != pbDecodedNameInfo)
{
LocalFree(pbDecodedNameInfo);
}
if (NULL != pNameInfo)
{
csiFreeCertNameInfo(pNameInfo);
}
return fInvalidRDN;
}
/*HRESULT ExtractCommonName(LPCWSTR pcwszDN, LPWSTR* ppwszCN)
{
HRESULT hr = S_OK;
WCHAR* pszComma;
LPWSTR pwszDNUpperCase = NULL;
const WCHAR* pszCN = pcwszDN;
if(0!=_wcsnicmp(pcwszDN, L"CN=", wcslen(L"CN=")))
{
hr = E_INVALIDARG;
_JumpError(hr, error,
"distinguished name doesn't start with the common name");
}
pszCN += wcslen(L"CN=");
while(iswspace(*pszCN))
pszCN++;
pszComma = wcsstr(pszCN, L",");
DWORD iChars;
if (pszComma == NULL)
{
// ONLY CN= string, no additional names
iChars = wcslen(pszCN);
}
else
{
iChars = SAFE_SUBTRACT_POINTERS(pszComma, pszCN);
}
if(0==iChars)
{
hr = E_INVALIDARG;
_JumpError(hr, error,
"invalid syntax, common name should follow CN=");
}
*ppwszCN = (LPWSTR)LocalAlloc(LMEM_FIXED, (iChars+1)*sizeof(WCHAR));
_JumpIfAllocFailed(*ppwszCN, error);
CopyMemory(*ppwszCN, pszCN, iChars*sizeof(WCHAR));
(*ppwszCN)[iChars] = L'\0';
error:
LOCAL_FREE(pwszDNUpperCase);
return hr;
}*/
HRESULT
HandleIdInfoWizNextOrBack(
HWND hDlg,
PER_COMPONENT_DATA *pComp,
PAGESTRINGS *pIdPageString,
int iWizBN)
{
HRESULT hr;
WCHAR *pwszSanitizedName = NULL;
CASERVERSETUPINFO *pServer = pComp->CA.pServer;
BOOL fDontNext = FALSE;
BOOL fValidDigitString;
WCHAR * pwszFullPath = NULL;
WCHAR * pwszDir = NULL;
DWORD cDirLen;
hr = FinishWizardPageEditControls(hDlg, pIdPageString);
_JumpIfError(hr, error, "FinishWizardPageEditControls");
if (PSN_WIZBACK == iWizBN)
{
goto done;
}
hr = WizardPageValidation(pComp->hInstance, pComp->fUnattended,
hDlg, pIdPageString);
if (S_OK != hr)
{
_PrintError(hr, "WizardPageValidation");
fDontNext = TRUE;
goto done;
}
// snag the full DN specified
if (NULL != pServer->pwszCACommonName)
{
LocalFree(pServer->pwszCACommonName);
pServer->pwszCACommonName = NULL;
}
if (NULL != pServer->pwszFullCADN)
{
LocalFree(pServer->pwszFullCADN);
pServer->pwszFullCADN = NULL;
}
if (NULL != pServer->pwszDNSuffix)
{
LocalFree(pServer->pwszDNSuffix);
pServer->pwszDNSuffix = NULL;
}
myUIGetWindowText(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), &pServer->pwszCACommonName);
myUIGetWindowText(GetDlgItem(hDlg, IDC_IDINFO_NAMEPREVIEW), &pServer->pwszFullCADN);
myUIGetWindowText(GetDlgItem(hDlg, IDC_IDINFO_DNSUFFIXEDIT), &pServer->pwszDNSuffix);
// if generate a new cert
if (NULL == pServer->pccExistingCert &&
IsAnyInvalidRDN(hDlg, pComp))
{
fDontNext = TRUE;
goto done;
}
// if we are not using an existing cert, verify the chosen validity
// period of the new cert.
if (NULL==pServer->pccExistingCert)
{
// convert validity count string to a number
pServer->dwValidityPeriodCount = myWtoI(
pServer->pwszValidityPeriodCount,
&fValidDigitString);
if (!fValidDigitString ||
!IsValidPeriod(pServer))
{
// validity out of range, put out a warning dlg
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_IDINFO_INVALID_VALIDITY,
0,
NULL);
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_IDINFO_EDIT_VALIDITYCOUNT), 0, MAXDWORD);
_PrintError(E_INVALIDARG, "invalid validity");
fDontNext = TRUE;
goto done;
}
}
// get sanitized name
hr = mySanitizeName(pServer->pwszCACommonName, &pwszSanitizedName);
_JumpIfError(hr, error, "mySanitizeName");
CSILOG(
hr,
IDS_ILOG_SANITIZEDNAME,
pwszSanitizedName,
NULL,
NULL);
if (MAX_PATH <= wcslen(pwszSanitizedName) + cwcSUFFIXMAX)
{
CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_KEYNAMETOOLONG,
S_OK,
MB_ICONWARNING | CMB_NOERRFROMSYS,
pwszSanitizedName);
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
// if we are making a new key, see if a key by that name already exists.
// if it does, see if the user wants to overwrite it.
if (NULL == pServer->pwszKeyContainerName)
{
if (S_OK == DetermineKeyExistence(pServer->pCSPInfo, pwszSanitizedName))
{
// warn user if key exist
if (IDYES != CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_WRN_OVERWRITEEXISTINGKEY,
S_OK,
MB_YESNO |
MB_ICONWARNING |
MB_DEFBUTTON2 |
CMB_NOERRFROMSYS,
pServer->pwszCACommonName))
{
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
}
}
if (NULL != pServer->pwszSanitizedName)
{
// free old
LocalFree(pServer->pwszSanitizedName);
}
pServer->pwszSanitizedName = pwszSanitizedName;
pwszSanitizedName = NULL;
if (pServer->fUseDS)
{
if (IsCAExistInDS(pServer->pwszSanitizedName))
{
int ret = CertMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_IDINFO_CAEXISTINDS,
0,
MB_YESNO |
MB_ICONWARNING |
CMB_NOERRFROMSYS,
NULL);
if (IDYES != ret)
{
// not overwrite
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
else
{
hr = RemoveCAInDS(pServer->pwszSanitizedName);
if(hr != S_OK)
{
_PrintError(hr, "RemoveCAInDS");
SetEditFocusAndSelect(GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT), 0, MAXDWORD);
fDontNext = TRUE;
goto done;
}
}
}
}
hr = UpdateDomainAndUserName(hDlg, pComp);
_JumpIfError(hr, error, "UpdateDomainAndUserName");
if(pServer->fUseDS)
{
pServer->dwRevocationFlags = REVEXT_DEFAULT_DS;
}
else
{
pServer->dwRevocationFlags = REVEXT_DEFAULT_NODS;
}
// validate cert file path lenght
cDirLen = wcslen(pComp->pwszSystem32)+
wcslen(wszCERTENROLLSHAREPATH) + 1;
pwszDir = (WCHAR *) LocalAlloc(LMEM_FIXED, cDirLen * sizeof(WCHAR));
if (NULL == pwszDir)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
wcscpy(pwszDir, pComp->pwszSystem32); // has trailing "\\"
wcscat(pwszDir, wszCERTENROLLSHAREPATH);
hr = csiBuildFileName(
pwszDir,
pServer->pwszSanitizedName,
L".crt",
0,
&pwszFullPath,
pComp->hInstance,
pComp->fUnattended,
hDlg);
_JumpIfError(hr, error, "csiBuildFileName");
if (MAX_PATH <= wcslen(pwszFullPath) + cwcSUFFIXMAX)
{
// pop up warning
CertWarningMessageBox(
pComp->hInstance,
pComp->fUnattended,
hDlg,
IDS_PATH_TOO_LONG_CANAME,
S_OK,
pwszFullPath);
fDontNext = TRUE;
goto done;
}
done:
if (fDontNext)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); // forbid
}
else
{
pServer->LastWiz = ENUM_WIZ_IDINFO;
}
hr = S_OK;
error:
if (NULL != pwszSanitizedName)
{
LocalFree(pwszSanitizedName);
}
if(NULL != pwszFullPath)
{
LocalFree(pwszFullPath);
}
if(NULL != pwszDir)
{
LocalFree(pwszDir);
}
return hr;
}
PAGESTRINGS g_aIdPageString[] =
{
{
IDC_IDINFO_NAMEEDIT,
IDS_LOG_CANAME,
IDS_IDINFO_NAMENULLSTRERR,
IDS_IDINFO_NAMELENSTRERR,
cchCOMMONNAMEMAX,
NULL,
},
{
IDC_IDINFO_EDIT_VALIDITYCOUNT,
IDS_LOG_VALIDITY,
IDS_IDINFO_VALIDITYNULLSTRERR,
IDS_IDINFO_VALIDITYLENSTRERR,
UB_VALIDITY,
NULL,
},
// you need to add code in HookIdInfoPageStrings if adding more...
{
0,
0,
0,
0,
0,
NULL,
}
};
LRESULT CALLBACK
IdInfoNameEditFilterHook(
HWND hwnd,
UINT iMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (iMsg)
{
case WM_CHAR:
if ((WCHAR)wParam == L',')
{
MessageBeep(0xFFFFFFFF);
return(0);
}
break;
}
return(CallWindowProc(
g_pfnIdInfoWndProcs,
hwnd,
iMsg,
wParam,
lParam));
}
//-------------------------------------------------------------------------
// WizIdInfoPageDlgProc
//-------------------------------------------------------------------------
INT_PTR
WizIdInfoPageDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PER_COMPONENT_DATA *pComp = NULL;
switch(iMsg)
{
case WM_INITDIALOG:
// point to component data
SetWindowLongPtr(hDlg, DWLP_USER,
(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam);
pComp = (PER_COMPONENT_DATA*)(ULONG_PTR)((PROPSHEETPAGE*)lParam)->lParam;
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = InitIdInfoWizControls(hDlg,
g_aIdPageString,
pComp);
_ReturnIfWizError(pComp->hrContinue);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_IDINFO_NAMEEDIT:
case IDC_IDINFO_DNSUFFIXEDIT:
if (HIWORD(wParam) == EN_CHANGE)
{
CAutoLPWSTR pwszCAName, pwszDNSuffix, pwszFullDN;
CASERVERSETUPINFO* pServer;
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pServer = pComp->CA.pServer;
// if using existing certs ignore the notification
// to avoid building the full DN
if(pServer->pccExistingCert)
{
break;
}
pComp->hrContinue = myUIGetWindowText(
GetDlgItem(hDlg, IDC_IDINFO_NAMEEDIT),
&pwszCAName);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = myUIGetWindowText(
GetDlgItem(hDlg, IDC_IDINFO_DNSUFFIXEDIT),
&pwszDNSuffix);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = BuildFullDN(
pwszCAName,
pwszDNSuffix,
&pwszFullDN);
_ReturnIfWizError(pComp->hrContinue);
SetDlgItemText(
hDlg,
IDC_IDINFO_NAMEPREVIEW,
pwszFullDN);
}
break;
case IDC_IDINFO_EDIT_VALIDITYCOUNT:
break;
case IDC_IDINFO_COMBO_VALIDITYSTRING:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleValidityStringChange(
hDlg,
pComp->CA.pServer);
_ReturnIfWizError(pComp->hrContinue);
break;
}
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
break;
case PSN_RESET:
break;
case PSN_QUERYCANCEL:
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
return CertConfirmCancel(hDlg, pComp);
break;
case PSN_SETACTIVE:
CSILOGDWORD(IDS_IDINFO_TITLE, dwWIZACTIVE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
pComp = _GetCompDataOrReturn(pComp, hDlg);
_DisableWizDisplayIfError(pComp, hDlg);
_ReturnIfWizError(pComp->hrContinue);
pComp->hrContinue = HandleIdInfoWizActive(hDlg,
pComp,
g_aIdPageString);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZBACK:
CSILOGDWORD(IDS_IDINFO_TITLE, dwWIZBACK);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleIdInfoWizNextOrBack(
hDlg, pComp, g_aIdPageString, PSN_WIZBACK);
_ReturnIfWizError(pComp->hrContinue);
break;
case PSN_WIZNEXT:
CSILOGDWORD(IDS_IDINFO_TITLE, dwWIZNEXT);
pComp = _GetCompDataOrReturnIfError(pComp, hDlg);
pComp->hrContinue = HandleIdInfoWizNextOrBack(
hDlg, pComp, g_aIdPageString, PSN_WIZNEXT);
_ReturnIfWizError(pComp->hrContinue);
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
break;
default:
return DefaultPageDlgProc(hDlg, iMsg, wParam, lParam);
}
return TRUE;
}
//-------------------------------------------------------------------------
// DefaultPageDlgProc
//-------------------------------------------------------------------------
INT_PTR
DefaultPageDlgProc(
IN HWND /* hDlg */ ,
IN UINT iMsg,
IN WPARAM /* wParam */ ,
IN LPARAM lParam)
{
LPCWSTR pwszHelpExecute;
switch(iMsg)
{
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_HELP:
pwszHelpExecute = myLoadResourceString(IDS_HELP_EXECUTE);
if (NULL == (LPCWSTR)pwszHelpExecute)
{
return FALSE;
}
ShellExecute(
NULL,
TEXT("open"),
pwszHelpExecute,
NULL,
NULL,
SW_SHOW);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}