//+------------------------------------------------------------------------- // // Microsoft Windows NT // // Copyright (C) Microsoft Corporation, 1995 - 1998 // // File: cepsetup.cpp // // Contents: The setup code for MSCEP //-------------------------------------------------------------------------- #include "global.hxx" #include #include "objsel.h" #include "setuputil.h" #include "cepsetup.h" #include "resource.h" #include "wincred.h" #include "netlib.h" #include "dsrole.h" //----------------------------------------------------------------------- // // Global data // //----------------------------------------------------------------------- HMODULE g_hModule=NULL; UINT g_cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST); //----------------------------------------------------------------------- //CN has to be the 1st item and O the third in the following list and C is the last item. No other requirements for //the order //----------------------------------------------------------------------- CEP_ENROLL_INFO g_rgRAEnrollInfo[RA_INFO_COUNT]= {L"CN=", IDC_ENROLL_NAME, L"E=", IDC_ENROLL_EMAIL, L"O=", IDC_ENROLL_COMPANY, L"OU=", IDC_ENROLL_DEPARTMENT, L"L=", IDC_ENROLL_CITY, L"S=", IDC_ENROLL_STATE, L"C=", IDC_ENROLL_COUNTRY, }; //----------------------------------------------------------------------- //the key length table //----------------------------------------------------------------------- DWORD g_rgdwKeyLength[] = { 512, 1024, 2048, 4096, }; DWORD g_dwKeyLengthCount=sizeof(g_rgdwKeyLength)/sizeof(g_rgdwKeyLength[0]); DWORD g_rgdwSmallKeyLength[] = { 128, 256, 512, 1024, }; DWORD g_dwSmallKeyLengthCount=sizeof(g_rgdwSmallKeyLength)/sizeof(g_rgdwSmallKeyLength[0]); //the list of possible default key lenght in the order of preference DWORD g_rgdwDefaultKey[] = { 1024, 2048, 512, 256, 4096, 128 }; DWORD g_dwDefaultKeyCount=sizeof(g_rgdwDefaultKey)/sizeof(g_rgdwDefaultKey[0]); //----------------------------------------------------------------------- // //The winProc for each of the setup wizard page // //----------------------------------------------------------------------- //----------------------------------------------------------------------- //Welcome //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_Welcome(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBigBold, hwndDlg,IDC_BIG_BOLD_TITLE); break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //App_ID //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_App_ID(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBold, hwndDlg,IDC_BOLD_TITLE); //by default, we use local machine account SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO1), BM_SETCHECK, BST_CHECKED, 0); SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO2), BM_SETCHECK, BST_UNCHECKED, 0); break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDC_APP_ID_RADIO1: SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO1), BM_SETCHECK, BST_CHECKED, 0); SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO2), BM_SETCHECK, BST_UNCHECKED, 0); break; case IDC_APP_ID_RADIO2: SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO1), BM_SETCHECK, BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwndDlg, IDC_APP_ID_RADIO2), BM_SETCHECK, BST_CHECKED, 0); break; default: break; } } break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //check for the application identity options if(BST_CHECKED==SendDlgItemMessage(hwndDlg,IDC_APP_ID_RADIO1, BM_GETCHECK, 0, 0)) { pCEPWizardInfo->fLocalSystem=TRUE; //skip the account page and goes to the challege page directly SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_CHALLENGE); } else { pCEPWizardInfo->fLocalSystem=FALSE; } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //Account //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_Account(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; WCHAR wszText[MAX_STRING_SIZE]; int idsText=IDS_ACCOUNT_INTRO_STD; int idsErr=0; DWORD dwChar=0; DWORD dwDomainChar=0; DWORD dwWinStatus=0; WCHAR wszUser[CREDUI_MAX_USERNAME_LENGTH+1]; WCHAR wszDomain[CREDUI_MAX_USERNAME_LENGTH+1]; HRESULT hr=S_OK; int idsHrErr=0; BOOL fMember=FALSE; SID_NAME_USE SidName; PRIVILEGE_SET ps; DWORD dwPSSize=0; DWORD dwSize=0; BOOL fAccessAllowed = FALSE; DWORD grantAccess=0; GENERIC_MAPPING GenericMapping={ ACTRL_DS_OPEN | ACTRL_DS_LIST | ACTRL_DS_SELF | ACTRL_DS_READ_PROP, ACTRL_DS_CREATE_CHILD | ACTRL_DS_DELETE_CHILD | ACTRL_DS_WRITE_PROP | ACTRL_DS_DELETE_TREE, ACTRL_DS_CREATE_CHILD | ACTRL_DS_DELETE_CHILD | ACTRL_DS_WRITE_PROP | ACTRL_DS_DELETE_TREE, ACTRL_DS_OPEN | ACTRL_DS_LIST | ACTRL_DS_SELF | ACTRL_DS_READ_PROP | ACTRL_DS_CREATE_CHILD | ACTRL_DS_DELETE_CHILD | ACTRL_DS_WRITE_PROP | ACTRL_DS_DELETE_TREE, }; LPWSTR pwszObjectPicker=NULL; LPWSTR pwszConfirm=NULL; LPWSTR pwszAccount=NULL; LPWSTR pwszIIS=NULL; //"xiaohs4\IIS_WPG" LPWSTR pwszDomain=NULL; LPWSTR pwszComputerName=NULL; PSID pSidIIS=NULL; HCERTTYPE hCertType=NULL; PSECURITY_DESCRIPTOR pCertTypeSD=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBold, hwndDlg,IDC_BOLD_TITLE); //update the intro statement based on the type of the CA if(pCEPWizardInfo->fEnterpriseCA) idsText=IDS_ACCOUNT_INTRO_ENT; if(LoadStringU(g_hModule, idsText, wszText, MAX_STRING_SIZE)) { SetDlgItemTextU(hwndDlg, IDC_ACCOUNT_INTRO, wszText); } break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { //user wants to browse for the account name if(LOWORD(wParam) == IDC_ACCOUNT_BROWSE) { if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; if(CEPGetAccountNameFromPicker(hwndDlg, pCEPWizardInfo->pIDsObjectPicker, &pwszObjectPicker)) { //set the account name in the edit box SetDlgItemTextU(hwndDlg, IDC_ACCOUNT_NAME, pwszObjectPicker); free(pwszObjectPicker); } } } break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //free the information if(pCEPWizardInfo->pwszUserName) { free(pCEPWizardInfo->pwszUserName); pCEPWizardInfo->pwszUserName=NULL; } if(pCEPWizardInfo->pwszPassword) { SecureZeroMemory(pCEPWizardInfo->pwszPassword, sizeof(WCHAR) * wcslen(pCEPWizardInfo->pwszPassword)); free(pCEPWizardInfo->pwszPassword); pCEPWizardInfo->pwszPassword=NULL; } if(pCEPWizardInfo->hAccountToken) { CloseHandle(pCEPWizardInfo->hAccountToken); pCEPWizardInfo->hAccountToken=NULL; } //get the account name if(0==(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_ACCOUNT_NAME, WM_GETTEXTLENGTH, 0, 0))) { idsErr=IDS_ACCOUNT_EMPTY; goto Account_Done; } pCEPWizardInfo->pwszUserName=(LPWSTR)malloc(sizeof(WCHAR)*(dwChar+1)); if(NULL==(pCEPWizardInfo->pwszUserName)) goto Account_Done; GetDlgItemTextU(hwndDlg, IDC_ACCOUNT_NAME, pCEPWizardInfo->pwszUserName, dwChar+1); //get the password if(0==(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_ACCOUNT_PASSWORD, WM_GETTEXTLENGTH, 0, 0))) { idsErr=IDS_PASSWORD_EMPTY; goto Account_Done; } pCEPWizardInfo->pwszPassword=(LPWSTR)malloc(sizeof(WCHAR)*(dwChar+1)); if(NULL==(pCEPWizardInfo->pwszPassword)) goto Account_Done; *(pCEPWizardInfo->pwszPassword)=L'\0'; GetDlgItemTextU(hwndDlg, IDC_ACCOUNT_PASSWORD, pCEPWizardInfo->pwszPassword, dwChar+1); //get the confirm if(0==(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_ACCOUNT_CONFIRM, WM_GETTEXTLENGTH, 0, 0))) { idsErr=IDS_PASSWORD_NO_MATCH; goto Account_Done; } pwszConfirm=(LPWSTR)malloc(sizeof(WCHAR)*(dwChar+1)); if(NULL==pwszConfirm) goto Account_Done; GetDlgItemTextU(hwndDlg, IDC_ACCOUNT_CONFIRM, pwszConfirm, dwChar+1); //Verify the password match if(0 != wcscmp(pwszConfirm, pCEPWizardInfo->pwszPassword)) { idsErr=IDS_PASSWORD_NO_MATCH; goto Account_Done; } //Verify the user name are correctly formatted wszDomain[0]=L'\0'; if(NO_ERROR != CredUIParseUserNameW( pCEPWizardInfo->pwszUserName, wszUser, sizeof(wszUser)/sizeof(WCHAR), wszDomain, sizeof(wszDomain)/sizeof(WCHAR))) { idsErr=IDS_INVALID_NAME; goto Account_Done; } //Verify the account does exist. Obtain the account's token //Interactive logon is required on a non-dc machine if(FALSE == pCEPWizardInfo->fDC) { if(!LogonUserW( wszUser, wszDomain, pCEPWizardInfo->pwszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &(pCEPWizardInfo->hAccountToken))) { idsHrErr=IDS_FAIL_LOGON_USER; goto Account_Done; } //do a network logon to obtain the impersonation handle if(pCEPWizardInfo->hAccountToken) { CloseHandle(pCEPWizardInfo->hAccountToken); pCEPWizardInfo->hAccountToken=NULL; } } //network logon to obtain the token if(!LogonUserW( wszUser, wszDomain, pCEPWizardInfo->pwszPassword, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &(pCEPWizardInfo->hAccountToken))) { idsHrErr=IDS_FAIL_LOGON_USER; goto Account_Done; } //build the account name for IIS_WPG group. //for a non-DC, it will be localhost\IIS_WPG //for a DC, it will be domain\IIS_WPG //get the domain or localhost name pwszAccount=GetAccountDomainName(pCEPWizardInfo->fDC); if(NULL==pwszAccount) { idsHrErr=IDS_FAIL_FIND_DOMAIN; goto Account_Done; } //build the IIS_WPG account pwszIIS=(LPWSTR)malloc((wcslen(pwszAccount) + 1 + wcslen(IIS_WPG) + 1)*sizeof(WCHAR)); if(NULL==pwszIIS) goto Account_Done; wcscpy(pwszIIS, pwszAccount); wcscat(pwszIIS, L"\\"); wcscat(pwszIIS, IIS_WPG); //Obtain the SID for the IIS_WPG group dwChar=0; dwDomainChar=0; LookupAccountNameW( NULL, //local system pwszIIS, NULL, &dwChar, NULL, &dwDomainChar, &SidName); pSidIIS=(PSID)malloc(dwChar); if(NULL==pSidIIS) goto Account_Done; pwszDomain=(LPWSTR)malloc(dwDomainChar * sizeof(WCHAR)); if(NULL==pwszDomain) goto Account_Done; if(!LookupAccountNameW( NULL, //local system pwszIIS, pSidIIS, &dwChar, pwszDomain, &dwDomainChar, &SidName)) { idsHrErr=IDS_FAIL_LOOK_UP; goto Account_Done; } //Verify the account is part of the local IIS_WPG group if(!CheckTokenMembership( pCEPWizardInfo->hAccountToken, pSidIIS, &fMember)) { idsHrErr=IDS_FAIL_CHECK_MEMBER; goto Account_Done; } if(FALSE == fMember) { idsErr=IDS_NOT_IIS_MEMBER; goto Account_Done; } //on an enterprise CA, verify the account as READ access to the template if(pCEPWizardInfo->fEnterpriseCA) { //make sure that this is an domain account: //DOMAIN_GROUP_RID_USERS if(0 != wcslen(wszDomain)) { dwSize=0; GetComputerNameExW(ComputerNamePhysicalDnsHostname, NULL, &dwSize); pwszComputerName=(LPWSTR)malloc(dwSize * sizeof(WCHAR)); if(NULL==pwszComputerName) goto Account_Done; if(!GetComputerNameExW(ComputerNamePhysicalDnsHostname, pwszComputerName, &dwSize)) { idsHrErr=IDS_FAIL_GET_COMPUTER_NAME; goto Account_Done; } if(0 == _wcsicmp(wszDomain, pwszComputerName)) { idsErr=IDS_NO_LOCAL_ACCOUNT; goto Account_Done; } } hr=CAFindCertTypeByName(wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE, NULL, CT_ENUM_MACHINE_TYPES, &hCertType); if(S_OK != hr) { idsHrErr=IDS_FAIL_FIND_CERT_TYPE; goto Account_Done; } //get the SD for the template hr=CACertTypeGetSecurity(hCertType, &pCertTypeSD); if(S_OK != hr) { idsHrErr=IDS_FAIL_FIND_SD_CERT_TYPE; goto Account_Done; } //check the DS_READ Access dwPSSize=sizeof(ps); if(!AccessCheck( pCertTypeSD, pCEPWizardInfo->hAccountToken, ACTRL_DS_LIST | ACTRL_DS_READ_PROP, &GenericMapping, &ps, &dwPSSize, &grantAccess, &fAccessAllowed)) { idsHrErr=IDS_FAIL_DETECT_READ_ACCESS; goto Account_Done; } //make sure the account has read access to the template if(FALSE == fAccessAllowed) { idsErr=IDS_NO_READ_ACCESS_TO_TEMPLATE; goto Account_Done; } } //everything looks good idsErr=0; idsHrErr=0; Account_Done: if(pwszComputerName) { free(pwszComputerName); } if(pwszConfirm) { free(pwszConfirm); } if(pwszAccount) { NetApiBufferFree(pwszAccount); } if(pwszIIS) { free(pwszIIS); } if(pwszDomain) { free(pwszDomain); } if(pSidIIS) { free(pSidIIS); } if(pCertTypeSD) { LocalFree(pCertTypeSD); } if(hCertType) { CACloseCertType(hCertType); } if(0 != idsErr) { CEPMessageBox(hwndDlg, idsErr, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); } else { if(0 != idsHrErr) { if(S_OK == hr) { hr=HRESULT_FROM_WIN32(GetLastError()); } CEPErrorMessageBoxEx(hwndDlg, idsHrErr, hr, MB_ICONERROR|MB_OK|MB_APPLMODAL, IDS_GEN_ERROR_MSG_HR, IDS_GEN_ERROR_MSG); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); } } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //Chanllenge //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_Challenge(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBold, hwndDlg,IDC_BOLD_TITLE); //by default, we should use Challenge password SendMessage(GetDlgItem(hwndDlg, IDC_CHALLENGE_CHECK), BM_SETCHECK, BST_CHECKED, 0); break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; if(TRUE == (pCEPWizardInfo->fLocalSystem)) { //skip the account page and goes to the application identity page SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_APP_ID); } break; case PSN_WIZNEXT: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //check for the Challenge password options if(BST_CHECKED==SendDlgItemMessage(hwndDlg,IDC_CHALLENGE_CHECK, BM_GETCHECK, 0, 0)) pCEPWizardInfo->fPassword=TRUE; else pCEPWizardInfo->fPassword=FALSE; //warn users about the implication of not using a password if(FALSE == pCEPWizardInfo->fPassword) { if(IDNO==CEPMessageBox(hwndDlg, IDS_NO_CHALLENGE_PASSWORD, MB_ICONWARNING|MB_YESNO|MB_APPLMODAL)) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } if(!EmptyCEPStore()) { CEPMessageBox(hwndDlg, IDS_EXISTING_RA, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL); if(IDNO==CEPMessageBox(hwndDlg, IDS_PROCESS_PENDING, MB_ICONQUESTION|MB_YESNO|MB_APPLMODAL)) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- // Enroll //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_Enroll(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; DWORD dwIndex=0; DWORD dwChar=0; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBold, hwndDlg,IDC_BOLD_TITLE); //by default, we do not use the advanced enrollment options SendMessage(GetDlgItem(hwndDlg, IDC_ENORLL_ADV_CHECK), BM_SETCHECK, BST_UNCHECKED, 0); //preset the country string since we only allow 2 characters SetDlgItemTextU(hwndDlg, IDC_ENROLL_COUNTRY, L"US"); break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //if the adv selection is made, it has to stay selected if(pCEPWizardInfo->fEnrollAdv) EnableWindow(GetDlgItem(hwndDlg, IDC_ENORLL_ADV_CHECK), FALSE); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //gather RA subject informaton for(dwIndex=0; dwIndex < RA_INFO_COUNT; dwIndex++) { if(pCEPWizardInfo->rgpwszName[dwIndex]) { free(pCEPWizardInfo->rgpwszName[dwIndex]); pCEPWizardInfo->rgpwszName[dwIndex]=NULL; } if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, g_rgRAEnrollInfo[dwIndex].dwIDC, WM_GETTEXTLENGTH, 0, 0))) { pCEPWizardInfo->rgpwszName[dwIndex]=(LPWSTR)malloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=(pCEPWizardInfo->rgpwszName[dwIndex])) { GetDlgItemTextU(hwndDlg, g_rgRAEnrollInfo[dwIndex].dwIDC, pCEPWizardInfo->rgpwszName[dwIndex], dwChar+1); } } } //we require name and company if((NULL==(pCEPWizardInfo->rgpwszName[0])) || (NULL==(pCEPWizardInfo->rgpwszName[2])) ) { CEPMessageBox(hwndDlg, IDS_ENROLL_REQUIRE_NAME, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } //we only allow 2 characeters for the country if(NULL !=(pCEPWizardInfo->rgpwszName[RA_INFO_COUNT -1])) { if(2 < wcslen(pCEPWizardInfo->rgpwszName[RA_INFO_COUNT -1])) { CEPMessageBox(hwndDlg, IDS_ENROLL_COUNTRY_TOO_LARGE, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } //check for the advanced options if(BST_CHECKED==SendDlgItemMessage(hwndDlg,IDC_ENORLL_ADV_CHECK, BM_GETCHECK, 0, 0)) pCEPWizardInfo->fEnrollAdv=TRUE; else pCEPWizardInfo->fEnrollAdv=FALSE; //If the advanced is selected, skip the CSP Page if(FALSE== pCEPWizardInfo->fEnrollAdv) SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_COMPLETION); break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- // CSP //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_CSP(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; NM_LISTVIEW FAR * pnmv=NULL; BOOL fSign=FALSE; int idCombo=0; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBold, hwndDlg,IDC_BOLD_TITLE); //populate the CSP list and key length combo box InitCSPList(hwndDlg, IDC_CSP_SIGN_LIST, TRUE, pCEPWizardInfo); InitCSPList(hwndDlg, IDC_CSP_ENCRYPT_LIST, FALSE, pCEPWizardInfo); RefreshKeyLengthCombo(hwndDlg, IDC_CSP_SIGN_LIST, IDC_CSP_SIGN_COMBO, TRUE, pCEPWizardInfo); RefreshKeyLengthCombo(hwndDlg, IDC_CSP_ENCRYPT_LIST, IDC_CSP_ENCRYPT_COMBO, FALSE, pCEPWizardInfo); break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case LVN_ITEMCHANGED: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; pnmv = (LPNMLISTVIEW) lParam; if(NULL==pnmv) break; if (pnmv->uNewState & LVIS_SELECTED) { if(IDC_CSP_SIGN_LIST == (pnmv->hdr).idFrom) { fSign=TRUE; idCombo=IDC_CSP_SIGN_COMBO; } else { if(IDC_CSP_ENCRYPT_LIST != (pnmv->hdr).idFrom) break; fSign=FALSE; idCombo=IDC_CSP_ENCRYPT_COMBO; } RefreshKeyLengthCombo( hwndDlg, (int)((pnmv->hdr).idFrom), idCombo, fSign, pCEPWizardInfo); } break; case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the select CSP and key length if(!GetSelectedCSP(hwndDlg, IDC_CSP_SIGN_LIST, &(pCEPWizardInfo->dwSignProvIndex))) { CEPMessageBox(hwndDlg, IDS_SELECT_SIGN_CSP, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } if(!GetSelectedCSP(hwndDlg, IDC_CSP_ENCRYPT_LIST, &(pCEPWizardInfo->dwEncryptProvIndex))) { CEPMessageBox(hwndDlg, IDS_SELECT_ENCRYPT_CSP, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } if(!GetSelectedKeyLength(hwndDlg, IDC_CSP_SIGN_COMBO, &(pCEPWizardInfo->dwSignKeyLength))) { CEPMessageBox(hwndDlg, IDS_SELECT_SIGN_KEY_LENGTH, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } if(!GetSelectedKeyLength(hwndDlg, IDC_CSP_ENCRYPT_COMBO, &(pCEPWizardInfo->dwEncryptKeyLength))) { CEPMessageBox(hwndDlg, IDS_SELECT_ENCRYPT_KEY_LENGTH, MB_ICONERROR|MB_OK|MB_APPLMODAL); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //Completion //----------------------------------------------------------------------- INT_PTR APIENTRY CEP_Completion(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CEP_WIZARD_INFO *pCEPWizardInfo=NULL; PROPSHEETPAGE *pPropSheet=NULL; HWND hwndControl=NULL; LV_COLUMNW lvC; HCURSOR hPreCursor=NULL; HCURSOR hWinPreCursor=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGE *) lParam; pCEPWizardInfo = (CEP_WIZARD_INFO *) (pPropSheet->lParam); //make sure pCertWizardInfo is a valid pointer if(NULL==pCEPWizardInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCEPWizardInfo); SetControlFont(pCEPWizardInfo->hBigBold, hwndDlg,IDC_BIG_BOLD_TITLE); //insert two columns hwndControl=GetDlgItem(hwndDlg, IDC_COMPLETION_LIST); memset(&lvC, 0, sizeof(LV_COLUMNW)); lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; // Left-align the column. lvC.cx = 20; // Width of the column, in pixels. lvC.pszText = L""; // The text for the column. lvC.iSubItem=0; if (ListView_InsertColumnU(hwndControl, 0, &lvC) == -1) break; //2nd column is the content memset(&lvC, 0, sizeof(LV_COLUMNW)); lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; // Left-align the column. lvC.cx = 10; //(dwMaxSize+2)*7; // Width of the column, in pixels. lvC.pszText = L""; // The text for the column. lvC.iSubItem= 1; if (ListView_InsertColumnU(hwndControl, 1, &lvC) == -1) break; break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK|PSWIZB_FINISH); if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; if(hwndControl=GetDlgItem(hwndDlg, IDC_COMPLETION_LIST)) DisplayConfirmation(hwndControl, pCEPWizardInfo); break; case PSN_WIZBACK: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //skip CSP page if adv is not selected if(FALSE == pCEPWizardInfo->fEnrollAdv) SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_ENROLL); break; case PSN_WIZFINISH: if(NULL==(pCEPWizardInfo=(CEP_WIZARD_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //overwrite the cursor for this window class hWinPreCursor=(HCURSOR)SetClassLongPtr(hwndDlg, GCLP_HCURSOR, (LONG_PTR)NULL); hPreCursor=SetCursor(LoadCursor(NULL, IDC_WAIT)); //do the real setup work I_DoSetupWork(hwndDlg, pCEPWizardInfo); //set the cursor back SetCursor(hPreCursor); SetWindowLongPtr(hwndDlg, GCLP_HCURSOR, (LONG_PTR)hWinPreCursor); break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // // Helper Functions for the wizard pages // //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // // CEPGetAccountNameFromPicker // //-------------------------------------------------------------------------- BOOL CEPGetAccountNameFromPicker(HWND hwndParent, IDsObjectPicker *pIDsObjectPicker, LPWSTR *ppwszSelectedUserSAM) { BOOL fResult=FALSE; BOOL fGotStgMedium = FALSE; LPWSTR pwszPath=NULL; DWORD dwIndex =0 ; DWORD dwCount=0; WCHAR wszWinNT[]=L"WinNT://"; DWORD dwSize=0; LPWSTR pwsz=NULL; DWORD cCount=0; IDataObject *pdo = NULL; PDS_SELECTION_LIST pDsSelList=NULL; LPWSTR pwszComputerName=NULL; STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)g_cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; //input check if((NULL == pIDsObjectPicker) || (NULL == ppwszSelectedUserSAM)) goto CLEANUP; *ppwszSelectedUserSAM = NULL; if(S_OK != pIDsObjectPicker->InvokeDialog(hwndParent, &pdo)) goto CLEANUP; if(S_OK != pdo->GetData(&formatetc, &stgmedium)) goto CLEANUP; fGotStgMedium = TRUE; pDsSelList = (PDS_SELECTION_LIST)GlobalLock(stgmedium.hGlobal); if(!pDsSelList) goto CLEANUP; //detect if this is a domain account //local account will be in the format of Winnt://workgroup/machine/foo //Get the SAM name if((pDsSelList->aDsSelection[0]).pwzADsPath == NULL) goto CLEANUP; //the ADsPath is in the form of "WinNT://" if(wcslen((pDsSelList->aDsSelection[0]).pwzADsPath) <= wcslen(wszWinNT)) goto CLEANUP; if( 0 != _wcsnicmp((pDsSelList->aDsSelection[0]).pwzADsPath, wszWinNT, wcslen(wszWinNT))) goto CLEANUP; pwsz = ((pDsSelList->aDsSelection[0]).pwzADsPath) + wcslen(wszWinNT); while(L'\0' != (*pwsz)) { if(L'/' == (*pwsz)) { cCount++; } pwsz++; } if(1 == cCount) { //domain\administrator have no UPN //if((pDsSelList->aDsSelection[0]).pwzUPN != NULL) //if(0 != _wcsicmp(L"",(pDsSelList->aDsSelection[0]).pwzUPN)) pwszPath = ((pDsSelList->aDsSelection[0]).pwzADsPath) + wcslen(wszWinNT); *ppwszSelectedUserSAM=(LPWSTR)malloc((wcslen(pwszPath) + 1) * sizeof(WCHAR)); if(NULL == (*ppwszSelectedUserSAM)) goto CLEANUP; wcscpy(*ppwszSelectedUserSAM, pwszPath); //search for the "/" and make it "\". Since the ADsPath is in the form //of "WinNT://domain/name". We need the SAM name in the form of //domain\name dwCount = wcslen(*ppwszSelectedUserSAM); for(dwIndex = 0; dwIndex < dwCount; dwIndex++) { if((*ppwszSelectedUserSAM)[dwIndex] == L'/') { (*ppwszSelectedUserSAM)[dwIndex] = L'\\'; break; } } } //use the format of localMachine\\account for local account if(NULL == (*ppwszSelectedUserSAM)) { if(NULL == (pDsSelList->aDsSelection[0]).pwzName) goto CLEANUP; //Get the computer name dwSize=0; GetComputerNameExW(ComputerNamePhysicalDnsHostname, NULL, &dwSize); pwszComputerName=(LPWSTR)malloc(dwSize * sizeof(WCHAR)); if(NULL==pwszComputerName) goto CLEANUP; if(!GetComputerNameExW(ComputerNamePhysicalDnsHostname, pwszComputerName, &dwSize)) goto CLEANUP; *ppwszSelectedUserSAM=(LPWSTR)malloc((wcslen(pwszComputerName) + wcslen((pDsSelList->aDsSelection[0]).pwzName) + wcslen(L"\\") + 1) * sizeof(WCHAR)); if(NULL == (*ppwszSelectedUserSAM)) goto CLEANUP; wcscpy(*ppwszSelectedUserSAM, pwszComputerName); wcscat(*ppwszSelectedUserSAM, L"\\"); wcscat(*ppwszSelectedUserSAM, (pDsSelList->aDsSelection[0]).pwzName); } fResult=TRUE; CLEANUP: if(pwszComputerName) free(pwszComputerName); if(pDsSelList) GlobalUnlock(stgmedium.hGlobal); if (TRUE == fGotStgMedium) ReleaseStgMedium(&stgmedium); if(pdo) pdo->Release(); return fResult; } //-------------------------------------------------------------------------- // // RefreshKeyLengthCombo // //-------------------------------------------------------------------------- BOOL WINAPI RefreshKeyLengthCombo(HWND hwndDlg, int idsList, int idsCombo, BOOL fSign, CEP_WIZARD_INFO *pCEPWizardInfo) { BOOL fResult=FALSE; DWORD dwDefaultKeyLength=0; DWORD *pdwList=NULL; DWORD dwListCount=0; DWORD dwMax=0; DWORD dwMin=0; DWORD dwIndex=0; DWORD dwCSPIndex=0; CEP_CSP_INFO *pCSPInfo=NULL; int iInsertedIndex=0; WCHAR wszKeyLength[CEP_KEY_LENGTH_STRING]; BOOL fSelected=FALSE; //get the selected list view item if(!GetSelectedCSP(hwndDlg,idsList,&dwCSPIndex)) goto CLEANUP; pCSPInfo= &(pCEPWizardInfo->rgCSPInfo[dwCSPIndex]); if(fSign) { dwDefaultKeyLength=pCSPInfo->dwDefaultSign; pdwList=pCSPInfo->pdwSignList; dwListCount= pCSPInfo->dwSignCount; dwMax=pCSPInfo->dwMaxSign; dwMin=pCSPInfo->dwMinSign; } else { dwDefaultKeyLength=pCSPInfo->dwDefaultEncrypt; pdwList=pCSPInfo->pdwEncryptList; dwListCount=pCSPInfo->dwEncryptCount; dwMax=pCSPInfo->dwMaxEncrypt; dwMin=pCSPInfo->dwMinEncrypt; } //clear out the combo box SendDlgItemMessageU(hwndDlg, idsCombo, CB_RESETCONTENT, 0, 0); for(dwIndex=0; dwIndex < dwListCount; dwIndex++) { if((pdwList[dwIndex] >= dwMin) && (pdwList[dwIndex] <= dwMax)) { _ltow(pdwList[dwIndex], wszKeyLength, 10); // 64 bit- will never insert more than 1B entries, so INT is fine iInsertedIndex=(int)SendDlgItemMessageU(hwndDlg, idsCombo, CB_ADDSTRING, 0, (LPARAM)wszKeyLength); if((iInsertedIndex != CB_ERR) && (iInsertedIndex != CB_ERRSPACE)) { SendDlgItemMessage(hwndDlg, idsCombo, CB_SETITEMDATA, (WPARAM)iInsertedIndex, (LPARAM)pdwList[dwIndex]); if(dwDefaultKeyLength==pdwList[dwIndex]) { SendDlgItemMessageU(hwndDlg, idsCombo, CB_SETCURSEL, iInsertedIndex, 0); fSelected=TRUE; } } } } if(fSelected==FALSE) SendDlgItemMessageU(hwndDlg, idsCombo, CB_SETCURSEL, 0, 0); fResult=TRUE; CLEANUP: return fResult; } //-------------------------------------------------------------------------- // // InitCSPList // //-------------------------------------------------------------------------- BOOL WINAPI InitCSPList(HWND hwndDlg, int idControl, BOOL fSign, CEP_WIZARD_INFO *pCEPWizardInfo) { BOOL fResult=FALSE; DWORD dwIndex=0; CEP_CSP_INFO *pCSPInfo=NULL; int iInsertedIndex=0; HWND hwndList=NULL; LV_ITEMW lvItem; LV_COLUMNW lvC; BOOL fSelected=FALSE; if(NULL==(hwndList=GetDlgItem(hwndDlg, idControl))) goto CLEANUP; //insert a column into the list view memset(&lvC, 0, sizeof(LV_COLUMNW)); lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; // Left-align the column. lvC.cx = 20; //(dwMaxSize+2)*7; // Width of the column, in pixels. lvC.pszText = L""; // The text for the column. lvC.iSubItem=0; if (-1 == ListView_InsertColumnU(hwndList, 0, &lvC)) goto CLEANUP; // set up the fields in the list view item struct that don't change from item to item memset(&lvItem, 0, sizeof(LV_ITEMW)); lvItem.mask = LVIF_TEXT | LVIF_STATE |LVIF_PARAM ; for(dwIndex=0; dwIndex < pCEPWizardInfo->dwCSPCount; dwIndex++) { fSelected=FALSE; pCSPInfo= &(pCEPWizardInfo->rgCSPInfo[dwIndex]); if(fSign) { if(!(pCSPInfo->fSignature)) continue; if(dwIndex==pCEPWizardInfo->dwSignProvIndex) fSelected=TRUE; } else { if(!(pCSPInfo->fEncryption)) continue; if(dwIndex==pCEPWizardInfo->dwEncryptProvIndex) fSelected=TRUE; } lvItem.iItem=dwIndex; lvItem.lParam = (LPARAM)dwIndex; lvItem.pszText=pCSPInfo->pwszCSPName; iInsertedIndex=ListView_InsertItemU(hwndList, &lvItem); if(fSelected) { ListView_SetItemState( hwndList, iInsertedIndex, LVIS_SELECTED, LVIS_SELECTED); } } //make the column autosize ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); fResult=TRUE; CLEANUP: return fResult; } //-------------------------------------------------------------------------- // // GetSelectedCSP // //-------------------------------------------------------------------------- BOOL WINAPI GetSelectedCSP(HWND hwndDlg, int idControl, DWORD *pdwCSPIndex) { BOOL fResult=FALSE; HWND hwndControl=NULL; LV_ITEM lvItem; int iIndex=0; //get the window handle of the list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, idControl))) goto CLEANUP; //now, mark the one that is selected if(-1 == (iIndex= ListView_GetNextItem( hwndControl, -1, LVNI_SELECTED ))) goto CLEANUP; memset(&lvItem, 0, sizeof(LV_ITEM)); lvItem.mask=LVIF_PARAM; lvItem.iItem=iIndex; if(!ListView_GetItem(hwndControl, &lvItem)) goto CLEANUP; // will never have more than 1B CSPs, so this is fine *pdwCSPIndex=(DWORD)(lvItem.lParam); fResult=TRUE; CLEANUP: return fResult; } //-------------------------------------------------------------------------- // // GetSelectedKeyLength // //-------------------------------------------------------------------------- BOOL WINAPI GetSelectedKeyLength(HWND hwndDlg, int idControl, DWORD *pdwKeyLength) { int iIndex=0; BOOL fResult=FALSE; iIndex=(int)SendDlgItemMessage(hwndDlg, idControl, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) goto CLEANUP; // will never be > 1B bits long, so this is ok *pdwKeyLength=(DWORD)SendDlgItemMessage(hwndDlg, idControl, CB_GETITEMDATA, iIndex, 0); fResult=TRUE; CLEANUP: return fResult; } //-------------------------------------------------------------------------- // // FormatMessageStr // //-------------------------------------------------------------------------- int ListView_InsertItemU_IDS(HWND hwndList, LV_ITEMW *plvItem, UINT idsString, LPWSTR pwszText) { WCHAR wszText[MAX_STRING_SIZE]; if(pwszText) plvItem->pszText=pwszText; else { if(!LoadStringU(g_hModule, idsString, wszText, MAX_STRING_SIZE)) return -1; plvItem->pszText=wszText; } return ListView_InsertItemU(hwndList, plvItem); } //------------------------------------------------------------------------- // // populate the wizards's confirmation page in the order of Challenge, // RA informaton, and CSPs // //------------------------------------------------------------------------- void WINAPI DisplayConfirmation(HWND hwndControl, CEP_WIZARD_INFO *pCEPWizardInfo) { WCHAR wszYes[MAX_TITLE_LENGTH]; DWORD dwIndex=0; UINT ids=0; BOOL fNewItem=FALSE; WCHAR wszLength[CEP_KEY_LENGTH_STRING]; LV_COLUMNW lvC; LV_ITEMW lvItem; //delete all the old items in the listView ListView_DeleteAllItems(hwndControl); //insert row by row memset(&lvItem, 0, sizeof(LV_ITEMW)); // set up the fields in the list view item struct that don't change from item to item lvItem.mask = LVIF_TEXT | LVIF_STATE ; lvItem.state = 0; lvItem.stateMask = 0; //******************************************************************* //account information lvItem.iItem=0; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_ACCOUNT_INFORMATION, NULL); //content (lvItem.iSubItem)++; if(FALSE == (pCEPWizardInfo->fLocalSystem)) { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pCEPWizardInfo->pwszUserName); } else { if(LoadStringU(g_hModule, IDS_LOCAL_SYSTEM, wszYes, MAX_TITLE_LENGTH)) ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszYes); } //******************************************************************* //challenge lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CHALLENGE_PHRASE, NULL); //content (lvItem.iSubItem)++; if(pCEPWizardInfo->fPassword) ids=IDS_YES; else ids=IDS_NO; if(LoadStringU(g_hModule, ids, wszYes, MAX_TITLE_LENGTH)) ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszYes); //*************************************************************************** // RA credentials lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_RA_CREDENTIAL, NULL); //content for(dwIndex=0; dwIndexrgpwszName[dwIndex]) { if(TRUE==fNewItem) { //increase the row lvItem.iItem++; lvItem.pszText=L""; lvItem.iSubItem=0; ListView_InsertItemU(hwndControl, &lvItem); } else fNewItem=TRUE; lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pCEPWizardInfo->rgpwszName[dwIndex]); } } //*************************************************************************** //CSPInfo if(pCEPWizardInfo->fEnrollAdv) { //signature CSP Name lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_SIGN_CSP, NULL); lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwSignProvIndex].pwszCSPName); //signaure key length lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_SIGN_KEY_LENGTH, NULL); lvItem.iSubItem++; _ltow(pCEPWizardInfo->dwSignKeyLength, wszLength, 10); ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszLength); //encryption CSP name lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_ENCRYPT_CSP, NULL); lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwEncryptProvIndex].pwszCSPName); //encryption key length lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_ENCRYPT_KEY_LENGTH, NULL); lvItem.iSubItem++; _ltow(pCEPWizardInfo->dwEncryptKeyLength, wszLength, 10); ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszLength); } //autosize the columns ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); ListView_SetColumnWidth(hwndControl, 1, LVSCW_AUTOSIZE); return; } //-------------------------------------------------------------------- // // GetServiceWaitPeriod // // Obtain the value from the registry // //-------------------------------------------------------------------------- void GetServiceWaitPeriod(DWORD *pdwServiceWait) { DWORD cbData=0; DWORD dwData=0; DWORD dwType=0; HKEY hKeyCEP=NULL; //set the default value *pdwServiceWait=SCEP_SERVICE_WAIT_PERIOD; //get the CA's type from the registry cbData=sizeof(dwData); //we have to have the knowledge of the ca type if(ERROR_SUCCESS == RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_LOCATION, 0, KEY_READ, &hKeyCEP)) { if(ERROR_SUCCESS == RegQueryValueExU( hKeyCEP, MSCEP_KEY_SERVICE_WAIT, NULL, &dwType, (BYTE *)&dwData, &cbData)) { if ((dwType == REG_DWORD) || (dwType == REG_BINARY)) { *pdwServiceWait=dwData; } } } if(hKeyCEP) RegCloseKey(hKeyCEP); return; } //-------------------------------------------------------------------- // // Main Function // //-------------------------------------------------------------------------- extern "C" int _cdecl wmain(int nArgs, WCHAR ** rgwszArgs) { BOOL fResult=FALSE; UINT idsMsg=IDS_FAIL_INIT_WIZARD; HRESULT hr=E_FAIL; PROPSHEETPAGEW rgCEPSheet[CEP_PROP_SHEET]; PROPSHEETHEADERW cepHeader; CEP_PAGE_INFO rgCEPPageInfo[CEP_PROP_SHEET]= {(LPCWSTR)MAKEINTRESOURCE(IDD_WELCOME), CEP_Welcome, (LPCWSTR)MAKEINTRESOURCE(IDD_APP_ID), CEP_App_ID, (LPCWSTR)MAKEINTRESOURCE(IDD_ACCOUNT), CEP_Account, (LPCWSTR)MAKEINTRESOURCE(IDD_CHALLENGE), CEP_Challenge, (LPCWSTR)MAKEINTRESOURCE(IDD_ENROLL), CEP_Enroll, (LPCWSTR)MAKEINTRESOURCE(IDD_CSP), CEP_CSP, (LPCWSTR)MAKEINTRESOURCE(IDD_COMPLETION), CEP_Completion, }; DWORD dwIndex=0; WCHAR wszTitle[MAX_TITLE_LENGTH]; INT_PTR iReturn=-1; ENUM_CATYPES catype; DWORD dwWaitCounter=0; BOOL fEnterpriseCA=FALSE; DSOP_SCOPE_INIT_INFO ScopeInit; DSOP_INIT_INFO InitInfo; DWORD dwServiceWait=SCEP_SERVICE_WAIT_PERIOD; OSVERSIONINFOEXW versionInfo; CEP_WIZARD_INFO CEPWizardInfo; DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDomainInfo=NULL; memset(rgCEPSheet, 0, sizeof(PROPSHEETPAGEW)*CEP_PROP_SHEET); memset(&cepHeader, 0, sizeof(PROPSHEETHEADERW)); memset(&CEPWizardInfo, 0, sizeof(CEP_WIZARD_INFO)); if(FAILED(CoInitialize(NULL))) return FALSE; if(NULL==(g_hModule=GetModuleHandle(NULL))) goto CommonReturn; if(!IsValidInstallation(&idsMsg)) goto ErrorReturn; //get the wait period for start/stop service account GetServiceWaitPeriod(&dwServiceWait); if(!IsCaRunning()) { if(S_OK != (hr=CepStartService(CERTSVC_NAME))) { idsMsg=IDS_NO_CA_RUNNING; goto ErrorWithHResultReturn; } } //make sure the CA is up running for (dwWaitCounter=0; dwWaitCounter < dwServiceWait; dwWaitCounter++) { if (!IsCaRunning()) Sleep(1000); else break; } if (dwServiceWait == dwWaitCounter) { idsMsg=IDS_CAN_NOT_START_CA; goto ErrorWithHResultReturn; } //make sure we have the correct admin rights based on the CA type if(S_OK != (hr=GetCaType(&catype))) { idsMsg=IDS_FAIL_GET_CA_TYPE; goto ErrorWithHResultReturn; } //some cisco routers only work with root CA if((ENUM_ENTERPRISE_ROOTCA != catype) && (ENUM_STANDALONE_ROOTCA != catype)) { if(IDNO==CEPMessageBox(NULL, IDS_CAN_NOT_ROOT_CA, MB_ICONWARNING|MB_YESNO|MB_APPLMODAL)) { fResult=FALSE; goto CommonReturn; } } //for either Enteprise CA or Standalone CA, the user has to be the local machine admin // check for machine admin if(!IsUserInAdminGroup(FALSE)) { idsMsg=IDS_NOT_MACHINE_ADMIN; goto ErrorReturn; } if (ENUM_ENTERPRISE_ROOTCA==catype || ENUM_ENTERPRISE_SUBCA==catype) { fEnterpriseCA=TRUE; // check for enterprise admin if(!IsUserInAdminGroup(TRUE)) { idsMsg=IDS_NOT_ENT_ADMIN; goto ErrorReturn; } } //everything looks good. We start the wizard page if(!CEPWizardInit()) goto ErrorWithWin32Return; CEPWizardInfo.fEnrollAdv=FALSE; CEPWizardInfo.fPassword=FALSE; CEPWizardInfo.fEnterpriseCA=fEnterpriseCA; CEPWizardInfo.fDC=FALSE; CEPWizardInfo.fDomain=TRUE; //defeult to assume the machine is on a domain CEPWizardInfo.dwServiceWait=dwServiceWait; //detect if the machine is a DC versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if(GetVersionEx(reinterpret_cast(&versionInfo))) { CEPWizardInfo.fDC = (versionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER); } //detect if the machine is on a domain if(ERROR_SUCCESS != DsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic, (PBYTE*)&pDomainInfo)) { idsMsg=IDS_FAIL_DOMAIN_INFO; goto ErrorReturn; } if((DsRole_RoleStandaloneWorkstation == (pDomainInfo->MachineRole)) || (DsRole_RoleStandaloneServer == (pDomainInfo->MachineRole)) ) { CEPWizardInfo.fDomain=FALSE; } //initialize the object picker object //init for the user selection dialogue memset(&ScopeInit, 0, sizeof(DSOP_SCOPE_INIT_INFO)); memset(&InitInfo, 0, sizeof(InitInfo)); ScopeInit.cbSize = sizeof(DSOP_SCOPE_INIT_INFO); //only domain account for enterprise CA if(fEnterpriseCA) { ScopeInit.flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN|DSOP_SCOPE_TYPE_GLOBAL_CATALOG; } else { ScopeInit.flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN|DSOP_SCOPE_TYPE_GLOBAL_CATALOG|DSOP_SCOPE_TYPE_TARGET_COMPUTER; } ScopeInit.flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; //this will give us the SAM name for the user ScopeInit.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS; ScopeInit.FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS; InitInfo.cbSize = sizeof(InitInfo); InitInfo.pwzTargetComputer = NULL; // NULL == local machine InitInfo.cDsScopeInfos = 1; InitInfo.aDsScopeInfos = &ScopeInit; InitInfo.flOptions = 0; //we are doing single select //create the COM object if(S_OK != (hr=CoCreateInstance (CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void **) &(CEPWizardInfo.pIDsObjectPicker)))) { idsMsg=IDS_FAIL_GET_OBJECT_PICKER; goto ErrorWithHResultReturn; } if(S_OK != (hr=CEPWizardInfo.pIDsObjectPicker->Initialize(&InitInfo))) { idsMsg=IDS_FAIL_GET_OBJECT_PICKER; goto ErrorWithHResultReturn; } //initialize the CSP information if(!CEPGetCSPInformation(&CEPWizardInfo)) { idsMsg=IDS_FAIL_GET_CSP_INFO; goto ErrorWithWin32Return; } for(dwIndex=0; dwIndexfPassword, pCEPWizardInfo->fEnterpriseCA)) { idsMsg=IDS_FAIL_UPDATE_REGISTRY; goto ErrorWithWin32Return; } //************************************************************************************ // Add the virtual root if(S_OK != (hr=AddVDir(pCEPWizardInfo->fDC, CEP_DIR_NAME, SCEP_APPLICATION_POOL, pCEPWizardInfo->fLocalSystem, pCEPWizardInfo->pwszUserName, pCEPWizardInfo->pwszPassword))) { idsMsg=IDS_FAIL_ADD_VROOT; goto ErrorWithHResultReturn; } //************************************************************************************ // Stop and Start W3SVC service for the change to take effect CepStopService(pCEPWizardInfo->dwServiceWait,IIS_NAME, &bStart); if(S_OK != (hr=CepStartService(IIS_NAME))) { idsMsg=IDS_FAIL_START_IIS; goto ErrorWithHResultReturn; } //make sure the w3svc is up running for (dwWaitCounter=0; dwWaitCounter < pCEPWizardInfo->dwServiceWait; dwWaitCounter++) { if (!IsServiceRunning(IIS_NAME)) Sleep(1000); else break; } if (pCEPWizardInfo->dwServiceWait == dwWaitCounter) { idsMsg=IDS_FAIL_START_IIS; goto ErrorWithHResultReturn; } //************************************************************************************ //Get the security ID for the account //get the account's SID if(FALSE == (pCEPWizardInfo->fLocalSystem)) { if(NULL == pCEPWizardInfo->hAccountToken) { idsMsg=IDS_FAIL_SID_FROM_ACCOUNT; hr=E_INVALIDARG; goto ErrorWithHResultReturn; } GetTokenInformation(pCEPWizardInfo->hAccountToken, TokenUser, NULL, 0, &cbUserInfo); if(cbUserInfo == 0) { idsMsg=IDS_FAIL_SID_FROM_ACCOUNT; goto ErrorWithWin32Return; } pUserInfo = (PTOKEN_USER)LocalAlloc(LPTR, cbUserInfo); if(pUserInfo == NULL) { idsMsg=IDS_FAIL_SID_FROM_ACCOUNT; hr=E_OUTOFMEMORY; goto ErrorWithHResultReturn; } if(!GetTokenInformation(pCEPWizardInfo->hAccountToken, TokenUser, pUserInfo, cbUserInfo, &cbUserInfo)) { idsMsg=IDS_FAIL_SID_FROM_ACCOUNT; goto ErrorWithWin32Return; } } //************************************************************************************ //Update the certificate template and its ACLs for enterprise CA if (pCEPWizardInfo->fEnterpriseCA) { // get the templates and permisisons right if(S_OK != (hr=DoCertSrvEnterpriseChanges(pCEPWizardInfo->fLocalSystem ? NULL : (SID *)((pUserInfo->User).Sid)))) { idsMsg=IDS_FAIL_ADD_TEMPLATE; goto ErrorWithHResultReturn; } } //************************************************************************************ //Enroll for the RA certificate //build the name in the form of L"C=US;S=Washington;CN=TestSetupUtil" pwszRADN=(LPWSTR)malloc(sizeof(WCHAR)); if(NULL==pwszRADN) { idsMsg=IDS_NO_MEMORY; goto ErrorReturn; } *pwszRADN=L'\0'; for(dwIndex=0; dwIndexrgpwszName)[dwIndex]) { if(0 != wcslen(pwszRADN)) wcscat(pwszRADN, L";"); pwszRADN=(LPWSTR)realloc(pwszRADN, sizeof(WCHAR) * (wcslen(pwszRADN) + wcslen((pCEPWizardInfo->rgpwszName)[dwIndex]) + wcslen(L";") + wcslen(g_rgRAEnrollInfo[dwIndex].pwszPreFix) + 1)); if(NULL==pwszRADN) { idsMsg=IDS_NO_MEMORY; goto ErrorReturn; } wcscat(pwszRADN,g_rgRAEnrollInfo[dwIndex].pwszPreFix); wcscat(pwszRADN,(pCEPWizardInfo->rgpwszName)[dwIndex]); } } if(S_OK != (hr=EnrollForRACertificates( pwszRADN, (pCEPWizardInfo->rgCSPInfo)[pCEPWizardInfo->dwSignProvIndex].pwszCSPName, (pCEPWizardInfo->rgCSPInfo)[pCEPWizardInfo->dwSignProvIndex].dwCSPType, pCEPWizardInfo->dwSignKeyLength, (pCEPWizardInfo->rgCSPInfo)[pCEPWizardInfo->dwEncryptProvIndex].pwszCSPName, (pCEPWizardInfo->rgCSPInfo)[pCEPWizardInfo->dwEncryptProvIndex].dwCSPType, pCEPWizardInfo->dwEncryptKeyLength, pCEPWizardInfo->fLocalSystem ? NULL : (SID *)((pUserInfo->User).Sid)))) { idsMsg=IDS_FAIL_ENROLL_RA_CERT; goto ErrorWithHResultReturn; } //************************************************************************************ //CA policy registry CepStopService(pCEPWizardInfo->dwServiceWait, CERTSVC_NAME, &bStart); if(S_OK != (hr=DoCertSrvRegChanges(FALSE))) { idsMsg=IDS_FAIL_UPDATE_CERTSVC; goto ErrorWithHResultReturn; } if(S_OK != (hr=CepStartService(CERTSVC_NAME))) { idsMsg=IDS_FAIL_START_CERTSVC; goto ErrorWithHResultReturn; } //make sure the CA is up running for (dwWaitCounter=0; dwWaitCounter < pCEPWizardInfo->dwServiceWait; dwWaitCounter++) { if (!IsCaRunning()) Sleep(1000); else break; } if (pCEPWizardInfo->dwServiceWait == dwWaitCounter) { idsMsg=IDS_CAN_NOT_START_CA; goto ErrorWithHResultReturn; } //************************************************************************************ //Add the EventLog Source if(S_OK != AddLogSourceToRegistry(L"%SystemRoot%\\System32\\Certsrv\\Mscep\\mscep.dll")) { idsMsg=IDS_FAIL_REG_EVENT_LOG; goto ErrorWithHResultReturn; } //************************************************************************************ //success //inform the user of the password location and URL dwSize=0; GetComputerNameExW(ComputerNamePhysicalDnsHostname, NULL, &dwSize); pwszComputerName=(LPWSTR)malloc(dwSize * sizeof(WCHAR)); if(NULL==pwszComputerName) { idsMsg=IDS_NO_MEMORY; goto ErrorReturn; } if(!GetComputerNameExW(ComputerNamePhysicalDnsHostname, pwszComputerName, &dwSize)) { idsMsg=IDS_FAIL_GET_COMPUTER_NAME; goto ErrorWithWin32Return; } if(!FormatMessageUnicode(&pwszText, IDS_CEP_SUCCESS_INFO, pwszComputerName, CEP_DIR_NAME, CEP_DLL_NAME)) { idsMsg=IDS_NO_MEMORY; goto ErrorWithWin32Return; } wszTitle[0]=L'\0'; LoadStringU(g_hModule, IDS_WIZARD_CAPTION, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0])); MessageBoxU(hWnd, pwszText, wszTitle, MB_OK | MB_APPLMODAL); fResult=TRUE; CommonReturn: if(pUserInfo) { LocalFree(pUserInfo); } if(pwszText) LocalFree((HLOCAL)pwszText); if(pwszComputerName) free(pwszComputerName); if(pwszRADN) free(pwszRADN); return fResult; ErrorReturn: fResult=FALSE; CEPMessageBox(hWnd, idsMsg, MB_ICONERROR|MB_OK|MB_APPLMODAL); goto CommonReturn; ErrorWithHResultReturn: fResult=FALSE; CEPErrorMessageBox(hWnd, idsMsg, hr, MB_ICONERROR|MB_OK|MB_APPLMODAL); goto CommonReturn; ErrorWithWin32Return: fResult=FALSE; hr=HRESULT_FROM_WIN32(GetLastError()); CEPErrorMessageBox(hWnd, idsMsg, hr, MB_ICONERROR|MB_OK|MB_APPLMODAL); goto CommonReturn; } //----------------------------------------------------------------------- // // CEPGetCSPInformation // // We initialize the following members of CEP_WIZARD_INFO: // // CEP_CSP_INFO *rgCSPInfo; // DWORD dwCSPCount; // DWORD dwSignProvIndex; // DWORD dwSignKeySize; // DWORD dwEncryptProvIndex; // DWORD dwEncryptKeySize; // // // typedef struct _CEP_CSP_INFO //{ // LPWSTR pwszCSPName; // DWORD dwCSPType; // BOOL fSignature; // BOOL fExchange; // DWORD dwMaxSign; //Max key length of signature // DWORD dwMinSign; //Min key length of signature // DWORD dwDefaultSign; //default key length of signature // DWORD dwMaxEncrypt; // DWORD dwMinEncrypt; // DWORD dwDefaultEncrypt; // DWORD *pdwSignList; //the table of possible signing key length // DWORD dwSignCount; //the count of entries in the table // DWORD *pdwEncryptList; // DWORD dwEncryptCount; //}CEP_CSP_INFO; // // //------------------------------------------------------------------------ BOOL WINAPI CEPGetCSPInformation(CEP_WIZARD_INFO *pCEPWizardInfo) { BOOL fResult=FALSE; DWORD dwCSPIndex=0; DWORD dwProviderType=0; DWORD cbSize=0; DWORD dwFlags=0; DWORD dwIndex=0; int iDefaultSignature=-1; int iDefaultEncryption=-1; PROV_ENUMALGS_EX paramData; CEP_CSP_INFO *pCSPInfo=NULL; HCRYPTPROV hProv = NULL; //enum all the providers on the system while(CryptEnumProvidersU( dwCSPIndex, NULL, 0, &dwProviderType, NULL, &cbSize)) { pCSPInfo=(CEP_CSP_INFO *)malloc(sizeof(CEP_CSP_INFO)); if(NULL == pCSPInfo) goto MemoryErr; memset(pCSPInfo, 0, sizeof(CEP_CSP_INFO)); pCSPInfo->pwszCSPName=(LPWSTR)malloc(cbSize); if(NULL==(pCSPInfo->pwszCSPName)) goto MemoryErr; //get the CSP name and the type if(!CryptEnumProvidersU( dwCSPIndex, NULL, 0, &(pCSPInfo->dwCSPType), pCSPInfo->pwszCSPName, &cbSize)) goto TryNext; if(!CryptAcquireContextU(&hProv, NULL, pCSPInfo->pwszCSPName, pCSPInfo->dwCSPType, CRYPT_VERIFYCONTEXT)) goto TryNext; //get the max/min of key length for both signature and encryption dwFlags=CRYPT_FIRST; cbSize=sizeof(paramData); memset(¶mData, 0, sizeof(PROV_ENUMALGS_EX)); while(CryptGetProvParam( hProv, PP_ENUMALGS_EX, (BYTE *) ¶mData, &cbSize, dwFlags)) { if (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(paramData.aiAlgid)) { pCSPInfo->fSignature=TRUE; pCSPInfo->dwMaxSign = paramData.dwMaxLen; pCSPInfo->dwMinSign = paramData.dwMinLen; } if (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(paramData.aiAlgid)) { pCSPInfo->fEncryption=TRUE; pCSPInfo->dwMaxEncrypt = paramData.dwMaxLen; pCSPInfo->dwMinEncrypt = paramData.dwMinLen; } dwFlags=0; cbSize=sizeof(paramData); memset(¶mData, 0, sizeof(PROV_ENUMALGS_EX)); } //the min/max has to within the limit if(pCSPInfo->fSignature) { if(pCSPInfo->dwMaxSign < g_rgdwSmallKeyLength[0]) pCSPInfo->fSignature=FALSE; if(pCSPInfo->dwMinSign > g_rgdwKeyLength[g_dwKeyLengthCount-1]) pCSPInfo->fSignature=FALSE; } if(pCSPInfo->fEncryption) { if(pCSPInfo->dwMaxEncrypt < g_rgdwSmallKeyLength[0]) pCSPInfo->fEncryption=FALSE; if(pCSPInfo->dwMinEncrypt > g_rgdwKeyLength[g_dwKeyLengthCount-1]) pCSPInfo->fEncryption=FALSE; } if((FALSE == pCSPInfo->fEncryption) && (FALSE==pCSPInfo->fSignature)) goto TryNext; //decide the default key length for(dwIndex=0; dwIndexfSignature) && (0==pCSPInfo->dwDefaultSign)) { if((g_rgdwDefaultKey[dwIndex] >= pCSPInfo->dwMinSign) && (g_rgdwDefaultKey[dwIndex] <= pCSPInfo->dwMaxSign) ) pCSPInfo->dwDefaultSign=g_rgdwDefaultKey[dwIndex]; } if((pCSPInfo->fEncryption) && (0==pCSPInfo->dwDefaultEncrypt)) { if((g_rgdwDefaultKey[dwIndex] >= pCSPInfo->dwMinEncrypt) && (g_rgdwDefaultKey[dwIndex] <= pCSPInfo->dwMaxEncrypt) ) pCSPInfo->dwDefaultEncrypt=g_rgdwDefaultKey[dwIndex]; } } //make sure that we have find a default if((pCSPInfo->fSignature) && (0==pCSPInfo->dwDefaultSign)) goto TryNext; if((pCSPInfo->fEncryption) && (0==pCSPInfo->dwDefaultEncrypt)) goto TryNext; //decide the display list if(pCSPInfo->fSignature) { if(pCSPInfo->dwMaxSign <= g_rgdwSmallKeyLength[g_dwSmallKeyLengthCount-1]) { pCSPInfo->pdwSignList=g_rgdwSmallKeyLength; pCSPInfo->dwSignCount=g_dwSmallKeyLengthCount; } else { pCSPInfo->pdwSignList=g_rgdwKeyLength; pCSPInfo->dwSignCount=g_dwKeyLengthCount; } } if(pCSPInfo->fEncryption) { if(pCSPInfo->dwMaxEncrypt <= g_rgdwSmallKeyLength[g_dwSmallKeyLengthCount-1]) { pCSPInfo->pdwEncryptList=g_rgdwSmallKeyLength; pCSPInfo->dwEncryptCount=g_dwSmallKeyLengthCount; } else { pCSPInfo->pdwEncryptList=g_rgdwKeyLength; pCSPInfo->dwEncryptCount=g_dwKeyLengthCount; } } //the CSP looks good (pCEPWizardInfo->dwCSPCount)++; //realloc to mapped to LocalRealloc which does not take NULL if(1 == pCEPWizardInfo->dwCSPCount) pCEPWizardInfo->rgCSPInfo=(CEP_CSP_INFO *)malloc(sizeof(CEP_CSP_INFO)); else pCEPWizardInfo->rgCSPInfo=(CEP_CSP_INFO *)realloc(pCEPWizardInfo->rgCSPInfo, (pCEPWizardInfo->dwCSPCount) * sizeof(CEP_CSP_INFO)); if(NULL==pCEPWizardInfo->rgCSPInfo) { pCEPWizardInfo->dwCSPCount=0; goto MemoryErr; } memcpy(&(pCEPWizardInfo->rgCSPInfo[(pCEPWizardInfo->dwCSPCount)-1]), pCSPInfo, sizeof(CEP_CSP_INFO)); free(pCSPInfo); pCSPInfo=NULL; //we default to use RSA_FULL if(0 == _wcsicmp(pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwCSPCount-1].pwszCSPName, MS_DEF_PROV_W)) { if(pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwCSPCount-1].fSignature) { iDefaultSignature=pCEPWizardInfo->dwCSPCount-1; } if(pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwCSPCount-1].fEncryption) { iDefaultEncryption=pCEPWizardInfo->dwCSPCount-1; } } TryNext: cbSize=0; dwCSPIndex++; if(pCSPInfo) { if(pCSPInfo->pwszCSPName) free(pCSPInfo->pwszCSPName); free(pCSPInfo); } pCSPInfo=NULL; if(hProv) CryptReleaseContext(hProv, 0); hProv=NULL; } //we need to have some valid data if((0==pCEPWizardInfo->dwCSPCount) || (NULL==pCEPWizardInfo->rgCSPInfo)) goto InvalidArgErr; //get the default CSP selection if(-1 != iDefaultSignature) pCEPWizardInfo->dwSignProvIndex=iDefaultSignature; else { //find the 1st signature CSP for(dwIndex=0; dwIndex < pCEPWizardInfo->dwCSPCount; dwIndex++) { if(pCEPWizardInfo->rgCSPInfo[dwIndex].fSignature) { pCEPWizardInfo->dwSignProvIndex=dwIndex; break; } //we do no have signature CSPs if(dwIndex == pCEPWizardInfo->dwCSPCount) goto InvalidArgErr; } } pCEPWizardInfo->dwSignKeyLength=pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwSignProvIndex].dwDefaultSign; if(-1 != iDefaultEncryption) pCEPWizardInfo->dwEncryptProvIndex=iDefaultEncryption; else { //find the 1st exchange CSP for(dwIndex=0; dwIndex < pCEPWizardInfo->dwCSPCount; dwIndex++) { if(pCEPWizardInfo->rgCSPInfo[dwIndex].fEncryption) { pCEPWizardInfo->dwEncryptProvIndex=dwIndex; break; } //we do no have encryption CSPs if(dwIndex == pCEPWizardInfo->dwCSPCount) goto InvalidArgErr; } } pCEPWizardInfo->dwEncryptKeyLength=pCEPWizardInfo->rgCSPInfo[pCEPWizardInfo->dwEncryptProvIndex].dwDefaultEncrypt; fResult=TRUE; CommonReturn: return fResult; ErrorReturn: if(pCSPInfo) { if(pCSPInfo->pwszCSPName) free(pCSPInfo->pwszCSPName); free(pCSPInfo); } if(hProv) CryptReleaseContext(hProv, 0); if(pCEPWizardInfo->rgCSPInfo) { for(dwIndex=0; dwIndex < pCEPWizardInfo->dwCSPCount; dwIndex++) { if(pCEPWizardInfo->rgCSPInfo[dwIndex].pwszCSPName) free(pCEPWizardInfo->rgCSPInfo[dwIndex].pwszCSPName); } free(pCEPWizardInfo->rgCSPInfo); } pCEPWizardInfo->dwCSPCount=0; pCEPWizardInfo->rgCSPInfo=NULL; fResult=FALSE; goto CommonReturn; SET_ERROR(MemoryErr, E_OUTOFMEMORY); SET_ERROR(InvalidArgErr, E_INVALIDARG); } //----------------------------------------------------------------------- // // UpdateCEPRegistry // //------------------------------------------------------------------------ BOOL WINAPI UpdateCEPRegistry(BOOL fPassword, BOOL fEnterpriseCA) { BOOL fResult=FALSE; DWORD dwDisposition=0; LPWSTR pwszReg[]={MSCEP_REFRESH_LOCATION, MSCEP_PASSWORD_LOCATION, MSCEP_PASSWORD_MAX_LOCATION, MSCEP_PASSWORD_VALIDITY_LOCATION, MSCEP_CACHE_REQUEST_LOCATION, MSCEP_CATYPE_LOCATION}; DWORD dwRegCount=0; DWORD dwRegIndex=0; HKEY hKey=NULL; //we delete all existing CEP related registry keys dwRegCount=sizeof(pwszReg)/sizeof(pwszReg[0]); for(dwRegIndex=0; dwRegIndex < dwRegCount; dwRegIndex++) { RegDeleteKeyU(HKEY_LOCAL_MACHINE, pwszReg[dwRegIndex]); } //password if (ERROR_SUCCESS != RegCreateKeyExU( HKEY_LOCAL_MACHINE, MSCEP_PASSWORD_LOCATION, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition)) goto RegErr; if(fPassword) dwDisposition=1; else dwDisposition=0; if(ERROR_SUCCESS != RegSetValueExU( hKey, MSCEP_KEY_PASSWORD, 0, REG_DWORD, (BYTE *)&dwDisposition, sizeof(dwDisposition))) goto RegErr; if(hKey) RegCloseKey(hKey); hKey=NULL; //caType dwDisposition=0; if (ERROR_SUCCESS != RegCreateKeyExU( HKEY_LOCAL_MACHINE, MSCEP_CATYPE_LOCATION, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition)) goto RegErr; if(fEnterpriseCA) dwDisposition=1; else dwDisposition=0; if(ERROR_SUCCESS != RegSetValueExU( hKey, MSCEP_KEY_CATYPE, 0, REG_DWORD, (BYTE *)&dwDisposition, sizeof(dwDisposition))) goto RegErr; fResult=TRUE; CommonReturn: if(hKey) RegCloseKey(hKey); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(RegErr); } //----------------------------------------------------------------------- // // EmptyCEPStore // //------------------------------------------------------------------------ BOOL WINAPI EmptyCEPStore() { BOOL fResult=TRUE; HCERTSTORE hCEPStore=NULL; PCCERT_CONTEXT pCurCert=NULL; if(NULL == (hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, ENCODE_TYPE, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, CEP_STORE_NAME))) return TRUE; if(NULL != (pCurCert=CertEnumCertificatesInStore(hCEPStore, NULL))) { CertFreeCertificateContext(pCurCert); fResult=FALSE; } CertCloseStore(hCEPStore, 0); return fResult; } //----------------------------------------------------------------------- // // RemoveRACertificates // //------------------------------------------------------------------------ BOOL WINAPI RemoveRACertificates() { PCCERT_CONTEXT pCurCert=NULL; PCCERT_CONTEXT pPreCert=NULL; PCCERT_CONTEXT pDupCert=NULL; BOOL fResult=TRUE; HCERTSTORE hCEPStore=NULL; if(hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, ENCODE_TYPE, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, CEP_STORE_NAME)) { while(pCurCert=CertEnumCertificatesInStore(hCEPStore, pPreCert)) { if(pDupCert=CertDuplicateCertificateContext(pCurCert)) { if(!CertDeleteCertificateFromStore(pDupCert)) { fResult=FALSE; } pDupCert=NULL; } else fResult=FALSE; pPreCert=pCurCert; } CertCloseStore(hCEPStore, 0); } return fResult; } //----------------------------------------------------------------------- // // FreeCEPWizardInfo // //------------------------------------------------------------------------ void WINAPI FreeCEPWizardInfo(CEP_WIZARD_INFO *pCEPWizardInfo) { DWORD dwIndex=0; if(pCEPWizardInfo) { DestroyFonts(pCEPWizardInfo->hBigBold, pCEPWizardInfo->hBold); for(dwIndex=0; dwIndexrgpwszName[dwIndex]) free(pCEPWizardInfo->rgpwszName[dwIndex]); } if(pCEPWizardInfo->rgCSPInfo) { for(dwIndex=0; dwIndex < pCEPWizardInfo->dwCSPCount; dwIndex++) { if(pCEPWizardInfo->rgCSPInfo[dwIndex].pwszCSPName) free(pCEPWizardInfo->rgCSPInfo[dwIndex].pwszCSPName); } free(pCEPWizardInfo->rgCSPInfo); } if(pCEPWizardInfo->pwszUserName) { free(pCEPWizardInfo->pwszUserName); } if(pCEPWizardInfo->pwszPassword) { SecureZeroMemory(pCEPWizardInfo->pwszPassword, sizeof(WCHAR) * wcslen(pCEPWizardInfo->pwszPassword)); free(pCEPWizardInfo->pwszPassword); } if(pCEPWizardInfo->hAccountToken) { CloseHandle(pCEPWizardInfo->hAccountToken); } if(pCEPWizardInfo->pIDsObjectPicker) { (pCEPWizardInfo->pIDsObjectPicker)->Release(); } memset(pCEPWizardInfo, 0, sizeof(CEP_WIZARD_INFO)); } } //----------------------------------------------------------------------- // // CEPWizardInit // //------------------------------------------------------------------------ BOOL WINAPI CEPWizardInit() { INITCOMMONCONTROLSEX initcomm = { sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES }; return InitCommonControlsEx(&initcomm); } //----------------------------------------------------------------------- // // IsValidInstallation // //------------------------------------------------------------------------ BOOL WINAPI IsValidInstallation(UINT *pidsMsg) { if(!IsNT5()) { *pidsMsg=IDS_NO_NT5; return FALSE; } if(!IsIISInstalled()) { *pidsMsg=IDS_NO_IIS; return FALSE; } if(!IsGoodCaInstalled()) { *pidsMsg=IDS_NO_GOOD_CA; return FALSE; } return TRUE; } //----------------------------------------------------------------------- // // CEPErrorMessageBox // //------------------------------------------------------------------------ int WINAPI CEPErrorMessageBox( HWND hWnd, UINT idsReason, HRESULT hr, UINT uType ) { return CEPErrorMessageBoxEx(hWnd, idsReason, hr, uType, IDS_CEP_ERROR_MSG_HR, IDS_CEP_ERROR_MSG); } //----------------------------------------------------------------------- // // CEPErrorMessageBoxEx // //------------------------------------------------------------------------ int WINAPI CEPErrorMessageBoxEx( HWND hWnd, UINT idsReason, HRESULT hr, UINT uType, UINT idsFormat1, UINT idsFormat2 ) { WCHAR wszReason[MAX_STRING_SIZE]; WCHAR wszCaption[MAX_STRING_SIZE]; UINT intReturn=0; LPWSTR pwszText=NULL; LPWSTR pwszErrorMsg=NULL; if(!LoadStringU(g_hModule, IDS_MEG_CAPTION, wszCaption, sizeof(wszCaption)/sizeof(WCHAR))) goto CLEANUP; if(!LoadStringU(g_hModule, idsReason, wszReason, sizeof(wszReason)/sizeof(WCHAR))) goto CLEANUP; if(!FAILED(hr)) hr=E_FAIL; //using W version because this is a NT5 only function call if(FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPWSTR) &pwszErrorMsg, 0, NULL)) { if(!FormatMessageUnicode(&pwszText, idsFormat1, wszReason, pwszErrorMsg)) goto CLEANUP; } else { if(!FormatMessageUnicode(&pwszText, idsFormat2, wszReason)) goto CLEANUP; } intReturn=MessageBoxU(hWnd, pwszText, wszCaption, uType); CLEANUP: if(pwszText) LocalFree((HLOCAL)pwszText); if(pwszErrorMsg) LocalFree((HLOCAL)pwszErrorMsg); return intReturn; } //----------------------------------------------------------------------- // // CEPMessageBox // //------------------------------------------------------------------------ int WINAPI CEPMessageBox( HWND hWnd, UINT idsText, UINT uType ) { WCHAR wszText[MAX_STRING_SIZE]; WCHAR wszCaption[MAX_STRING_SIZE]; UINT intReturn=0; if(!LoadStringU(g_hModule, IDS_MEG_CAPTION, wszCaption, sizeof(wszCaption)/sizeof(WCHAR))) return 0; if(!LoadStringU(g_hModule, idsText, wszText, sizeof(wszText)/sizeof(WCHAR))) return 0; intReturn=MessageBoxU(hWnd, wszText, wszCaption, uType); return intReturn; } //-------------------------------------------------------------------------- // // SetControlFont // //-------------------------------------------------------------------------- void WINAPI SetControlFont( IN HFONT hFont, IN HWND hwnd, IN INT nId ) { if( hFont ) { HWND hwndControl = GetDlgItem(hwnd, nId); if( hwndControl ) { SetWindowFont(hwndControl, hFont, TRUE); } } } //-------------------------------------------------------------------------- // // SetupFonts // //-------------------------------------------------------------------------- BOOL WINAPI SetupFonts( IN HINSTANCE hInstance, IN HWND hwnd, IN HFONT *pBigBoldFont, IN HFONT *pBoldFont ) { // // Create the fonts we need based on the dialog font // NONCLIENTMETRICS ncm = {0}; ncm.cbSize = sizeof(ncm); if(!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) return FALSE; LOGFONT BigBoldLogFont = ncm.lfMessageFont; LOGFONT BoldLogFont = ncm.lfMessageFont; // // Create Big Bold Font and Bold Font // BigBoldLogFont.lfWeight = FW_BOLD; BoldLogFont.lfWeight = FW_BOLD; INT BigBoldFontSize = 12; HDC hdc = GetDC( hwnd ); if( hdc ) { BigBoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * BigBoldFontSize / 72); *pBigBoldFont = CreateFontIndirect(&BigBoldLogFont); *pBoldFont = CreateFontIndirect(&BoldLogFont); ReleaseDC(hwnd,hdc); if(*pBigBoldFont && *pBoldFont) return TRUE; else { if( *pBigBoldFont ) { DeleteObject(*pBigBoldFont); *pBigBoldFont=NULL; } if( *pBoldFont ) { DeleteObject(*pBoldFont); *pBoldFont=NULL; } return FALSE; } } return FALSE; } //-------------------------------------------------------------------------- // // DestroyFonts // //-------------------------------------------------------------------------- void WINAPI DestroyFonts( IN HFONT hBigBoldFont, IN HFONT hBoldFont ) { if( hBigBoldFont ) { DeleteObject( hBigBoldFont ); } if( hBoldFont ) { DeleteObject( hBoldFont ); } } //-------------------------------------------------------------------------- // // FormatMessageUnicode // //-------------------------------------------------------------------------- BOOL WINAPI FormatMessageUnicode(LPWSTR *ppwszFormat,UINT ids,...) { // get format string from resources WCHAR wszFormat[1000]; va_list argList; DWORD cbMsg=0; BOOL fResult=FALSE; HRESULT hr=S_OK; if(NULL == ppwszFormat) goto InvalidArgErr; if(!LoadStringU(g_hModule, ids, wszFormat, sizeof(wszFormat)/sizeof(WCHAR))) goto LoadStringError; // format message into requested buffer va_start(argList, ids); cbMsg = FormatMessageU( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, wszFormat, 0, // dwMessageId 0, // dwLanguageId (LPWSTR) (ppwszFormat), 0, // minimum size to allocate &argList); va_end(argList); if(!cbMsg) goto FormatMessageError; fResult=TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(LoadStringError); TRACE_ERROR(FormatMessageError); SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // AddLogSourceToRegistry // //-------------------------------------------------------------------------- HRESULT WINAPI AddLogSourceToRegistry(LPWSTR pwszMsgDLL) { DWORD dwError=ERROR_SUCCESS; DWORD dwData=0; WCHAR const *pwszRegPath = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; WCHAR NameBuf[MAX_STRING_SIZE]; HKEY hkey = NULL; wcscpy(NameBuf, pwszRegPath); wcscat(NameBuf, MSCEP_EVENT_LOG); // Create a new key for our application if(ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE, NameBuf, &hkey)) { if(ERROR_SUCCESS != (dwError = RegCreateKey(HKEY_LOCAL_MACHINE, NameBuf, &hkey))) goto CLEANUP; } // Add the Event-ID message-file name to the subkey dwError = RegSetValueEx( hkey, L"EventMessageFile", 0, REG_EXPAND_SZ, (const BYTE *) pwszMsgDLL, (wcslen(pwszMsgDLL) + 1) * sizeof(WCHAR)); if(ERROR_SUCCESS != dwError) goto CLEANUP; // Set the supported types flags and add it to the subkey dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; dwError = RegSetValueEx( hkey, L"TypesSupported", 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD)); if(ERROR_SUCCESS != dwError) goto CLEANUP; dwError=ERROR_SUCCESS; CLEANUP: if (NULL != hkey) { RegCloseKey(hkey); } return(HRESULT_FROM_WIN32(dwError)); } LPWSTR GetAccountDomainName(BOOL fDC) /*++ Routine Description: Returns the name of the account domain for this machine. For workstatations, the account domain is the netbios computer name. For DCs, the account domain is the netbios domain name. Arguments: None. Return Values: Returns a pointer to the name. The name should be free using NetApiBufferFree. NULL - on error. --*/ { DWORD WinStatus; LPWSTR AllocatedName = NULL; // // If this machine is a domain controller, // get the domain name. // if ( fDC ) { WinStatus = NetpGetDomainName( &AllocatedName ); if ( WinStatus != NO_ERROR ) { SetLastError(WinStatus); return NULL; } // // Otherwise, the 'account domain' is the computername // } else { WinStatus = NetpGetComputerName( &AllocatedName ); if ( WinStatus != NO_ERROR ) { SetLastError(WinStatus); return NULL; } } return AllocatedName; }