//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997-2001. // // File: ACRSLast.cpp // // Contents: Implementation of Auto Cert Request Wizard Completion Page // //---------------------------------------------------------------------------- #include "stdafx.h" #include #include "ACRSLast.h" #include "ACRSPSht.h" #include "storegpe.h" USE_HANDLE_MACROS("CERTMGR(ACRSLast.cpp)") #ifdef _DEBUG #ifndef ALPHA #define new DEBUG_NEW #endif #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Gross #define MAX_GPE_NAME_SIZE 40 ///////////////////////////////////////////////////////////////////////////// // ACRSCompletionPage property page IMPLEMENT_DYNCREATE (ACRSCompletionPage, CWizard97PropertyPage) ACRSCompletionPage::ACRSCompletionPage () : CWizard97PropertyPage (ACRSCompletionPage::IDD) { //{{AFX_DATA_INIT(ACRSCompletionPage) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT InitWizard97 (TRUE); } ACRSCompletionPage::~ACRSCompletionPage () { } void ACRSCompletionPage::DoDataExchange (CDataExchange* pDX) { CWizard97PropertyPage::DoDataExchange (pDX); //{{AFX_DATA_MAP(ACRSCompletionPage) DDX_Control (pDX, IDC_CHOICES_LIST, m_choicesList); DDX_Control (pDX, IDC_BOLD_STATIC, m_staticBold); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(ACRSCompletionPage, CWizard97PropertyPage) //{{AFX_MSG_MAP(ACRSCompletionPage) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // ACRSCompletionPage message handlers BOOL ACRSCompletionPage::OnInitDialog () { CWizard97PropertyPage::OnInitDialog (); m_staticBold.SetFont (&GetBigBoldFont ()); // Set up columns in list view int colWidths[NUM_COLS] = {150, 200}; VERIFY (m_choicesList.InsertColumn (COL_OPTION, L"", LVCFMT_LEFT, colWidths[COL_OPTION], COL_OPTION) != -1); VERIFY (m_choicesList.InsertColumn (COL_VALUE, L"", LVCFMT_LEFT, colWidths[COL_VALUE], COL_VALUE) != -1); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } BOOL ACRSCompletionPage::OnSetActive () { BOOL bResult = CWizard97PropertyPage::OnSetActive (); if ( bResult ) { // Remove all items then repopulate. ACRSWizardPropertySheet* pSheet = reinterpret_cast (m_pWiz); ASSERT (pSheet); if ( pSheet ) { // If edit mode and nothing changed, show disabled finish if ( pSheet->GetACR () && !pSheet->m_bEditModeDirty ) GetParent ()->PostMessage (PSM_SETWIZBUTTONS, 0, PSWIZB_DISABLEDFINISH | PSWIZB_BACK); else GetParent ()->PostMessage (PSM_SETWIZBUTTONS, 0, PSWIZB_FINISH | PSWIZB_BACK); if ( pSheet->IsDirty () ) pSheet->MarkAsClean (); VERIFY (m_choicesList.DeleteAllItems ()); CString text; LV_ITEM lvItem; int iItem = 0; // Display cert type selection VERIFY (text.LoadString (IDS_CERTIFICATE_TYPE_COLUMN_NAME)); ::ZeroMemory (&lvItem, sizeof (lvItem)); lvItem.mask = LVIF_TEXT; lvItem.iItem = iItem; lvItem.iSubItem = COL_OPTION; lvItem.pszText = (LPWSTR) (LPCWSTR) text; VERIFY (-1 != m_choicesList.InsertItem (&lvItem)); WCHAR** pawszPropertyValue = 0; HRESULT hResult = ::CAGetCertTypeProperty (pSheet->m_selectedCertType, CERTTYPE_PROP_FRIENDLY_NAME, &pawszPropertyValue); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) ) { if ( pawszPropertyValue[0] ) { VERIFY (m_choicesList.SetItemText (iItem, COL_VALUE, *pawszPropertyValue)); } VERIFY (SUCCEEDED (::CAFreeCertTypeProperty ( pSheet->m_selectedCertType, pawszPropertyValue))); } iItem++; // Display CA selection VERIFY (text.LoadString (IDS_CERTIFICATE_AUTHORITIES)); ::ZeroMemory (&lvItem, sizeof (lvItem)); lvItem.mask = LVIF_TEXT; lvItem.iSubItem = COL_OPTION; POSITION pos = 0; HCAINFO hCAInfo = 0; for (pos = pSheet->m_caInfoList.GetHeadPosition (); pos;) { lvItem.iItem = iItem; lvItem.pszText = (LPWSTR) (LPCWSTR) text; VERIFY (-1 != m_choicesList.InsertItem (&lvItem)); hCAInfo = pSheet->m_caInfoList.GetNext (pos); ASSERT (hCAInfo); if ( hCAInfo ) { hResult = ::CAGetCAProperty (hCAInfo, CA_PROP_DISPLAY_NAME, &pawszPropertyValue); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) ) { if ( pawszPropertyValue[0] ) { VERIFY (m_choicesList.SetItemText (iItem, COL_VALUE, *pawszPropertyValue)); } VERIFY (SUCCEEDED (::CAFreeCAProperty (hCAInfo, pawszPropertyValue))); } } text = L" "; // only the first one has text in it iItem++; } } } return bResult; } BOOL ACRSCompletionPage::OnWizardFinish () { BOOL bResult = TRUE; HRESULT hResult = S_OK; CWaitCursor waitCursor; ACRSWizardPropertySheet* pSheet = reinterpret_cast (m_pWiz); ASSERT (pSheet); if ( pSheet ) { // If edit mode and nothing changed, just return if ( pSheet->GetACR () && !pSheet->m_bEditModeDirty ) { ASSERT (0); return FALSE; } PCTL_ENTRY pCTLEntry = NULL; DWORD cCTLEntry = 0; hResult = GetCTLEntry (&cCTLEntry, &pCTLEntry); if ( SUCCEEDED (hResult) ) { BYTE *pbEncodedCTL = NULL; DWORD cbEncodedCTL = 0; hResult = MakeCTL (cCTLEntry, pCTLEntry, &pbEncodedCTL, &cbEncodedCTL); if ( SUCCEEDED (hResult) ) { bResult = pSheet->m_pCertStore->AddEncodedCTL ( X509_ASN_ENCODING, pbEncodedCTL, cbEncodedCTL, CERT_STORE_ADD_REPLACE_EXISTING, NULL); if ( !bResult ) { DWORD dwErr = GetLastError (); hResult = HRESULT_FROM_WIN32 (dwErr); DisplaySystemError (m_hWnd, dwErr); } } if (pbEncodedCTL) ::LocalFree (pbEncodedCTL); } if (pCTLEntry) ::LocalFree (pCTLEntry); } if ( SUCCEEDED (hResult) ) bResult = CWizard97PropertyPage::OnWizardFinish (); else bResult = FALSE; return bResult; } HRESULT ACRSCompletionPage::GetCTLEntry (OUT DWORD *pcCTLEntry, OUT PCTL_ENTRY *ppCTLEntry) { HRESULT hResult = S_OK; ACRSWizardPropertySheet* pSheet = reinterpret_cast (m_pWiz); ASSERT (pSheet); if ( pSheet ) { const size_t HASH_SIZE = 20; DWORD cCA = (DWORD)pSheet->m_caInfoList.GetCount (); PCTL_ENTRY pCTLEntry = (PCTL_ENTRY) ::LocalAlloc (LPTR, (sizeof (CTL_ENTRY) + HASH_SIZE) *cCA); if ( pCTLEntry ) { PBYTE pbHash = (PBYTE) (pCTLEntry + cCA); HCAINFO hCAInfo = NULL; PCCERT_CONTEXT pCertContext = NULL; DWORD cbHash = HASH_SIZE; DWORD iCA = 0; for (POSITION pos = pSheet->m_caInfoList.GetHeadPosition (); pos;) { hCAInfo = pSheet->m_caInfoList.GetNext (pos); ASSERT (hCAInfo); if ( hCAInfo ) { hResult = ::CAGetCACertificate (hCAInfo, &pCertContext); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) ) { cbHash = HASH_SIZE; if (::CertGetCertificateContextProperty (pCertContext, CERT_SHA1_HASH_PROP_ID, pbHash, &cbHash)) { pCTLEntry[iCA].SubjectIdentifier.cbData = cbHash; pCTLEntry[iCA].SubjectIdentifier.pbData = pbHash; pbHash += cbHash; ::CertFreeCertificateContext (pCertContext); iCA++; } else { DWORD dwErr = GetLastError (); hResult = HRESULT_FROM_WIN32 (dwErr); DisplaySystemError (m_hWnd, dwErr); break; } } else break; } } if ( SUCCEEDED (hResult) ) { *pcCTLEntry = cCA; *ppCTLEntry = pCTLEntry; } else { if (pCTLEntry) ::LocalFree (pCTLEntry); } } else { hResult = E_OUTOFMEMORY; } } return hResult; } HRESULT ACRSCompletionPage::MakeCTL ( IN DWORD cCTLEntry, IN PCTL_ENTRY pCTLEntry, OUT BYTE **ppbEncodedCTL, OUT DWORD *pcbEncodedCTL) { HRESULT hResult = S_OK; ACRSWizardPropertySheet* pSheet = reinterpret_cast (m_pWiz); ASSERT (pSheet); if ( pSheet ) { PCERT_EXTENSIONS pCertExtensions = NULL; hResult = ::CAGetCertTypeExtensions (pSheet->m_selectedCertType, &pCertExtensions); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) ) { CMSG_SIGNED_ENCODE_INFO SignerInfo; memset (&SignerInfo, 0, sizeof (SignerInfo)); CTL_INFO CTLInfo; memset (&CTLInfo, 0, sizeof (CTLInfo)); WCHAR** pawszPropName = 0; ZeroMemory(&CTLInfo, sizeof(CTLInfo)); // set up the CTL info CTLInfo.dwVersion = sizeof (CTLInfo); CTLInfo.SubjectUsage.cUsageIdentifier = 1; hResult = ::CAGetCertTypeProperty (pSheet->m_selectedCertType, CERTTYPE_PROP_DN, &pawszPropName); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) && pawszPropName[0] ) { LPSTR psz = szOID_AUTO_ENROLL_CTL_USAGE; WCHAR pwszGPEName[MAX_GPE_NAME_SIZE]; IGPEInformation *pGPEInfo = pSheet->m_pCertStore->GetGPEInformation(); ZeroMemory(pwszGPEName, MAX_GPE_NAME_SIZE*sizeof (WCHAR)); CTLInfo.ListIdentifier.cbData = (DWORD) (sizeof (WCHAR) * (wcslen (pawszPropName[0]) + 1)); if(pGPEInfo) { pGPEInfo->GetName(pwszGPEName, sizeof(pwszGPEName)/sizeof(pwszGPEName[0])); CTLInfo.ListIdentifier.cbData += (DWORD) (sizeof(WCHAR)*(wcslen(pwszGPEName)+1)); } CTLInfo.ListIdentifier.pbData = (PBYTE)LocalAlloc(LPTR, CTLInfo.ListIdentifier.cbData); if(CTLInfo.ListIdentifier.pbData == NULL) { hResult = E_OUTOFMEMORY; } if(pwszGPEName[0]) { wcscpy((LPWSTR)CTLInfo.ListIdentifier.pbData, pwszGPEName); wcscat((LPWSTR)CTLInfo.ListIdentifier.pbData, L"|"); } wcscat((LPWSTR)CTLInfo.ListIdentifier.pbData, pawszPropName[0]); CTLInfo.SubjectUsage.rgpszUsageIdentifier = &psz; ::GetSystemTimeAsFileTime (&CTLInfo.ThisUpdate); CTLInfo.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1; CTLInfo.cCTLEntry = cCTLEntry; CTLInfo.rgCTLEntry = pCTLEntry; // UNDONE - add the cert type extension // add all the reg info as an extension CTLInfo.cExtension = pCertExtensions->cExtension; CTLInfo.rgExtension = pCertExtensions->rgExtension; // encode the CTL *pcbEncodedCTL = 0; SignerInfo.cbSize = sizeof (SignerInfo); if ( ::CryptMsgEncodeAndSignCTL (PKCS_7_ASN_ENCODING, &CTLInfo, &SignerInfo, 0, NULL, pcbEncodedCTL) ) { *ppbEncodedCTL = (BYTE*) ::LocalAlloc (LPTR, *pcbEncodedCTL); if ( *ppbEncodedCTL ) { if (!::CryptMsgEncodeAndSignCTL (PKCS_7_ASN_ENCODING, &CTLInfo, &SignerInfo, 0, *ppbEncodedCTL, pcbEncodedCTL)) { DWORD dwErr = GetLastError (); hResult = HRESULT_FROM_WIN32 (dwErr); DisplaySystemError (m_hWnd, dwErr); } } else { hResult = E_OUTOFMEMORY; } } else { DWORD dwErr = GetLastError (); hResult = HRESULT_FROM_WIN32 (dwErr); DisplaySystemError (m_hWnd, dwErr); } VERIFY (SUCCEEDED (::CAFreeCertTypeProperty ( pSheet->m_selectedCertType, pawszPropName))); } if(CTLInfo.ListIdentifier.pbData) { ::LocalFree(CTLInfo.ListIdentifier.pbData); } } if (pCertExtensions) ::LocalFree (pCertExtensions); } return hResult; }