//------------------------------------------------------------- // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: mgrcert.cpp // // Contents: The cpp file to implement cert mgr dialogue // // History: Feb-26-98 xiaohs created // //-------------------------------------------------------------- #include "wzrdpvk.h" #include "winuser.h" //need this file for VK_DELETE #include "mgrcert.h" //context sensitive help for the main dialogue static const HELPMAP CertMgrMainHelpMap[] = { {IDC_CERTMGR_LIST, IDH_CERTMGR_LIST}, {IDC_CERTMGR_PURPOSE_COMBO, IDH_CERTMGR_PURPOSE_COMBO}, {IDC_CERTMGR_IMPORT, IDH_CERTMGR_IMPORT}, {IDC_CERTMGR_EXPORT, IDH_CERTMGR_EXPORT}, {IDC_CERTMGR_VIEW, IDH_CERTMGR_VIEW}, {IDC_CERTMGR_REMOVE, IDH_CERTMGR_REMOVE}, {IDC_CERTMGR_ADVANCE, IDH_CERTMGR_ADVANCE}, {IDC_CERTMGR_PURPOSE, IDH_CERTMGR_FIELD_PURPOSE}, }; //context sensitive help for the main dialogue static const HELPMAP CertMgrAdvHelpMap[] = { {IDC_CERTMGR_ADV_LIST, IDH_CERTMGR_ADV_LIST}, {IDC_CERTMGR_EXPORT_COMBO, IDH_CERTMGR_EXPORT_COMBO}, {IDC_CERTMGR_EXPORT_CHECK, IDH_CERTMGR_EXPORT_CHECK}, }; // Primary store associated with each tab. Store to be imported into. static const LPCWSTR rgpwszTabStoreName[] = { L"My", // 0 L"AddressBook", // 1 L"Ca", // 2 L"Root", // 3 L"TrustedPublisher", // 4 }; #define TAB_STORE_NAME_CNT (sizeof(rgpwszTabStoreName) / \ sizeof(rgpwszTabStoreName[0])) /* // The following code is obsolete due to new cert chain building code //---------------------------------------------------------------------------- // AddCertChainToStore //---------------------------------------------------------------------------- BOOL AddCertChainToStore(HCERTSTORE hStore, PCCERT_CONTEXT pCertContext) { BOOL fResult=FALSE; HCERTSTORE rghCertStores[20]; DWORD chStores; PCCERT_CONTEXT pChildCert; PCCERT_CONTEXT pParentCert; FILETIME fileTime; DWORD i; if(!hStore || !pCertContext) goto InvalidArgErr; GetSystemTimeAsFileTime(&fileTime); if (!TrustOpenStores(NULL, &chStores, rghCertStores, 0)) goto TraceErr; pChildCert = pCertContext; while (NULL != (pParentCert = TrustFindIssuerCertificate( pChildCert, pChildCert->dwCertEncodingType, chStores, rghCertStores, &fileTime, NULL, NULL, 0))) { CertAddCertificateContextToStore(hStore, pParentCert, CERT_STORE_ADD_NEW, NULL); if (pChildCert != pCertContext) { CertFreeCertificateContext(pChildCert); } pChildCert = pParentCert; } if (pChildCert != pCertContext) { CertFreeCertificateContext(pChildCert); } for (i=0; ipszText, -1, NULL, 0, NULL, NULL); if ((0 == cb) || (NULL == (TCItemA.pszText = (LPSTR) WizardAlloc(cb)))) { return -1; // this is the unsuccessful return code for this call } if( 0 == (WideCharToMultiByte( 0, 0, pitem->pszText, -1, TCItemA.pszText, cb, NULL, NULL))) { WizardFree(TCItemA.pszText); return -1; } iRet = (int)SendMessage(hwnd, TCM_INSERTITEMA, iItem, (LPARAM) &TCItemA); WizardFree(TCItemA.pszText); return iRet; } //---------------------------------------------------------------------------- // This is the rundll32 entry point for start menu, administartive tools, // CertMgr. //---------------------------------------------------------------------------- STDAPI CryptUIStartCertMgr(HINSTANCE hinst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { CRYPTUI_CERT_MGR_STRUCT CertMgrStruct; memset(&CertMgrStruct, 0, sizeof(CRYPTUI_CERT_MGR_STRUCT)); CertMgrStruct.dwSize=sizeof(CRYPTUI_CERT_MGR_STRUCT); CryptUIDlgCertMgr(&CertMgrStruct); return S_OK; } //---------------------------------------------------------------------------- // GetFileContentFromCert //---------------------------------------------------------------------------- BOOL GetFileContentFromCert(DWORD dwExportFormat, BOOL fExportChain, PCCERT_CONTEXT pCertContext, BYTE **ppBlob, DWORD *pdwSize) { BOOL fResult=FALSE; void *pData=NULL; DWORD dwSize=0; HCERTSTORE hMemoryStore=NULL; CRYPT_DATA_BLOB Blob; HRESULT hr=E_INVALIDARG; if(!ppBlob || !pdwSize || !pCertContext) goto InvalidArgErr; *ppBlob=NULL; *pdwSize=0; switch(dwExportFormat) { case CRYPTUI_WIZ_EXPORT_FORMAT_DER: dwSize=pCertContext->cbCertEncoded; pData=WizardAlloc(dwSize); if(!pData) goto MemoryErr; memcpy(pData, pCertContext->pbCertEncoded, dwSize); break; case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64: //base 64 encode the BLOB if(!CryptBinaryToStringA( pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, CRYPT_STRING_BASE64, NULL, &dwSize)) { hr = GetLastError(); goto SetErrVar; } pData=WizardAlloc(dwSize * sizeof(CHAR)); if(!pData) goto MemoryErr; if(!CryptBinaryToStringA( pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, CRYPT_STRING_BASE64, (char *)pData, &dwSize)) { hr = GetLastError(); goto SetErrVar; } break; case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7: //open a memory store hMemoryStore=CertOpenStore( CERT_STORE_PROV_MEMORY, g_dwMsgAndCertEncodingType, NULL, 0, NULL); if(!hMemoryStore) goto TraceErr; if(FALSE == fExportChain) { if(!CertAddCertificateContextToStore( hMemoryStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) goto TraceErr; } else { if(!AddChainToStore( hMemoryStore, pCertContext, 0, NULL, FALSE, NULL)) goto TraceErr; } //save the store to a PKCS#7 Blob.cbData=0; Blob.pbData=NULL; if(!CertSaveStore(hMemoryStore, g_dwMsgAndCertEncodingType, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &Blob, 0)) goto TraceErr; dwSize=Blob.cbData; pData=WizardAlloc(dwSize); if(!pData) goto MemoryErr; Blob.pbData=(BYTE *)pData; if(!CertSaveStore(hMemoryStore, g_dwMsgAndCertEncodingType, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &Blob, 0)) goto TraceErr; break; default: goto InvalidArgErr; break; } //set up the return value *pdwSize=dwSize; *ppBlob=(BYTE *)pData; pData=NULL; fResult=TRUE; CommonReturn: if(hMemoryStore) CertCloseStore(hMemoryStore, 0); return fResult; ErrorReturn: if(pData) WizardFree(pData); fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); SET_ERROR_VAR(SetErrVar, hr); TRACE_ERROR(TraceErr); } //---------------------------------------------------------------------------- // FreeFileNameAndContent //---------------------------------------------------------------------------- BOOL FreeFileNameAndContent( DWORD dwCount, LPWSTR *prgwszFileName, BYTE **prgBlob, DWORD *prgdwSize) { DWORD dwIndex=0; if(prgwszFileName) { for(dwIndex=0; dwIndex < dwCount; dwIndex++) { if(prgwszFileName[dwIndex]) WizardFree(prgwszFileName[dwIndex]); } WizardFree(prgwszFileName); } if(prgBlob) { for(dwIndex=0; dwIndex < dwCount; dwIndex++) { if(prgBlob[dwIndex]) WizardFree(prgBlob[dwIndex]); } WizardFree(prgBlob); } if(prgdwSize) WizardFree(prgdwSize); return TRUE; } //---------------------------------------------------------------------------- // Get a valid friendly name of the certificate //---------------------------------------------------------------------------- BOOL GetValidFriendlyName(PCCERT_CONTEXT pCertContext, LPWSTR *ppwszName) { BOOL fResult=FALSE; DWORD dwChar=0; LPWSTR pwsz=NULL; DWORD dwIndex=0; if(!pCertContext || !ppwszName) return FALSE; //init *ppwszName=NULL; dwChar=0; if(CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dwChar) && (0!=dwChar)) { pwsz=(LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)); if(pwsz) { CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pwsz, &dwChar); } } if(NULL==pwsz) goto CLEANUP; //make sure pwsz is a valid name if(0 == (dwChar=wcslen(pwsz))) goto CLEANUP; //the friendly name can not be spaces all the time for(dwIndex=0; dwIndex 1) && (NULL != (pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR))))) { if(!CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pwszName, dwChar)) goto GetNameErr; pwszFirstPart=pwszName; } else { //load the string for Certificate if(!LoadStringU(g_hmodThisDll, IDS_CERTIFICATE, wszCertificate, MAX_TITLE_LENGTH)) goto LoadStringErr; pwszFirstPart=wszCertificate; } } else pwszFirstPart=pwszFriendlyName; //determine the extension for the file switch(dwExportFormat) { case CRYPTUI_WIZ_EXPORT_FORMAT_DER: idsExt=IDS_CER; break; case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64: idsExt=IDS_CER; break; case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7: idsExt=IDS_P7C; break; default: idsExt=IDS_CER; break; } //load the string for Certificate if(!LoadStringU(g_hmodThisDll, idsExt, wszExt, MAX_TITLE_LENGTH)) goto LoadStringErr; //determine the max length of the file name dwChar = wcslen(pwszFirstPart) > (CERTMGR_MAX_FILE_NAME - wcslen(wszExt) -1) ? (CERTMGR_MAX_FILE_NAME - wcslen(wszExt) -1) : wcslen(pwszFirstPart); wcsncpy(pwszFileName, pwszFirstPart, dwChar); *(pwszFileName + dwChar)=L'\0'; wcscat(pwszFileName, wszExt); //now, we replace the invalid file characters : ; / \ //with space dwChar = wcslen(pwszFileName); for(dwIndex =0; dwIndex is selected //---------------------------------------------------------------------------- BOOL IsAdvancedSelected(HWND hwndDlg) { BOOL fSelected=FALSE; int iIndex=0; LPWSTR pwszOIDName=NULL; WCHAR wszText[MAX_STRING_SIZE]; if(!hwndDlg) goto CLEANUP; //get the selected string from the combo box iIndex=(int)SendDlgItemMessage(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) goto CLEANUP; //get the selected purpose name if(CB_ERR == SendDlgItemMessageU_GETLBTEXT(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, iIndex, &pwszOIDName)) goto CLEANUP; //check to see if is selected if(!LoadStringU(g_hmodThisDll, IDS_OID_ADVANCED, wszText, MAX_STRING_SIZE)) goto CLEANUP; //check if advanced option is selected if(0 == _wcsicmp(pwszOIDName, wszText)) fSelected=TRUE; CLEANUP: if(pwszOIDName) WizardFree(pwszOIDName); return fSelected; } //---------------------------------------------------------------------------- // Update the window title based on the tab that user has selected //---------------------------------------------------------------------------- BOOL RefreshWindowTitle(HWND hwndDlg, PCRYPTUI_CERT_MGR_STRUCT pCertMgrStruct) { BOOL fResult=FALSE; WCHAR wszTitle[MAX_TITLE_LENGTH]; WCHAR wszText[MAX_TITLE_LENGTH]; LPWSTR pwszTitle=NULL; LPWSTR pwszText=NULL; UINT ids=0; DWORD dwTabIndex=0; if(!hwndDlg || !pCertMgrStruct) goto CLEANUP; //get the string ids based on the tab selected if (pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) dwTabIndex = pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK; else if(-1 == (dwTabIndex=TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_CERTMGR_TAB)))) goto CLEANUP; //open the correct store based on the tab selected switch (dwTabIndex) { case 0: ids=IDS_TAB_PERSONAL; break; case 1: ids=IDS_TAB_OTHER; break; case 2: ids=IDS_TAB_CA; break; case 3: ids=IDS_TAB_ROOT; break; case 4: ids=IDS_TAB_PUBLISHER; break; default: goto CLEANUP; break; } //load the string for tabs if(!LoadStringU(g_hmodThisDll, ids, wszText, MAX_TITLE_LENGTH)) goto CLEANUP; //get the window string if(pCertMgrStruct->pwszTitle) pwszTitle=(LPWSTR)(pCertMgrStruct->pwszTitle); else { if(!LoadStringU(g_hmodThisDll, IDS_CERT_MGR_TITLE, wszTitle, MAX_TITLE_LENGTH)) goto CLEANUP; pwszTitle=wszTitle; } pwszText=(LPWSTR)WizardAlloc(sizeof(WCHAR) * ( wcslen(pwszTitle) + wcslen(wszText) + wcslen(L" - ") +1)); if(!pwszText) goto CLEANUP; //concatenate the window title as: "Certifiate Manager - Personal" *pwszText=L'\0'; wcscat(pwszText, pwszTitle); wcscat(pwszText, L" - "); wcscat(pwszText, wszText); //set the window text SetWindowTextU(hwndDlg, pwszText); fResult=TRUE; CLEANUP: if(pwszText) WizardFree(pwszText); return fResult; } //---------------------------------------------------------------------------- // Check to see if the certificate's key usage is the same as // the one selected on the combo box // //---------------------------------------------------------------------------- BOOL IsValidUsage(PCCERT_CONTEXT pCertContext, HWND hwndDlg, CERT_MGR_INFO *pCertMgrInfo) { BOOL fValidUsage=FALSE; int iIndex=0; LPWSTR pwszOIDName=NULL; LPSTR pszOID=NULL; WCHAR wszText[MAX_STRING_SIZE]; BOOL fAdvanced=FALSE; DWORD dwIndex=0; DWORD dwAdvIndex=0; int cNumOID=0; LPSTR *rgOID=NULL; DWORD cbOID=0; //input check if(!pCertContext || !hwndDlg || !pCertMgrInfo) return FALSE; //get the selected string from the combo box iIndex=(int)SendDlgItemMessage(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) goto CLEANUP; //get the selected purpose name if(CB_ERR == SendDlgItemMessageU_GETLBTEXT(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, iIndex, &pwszOIDName)) goto CLEANUP; //check to see if is selected if(!LoadStringU(g_hmodThisDll, IDS_OID_ALL, wszText, MAX_STRING_SIZE)) goto CLEANUP; if(0 == _wcsicmp(pwszOIDName, wszText)) { fValidUsage=TRUE; goto CLEANUP; } //check to see if is selected if(!LoadStringU(g_hmodThisDll, IDS_OID_ADVANCED, wszText, MAX_STRING_SIZE)) goto CLEANUP; //check if advanced option is selected if(0 == _wcsicmp(pwszOIDName, wszText)) fAdvanced=TRUE; if(FALSE==fAdvanced) { //determin the OID for the selected usage name for(dwIndex=0; dwIndexdwOIDInfo; dwIndex++) { if(0==_wcsicmp(pwszOIDName, (pCertMgrInfo->rgOIDInfo[dwIndex]).pwszName)) pszOID=(pCertMgrInfo->rgOIDInfo[dwIndex]).pszOID; } //we are in trouble if we can not find the maching OID based on //the name selected if(NULL==pszOID) goto CLEANUP; } //get the certificate's list of usage OIDs //get the OIDs from the cert if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, NULL, &cbOID)) goto CLEANUP; rgOID=(LPSTR *)WizardAlloc(cbOID); if(NULL==rgOID) goto CLEANUP; if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, rgOID, &cbOID)) goto CLEANUP; //-1 means the certiifcate is good for everything if(-1==cNumOID) { fValidUsage=TRUE; goto CLEANUP; } //we need to decide if the certificate include the selected //usage if(FALSE==fAdvanced) { for(dwIndex=0; dwIndex<(DWORD)cNumOID; dwIndex++) { if(0==_stricmp(pszOID, rgOID[dwIndex])) { fValidUsage=TRUE; goto CLEANUP; } } } else { //the certificates have to have advanced OIDs for(dwAdvIndex=0; dwAdvIndexdwOIDInfo; dwAdvIndex++) { //only interested in the OIDs with advanced marked if(TRUE==(pCertMgrInfo->rgOIDInfo[dwAdvIndex]).fSelected) { for(dwIndex=0; dwIndex<(DWORD)cNumOID; dwIndex++) { if(0==_stricmp((pCertMgrInfo->rgOIDInfo[dwAdvIndex]).pszOID, rgOID[dwIndex])) { fValidUsage=TRUE; goto CLEANUP; } } } } } //now, we have examed all the possibilities fValidUsage=FALSE; CLEANUP: if(pwszOIDName) WizardFree(pwszOIDName); if(rgOID) WizardFree(rgOID); return fValidUsage; } //---------------------------------------------------------------------------- // Check to see if the certificate is an end-entity cert // //---------------------------------------------------------------------------- BOOL IsCertificateEndEntity(PCCERT_CONTEXT pCertContext) { PCERT_EXTENSION pCertExt=NULL; BOOL fEndEntity=FALSE; DWORD cbData=0; PCERT_BASIC_CONSTRAINTS_INFO pBasicInfo=NULL; PCERT_BASIC_CONSTRAINTS2_INFO pBasicInfo2=NULL; if(!pCertContext) return FALSE; //get the extension szOID_BASIC_CONSTRAINTS2 pCertExt=CertFindExtension( szOID_BASIC_CONSTRAINTS2, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if(pCertExt) { //deocde the extension cbData=0; if(!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, pCertExt->Value.pbData, pCertExt->Value.cbData, 0, NULL, &cbData)) goto CLEANUP; pBasicInfo2=(PCERT_BASIC_CONSTRAINTS2_INFO)WizardAlloc(cbData); if(NULL==pBasicInfo2) goto CLEANUP; if(!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, pCertExt->Value.pbData, pCertExt->Value.cbData, 0, pBasicInfo2, &cbData)) goto CLEANUP; if(pBasicInfo2->fCA) fEndEntity=FALSE; else fEndEntity=TRUE; } else { //get the extension szOID_BASIC_CONSTRAINTS pCertExt=CertFindExtension( szOID_BASIC_CONSTRAINTS, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if(pCertExt) { //deocde the extension cbData=0; if(!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS, pCertExt->Value.pbData, pCertExt->Value.cbData, 0, NULL, &cbData)) goto CLEANUP; pBasicInfo=(PCERT_BASIC_CONSTRAINTS_INFO)WizardAlloc(cbData); if(NULL==pBasicInfo) goto CLEANUP; if(!CryptDecodeObject( X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS, pCertExt->Value.pbData, pCertExt->Value.cbData, 0, pBasicInfo, &cbData)) goto CLEANUP; if(0 == pBasicInfo->SubjectType.cbData) { fEndEntity=FALSE; } else { if(CERT_END_ENTITY_SUBJECT_FLAG & (pBasicInfo->SubjectType.pbData[0])) fEndEntity=TRUE; else { if(CERT_CA_SUBJECT_FLAG & (pBasicInfo->SubjectType.pbData[0])) fEndEntity=FALSE; } } } } CLEANUP: if(pBasicInfo) WizardFree(pBasicInfo); if(pBasicInfo2) WizardFree(pBasicInfo2); return fEndEntity; } //---------------------------------------------------------------------------- // Add certificate to the pCertMgrInfo // //---------------------------------------------------------------------------- BOOL AddCertToCertMgrInfo(PCCERT_CONTEXT pCertContext, CERT_MGR_INFO *pCertMgrInfo) { pCertMgrInfo->prgCertContext=(PCCERT_CONTEXT *)WizardRealloc( pCertMgrInfo->prgCertContext, sizeof(PCCERT_CONTEXT *)*(pCertMgrInfo->dwCertCount +1)); if(NULL==pCertMgrInfo->prgCertContext) { pCertMgrInfo->dwCertCount=0; return FALSE; } pCertMgrInfo->prgCertContext[pCertMgrInfo->dwCertCount]=pCertContext; pCertMgrInfo->dwCertCount++; return TRUE; } //---------------------------------------------------------------------------- // Once a certificate is selected, refresh the static windows that display // the details of the certificate // //---------------------------------------------------------------------------- BOOL RefreshCertDetails(HWND hwndDlg, PCCERT_CONTEXT pCertContext) { BOOL fResult=FALSE; DWORD dwChar=0; WCHAR wszNone[MAX_TITLE_LENGTH]; LPWSTR pwszName=NULL; if(!hwndDlg || !pCertContext) return FALSE; //load the string for NONE if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH)) wszNone[0]=L'\0'; //Subject /* dwChar=CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); if ((dwChar != 0) && (NULL != (pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR))))) { CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pwszName, dwChar); SetDlgItemTextU(hwndDlg, IDC_CERTMGR_SUBJECT, pwszName); } else { SetDlgItemTextU(hwndDlg, IDC_CERTMGR_SUBJECT, wszNone); } //WizardFree the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } //Issuer dwChar=CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0); if ((dwChar != 0) && (NULL != (pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR))))) { CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, pwszName, dwChar); SetDlgItemTextU(hwndDlg, IDC_CERTMGR_ISSUER, pwszName); } else SetDlgItemTextU(hwndDlg, IDC_CERTMGR_ISSUER, wszNone); //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } //Expiration if(WizardFormatDateString(&pwszName,pCertContext->pCertInfo->NotAfter, FALSE)) SetDlgItemTextU(hwndDlg, IDC_CERTMGR_EXPIRE, pwszName); else SetDlgItemTextU(hwndDlg, IDC_CERTMGR_EXPIRE, wszNone); //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } */ //purpose if(MyFormatEnhancedKeyUsageString(&pwszName,pCertContext, FALSE, FALSE)) { SetDlgItemTextU(hwndDlg, IDC_CERTMGR_PURPOSE, pwszName); } //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } //friendly name /* dwChar=0; if(CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dwChar) && (0!=dwChar)) { pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)); if(pwszName) { CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pwszName, &dwChar); SetDlgItemTextU(hwndDlg, IDC_CERTMGR_NAME, pwszName); } else SetDlgItemTextU(hwndDlg, IDC_CERTMGR_NAME, wszNone); } else SetDlgItemTextU(hwndDlg, IDC_CERTMGR_NAME, wszNone); //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } */ return TRUE; } //---------------------------------------------------------------------------- // Add certificate to the ListView // //---------------------------------------------------------------------------- BOOL AddCertToListView(HWND hwndControl, PCCERT_CONTEXT pCertContext, int iItem) { BOOL fResult=FALSE; LV_ITEMW lvItem; DWORD dwChar=0; WCHAR wszNone[MAX_TITLE_LENGTH]; LPWSTR pwszName=NULL; if(!hwndControl || !pCertContext) return FALSE; // set up the fields in the list view item struct that don't change from item to item lvItem.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE |LVIF_PARAM ; lvItem.state = 0; lvItem.stateMask = 0; lvItem.iItem=iItem; lvItem.iSubItem=0; lvItem.iImage = 0; lvItem.lParam = (LPARAM)pCertContext; //load the string for NONE if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH)) wszNone[0]=L'\0'; //Subject if (NULL == (pwszName = GetDisplayNameString(pCertContext, 0))) { lvItem.pszText=wszNone; ListView_InsertItemU(hwndControl, &lvItem); } else { lvItem.pszText=pwszName; ListView_InsertItemU(hwndControl, &lvItem); free(pwszName); pwszName = NULL; } //Issuer lvItem.iSubItem++; if (NULL == (pwszName = GetDisplayNameString(pCertContext, CERT_NAME_ISSUER_FLAG))) { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszNone); } else { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszName); free(pwszName); pwszName = NULL; } //Expiration lvItem.iSubItem++; if(WizardFormatDateString(&pwszName,pCertContext->pCertInfo->NotAfter, FALSE)) { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszName); } else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszNone); //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } //purpose /*lvItem.iSubItem++; if(WizardFormatEnhancedKeyUsageString(&pwszName,pCertContext, FALSE, FALSE) && L'\0' != *pwszName) { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszName); } else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszNone); //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } */ //friendly name lvItem.iSubItem++; dwChar=0; if(CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dwChar) && (0!=dwChar)) { pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)); if(pwszName) { CertGetCertificateContextProperty( pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pwszName, &dwChar); ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszName); } else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszNone); } else { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, wszNone); } //free the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } return TRUE; } //----------------------------------------------------------------------- // Based on the tab(store) and the intended purpose selected, // find the correct certificates and refresh the list view // Criteria: // Tab 0: My Store with private key // Tab 1: Ca Store's end-entity cert and the "ADDRESSBOOK" store // Tab 2: Ca Store's CA certs // Tab 3: Root store's self signed certs // Tab 4: Trusted publisher certs //----------------------------------------------------------------------- void RefreshCertListView(HWND hwndDlg, CERT_MGR_INFO *pCertMgrInfo) { HWND hwndControl=NULL; DWORD dwIndex=0; DWORD dwTabIndex=0; HCERTSTORE rghCertStore[]={NULL, NULL}; DWORD dwStoreCount=0; PCCERT_CONTEXT pCurCertContext=NULL; PCCERT_CONTEXT pPreCertContext=NULL; BOOL fValidCert=FALSE; DWORD cbData=0; DWORD dwSortParam=0; PCCRYPTUI_CERT_MGR_STRUCT pCertMgrStruct = NULL; HCURSOR hPreCursor=NULL; HCURSOR hWinPreCursor=NULL; if(!hwndDlg || !pCertMgrInfo) return; pCertMgrStruct = pCertMgrInfo->pCertMgrStruct; if(!pCertMgrStruct) return; //overwrite the cursor for this window class hWinPreCursor=(HCURSOR)SetClassLongPtr(hwndDlg, GCLP_HCURSOR, NULL); hPreCursor=SetCursor(LoadCursor(NULL, IDC_WAIT)); //free all the original certificates hwndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST); if(!hwndControl) goto CLEANUP; FreeCerts(pCertMgrInfo); //deletel all the certs from the listView ListView_DeleteAllItems(hwndControl); //clear the ceritificate details group box SetDlgItemTextU(hwndDlg, IDC_CERTMGR_PURPOSE, L" "); //get the tab that is selected if (pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) dwTabIndex = pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK; else if(-1 == (dwTabIndex=TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_CERTMGR_TAB)))) goto CLEANUP; //open the correct store based on the tab selected switch (dwTabIndex) { case 0: //open my store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (LPWSTR)L"my")) dwStoreCount++; else goto CLEANUP; break; case 1: //open ca store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (LPWSTR)L"ca")) dwStoreCount++; else goto CLEANUP; //open the "AddressBook" store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, (LPWSTR)L"ADDRESSBOOK")) dwStoreCount++; else { //it is OK that user does not have "AddressBook" store rghCertStore[dwStoreCount]=NULL; } break; case 2: //open CA store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (LPWSTR)L"ca")) dwStoreCount++; else goto CLEANUP; break; case 3: //open root store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (LPWSTR)L"root")) dwStoreCount++; else goto CLEANUP; break; case 4: //open trusted publisher store if(rghCertStore[dwStoreCount]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, (LPWSTR)L"TrustedPublisher")) dwStoreCount++; else goto CLEANUP; break; default: goto CLEANUP; break; } //gather new certificates from the store opened for(dwIndex=0; dwIndex < dwStoreCount; dwIndex++) { pPreCertContext=NULL; while(pCurCertContext=CertEnumCertificatesInStore( rghCertStore[dwIndex], pPreCertContext)) { //make sure the certificate has the correct usage oid if(IsValidUsage(pCurCertContext, hwndDlg, pCertMgrInfo)) { switch (dwTabIndex) { case 0: //certificate has to have private key associated //with it cbData=0; if( (CertGetCertificateContextProperty( pCurCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbData) && (0!=cbData)) || (CertGetCertificateContextProperty( pCurCertContext, CERT_PVK_FILE_PROP_ID, NULL, &cbData) && (0!=cbData)) ) fValidCert=TRUE; break; case 1: //the certificate has to be end entity cert for CA cert if(0 == dwIndex) { if(IsCertificateEndEntity(pCurCertContext)) fValidCert=TRUE; } //we display everything in the addressbook store if(1==dwIndex) fValidCert=TRUE; break; case 2: //for certificate in CA store, has to be CA cert if(!IsCertificateEndEntity(pCurCertContext)) fValidCert=TRUE; break; case 4: fValidCert=TRUE; break; case 3: default: //the certificate has to be self-signed if(TrustIsCertificateSelfSigned( pCurCertContext, pCurCertContext->dwCertEncodingType, 0)) fValidCert=TRUE; break; } if(fValidCert) { AddCertToCertMgrInfo( CertDuplicateCertificateContext(pCurCertContext), pCertMgrInfo); } fValidCert=FALSE; } pPreCertContext=pCurCertContext; pCurCertContext=NULL; } } //put the certificate in the listView for(dwIndex=0; dwIndexdwCertCount; dwIndex++) AddCertToListView(hwndControl, (pCertMgrInfo->prgCertContext)[dwIndex], dwIndex); // if there is no cert selected initially disable the // "view cert button", "export" and "remove" button if (ListView_GetSelectedCount(hwndControl) == 0) { EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_VIEW), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_REMOVE), FALSE); } //we sort by the 1st column dwSortParam=pCertMgrInfo->rgdwSortParam[pCertMgrInfo->iColumn]; if(0!=dwSortParam) { //sort the 1st column SendDlgItemMessage(hwndDlg, IDC_CERTMGR_LIST, LVM_SORTITEMS, (WPARAM) (LPARAM) dwSortParam, (LPARAM) (PFNLVCOMPARE)CompareCertificate); } CLEANUP: //close all the certificate stores for(dwIndex=0; dwIndexcUsageIdentifier; dwIndex++) { if(0 == _stricmp(pKeyUsage->rgpszUsageIdentifier[dwIndex], pszOID)) return FALSE; } return TRUE; } //----------------------------------------------------------------------- //The call back function for enum //----------------------------------------------------------------------- static BOOL WINAPI EnumOidCallback( IN PCCRYPT_OID_INFO pInfo, IN void *pvArg ) { PURPOSE_OID_CALL_BACK *pCallBackInfo=NULL; BOOL fResult=FALSE; pCallBackInfo=(PURPOSE_OID_CALL_BACK *)pvArg; if(NULL==pvArg || NULL==pInfo) goto InvalidArgErr; //increment the oid list (*(pCallBackInfo->pdwOIDCount))++; //get more memory for the pointer list *(pCallBackInfo->pprgOIDInfo)=(PURPOSE_OID_INFO *)WizardRealloc(*(pCallBackInfo->pprgOIDInfo), (*(pCallBackInfo->pdwOIDCount)) * sizeof(PURPOSE_OID_INFO)); if(NULL==*(pCallBackInfo->pprgOIDInfo)) goto MemoryErr; //memset memset(&((*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1]), 0, sizeof(PURPOSE_OID_INFO)); (*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1].pszOID=WizardAllocAndCopyStr((LPSTR)(pInfo->pszOID)); (*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1].pwszName=WizardAllocAndCopyWStr((LPWSTR)(pInfo->pwszName)); (*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1].fSelected=FALSE; if(NULL==(*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1].pszOID || NULL==(*(pCallBackInfo->pprgOIDInfo))[*(pCallBackInfo->pdwOIDCount)-1].pwszName) goto MemoryErr; fResult=TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); } //---------------------------------------------------------------------------- // Get the list of supported enhanced key OIDs //---------------------------------------------------------------------------- BOOL InitPurposeOID(LPCSTR pszInitUsageOID, DWORD *pdwOIDInfo, PURPOSE_OID_INFO **pprgOIDInfo) { BOOL fResult=FALSE; DWORD dwIndex=0; PURPOSE_OID_CALL_BACK OidInfoCallBack; DWORD dwOIDRequested=0; LPWSTR pwszName=NULL; if(!pdwOIDInfo || !pprgOIDInfo) goto InvalidArgErr; //init *pdwOIDInfo=0; *pprgOIDInfo=NULL; OidInfoCallBack.pdwOIDCount=pdwOIDInfo; OidInfoCallBack.pprgOIDInfo=pprgOIDInfo; //enum all the enhanced key usages if(!CryptEnumOIDInfo( CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, &OidInfoCallBack, EnumOidCallback)) goto TraceErr; fResult=TRUE; CommonReturn: //free the memory return fResult; ErrorReturn: FreeUsageOID(*pdwOIDInfo,*pprgOIDInfo); *pdwOIDInfo=0; *pprgOIDInfo=NULL; fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(TraceErr); } //----------------------------------------------------------------------- // Initialize the tab control //----------------------------------------------------------------------- void InitTabControl(HWND hWndControl, PCCRYPTUI_CERT_MGR_STRUCT pCertMgrStruct) { DWORD dwIndex=0; DWORD dwCount=0; WCHAR wszText[MAX_STRING_SIZE]; UINT rgIDS[]={IDS_TAB_PERSONAL, IDS_TAB_OTHER, IDS_TAB_CA, IDS_TAB_ROOT, IDS_TAB_PUBLISHER, }; TCITEMW tcItem; if(!hWndControl) return; memset(&tcItem, 0, sizeof(TCITEM)); tcItem.mask=TCIF_TEXT; tcItem.pszText=wszText; if (pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) { dwIndex = pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK; //get the column header wszText[0]=L'\0'; LoadStringU(g_hmodThisDll, rgIDS[dwIndex], wszText, MAX_STRING_SIZE); TabCtrl_InsertItemU(hWndControl, 0, &tcItem); } else { dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]); //insert the tabs one at a time for(dwIndex=0; dwIndexprgCertContext) { for(dwIndex=0; dwIndexdwCertCount; dwIndex++) { if(pCertMgrInfo->prgCertContext[dwIndex]) CertFreeCertificateContext(pCertMgrInfo->prgCertContext[dwIndex]); } WizardFree(pCertMgrInfo->prgCertContext); } pCertMgrInfo->dwCertCount=0; pCertMgrInfo->prgCertContext=NULL; return; } //-------------------------------------------------------------- // Initialize the Purpose Combo //-------------------------------------------------------------- void InitPurposeCombo(HWND hwndDlg, CERT_MGR_INFO *pCertMgrInfo) { DWORD dwIndex=0; DWORD dwCount=0; WCHAR wszText[MAX_STRING_SIZE]; UINT rgIDS[]={IDS_OID_ADVANCED, IDS_OID_ALL}; LPWSTR pwszInitOIDName=NULL; CRYPTUI_CERT_MGR_STRUCT *pCertMgrStruct=NULL; int iIndex=0; if(!hwndDlg || !pCertMgrInfo) return; pCertMgrStruct=(CRYPTUI_CERT_MGR_STRUCT *)(pCertMgrInfo->pCertMgrStruct); //delete all the entries in the comobox SendDlgItemMessage(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_RESETCONTENT, 0, 0); //copy all the basic OIDs to the comobox for(dwIndex=0; dwIndexdwOIDInfo; dwIndex++) { if(FALSE == (pCertMgrInfo->rgOIDInfo[dwIndex].fSelected)) { SendDlgItemMessageU(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_ADDSTRING, 0, (LPARAM)(pCertMgrInfo->rgOIDInfo[dwIndex].pwszName)); //looking for the initial OID if(pCertMgrStruct->pszInitUsageOID) { if(0 == _stricmp(pCertMgrStruct->pszInitUsageOID, pCertMgrInfo->rgOIDInfo[dwIndex].pszOID)) pwszInitOIDName=pCertMgrInfo->rgOIDInfo[dwIndex].pwszName; } } } //copy and to the list dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]); //insert the column one at a time for(dwIndex=0; dwIndex is what user specify is not either //client auth or secure e-mail if(pCertMgrStruct->pszInitUsageOID) { if(NULL==pwszInitOIDName) { wszText[0]=L'\0'; LoadStringU(g_hmodThisDll, IDS_OID_ADVANCED, wszText, MAX_STRING_SIZE); pwszInitOIDName=wszText; } } //use when NULL==pCertMgrStruct->pszInitUsageOID if(NULL==pwszInitOIDName) { //use as the initial case wszText[0]=L'\0'; LoadStringU(g_hmodThisDll, IDS_OID_ALL, wszText, MAX_STRING_SIZE); pwszInitOIDName=wszText; } iIndex=(int)SendDlgItemMessageU( hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_FINDSTRINGEXACT, -1, (LPARAM)pwszInitOIDName); if(CB_ERR == iIndex) return; //set the selection SendDlgItemMessageU(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_SETCURSEL, iIndex,0); return; } //-------------------------------------------------------------- // Initialize the Purpose Combo //-------------------------------------------------------------- void RepopulatePurposeCombo(HWND hwndDlg, CERT_MGR_INFO *pCertMgrInfo) { LPWSTR pwszSelectedOIDName=NULL; int iIndex=0; if(!hwndDlg || !pCertMgrInfo) return; //get the selected string from the combo box iIndex=(int)SendDlgItemMessage(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) return; //get the selected purpose if(CB_ERR == SendDlgItemMessageU_GETLBTEXT(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, iIndex, &pwszSelectedOIDName)) goto CLEANUP; InitPurposeCombo(hwndDlg, pCertMgrInfo); iIndex=(int)SendDlgItemMessageU( hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_FINDSTRINGEXACT, -1, (LPARAM)pwszSelectedOIDName); if(CB_ERR == iIndex) goto CLEANUP; //set the selection SendDlgItemMessageU(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO, CB_SETCURSEL, iIndex,0); CLEANUP: if(pwszSelectedOIDName) WizardFree(pwszSelectedOIDName); return; } //-------------------------------------------------------------- // The winProc for the advanced option diagloue for certMgr UI //-------------------------------------------------------------- INT_PTR APIENTRY CertMgrAdvancedProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_MGR_INFO *pCertMgrInfo=NULL; PCCRYPTUI_CERT_MGR_STRUCT pCertMgrStruct=NULL; UINT rgIDS[]={IDS_CERTMGR_DER, IDS_CERTMGR_BASE64, IDS_CERTMGR_PKCS7}; WCHAR wszText[MAX_STRING_SIZE]; DWORD dwCount=0; DWORD dwIndex=0; DWORD dwSelectedIndex=0; LV_ITEMW lvItem; LV_COLUMNW lvC; HWND hwndControl=NULL; int iIndex=0; int listIndex=0; NM_LISTVIEW FAR * pnmv=NULL; HWND hwnd=NULL; switch ( msg ) { case WM_INITDIALOG: pCertMgrInfo = (CERT_MGR_INFO *) lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pCertMgrInfo); pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; //init the export format control dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]); for(dwIndex=0; dwIndex < dwCount; dwIndex++) { LoadStringU(g_hmodThisDll, rgIDS[dwIndex], wszText, MAX_STRING_SIZE); SendDlgItemMessageU(hwndDlg, IDC_CERTMGR_EXPORT_COMBO, CB_INSERTSTRING, -1, (LPARAM)wszText); } //select the export format based on the selection switch (pCertMgrInfo->dwExportFormat) { case CRYPTUI_WIZ_EXPORT_FORMAT_DER: dwSelectedIndex=0; break; case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64: dwSelectedIndex=1; break; case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7: dwSelectedIndex=2; break; default: dwSelectedIndex=0; } SendDlgItemMessageU(hwndDlg, IDC_CERTMGR_EXPORT_COMBO, CB_SETCURSEL, (WPARAM)dwSelectedIndex,0); //init the chain check-box if(pCertMgrInfo->fExportChain) SendDlgItemMessage(hwndDlg, IDC_CERTMGR_EXPORT_CHECK, BM_SETCHECK, 1, 0); else SendDlgItemMessage(hwndDlg, IDC_CERTMGR_EXPORT_CHECK, BM_SETCHECK, 0, 0); if(dwSelectedIndex != 2) EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_CHECK), FALSE); else EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_CHECK), TRUE); //init the advanced OID list hwndControl = GetDlgItem(hwndDlg, IDC_CERTMGR_ADV_LIST); //mark the list is selected by a check box ListView_SetExtendedListViewStyle(hwndControl, LVS_EX_CHECKBOXES); //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 =10; // (dwMaxSize+2)*7; // 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; //populate the list memset(&lvItem, 0, sizeof(LV_ITEMW)); lvItem.mask=LVIF_TEXT | LVIF_STATE; for(dwIndex=0; dwIndexdwOIDInfo; dwIndex++) { lvItem.iItem=dwIndex; lvItem.pszText=(pCertMgrInfo->rgOIDInfo[dwIndex]).pwszName; lvItem.cchTextMax=sizeof(WCHAR)*(1+wcslen((pCertMgrInfo->rgOIDInfo[dwIndex]).pwszName)); lvItem.stateMask = LVIS_STATEIMAGEMASK; lvItem.state = (pCertMgrInfo->rgOIDInfo[dwIndex]).fSelected ? 0x00002000 : 0x00001000; // insert and set state ListView_SetItemState(hwndControl, ListView_InsertItemU(hwndControl, &lvItem), (pCertMgrInfo->rgOIDInfo[dwIndex]).fSelected ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK); } //autosize the column ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); #if (1) // DSIE: bug 282268. ListView_SetItemState(hwndControl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); #endif break; case WM_NOTIFY: pCertMgrInfo = (CERT_MGR_INFO *) GetWindowLongPtr(hwndDlg, DWLP_USER); if(NULL == pCertMgrInfo) break; pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; switch (((NMHDR FAR *) lParam)->code) { case LVN_ITEMCHANGED: //if the state of the advanced OID check box //has been changed, mark the flag pnmv = (NM_LISTVIEW FAR *) lParam; if(NULL==pnmv) break; //see if the new item is de-selected if(pnmv->uChanged & LVIF_STATE) pCertMgrInfo->fAdvOIDChanged=TRUE; break; } break; case WM_DESTROY: break; case WM_HELP: case WM_CONTEXTMENU: if (msg == WM_HELP) { hwnd = GetDlgItem(hwndDlg, ((LPHELPINFO)lParam)->iCtrlId); } else { hwnd = (HWND) wParam; } if ((hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_ADV_LIST)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_COMBO)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_CHECK)) && (hwnd != GetDlgItem(hwndDlg, IDOK)) && (hwnd != GetDlgItem(hwndDlg, IDCANCEL))) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } else { return OnContextHelp(hwndDlg, msg, wParam, lParam, CertMgrAdvHelpMap); } break; case WM_COMMAND: pCertMgrInfo = (CERT_MGR_INFO *) GetWindowLongPtr(hwndDlg, DWLP_USER); if(NULL == pCertMgrInfo) break; pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; //a control is clicked if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDCANCEL: pCertMgrInfo->fAdvOIDChanged=FALSE; EndDialog(hwndDlg, DIALOGUE_CANCEL); break; case IDOK: //the OK button is selected //get the default export format iIndex=(int)SendDlgItemMessage(hwndDlg, IDC_CERTMGR_EXPORT_COMBO, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) break; switch(iIndex) { case 0: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_DER; break; case 1: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_BASE64; break; case 2: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7; break; default: pCertMgrInfo->dwExportFormat=0; break; } if(TRUE==SendDlgItemMessage( hwndDlg, IDC_CERTMGR_EXPORT_CHECK, BM_GETCHECK, 0,0)) pCertMgrInfo->fExportChain=TRUE; else pCertMgrInfo->fExportChain=FALSE; //get the list of advanded OIDs if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_ADV_LIST))) break; //get the count of selected OIDs and mark them for(dwIndex=0; dwIndexdwOIDInfo; dwIndex++) { //mark the selected OIDS. Keep track of //if the OID selections have been changed if(ListView_GetCheckState(hwndControl, dwIndex)) { ((pCertMgrInfo->rgOIDInfo)[dwIndex]).fSelected=TRUE; } else { ((pCertMgrInfo->rgOIDInfo)[dwIndex]).fSelected=FALSE; } } //save the advanced options to the registry SaveAdvValueToReg(pCertMgrInfo); EndDialog(hwndDlg, DIALOGUE_OK); break; } } //a combo box's selection has been changed if(HIWORD(wParam) == CBN_SELCHANGE) { switch(LOWORD(wParam)) { case IDC_CERTMGR_EXPORT_COMBO: //the export format combo box has been changed //get the selected item index iIndex=(int)SendDlgItemMessage(hwndDlg, IDC_CERTMGR_EXPORT_COMBO, CB_GETCURSEL, 0, 0); if(CB_ERR==iIndex) break; //enable the check box for the chain if //PKCS#7 option is selected if(2 == iIndex) EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_CHECK), TRUE); else EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT_CHECK), FALSE); break; } } break; } return FALSE; } //-------------------------------------------------------------- // The winProc for CertMgrDialogProc //-------------------------------------------------------------- INT_PTR APIENTRY CertMgrDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_MGR_INFO *pCertMgrInfo=NULL; PCCRYPTUI_CERT_MGR_STRUCT pCertMgrStruct=NULL; HWND hWndListView=NULL; HWND hWndControl=NULL; DWORD dwIndex=0; DWORD dwCount=0; WCHAR wszText[MAX_STRING_SIZE]; BOOL fCanDelete=FALSE; UINT rgIDS[]={IDS_COLUMN_SUBJECT, IDS_COLUMN_ISSUER, IDS_COLUMN_EXPIRE, IDS_COLUMN_NAME}; NM_LISTVIEW FAR * pnmv=NULL; LPNMLVKEYDOWN pnkd=NULL; LV_COLUMNW lvC; int listIndex=0; LV_ITEM lvItem; BOOL fPropertyChanged=FALSE; HIMAGELIST hIml=NULL; CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct; CRYPTUI_WIZ_EXPORT_INFO CryptUIWizExportInfo; UINT idsDeleteConfirm=0; int iIndex=0; DWORD dwSortParam=0; HCERTSTORE hCertStore=NULL; HWND hwnd=NULL; DWORD cbData=0; switch ( msg ) { case WM_INITDIALOG: pCertMgrInfo = (CERT_MGR_INFO *) lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pCertMgrInfo); pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; // // set the dialog title // if (pCertMgrStruct->pwszTitle) { SetWindowTextU(hwndDlg, pCertMgrStruct->pwszTitle); } //create the image list hIml = ImageList_LoadImage(g_hmodThisDll, MAKEINTRESOURCE(IDB_CERT), 0, 1, RGB(255,0,255), IMAGE_BITMAP, 0); // // add the colums to the list view // hWndListView = GetDlgItem(hwndDlg, IDC_CERTMGR_LIST); if(NULL==hWndListView) break; //set the image list if (hIml != NULL) { ListView_SetImageList(hWndListView, hIml, LVSIL_SMALL); } dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]); //set up the common info for the column 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 = 80; // Width of the column, in pixels. lvC.iSubItem=0; lvC.pszText = wszText; // The text for the column. //inser the column one at a time for(dwIndex=0; dwIndexdwFlags & (CRYPTUI_CERT_MGR_TAB_MASK | CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) )) ? 4 : 0 ); //Init the purpose combo box InitPurposeCombo(hwndDlg,pCertMgrInfo); //Init the certificates in the list view based on the tab selected //and the purpose selected RefreshCertListView(hwndDlg, pCertMgrInfo); //Set the correct window title based on the tab selection // RefreshWindowTitle(hwndDlg, (CRYPTUI_CERT_MGR_STRUCT *)pCertMgrStruct); //register the listView window as the drop desitination if(S_OK == CCertMgrDropTarget_CreateInstance( hwndDlg, pCertMgrInfo, &(pCertMgrInfo->pIDropTarget))) { __try { RegisterDragDrop(hWndListView, pCertMgrInfo->pIDropTarget); } __except(EXCEPTION_EXECUTE_HANDLER) { } } break; case WM_NOTIFY: pCertMgrInfo = (CERT_MGR_INFO *) GetWindowLongPtr(hwndDlg, DWLP_USER); if(NULL == pCertMgrInfo) break; pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; switch (((NMHDR FAR *) lParam)->code) { //the delete key has been pressed case LVN_KEYDOWN: pnkd = (LPNMLVKEYDOWN) lParam; if(VK_DELETE == pnkd->wVKey) { if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; GetAllSelectedItem(hWndControl, ALL_SELECTED_CAN_DELETE, &fCanDelete); if(!fCanDelete) { I_MessageBox( hwndDlg, IDS_CANNOT_DELETE_CERTS, IDS_CERT_MGR_TITLE, pCertMgrStruct->pwszTitle, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); } else { //same action as user has click on the DELETE button SendDlgItemMessage(hwndDlg, IDC_CERTMGR_REMOVE, BM_CLICK, 0,0); } } break; //drag drop operation has begun case LVN_BEGINDRAG: case LVN_BEGINRDRAG: pnmv = (LPNMLISTVIEW) lParam; if(!pnmv) break; if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_SELECTED ); if(listIndex != -1) //start the drag and drop CertMgrUIStartDragDrop(pnmv, hWndControl, pCertMgrInfo->dwExportFormat, pCertMgrInfo->fExportChain); break; //the item has been selected case LVN_ITEMCHANGED: if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; pnmv = (LPNMLISTVIEW) lParam; if(NULL==pnmv) break; if (pnmv->uNewState & LVIS_SELECTED) { //enable the export buttons EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT), TRUE); //if more than one certificates are selected, diable the view button if(ListView_GetSelectedCount(hWndControl) > 1) EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_VIEW), FALSE); else EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_VIEW), TRUE); //enable the delete window only if the certificate is deletable GetAllSelectedItem(hWndControl, ALL_SELECTED_CAN_DELETE, &fCanDelete); if(fCanDelete) EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_REMOVE), TRUE); else EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_REMOVE), FALSE); //display the details of the certificate if //only 1 cert is selected if(1 == ListView_GetSelectedCount(hWndControl)) { RefreshCertDetails(hwndDlg, (PCCERT_CONTEXT)(pnmv->lParam)); } else { //clear the ceritificate details group box SetDlgItemTextU(hwndDlg, IDC_CERTMGR_PURPOSE, L" "); } } else { //if the state is deselection if(0 == ListView_GetSelectedCount(hWndControl)) { //we diable the buttons if no certificate is selected EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_VIEW), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_CERTMGR_REMOVE), FALSE); //clear the ceritificate details group box SetDlgItemTextU(hwndDlg, IDC_CERTMGR_PURPOSE, L" "); } } break; //the column has been changed case LVN_COLUMNCLICK: pnmv = (NM_LISTVIEW FAR *) lParam; //get the column number dwSortParam=0; switch(pnmv->iSubItem) { case 0: case 1: case 2: case 3: case 4: dwSortParam=pCertMgrInfo->rgdwSortParam[pnmv->iSubItem]; break; default: dwSortParam=0; break; } if(0!=dwSortParam) { //remember to flip the ascend ording if(dwSortParam & SORT_COLUMN_ASCEND) { dwSortParam &= 0x0000FFFF; dwSortParam |= SORT_COLUMN_DESCEND; } else { if(dwSortParam & SORT_COLUMN_DESCEND) { dwSortParam &= 0x0000FFFF; dwSortParam |= SORT_COLUMN_ASCEND; } } //sort the column SendDlgItemMessage(hwndDlg, IDC_CERTMGR_LIST, LVM_SORTITEMS, (WPARAM) (LPARAM) dwSortParam, (LPARAM) (PFNLVCOMPARE)CompareCertificate); pCertMgrInfo->rgdwSortParam[pnmv->iSubItem]=dwSortParam; //remember the column number pCertMgrInfo->iColumn=pnmv->iSubItem; } break; //the tab has been changed case TCN_SELCHANGE: //we need to refresh the column sorting state pCertMgrInfo->rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND; pCertMgrInfo->rgdwSortParam[1]=SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND; pCertMgrInfo->rgdwSortParam[2]=SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND; pCertMgrInfo->rgdwSortParam[3]=SORT_COLUMN_NAME | SORT_COLUMN_DESCEND; pCertMgrInfo->rgdwSortParam[4]=SORT_COLUMN_NAME | SORT_COLUMN_DESCEND; pCertMgrInfo->iColumn=0; //if the tab is changed, we need to //refresh the list view and certificate's //detailed view RefreshCertListView(hwndDlg, pCertMgrInfo); //we also we to update the window title //based on the tabl selection //RefreshWindowTitle(hwndDlg, (CRYPTUI_CERT_MGR_STRUCT *)pCertMgrStruct); break; //double-click on the list view of the certificates case NM_DBLCLK: { switch (((NMHDR FAR *) lParam)->idFrom) { case IDC_CERTMGR_LIST: { //get the window handle of the cert list view if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; //get the selected cert listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_SELECTED ); if (listIndex != -1) { //get the selected certificate memset(&lvItem, 0, sizeof(LV_ITEM)); lvItem.mask=LVIF_PARAM; lvItem.iItem=listIndex; if(ListView_GetItem(hWndControl, &lvItem)) { //view certiificate if(pCertMgrInfo->dwCertCount > (DWORD)listIndex) { memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT)); CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT); CertViewStruct.pCertContext=(PCCERT_CONTEXT)(lvItem.lParam); CertViewStruct.hwndParent=hwndDlg; fPropertyChanged=FALSE; CryptUIDlgViewCertificate(&CertViewStruct, &fPropertyChanged); if(fPropertyChanged) { RefreshCertListView(hwndDlg, pCertMgrInfo); //we reselect the one ListView_SetItemState( hWndControl, listIndex, LVIS_SELECTED, LVIS_SELECTED); } } } } break; } } break; } #if (1) //DSIE: bug 264568. case NM_SETFOCUS: { //get the window handle of the cert list view if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; //get the selected cert listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_FOCUSED ); //select first item to show hilite. if (listIndex == -1) ListView_SetItemState(hWndControl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); break; } #endif } break; case WM_DESTROY: __try { //revoke drag drop RevokeDragDrop(GetDlgItem(hwndDlg, IDC_CERTMGR_LIST)); } __except(EXCEPTION_EXECUTE_HANDLER) { } pCertMgrInfo = (CERT_MGR_INFO *) GetWindowLongPtr(hwndDlg, DWLP_USER); if(pCertMgrInfo) { if(pCertMgrInfo->pIDropTarget) pCertMgrInfo->pIDropTarget->Release(); } // destroy the image list in the list view // hWndListView = GetDlgItem(hwndDlg, IDC_CERTMGR_LIST); if(NULL==hWndListView) break; //no need to destroy the image list. Handled by ListView //ImageList_Destroy(ListView_GetImageList(hWndListView, LVSIL_SMALL)); break; case WM_HELP: case WM_CONTEXTMENU: if (msg == WM_HELP) { hwnd = GetDlgItem(hwndDlg, ((LPHELPINFO)lParam)->iCtrlId); } else { hwnd = (HWND) wParam; } if ((hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_LIST)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_PURPOSE_COMBO)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_IMPORT)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_EXPORT)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_VIEW)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_REMOVE)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_ADVANCE)) && (hwnd != GetDlgItem(hwndDlg, IDOK)) && (hwnd != GetDlgItem(hwndDlg, IDC_CERTMGR_PURPOSE))) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } else { return OnContextHelp(hwndDlg, msg, wParam, lParam, CertMgrMainHelpMap); } break; case WM_COMMAND: pCertMgrInfo = (CERT_MGR_INFO *) GetWindowLongPtr(hwndDlg, DWLP_USER); if(NULL == pCertMgrInfo) break; pCertMgrStruct=pCertMgrInfo->pCertMgrStruct; if(NULL == pCertMgrStruct) break; //a control is clicked if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDC_CERTMGR_ADVANCE: //lauch the advanced dialogue if(DIALOGUE_OK == DialogBoxParamU( g_hmodThisDll, (LPCWSTR)(MAKEINTRESOURCE(IDD_CERTMGR_ADVANCED)), hwndDlg, CertMgrAdvancedProc, (LPARAM) pCertMgrInfo)) { //if the advanced OIDs' list has been changed, //we need to refresh the list window if(TRUE == pCertMgrInfo->fAdvOIDChanged) { //mark the flag pCertMgrInfo->fAdvOIDChanged=FALSE; //repopulate the combo box based on //the new selection RepopulatePurposeCombo(hwndDlg, pCertMgrInfo); //refresh the list window only if // is selected if(IsAdvancedSelected(hwndDlg)) RefreshCertListView(hwndDlg, pCertMgrInfo); } } break; case IDC_CERTMGR_REMOVE: //get the selected certificate if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; //get the selected cert listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_SELECTED ); if (listIndex != -1) { //get the selected tab if (pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) iIndex = pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK; else iIndex=TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_CERTMGR_TAB)); if(-1==iIndex) break; //delete confirmation switch(iIndex) { case 0: idsDeleteConfirm=IDS_CERTMGR_PERSONAL_REMOVE; break; case 1: idsDeleteConfirm=IDS_CERTMGR_OTHER_REMOVE; break; case 2: idsDeleteConfirm=IDS_CERTMGR_CA_REMOVE; break; case 3: idsDeleteConfirm=IDS_CERTMGR_ROOT_REMOVE; break; case 4: idsDeleteConfirm=IDS_CERTMGR_PUBLISHER_REMOVE; break; default: idsDeleteConfirm=IDS_CERTMGR_PERSONAL_REMOVE; break; } iIndex=I_MessageBox(hwndDlg, idsDeleteConfirm, IDS_CERT_MGR_TITLE, pCertMgrStruct->pwszTitle, MB_ICONEXCLAMATION|MB_YESNO|MB_APPLMODAL); if(IDYES == iIndex) { //delete all the selected certificates GetAllSelectedItem(hWndControl, ALL_SELECTED_DELETE, NULL); //refresh the list view since some certificates //might be deleted //send the tab control SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) 0, (LPARAM) NULL); RefreshCertListView(hwndDlg, pCertMgrInfo); } } else { //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_CERT_MGR_TITLE, pCertMgrStruct->pwszTitle, MB_ICONERROR|MB_OK|MB_APPLMODAL); } break; case IDC_CERTMGR_IMPORT: { DWORD dwTabIndex; HCERTSTORE hTabStore = NULL; // Import into the store associated with the // currently selected tab if (pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG) dwTabIndex = pCertMgrStruct->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK; else dwTabIndex = TabCtrl_GetCurSel( GetDlgItem(hwndDlg, IDC_CERTMGR_TAB)); if (TAB_STORE_NAME_CNT > dwTabIndex) { hTabStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_SET_LOCALIZED_NAME_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, rgpwszTabStoreName[dwTabIndex] ); } //call the certificate import wizard CryptUIWizImport( 0, hwndDlg, NULL, NULL, hTabStore); if (hTabStore) CertCloseStore(hTabStore, 0); //refresh the list view since new certificates //might be added RefreshCertListView(hwndDlg, pCertMgrInfo); } break; case IDC_CERTMGR_EXPORT: //get the selected certificate if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; //get the selected cert listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_SELECTED ); if (listIndex != -1) { //we call the export wizard differently based //on single or multiple selection if(ListView_GetSelectedCount(hWndControl) > 1) { //open a memory store hCertStore=CertOpenStore( CERT_STORE_PROV_MEMORY, g_dwMsgAndCertEncodingType, NULL, 0, NULL); if(hCertStore) { GetAllSelectedItem(hWndControl, ALL_SELECTED_COPY, &hCertStore); //call the export wizard memset(&CryptUIWizExportInfo, 0, sizeof(CRYPTUI_WIZ_EXPORT_INFO)); CryptUIWizExportInfo.dwSize=sizeof(CRYPTUI_WIZ_EXPORT_INFO); CryptUIWizExportInfo.dwSubjectChoice=CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY; CryptUIWizExportInfo.hCertStore=hCertStore; CryptUIWizExport(0, hwndDlg, NULL, &CryptUIWizExportInfo, NULL); CertCloseStore(hCertStore, 0); hCertStore=NULL; } } else { memset(&lvItem, 0, sizeof(LV_ITEM)); lvItem.mask=LVIF_PARAM; lvItem.iItem=listIndex; if(ListView_GetItem(hWndControl, &lvItem)) { if(pCertMgrInfo->dwCertCount > (DWORD)listIndex) { //call the export wizard memset(&CryptUIWizExportInfo, 0, sizeof(CRYPTUI_WIZ_EXPORT_INFO)); CryptUIWizExportInfo.dwSize=sizeof(CRYPTUI_WIZ_EXPORT_INFO); CryptUIWizExportInfo.dwSubjectChoice=CRYPTUI_WIZ_EXPORT_CERT_CONTEXT; CryptUIWizExportInfo.pCertContext=(PCCERT_CONTEXT)(lvItem.lParam); CryptUIWizExport(0, hwndDlg, NULL, &CryptUIWizExportInfo, NULL); } } } } else //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_CERT_MGR_TITLE, pCertMgrStruct->pwszTitle, MB_ICONERROR|MB_OK|MB_APPLMODAL); break; case IDC_CERTMGR_VIEW: //get the selected certificate if(NULL==(hWndControl=GetDlgItem(hwndDlg, IDC_CERTMGR_LIST))) break; //get the selected cert listIndex = ListView_GetNextItem( hWndControl, -1, LVNI_SELECTED ); if (listIndex != -1) { //view certiificate if(pCertMgrInfo->dwCertCount > (DWORD)listIndex) { memset(&lvItem, 0, sizeof(LV_ITEM)); lvItem.mask=LVIF_PARAM; lvItem.iItem=listIndex; if(ListView_GetItem(hWndControl, &lvItem)) { memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT)); CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT); CertViewStruct.pCertContext=(PCCERT_CONTEXT)(lvItem.lParam); CertViewStruct.hwndParent=hwndDlg; fPropertyChanged=FALSE; CryptUIDlgViewCertificate(&CertViewStruct, &fPropertyChanged); if(fPropertyChanged) { RefreshCertListView(hwndDlg, pCertMgrInfo); //we reselect the one ListView_SetItemState( hWndControl, listIndex, LVIS_SELECTED, LVIS_SELECTED); } } } } else //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_CERT_MGR_TITLE, pCertMgrStruct->pwszTitle, MB_ICONERROR|MB_OK|MB_APPLMODAL); break; case IDOK: case IDCANCEL: EndDialog(hwndDlg, NULL); break; default: break; } } //a combo box's selection has been changed if(HIWORD(wParam) == CBN_SELCHANGE) { switch(LOWORD(wParam)) { case IDC_CERTMGR_PURPOSE_COMBO: //if the purpose is changed, we need to //refresh the list view and certificate's //detailed view RefreshCertListView(hwndDlg, pCertMgrInfo); break; } } break; } return FALSE; } //-------------------------------------------------------------- // // Save the advanced option from the registry //-------------------------------------------------------------- void SaveAdvValueToReg(CERT_MGR_INFO *pCertMgrInfo) { HKEY hKeyExport=NULL; HKEY hKeyPurpose=NULL; DWORD dwDisposition=0; DWORD dwExportFormat=0; DWORD dwIndex=0; LPSTR pszDefaultOID=NULL; LPSTR pszOID=NULL; if(NULL==pCertMgrInfo) return; //open a registry entry for the export format under HKEY_CURRENT_USER if (ERROR_SUCCESS == RegCreateKeyExU( HKEY_CURRENT_USER, WSZCertMgrExportRegLocation, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyExport, &dwDisposition)) { //set the value switch(pCertMgrInfo->dwExportFormat) { case CRYPTUI_WIZ_EXPORT_FORMAT_DER: if(pCertMgrInfo->fExportChain) dwExportFormat=4; else dwExportFormat=1; break; case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64: if(pCertMgrInfo->fExportChain) dwExportFormat=5; else dwExportFormat=2; break; case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7: if(pCertMgrInfo->fExportChain) dwExportFormat=6; else dwExportFormat=3; break; default: break; } if(0 != dwExportFormat) { //set the value RegSetValueExU( hKeyExport, WSZCertMgrExportName, 0, // dwReserved REG_DWORD, (BYTE *) &dwExportFormat, sizeof(dwExportFormat)); } } //open the registry entry for the advanced OIDs dwDisposition=0; if (ERROR_SUCCESS == RegCreateKeyExU( HKEY_CURRENT_USER, WSZCertMgrPurposeRegLocation, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyPurpose, &dwDisposition)) { //build a char "," seperated string for simple OID pszDefaultOID=(LPSTR)WizardAlloc(sizeof(CHAR)); if(NULL == pszDefaultOID) goto CLEANUP; *pszDefaultOID=L'\0'; for(dwIndex=0; dwIndexdwOIDInfo; dwIndex++) { if(FALSE==(pCertMgrInfo->rgOIDInfo)[dwIndex].fSelected) { if(strlen(pszDefaultOID)!=0) strcat(pszDefaultOID, ","); pszOID=(pCertMgrInfo->rgOIDInfo)[dwIndex].pszOID; pszDefaultOID=(LPSTR)WizardRealloc(pszDefaultOID, sizeof(CHAR)*(strlen(pszDefaultOID)+strlen(pszOID)+strlen(",")+1)); if(NULL==pszDefaultOID) goto CLEANUP; strcat(pszDefaultOID,pszOID); } } //set the value RegSetValueEx( hKeyPurpose, SZCertMgrPurposeName, 0, REG_SZ, (BYTE *)(pszDefaultOID), (strlen(pszDefaultOID) + 1) * sizeof(CHAR)); } CLEANUP: if(pszDefaultOID) WizardFree(pszDefaultOID); //close the registry keys if(hKeyExport) RegCloseKey(hKeyExport); if(hKeyPurpose) RegCloseKey(hKeyPurpose); } //-------------------------------------------------------------- // // Get init value from the registry //-------------------------------------------------------------- void GetInitValueFromReg(CERT_MGR_INFO *pCertMgrInfo) { HKEY hKeyExport=NULL; HKEY hKeyPurpose=NULL; DWORD dwType=0; DWORD dwExportFormat=0; DWORD cbExportFormat=0; LPSTR pszDefaultOID=NULL; DWORD cbDefaultOID=0; LPSTR pszTok=NULL; DWORD cTok = 0; DWORD cCount=0; CERT_ENHKEY_USAGE KeyUsage; LPSTR rgBasicOID[]={szOID_PKIX_KP_CLIENT_AUTH, szOID_PKIX_KP_EMAIL_PROTECTION}; BOOL fNoRegData=FALSE; if(NULL==pCertMgrInfo) return; //memset memset(&KeyUsage,0,sizeof(CERT_ENHKEY_USAGE)); //open the registry key if user has saved the advaced options if(ERROR_SUCCESS == RegOpenKeyExU(HKEY_CURRENT_USER, WSZCertMgrExportRegLocation, 0, KEY_READ, &hKeyExport)) { //get the data cbExportFormat=sizeof(dwExportFormat); if(ERROR_SUCCESS == RegQueryValueExU( hKeyExport, WSZCertMgrExportName, NULL, &dwType, (BYTE *)&dwExportFormat, &cbExportFormat)) { // added check for reg_binary because on WIN95 OSR2 when the machine is changed // from mutli-user profiles to single user profile, the registry DWORD values // change to BINARY // if ((dwType == REG_DWORD) || (dwType == REG_BINARY)) { switch(dwExportFormat) { case 1: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_DER; pCertMgrInfo->fExportChain=FALSE; break; case 2: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_BASE64; pCertMgrInfo->fExportChain=FALSE; break; case 3: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7; pCertMgrInfo->fExportChain=FALSE; break; case 4: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_DER; pCertMgrInfo->fExportChain=TRUE; break; case 5: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_BASE64; pCertMgrInfo->fExportChain=TRUE; break; case 6: pCertMgrInfo->dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7; pCertMgrInfo->fExportChain=TRUE; break; default: break; } } } } //get the advanced purposed if(ERROR_SUCCESS == RegOpenKeyExU(HKEY_CURRENT_USER, WSZCertMgrPurposeRegLocation, 0, KEY_READ, &hKeyPurpose)) { dwType=0; cbDefaultOID=0; if((ERROR_SUCCESS == RegQueryValueEx( hKeyPurpose, SZCertMgrPurposeName, NULL, &dwType, NULL, &cbDefaultOID))&&(cbDefaultOID!=0)) { pszDefaultOID=(LPSTR)WizardAlloc(cbDefaultOID); if(NULL==pszDefaultOID) goto CLEANUP; if(ERROR_SUCCESS != RegQueryValueEx( hKeyPurpose, SZCertMgrPurposeName, NULL, &dwType, (BYTE *)pszDefaultOID, &cbDefaultOID)) goto CLEANUP; // // Count the number of OIDs as well as converting from comma delimited // to NULL character delimited // if(0==strlen(pszDefaultOID)) fNoRegData=TRUE; else { pszTok = strtok(pszDefaultOID, ","); while ( pszTok != NULL ) { cTok++; pszTok = strtok(NULL, ","); } // // Allocate a cert enhanced key usage structure and fill it in with // the string tokens // pszTok = pszDefaultOID; KeyUsage.cUsageIdentifier = cTok; KeyUsage.rgpszUsageIdentifier = (LPSTR *)WizardAlloc(cTok * sizeof(LPSTR)); if(NULL==KeyUsage.rgpszUsageIdentifier) goto CLEANUP; for ( cCount = 0; cCount < cTok; cCount++ ) { KeyUsage.rgpszUsageIdentifier[cCount] = pszTok; pszTok = pszTok+strlen(pszTok)+1; } } } } //set up the default OIDs if the registry is empty if(0 == KeyUsage.cUsageIdentifier && TRUE != fNoRegData) { KeyUsage.cUsageIdentifier=2; KeyUsage.rgpszUsageIdentifier=rgBasicOID; } //mark the OIDs as advanced for basic for(cCount=0; cCountdwOIDInfo; cCount++) { if(IsAdvancedOID(&KeyUsage, (pCertMgrInfo->rgOIDInfo)[cCount].pszOID)) (pCertMgrInfo->rgOIDInfo)[cCount].fSelected=TRUE; } CLEANUP: //free memory if(pszDefaultOID) { WizardFree(pszDefaultOID); if(KeyUsage.rgpszUsageIdentifier) WizardFree(KeyUsage.rgpszUsageIdentifier); } //close the registry keys if(hKeyExport) RegCloseKey(hKeyExport); if(hKeyPurpose) RegCloseKey(hKeyPurpose); return; } //-------------------------------------------------------------- // // Parameters: // pCryptUICertMgr IN Required // // //-------------------------------------------------------------- BOOL WINAPI CryptUIDlgCertMgr( IN PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr) { BOOL fResult=FALSE; CERT_MGR_INFO CertMgrInfo; HRESULT hr=S_OK; DWORD dwException=0; //check the input parameter if(NULL==pCryptUICertMgr) goto InvalidArgErr; if(sizeof(CRYPTUI_CERT_MGR_STRUCT) != pCryptUICertMgr->dwSize) goto InvalidArgErr; if ((pCryptUICertMgr->dwFlags & CRYPTUI_CERT_MGR_TAB_MASK) > CRYPTUI_CERT_MGR_PUBLISHER_TAB) goto InvalidArgErr; if (!WizardInit()) { goto InitOIDErr; } //init struct memset(&CertMgrInfo, 0, sizeof(CertMgrInfo)); CertMgrInfo.pCertMgrStruct=pCryptUICertMgr; //get all the enhanced key usage OIDs if(!InitPurposeOID(pCryptUICertMgr->pszInitUsageOID, &(CertMgrInfo.dwOIDInfo), &(CertMgrInfo.rgOIDInfo))) goto InitOIDErr; //init the column sort CertMgrInfo.rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND; CertMgrInfo.rgdwSortParam[1]=SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND; CertMgrInfo.rgdwSortParam[2]=SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND; CertMgrInfo.rgdwSortParam[3]=SORT_COLUMN_NAME | SORT_COLUMN_DESCEND; CertMgrInfo.rgdwSortParam[4]=SORT_COLUMN_NAME | SORT_COLUMN_DESCEND; //we sort the 1st column CertMgrInfo.iColumn=0; //init the export format CertMgrInfo.dwExportFormat=CRYPTUI_WIZ_EXPORT_FORMAT_DER; CertMgrInfo.fExportChain=FALSE; CertMgrInfo.fAdvOIDChanged=FALSE; //init the OLE library __try { if(!SUCCEEDED(hr=OleInitialize(NULL))) goto OLEInitErr; //get the initialization from the registry GetInitValueFromReg(&CertMgrInfo); //call the dialog box if (DialogBoxParamU( g_hmodThisDll, (LPCWSTR)(MAKEINTRESOURCE(IDD_CERTMGR_MAIN)), (pCryptUICertMgr->hwndParent != NULL) ? pCryptUICertMgr->hwndParent : GetDesktopWindow(), CertMgrDialogProc, (LPARAM) &CertMgrInfo) == -1) { OleUninitialize(); goto DialogBoxErr; } OleUninitialize(); } __except(EXCEPTION_EXECUTE_HANDLER) { dwException = GetExceptionCode(); goto ExceptionErr; } fResult=TRUE; CommonReturn: //free the cert arrays FreeCerts(&CertMgrInfo); //free the usage OID array FreeUsageOID(CertMgrInfo.dwOIDInfo, CertMgrInfo.rgOIDInfo); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); TRACE_ERROR(DialogBoxErr); TRACE_ERROR(InitOIDErr); SET_ERROR_VAR(OLEInitErr, hr); SET_ERROR_VAR(ExceptionErr, dwException) }