//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: cryptui.cpp // // Contents: Cert Server wrapper routines // //--------------------------------------------------------------------------- #include #pragma hdrstop #include "certmsg.h" #include "clibres.h" #include "setupids.h" #include "tfc.h" #include "Windowsx.h" #define __dwFILE__ __dwFILE_INITLIB_CERTUI_CPP__ HRESULT myGetConfigStringFromPicker( OPTIONAL IN HWND hwndParent, OPTIONAL IN WCHAR const *pwszPrompt, OPTIONAL IN WCHAR const *pwszTitle, OPTIONAL IN WCHAR const *pwszSharedFolder, IN BOOL fUseDS, OUT WCHAR **ppwszConfig) { HRESULT hr; DWORD dwCACount; CRYPTUI_CA_CONTEXT const *pCAContext = NULL; hr = myGetConfigFromPicker( hwndParent, pwszPrompt, pwszTitle, pwszSharedFolder, fUseDS, FALSE, &dwCACount, &pCAContext); _JumpIfError(hr, error, "myGetConfigFromPicker"); if (NULL == pCAContext) { hr = E_INVALIDARG; _JumpIfError(hr, error, "Internal error: myGetConfigFromPicker"); } hr = myFormConfigString( pCAContext->pwszCAMachineName, pCAContext->pwszCAName, ppwszConfig); _JumpIfError(hr, error, "myFormConfigString"); error: if (NULL != pCAContext) { CryptUIDlgFreeCAContext(pCAContext); } return(hr); } HRESULT myUIGetWindowText( IN HWND hwndCtrl, OUT WCHAR **ppwszText) { HRESULT hr; LRESULT len; DWORD i; WCHAR *pwszBegin; WCHAR *pwszEnd; WCHAR *pwszText = NULL; CSASSERT(NULL != hwndCtrl && NULL != ppwszText); // init *ppwszText = NULL; // get text string size len = SendMessage(hwndCtrl, WM_GETTEXTLENGTH, 0, 0); if (0 < len) { pwszText = (WCHAR*)LocalAlloc(LMEM_FIXED, (UINT)((len+1) * sizeof(WCHAR))); if (NULL == pwszText) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } if (len != SendMessage(hwndCtrl, WM_GETTEXT, (WPARAM)len+1, (LPARAM)pwszText)) { hr = HRESULT_FROM_WIN32(ERROR_BAD_LENGTH); _JumpError(hr, error, "Internal error"); } } else { goto done; } // trim trailing and heading blank strings pwszBegin = pwszText; pwszEnd = &pwszText[wcslen(pwszText) - 1]; while (pwszEnd > pwszBegin && iswspace(*pwszEnd) ) { *pwszEnd = L'\0'; --pwszEnd; } while (pwszBegin <= pwszEnd && L'\0' != *pwszBegin && iswspace(*pwszBegin) ) { ++pwszBegin; } if (pwszEnd >= pwszBegin) { MoveMemory( pwszText, pwszBegin, (SAFE_SUBTRACT_POINTERS(pwszEnd, pwszBegin) + 2) * sizeof(WCHAR)); } else { goto done; } *ppwszText = pwszText; pwszText = NULL; done: hr = S_OK; error: if (NULL != pwszText) { LocalFree(pwszText); } return hr; } // following code for CA selection UI control HRESULT UICASelectionUpdateCAList( HWND hwndList, WCHAR const *pwszzCAList) { HRESULT hr; int nItem; WCHAR const *pwszCA = pwszzCAList; // remove current list SendMessage(hwndList, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0); // add to list while (NULL != pwszCA && L'\0' != pwszCA[0]) { nItem = (INT)SendMessage( hwndList, CB_ADDSTRING, (WPARAM) 0, (LPARAM) pwszCA); if (LB_ERR == nItem) { hr = myHLastError(); _JumpError(hr, error, "SendMessage"); } pwszCA += wcslen(pwszCA) + 1; } if (NULL != pwszzCAList) { // attempt to choose the 1st one as default SendMessage(hwndList, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); } hr = S_OK; error: return hr; } LRESULT CALLBACK myUICASelectionComputerEditFilterHook( HWND hwndComputer, UINT iMsg, WPARAM wParam, LPARAM lParam) { LRESULT lr; HRESULT hr; CERTSRVUICASELECTION *pData = (CERTSRVUICASELECTION*) GetWindowLongPtr(hwndComputer, GWLP_USERDATA); CSASSERT(NULL != pData); switch(iMsg) { case WM_CHAR: // empty ca list hr = UICASelectionUpdateCAList(pData->hwndCAList, NULL); _PrintIfError(hr, "UICASelectionUpdateCAList"); break; } lr = CallWindowProc( pData->pfnUICASelectionComputerWndProcs, hwndComputer, iMsg, wParam, lParam); //error: return lr; } HRESULT myUICAConditionallyDisplayEnterpriseWarning( IN CERTSRVUICASELECTION *pData) { HRESULT hr = S_OK; CAINFO *pCAInfo = NULL; BOOL fCoInit = FALSE; hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, Ret, "CoInitialize"); } fCoInit = TRUE; hr = S_OK; // don't want to return this error pData->CAType = ENUM_UNKNOWN_CA; // pinging specific CA is done in both cases -- reselect or new machine pointed at WCHAR szCA[MAX_PATH]; WCHAR szComputer[MAX_PATH]; szCA[0]=L'\0'; szComputer[0]=L'\0'; int iSel; iSel = ComboBox_GetCurSel(pData->hwndCAList); ComboBox_GetLBText(pData->hwndCAList, iSel, szCA); GetWindowText(pData->hwndComputerEdit, szComputer, MAX_PATH); if ((szCA[0]==L'\0') || (szComputer[0]==L'\0')) { ShowWindow(GetDlgItem(pData->hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), SW_HIDE); goto Ret; } hr = myPingCertSrv( szCA, szComputer, NULL, NULL, &pCAInfo, NULL, NULL); if ((hr == S_OK) && (pCAInfo != NULL)) { // copy catype into returned data pData->CAType = pCAInfo->CAType; if (IsEnterpriseCA(pCAInfo->CAType)) { ShowWindow(GetDlgItem(pData->hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), SW_SHOW); } else { ShowWindow(GetDlgItem(pData->hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), SW_HIDE); } } Ret: if (NULL != pCAInfo) LocalFree(pCAInfo); if (fCoInit) CoUninitialize(); return hr; } HRESULT myUICAHandleCAListDropdown( IN int iNotification, IN OUT CERTSRVUICASELECTION *pData, IN OUT BOOL *pfComputerChange) { HRESULT hr; WCHAR *pwszComputer = NULL; WCHAR *pwszzCAList = NULL; BOOL fCoInit = FALSE; WCHAR *pwszDnsName = NULL; DWORD dwVersion; CSASSERT(NULL != pData); // if this isn't a focus or selection change and computer name stayed same, nothing to do if ((CBN_SELCHANGE != iNotification) && !*pfComputerChange) { goto done; } ShowWindow(GetDlgItem(pData->hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), SW_HIDE); SetCursor(LoadCursor(NULL, IDC_WAIT)); if (NULL == pData->hwndComputerEdit) { // not init goto done; } // make sure computer edit field is not empty hr = myUIGetWindowText(pData->hwndComputerEdit, &pwszComputer); _JumpIfError(hr, error, "myUIGetWindowText"); if (NULL == pwszComputer) { goto done; } if (*pfComputerChange) { // ping to get ca list hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "CoInitialize"); } fCoInit = TRUE; // reset once ca list is updated. Do this now to prevent recursion *pfComputerChange = FALSE; hr = myPingCertSrv( pwszComputer, NULL, &pwszzCAList, NULL, NULL, &dwVersion, &pwszDnsName); CSILOG(hr, IDS_ILOG_GETCANAME, pwszComputer, NULL, NULL); if (S_OK != hr) { // make sure null CSASSERT(NULL == pwszzCAList); // can't ping the ca. Set focus now to prevent recursion SetFocus(pData->hwndComputerEdit); SendMessage(pData->hwndComputerEdit, EM_SETSEL, 0, -1); CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_PINGCA_FAIL, hr, NULL); } else if(dwVersion<2 && pData->fWebProxySetup) { //bug 262316: don't allow installing Whistler proxy to an older CA hr = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION); if(pwszzCAList) { LocalFree(pwszzCAList); pwszzCAList = NULL; } SetFocus(pData->hwndComputerEdit); SendMessage(pData->hwndComputerEdit, EM_SETSEL, 0, -1); CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_OLD_CA, hr, NULL); } if (NULL!=pwszDnsName && 0!=wcscmp(pwszComputer, pwszDnsName)) { // update computer SendMessage(pData->hwndComputerEdit, WM_SETTEXT, 0, (LPARAM)pwszDnsName); } // update ca list hr = UICASelectionUpdateCAList(pData->hwndCAList, pwszzCAList); _JumpIfError(hr, error, "UICASelectionUpdateCAList"); } // pinging specific CA is done in both cases -- reselect or new machine pointed at hr = myUICAConditionallyDisplayEnterpriseWarning(pData); _PrintIfError(hr, "myUICAConditionallyDisplayEnterpriseWarning"); done: hr = S_OK; error: SetCursor(LoadCursor(NULL, IDC_ARROW)); if (fCoInit) { CoUninitialize(); } if (NULL != pwszzCAList) { LocalFree(pwszzCAList); } if (NULL != pwszComputer) { LocalFree(pwszComputer); } if (NULL != pwszDnsName) { LocalFree(pwszDnsName); } return hr; } HRESULT myInitUICASelectionControls( IN OUT CERTSRVUICASELECTION *pUICASelection, IN HINSTANCE hInstance, IN HWND hDlg, IN HWND hwndBrowseButton, IN HWND hwndComputerEdit, IN HWND hwndCAList, IN BOOL fDSCA, OUT BOOL *pfCAsExist) { HRESULT hr; PCCRYPTUI_CA_CONTEXT pCAContext = NULL; DWORD dwCACount; CString cstrText; SetCursor(LoadCursor(NULL, IDC_WAIT)); hr = myGetConfigFromPicker( hDlg, NULL, NULL, NULL, fDSCA, TRUE, // fCountOnly &dwCACount, &pCAContext); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (S_OK != hr) { dwCACount = 0; _PrintError(hr, "myGetConfigFromPicker"); } // enable/disable *pfCAsExist = 0 < dwCACount; EnableWindow(hwndBrowseButton, *pfCAsExist); // set computer edit control hook pUICASelection->pfnUICASelectionComputerWndProcs = (WNDPROC)SetWindowLongPtr(hwndComputerEdit, GWLP_WNDPROC, (LPARAM)myUICASelectionComputerEditFilterHook); pUICASelection->hInstance = hInstance; pUICASelection->hDlg = hDlg; pUICASelection->hwndComputerEdit = hwndComputerEdit; pUICASelection->hwndCAList = hwndCAList; // pass data to both controls SetWindowLongPtr(hwndComputerEdit, GWLP_USERDATA, (ULONG_PTR)pUICASelection); SetWindowLongPtr(hwndCAList, GWLP_USERDATA, (ULONG_PTR)pUICASelection); // by default, don't show Enterprise CA warning cstrText.LoadString(IDS_WARN_ENTERPRISE_REQUIREMENTS); SetWindowText(GetDlgItem(hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), cstrText); ShowWindow(GetDlgItem(hDlg, IDC_CLIENT_WARN_ENTERPRISE_REQUIREMENTS), SW_HIDE); if (NULL != pCAContext) { CryptUIDlgFreeCAContext(pCAContext); } hr = S_OK; //error: return hr; } HRESULT myUICAHandleCABrowseButton( CERTSRVUICASELECTION *pData, IN BOOL fUseDS, OPTIONAL IN int idsPickerTitle, OPTIONAL IN int idsPickerSubTitle, OPTIONAL OUT WCHAR **ppwszSharedFolder) { HRESULT hr = S_OK; PCCRYPTUI_CA_CONTEXT pCAContext = NULL; WCHAR *pwszSubTitle = NULL; WCHAR *pwszTitle = NULL; DWORD dwCACount; WCHAR *pwszzCAList = NULL; WCHAR *pwszComputer = NULL; WCHAR *pwszTemp = NULL; BOOL fCoInit = FALSE; DWORD dwVersion; if (NULL != ppwszSharedFolder) { *ppwszSharedFolder = NULL; } if (0 != idsPickerTitle) { hr = myLoadRCString(pData->hInstance, idsPickerTitle, &pwszTitle); if (S_OK != hr) { pwszTitle = NULL; _PrintError(hr, "myLoadRCString"); } } if (0 != idsPickerSubTitle) { hr = myLoadRCString(pData->hInstance, idsPickerSubTitle, &pwszSubTitle); if (S_OK != hr) { pwszSubTitle = NULL; _PrintError(hr, "myLoadRCString"); } } /* // REMOVED mattt 6/26/00: is this ever wanted: "Browse uses shared folder of machine editbox currently points at"? // just seems to make changing away from bad machine very very slow // get remote shared folder if possible hr = myUIGetWindowText(pData->hwndComputerEdit, &pwszComputer); _JumpIfError(hr, error, "myUIGetWindowText"); if (NULL != pwszComputer) { hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "CoInitialize"); } fCoInit = TRUE; // get shared folder path on remote machine here SetCursor(LoadCursor(NULL, IDC_WAIT)); hr = myPingCertSrv(pwszComputer, NULL, NULL, &pwszTemp, NULL, NULL, NULL); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (S_OK != hr) { CSASSERT(NULL == pwszTemp); _JumpError(hr, localsharedfolder, "myPingCertSrv"); } } localsharedfolder: */ hr = myGetConfigFromPicker( pData->hDlg, pwszSubTitle, pwszTitle, pwszTemp, fUseDS, FALSE, // fCountOnly &dwCACount, &pCAContext); if (S_OK != hr && HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr) { CSILOG(hr, IDS_ILOG_SELECTCA, NULL, NULL, NULL); _JumpError(hr, error, "myGetConfigFromPicker"); } if (S_OK != hr) goto done; if (NULL == pCAContext) { CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_CALIST_EMPTY, S_OK, NULL); SetWindowText(pData->hwndCAList, L""); SetFocus(pData->hwndComputerEdit); SendMessage(pData->hwndComputerEdit, EM_SETSEL, 0, -1); } else { CSILOG(hr, IDS_ILOG_SELECTCA, pCAContext->pwszCAMachineName, pCAContext->pwszCAName, NULL); // update computer SendMessage(pData->hwndComputerEdit, WM_SETTEXT, 0, (LPARAM)pCAContext->pwszCAMachineName); // construct a single multi string for list update DWORD len = wcslen(pCAContext->pwszCAName); pwszzCAList = (WCHAR*)LocalAlloc(LMEM_FIXED, (len+2) * sizeof(WCHAR)); if (NULL == pwszzCAList) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } wcscpy(pwszzCAList, pCAContext->pwszCAName); pwszzCAList[len+1] = '\0'; hr = UICASelectionUpdateCAList(pData->hwndCAList, pwszzCAList); _JumpIfError(hr, error, "UICASelectionUpdateCAList"); LocalFree(pwszzCAList); pwszzCAList = NULL; // this thread blocks paint message, send it before ping UpdateWindow(pData->hDlg); // ping the computer to see if found a matched ca if (!fCoInit) { hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "CoInitialize"); } fCoInit = TRUE; } SetCursor(LoadCursor(NULL, IDC_WAIT)); // ping to get ca list hr = myPingCertSrv( pCAContext->pwszCAMachineName, NULL, &pwszzCAList, NULL, NULL, &dwVersion, NULL); SetCursor(LoadCursor(NULL, IDC_ARROW)); CSILOG(hr, IDS_ILOG_GETCANAME, pCAContext->pwszCAMachineName, NULL, NULL); if (S_OK == hr) { //bug 262316: don't allow installing Whistler proxy to an older CA if(dwVersion<2 && pData->fWebProxySetup) { hr = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION); // focus on the CA list to trigger a verification of the CA SetFocus(pData->hwndCAList); } else { // ping successful WCHAR const *pwszPingCA = pwszzCAList; // go through the list to see if any match while (NULL != pwszPingCA && L'\0' != pwszPingCA[0]) { if (0 == wcscmp(pCAContext->pwszCAName, pwszPingCA)) { // found matched one goto done; } pwszPingCA += wcslen(pwszPingCA) + 1; } // if we get here, either the CA is offline or the machine is // offline and another machine is using the same IP address. CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_CANAME_NOT_MATCH, 0, NULL); // only empty combo edit field SetWindowText(pData->hwndCAList, L""); SetFocus(pData->hwndCAList); } } else { // can't ping the ca, selected an estranged ca CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_PINGCA_FAIL, hr, NULL); // empty list anyway hr = UICASelectionUpdateCAList(pData->hwndCAList, NULL); _JumpIfError(hr, error, "UICASelectionUpdateCAList"); SetFocus(pData->hwndComputerEdit); SendMessage(pData->hwndComputerEdit, EM_SETSEL, 0, -1); } } done: hr = myUICAConditionallyDisplayEnterpriseWarning(pData); _PrintIfError(hr, "myUICAConditionallyDisplayEnterpriseWarning"); if (NULL != ppwszSharedFolder) { *ppwszSharedFolder = pwszTemp; pwszTemp = NULL; } hr = S_OK; error: if (NULL != pwszzCAList) { LocalFree(pwszzCAList); } if (NULL != pwszSubTitle) { LocalFree(pwszSubTitle); } if (NULL != pwszTitle) { LocalFree(pwszTitle); } if (NULL != pwszTemp) { LocalFree(pwszTemp); } if (NULL != pwszComputer) { LocalFree(pwszComputer); } if (NULL != pCAContext) { CryptUIDlgFreeCAContext(pCAContext); } if (fCoInit) { CoUninitialize(); } return hr; } HRESULT myUICASelectionValidation( CERTSRVUICASELECTION *pData, BOOL *pfValidate) { HRESULT hr; WCHAR *pwszComputer = NULL; WCHAR *pwszCA = NULL; CSASSERT(NULL != pData); *pfValidate = FALSE; // first, make sure not empty hr = myUIGetWindowText(pData->hwndComputerEdit, &pwszComputer); _JumpIfError(hr, error, "myUIGetWindowText"); if (NULL == pwszComputer) { CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_COMPUTERNAME_EMPTY, 0, NULL); SetFocus(pData->hwndComputerEdit); goto done; } hr = myUIGetWindowText(pData->hwndCAList, &pwszCA); _JumpIfError(hr, error, "myUIGetWindowText"); if (NULL == pwszCA) { CertWarningMessageBox( pData->hInstance, FALSE, pData->hDlg, IDS_WRN_CANAME_EMPTY, 0, NULL); SetFocus(pData->hwndComputerEdit); SendMessage(pData->hwndComputerEdit, EM_SETSEL, 0, -1); goto done; } CSASSERT(pData->CAType != ENUM_UNKNOWN_CA); if (pData->CAType == ENUM_UNKNOWN_CA) { hr = E_UNEXPECTED; _JumpIfError(hr, error, "CAType not determined"); } // if hit here *pfValidate = TRUE; done: hr = S_OK; error: if (NULL != pwszComputer) { LocalFree(pwszComputer); } if (NULL != pwszCA) { LocalFree(pwszCA); } return hr; }