//------------------------------------------------------------- // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: buildctl.cpp // // Contents: The cpp file to implement the makectl wizard // // History: 10-11-1997 xiaohs created // //-------------------------------------------------------------- #include "wzrdpvk.h" #include "buildctl.h" #include "wintrustp.h" //*********************************************************************** // // WinProc helper functions //********************************************************************** //-------------------------------------------------------------------------- // // CheckReplace // //-------------------------------------------------------------------------- BOOL CheckReplace(HWND hwndDlg, LPWSTR pwszFileName) { BOOL fReplace=FALSE; WCHAR wszTitle[MAX_STRING_SIZE]; WCHAR wszText[MAX_STRING_SIZE]; WCHAR wszFileText[MAX_STRING_SIZE]; if(NULL == pwszFileName || NULL == hwndDlg) goto CLEANUP; //title #if (0) //DSIE: Bug 160615 if(!LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle))) #else if(!LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle) / sizeof(wszTitle[0]))) #endif goto CLEANUP; //text #if (0) //DSIE: Bug 160616 if(!LoadStringU(g_hmodThisDll, IDS_REPLACE_FILE, wszText, sizeof(wszText))) #else if(!LoadStringU(g_hmodThisDll, IDS_REPLACE_FILE, wszText, sizeof(wszText) / sizeof(wszText[0]))) #endif goto CLEANUP; if(0 == swprintf(wszFileText, wszText, pwszFileName)) goto CLEANUP; if(IDNO==MessageBoxExW(hwndDlg, wszFileText, wszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2|MB_APPLMODAL, 0)) fReplace=FALSE; else fReplace=TRUE; CLEANUP: return fReplace; } //-------------------------------------------------------------------------- // // DuratioinWithinLimit: We limit the CTL to 99 months. // //-------------------------------------------------------------------------- BOOL DurationWithinLimit(DWORD dwMonths, DWORD dwDays) { BOOL fResult=FALSE; FILETIME ThisUpdate; FILETIME NextUpdate; DWORD dwNewMonth=0; DWORD dwNewDay=0; if((0==dwMonths) && (0==dwDays)) return TRUE; //This update field GetSystemTimeAsFileTime(&ThisUpdate); AddDurationToFileTime(dwMonths, dwDays, &ThisUpdate, &NextUpdate); SubstractDurationFromFileTime( &NextUpdate, &ThisUpdate, &dwNewMonth, &dwNewDay); if((dwNewMonth > 99) || (dwNewMonth == 99 && dwNewDay !=0)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // // FormatMessageIDSU // //-------------------------------------------------------------------------- BOOL FormatMessageIDSU(LPWSTR *ppwszFormat,UINT ids, ...) { WCHAR wszFormat[MAX_STRING_SIZE]; LPWSTR pwszMsg=NULL; BOOL fResult=FALSE; va_list argList; va_start(argList, ids); #if (0) //DSIE: Bug 160614 if(!LoadStringU(g_hmodThisDll, ids, wszFormat, sizeof(wszFormat))) #else if(!LoadStringU(g_hmodThisDll, ids, wszFormat, sizeof(wszFormat) / sizeof(wszFormat[0]))) #endif goto LoadStringError; if(!FormatMessageU(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, wszFormat, 0, 0, (LPWSTR)&pwszMsg, 0, &argList)) goto FormatMessageError; if(!(*ppwszFormat=WizardAllocAndCopyWStr(pwszMsg))) goto SZtoWSZError; fResult=TRUE; CommonReturn: va_end(argList); if(pwszMsg) LocalFree((HLOCAL)pwszMsg); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(LoadStringError); TRACE_ERROR(FormatMessageError); TRACE_ERROR(SZtoWSZError); } /* // get format string from resources CHAR szFormat[256]; va_list argList; LPSTR pszMsg=NULL; DWORD cbMsg=0; BOOL fResult=FALSE; HRESULT hr=S_OK; if(!LoadStringA(g_hmodThisDll, ids, szFormat, sizeof(szFormat))) goto LoadStringError; // format message into requested buffer va_start(argList, ids); cbMsg = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, szFormat, 0, // dwMessageId 0, // dwLanguageId (LPSTR) &pszMsg, 0, // minimum size to allocate &argList); va_end(argList); if(!cbMsg) goto FormatMessageError; //copy the sz to wsz if(!(*ppwszFormat=MkWStr(pszMsg))) goto SZtoWSZError; fResult=TRUE; CommonReturn: if(pszMsg) LocalFree((HLOCAL)pszMsg); return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; TRACE_ERROR(LoadStringError); TRACE_ERROR(FormatMessageError); TRACE_ERROR(SZtoWSZError); } */ //---------------------------------------------------------------------------- // GetValidityString // //---------------------------------------------------------------------------- BOOL GetValidityString(DWORD dwValidMonths, DWORD dwValidDays, LPWSTR *ppwszString) { BOOL fResult=FALSE; if(!ppwszString) return FALSE; *ppwszString=NULL; if((0==dwValidMonths) && (0==dwValidDays)) return FALSE; if(dwValidMonths && dwValidDays) fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_MONTH_DAY, dwValidMonths, dwValidDays); else { if(dwValidMonths) fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_MONTH, dwValidMonths); else fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_DAY, dwValidDays); } return fResult; } //---------------------------------------------------------------------------- // Make sure that user has typed // //---------------------------------------------------------------------------- BOOL ValidDuration(LPWSTR pwszDuration) { DWORD i=0; if(NULL==pwszDuration) return FALSE; //only numerical numbers should be allowed for (i=0; i< (DWORD)(wcslen(pwszDuration)); i++) { if ((pwszDuration[i] < L'0') || (pwszDuration[i] > L'9')) return FALSE; } return TRUE; } //---------------------------------------------------------------------------- // SetStoreName // //---------------------------------------------------------------------------- void SetStoreName(HWND hwndControl, HCERTSTORE hDesStore) { LPWSTR pwszStoreName=NULL; // LV_COLUMNW lvC; // LV_ITEMW lvItem; DWORD dwSize=0; //get the store name if(!CertGetStoreProperty( hDesStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, &dwSize) || (0==dwSize)) { //DSIE: Prefix bug 427201. //Get the string pwszStoreName=(LPWSTR)WizardAlloc(MAX_TITLE_LENGTH * sizeof(WCHAR)); if(pwszStoreName) { *pwszStoreName=L'\0'; LoadStringU(g_hmodThisDll, IDS_UNKNOWN, pwszStoreName, MAX_TITLE_LENGTH); } } else { pwszStoreName=(LPWSTR)WizardAlloc(dwSize); if(pwszStoreName) { *pwszStoreName=L'\0'; CertGetStoreProperty( hDesStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, pwszStoreName, &dwSize); } } if(pwszStoreName) SetWindowTextU(hwndControl,pwszStoreName); if(pwszStoreName) WizardFree(pwszStoreName); /* //clear the ListView ListView_DeleteAllItems(hwndControl); //set the store name //only one column is needed 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; //(wcslen(pwszStoreName)+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) { if(pwszStoreName) WizardFree(pwszStoreName); return; } //insert the store name memset(&lvItem, 0, sizeof(LV_ITEMW)); // set up the fields in the list view item struct that don't change from item to item lvItem.mask = LVIF_TEXT | LVIF_STATE ; lvItem.state = 0; lvItem.stateMask = 0; lvItem.iItem=0; lvItem.iSubItem=0; lvItem.pszText=pwszStoreName; ListView_InsertItemU(hwndControl, &lvItem); //automatically resize the column ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); */ } BOOL SameCert(PCCERT_CONTEXT pCertOne, PCCERT_CONTEXT pCertTwo) { if(!pCertOne || !pCertTwo) return FALSE; if(pCertOne->cbCertEncoded != pCertTwo->cbCertEncoded) return FALSE; if(0 == memcmp(pCertOne->pbCertEncoded, pCertTwo->pbCertEncoded, pCertTwo->cbCertEncoded)) return TRUE; return FALSE; } //---------------------------------------------------------------------------- // Delete a certificate from the pCertBuildCTLInfo // //---------------------------------------------------------------------------- BOOL DeleteCertFromBuildCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo, PCCERT_CONTEXT pCertContext) { //we need to remove the cert from our array PCCERT_CONTEXT *prgCertContext=NULL; DWORD dwIndex=0; DWORD dwNewIndex=0; int iIndex=-1; if(!pCertBuildCTLInfo || !pCertContext) return FALSE; //consider the case of only one cert left if(pCertBuildCTLInfo->dwCertCount == 1) { pCertBuildCTLInfo->dwCertCount=0; //free the certificate context CertFreeCertificateContext(pCertBuildCTLInfo->prgCertContext[0]); WizardFree(pCertBuildCTLInfo->prgCertContext); pCertBuildCTLInfo->prgCertContext=NULL; } else { prgCertContext=pCertBuildCTLInfo->prgCertContext; //re-allocate the memory pCertBuildCTLInfo->prgCertContext=(PCCERT_CONTEXT *)WizardAlloc(sizeof(PCCERT_CONTEXT) * (pCertBuildCTLInfo->dwCertCount-1)); //if we are out of memory if(NULL==pCertBuildCTLInfo->prgCertContext) { //reset pCertBuildCTLInfo->prgCertContext=prgCertContext; return FALSE; } //copy the certificate context over dwNewIndex=0; for(dwIndex=0; dwIndexdwCertCount; dwIndex++) { //find the cert to delete, and do not copy it to the new array if(SameCert(prgCertContext[dwIndex], pCertContext)) { iIndex=dwIndex; continue; } pCertBuildCTLInfo->prgCertContext[dwNewIndex]=prgCertContext[dwIndex]; dwNewIndex++; } //remember that we are one cert less pCertBuildCTLInfo->dwCertCount=dwNewIndex; if(prgCertContext) { //free the certificate context if(-1 != iIndex) CertFreeCertificateContext(prgCertContext[iIndex]); WizardFree(prgCertContext); } } return TRUE; } //---------------------------------------------------------------------------- // Add certificate to the pCertBuildCTLInfo // //---------------------------------------------------------------------------- BOOL AddCertToBuildCTL(PCCERT_CONTEXT pCertContext, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { DWORD dwIndex=0; //check to see if the certificate is alreayd in the CTL for(dwIndex=0; dwIndex < pCertBuildCTLInfo->dwCertCount; dwIndex++) { if(pCertContext->cbCertEncoded == (pCertBuildCTLInfo->prgCertContext[dwIndex])->cbCertEncoded) { if(0==memcmp(pCertContext->pbCertEncoded, (pCertBuildCTLInfo->prgCertContext[dwIndex])->pbCertEncoded, pCertContext->cbCertEncoded)) //return FALSE if a duplicate exists return FALSE; } } pCertBuildCTLInfo->prgCertContext=(PCCERT_CONTEXT *)WizardRealloc( pCertBuildCTLInfo->prgCertContext, sizeof(PCCERT_CONTEXT *)*(pCertBuildCTLInfo->dwCertCount +1)); if(NULL==pCertBuildCTLInfo->prgCertContext) { pCertBuildCTLInfo->dwCertCount=0; return FALSE; } pCertBuildCTLInfo->prgCertContext[pCertBuildCTLInfo->dwCertCount]=pCertContext; pCertBuildCTLInfo->dwCertCount++; return TRUE; } //---------------------------------------------------------------------------- // Add certificate to the ListView // //---------------------------------------------------------------------------- BOOL AddCertToList(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_PARAM; lvItem.state = 0; lvItem.stateMask = 0; lvItem.iItem=iItem; lvItem.iSubItem=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 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); lvItem.pszText=pwszName; ListView_InsertItemU(hwndControl, &lvItem); } else { lvItem.pszText=wszNone; ListView_InsertItemU(hwndControl, &lvItem); } //WizardFree the memory if(pwszName) { WizardFree(pwszName); pwszName=NULL; } //Issuer lvItem.iSubItem++; 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); 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(MyFormatEnhancedKeyUsageString(&pwszName,pCertContext, FALSE, FALSE)) { ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszName); } //free the memory if(pwszName) { WizardFree(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; } return TRUE; } //---------------------------------------------------------------------------- // Make sure the cert has the same usage as the ones defined in CTL. // //---------------------------------------------------------------------------- BOOL CertMatchCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo, PCCERT_CONTEXT pCertContext) { BOOL fResult=FALSE; int cNumOID=0; LPSTR *rgOID=NULL; DWORD cbOID=0; DWORD dwIndex=0; DWORD dwOIDIndex=0; if(!pCertBuildCTLInfo || !pCertContext) return FALSE; //we have to have some oids in the list if(0==pCertBuildCTLInfo->dwPurposeCount || NULL==pCertBuildCTLInfo->prgPurpose) return FALSE; //get the OIDs from the cert if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, NULL, &cbOID)) return FALSE; rgOID=(LPSTR *)WizardAlloc(cbOID); if(NULL==rgOID) return FALSE; if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, rgOID, &cbOID)) goto CLEANUP; if(-1==cNumOID) { fResult=TRUE; goto CLEANUP; } //make sure the array of OIDs match the ones in the CTL for(dwIndex=0; dwIndexdwPurposeCount; dwIndex++) { if(NULL==pCertBuildCTLInfo->prgPurpose[dwIndex]) continue; if(FALSE==pCertBuildCTLInfo->prgPurpose[dwIndex]->fSelected) continue; if(NULL==pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID) continue; //we need to find at least one match from the oids supported by the cert for(dwOIDIndex=0; dwOIDIndex<(DWORD)cNumOID; dwOIDIndex++) { if(0==strcmp(pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID, rgOID[dwOIDIndex])) { fResult=TRUE; goto CLEANUP; } } } //we are hopeless at this point fResult=FALSE; CLEANUP: if(rgOID) WizardFree(rgOID); return fResult; } //---------------------------------------------------------------------------- // Find a cert from stores . // //---------------------------------------------------------------------------- static PCCERT_CONTEXT FindCertContextInStores( PCTL_ENTRY pCtlEntry, DWORD chStores1, HCERTSTORE *rghStores1, DWORD chStores2, HCERTSTORE *rghStores2, HCERTSTORE hExtraStore, DWORD dwFindType) { DWORD i; PCCERT_CONTEXT pCertContext = NULL; if (dwFindType == 0) { return NULL; } i = 0; while ((iSubjectIdentifier), NULL); } i = 0; while ((iSubjectIdentifier), NULL); } if (pCertContext == NULL) { pCertContext = CertFindCertificateInStore( hExtraStore, X509_ASN_ENCODING, 0, dwFindType, (void *)&(pCtlEntry->SubjectIdentifier), NULL); } return pCertContext; } //---------------------------------------------------------------------------- // See if the certificate is valid // //---------------------------------------------------------------------------- BOOL IsValidCert(HWND hwndDlg, PCCERT_CONTEXT pCertContext, CERT_BUILDCTL_INFO *pCertBuildCTLInfo, BOOL fMsg, BOOL fFromCTL) { //make sure the pCertContext is a self-signed certificate if(!TrustIsCertificateSelfSigned(pCertContext, pCertContext->dwCertEncodingType, 0)) { if(fMsg) { if(fFromCTL) I_MessageBox(hwndDlg, IDS_NOT_SELF_SIGNED_FROM_CTL, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); else I_MessageBox(hwndDlg, IDS_NOT_SELF_SIGNED, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); } return FALSE; } //make sure the certifcate match what is defined on the CTL list if(!CertMatchCTL(pCertBuildCTLInfo, pCertContext)) { if(fMsg) { if(fFromCTL) I_MessageBox(hwndDlg, IDS_NO_MATCH_USAGE_FROM_CTL, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); else I_MessageBox(hwndDlg, IDS_NO_MATCH_USAGE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); } return FALSE; } return TRUE; } //---------------------------------------------------------------------------- // Cert a ceritifcate from the file // //---------------------------------------------------------------------------- static HCERTSTORE GetCertStoreFromFile(HWND hwndDlg, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { OPENFILENAMEW OpenFileName; WCHAR szFileName[_MAX_PATH]; WCHAR szFilter[MAX_STRING_SIZE]; //"Certificate File (*.cer)\0*.cer\0Certificate File (*.crt)\0*.crt\0All Files\0*.*\0" BOOL fResult=FALSE; HCERTSTORE hCertStore=NULL; DWORD dwSize=0; DWORD dwContentType=0; if(!hwndDlg || !pCertBuildCTLInfo) return NULL; memset(&OpenFileName, 0, sizeof(OpenFileName)); *szFileName=L'\0'; OpenFileName.lStructSize = sizeof(OpenFileName); OpenFileName.hwndOwner = hwndDlg; OpenFileName.hInstance = NULL; //load the fileter string if(LoadFilterString(g_hmodThisDll, IDS_ALL_CER_FILTER, szFilter, MAX_STRING_SIZE)) { OpenFileName.lpstrFilter = szFilter; } OpenFileName.lpstrCustomFilter = NULL; OpenFileName.nMaxCustFilter = 0; OpenFileName.nFilterIndex = 1; OpenFileName.lpstrFile = szFileName; OpenFileName.nMaxFile = _MAX_PATH; OpenFileName.lpstrFileTitle = NULL; OpenFileName.nMaxFileTitle = 0; OpenFileName.lpstrInitialDir = NULL; OpenFileName.lpstrTitle = NULL; OpenFileName.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; OpenFileName.nFileOffset = 0; OpenFileName.nFileExtension = 0; OpenFileName.lpstrDefExt = L"cer"; OpenFileName.lCustData = NULL; OpenFileName.lpfnHook = NULL; OpenFileName.lpTemplateName = NULL; if (!WizGetOpenFileName(&OpenFileName)) return NULL; if(!ExpandAndCryptQueryObject(CERT_QUERY_OBJECT_FILE, szFileName, CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_CTL | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT | CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &dwContentType, NULL, &hCertStore, NULL, NULL) || (NULL==hCertStore)) { I_MessageBox(hwndDlg, IDS_INVALID_CERT_FILE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); goto CLEANUP; } if(dwContentType & CERT_QUERY_CONTENT_CTL) { I_MessageBox(hwndDlg, IDS_INVALID_CERT_FILE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); goto CLEANUP; } fResult=TRUE; CLEANUP: if(TRUE==fResult) return hCertStore; if(hCertStore) CertCloseStore(hCertStore, 0); return NULL; } //---------------------------------------------------------------------------- // CallBack fro cert selection call back // //---------------------------------------------------------------------------- static BOOL WINAPI SelCertCallBack( PCCERT_CONTEXT pCertContext, BOOL *pfInitialSelectedCert, void *pvCallbackData) { if(!pvCallbackData || !pCertContext) return FALSE; //make sure that this is a valid certificate return IsValidCert(((CERT_SEL_LIST *)pvCallbackData)->hwndDlg, pCertContext, ((CERT_SEL_LIST *)pvCallbackData)->pCertBuildCTLInfo, FALSE, FALSE); } ////////////////////////////////////////////////////////////////////////////////////// // The call back function for enum system stores for the signing certificate ////////////////////////////////////////////////////////////////////////////////////// static BOOL WINAPI EnumSysStoreSignCertCallBack( const void* pwszSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg ) { CERT_STORE_LIST *pCertStoreList=NULL; HCERTSTORE hCertStore=NULL; if(NULL==pvArg) return FALSE; pCertStoreList=(CERT_STORE_LIST *)pvArg; //open the store hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG, (LPWSTR)pwszSystemStore); if(!hCertStore) return FALSE; pCertStoreList->prgStore=(HCERTSTORE *)WizardRealloc( pCertStoreList->prgStore, sizeof(HCERTSTORE) *(pCertStoreList->dwStoreCount +1)); if(NULL==pCertStoreList->prgStore) { CertCloseStore(hCertStore, 0); pCertStoreList->dwStoreCount=0; } pCertStoreList->prgStore[pCertStoreList->dwStoreCount]=hCertStore; pCertStoreList->dwStoreCount++; return TRUE; } ////////////////////////////////////////////////////////////////////////////////////// // The call back function for enum system stores ////////////////////////////////////////////////////////////////////////////////////// static BOOL WINAPI EnumSysStoreCallBack( const void* pwszSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg ) { CERT_STORE_LIST *pCertStoreList=NULL; HCERTSTORE hCertStore=NULL; if(NULL==pvArg) return FALSE; pCertStoreList=(CERT_STORE_LIST *)pvArg; //open the store as read-only hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG|CERT_STORE_READONLY_FLAG, (LPWSTR)pwszSystemStore); //we can not open the store. if(!hCertStore) return TRUE; pCertStoreList->prgStore=(HCERTSTORE *)WizardRealloc( pCertStoreList->prgStore, sizeof(HCERTSTORE) *(pCertStoreList->dwStoreCount +1)); if(NULL==pCertStoreList->prgStore) { CertCloseStore(hCertStore, 0); pCertStoreList->dwStoreCount=0; } else // DSIE: Bug 227267 { pCertStoreList->prgStore[pCertStoreList->dwStoreCount]=hCertStore; pCertStoreList->dwStoreCount++; } return TRUE; } //---------------------------------------------------------------------------- // Cert a ceritifcate from the store // //---------------------------------------------------------------------------- static HCERTSTORE GetCertsFromStore(HWND hwndDlg, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { PCCERT_CONTEXT pCertContext=NULL; CRYPTUI_SELECTCERTIFICATE_STRUCT SelCert; CERT_SEL_LIST CertSelList; DWORD dwIndex=0; HCERTSTORE hCertStore; CERT_STORE_LIST CertStoreList; if(!hwndDlg || !pCertBuildCTLInfo) return NULL; //init memset(&CertStoreList, 0, sizeof(CertStoreList)); memset(&SelCert, 0, sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT)); memset(&CertSelList, 0, sizeof(CERT_SEL_LIST)); //set up the parameter for call back for cert selection dialogue CertSelList.hwndDlg=hwndDlg; CertSelList.pCertBuildCTLInfo=pCertBuildCTLInfo; if (NULL == (hCertStore = CertOpenStore( CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, NULL))) { goto CLEANUP; } //set up the parameter to get a list of certificate if (!CertEnumSystemStore( CERT_SYSTEM_STORE_CURRENT_USER, NULL, &CertStoreList, EnumSysStoreCallBack)) goto CLEANUP; //set up the parameter for cert selection dialogue SelCert.dwSize=sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT); SelCert.hwndParent=hwndDlg; SelCert.dwFlags = CRYPTUI_SELECTCERT_MULTISELECT; SelCert.pFilterCallback=SelCertCallBack; SelCert.pvCallbackData=&CertSelList; SelCert.cDisplayStores=CertStoreList.dwStoreCount; SelCert.rghDisplayStores=CertStoreList.prgStore; SelCert.hSelectedCertStore = hCertStore; CryptUIDlgSelectCertificate(&SelCert); CLEANUP: for(dwIndex=0; dwIndexpSrcCTL) { //open my, ca, trust, and root store if(rgHCertStore[dwIndex]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"my")) dwIndex++; if(rgHCertStore[dwIndex]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"trust")) dwIndex++; if(rgHCertStore[dwIndex]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"ca")) dwIndex++; if(rgHCertStore[dwIndex]=CertOpenStore( CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"root")) dwIndex++; //open the cert store hExtraStore = CertOpenStore( CERT_STORE_PROV_MSG, g_dwMsgAndCertEncodingType, NULL, 0, (const void *) (pCertBuildCTLInfo->pSrcCTL->hCryptMsg)); //find the certificate hash pCTLInfo=pCertBuildCTLInfo->pSrcCTL->pCtlInfo; if(pCertBuildCTLInfo->dwHashPropID==CERT_SHA1_HASH_PROP_ID) dwFindType=CERT_FIND_SHA1_HASH; else dwFindType=CERT_FIND_MD5_HASH; //look through each entry in the CTL list for(dwCertIndex=0; dwCertIndexcCTLEntry; dwCertIndex++) { pCertContext=FindCertContextInStores( &(pCTLInfo->rgCTLEntry[dwCertIndex]), dwIndex, rgHCertStore, 0, NULL, hExtraStore, dwFindType); if(NULL==pCertContext && TRUE==fFoundInCTLMsg) { I_MessageBox(hwndParent, IDS_NO_MATCH_IN_CTL, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); //no need to give the message again fFoundInCTLMsg=FALSE; continue; } else if (NULL==pCertContext) { continue; } if(!IsValidCert(hwndParent, pCertContext, pCertBuildCTLInfo, fInvalidCertMsg, TRUE)) { CertFreeCertificateContext(pCertContext); pCertContext=0; //no need to give message again fInvalidCertMsg=FALSE; continue; } if(!AddCertToBuildCTL(pCertContext, pCertBuildCTLInfo)) { CertFreeCertificateContext(pCertContext); pCertContext=NULL; continue; } } } else { //add the certificate from the hCertStore to the CTL if(NULL != hCertStore) { while(pCertContext=CertEnumCertificatesInStore(hCertStore, pPreCertContext)) { if(!IsValidCert(hwndParent, pCertContext, pCertBuildCTLInfo, FALSE, //do not want a message FALSE)) //not build from a CTL { pPreCertContext=pCertContext; continue; } //get a duplicate of the certificate context pPreCertContext=CertDuplicateCertificateContext(pCertContext); if(NULL==pPreCertContext) { pPreCertContext=pCertContext; continue; } //add the duplicate to the list if(!AddCertToBuildCTL(pPreCertContext, pCertBuildCTLInfo)) CertFreeCertificateContext(pPreCertContext); //continue for the next iteration pPreCertContext=pCertContext; } } } //free the certificate store if(hExtraStore) CertCloseStore(hExtraStore, 0); for(dwIndex=0; dwIndex < 4; dwIndex++) { if(rgHCertStore[dwIndex]) CertCloseStore(rgHCertStore[dwIndex], 0); } } //--------------------------------------------------------------------- // Init the certifcate list from the old CTL // //--------------------------------------------------------------------- void InitCertList(HWND hwndControl, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { DWORD dwIndex=0; if(!hwndControl || !pCertBuildCTLInfo) return; for(dwIndex=0; dwIndexdwCertCount; dwIndex++) { //add the certificat to the window AddCertToList(hwndControl,(pCertBuildCTLInfo->prgCertContext)[dwIndex], dwIndex); } } //----------------------------------------------------------------------- // The winProc for the new oid dialogue //----------------------------------------------------------------------- void FreeCerts(CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { DWORD dwIndex=0; if(!pCertBuildCTLInfo) return; if(pCertBuildCTLInfo->prgCertContext) { for(dwIndex=0; dwIndexdwCertCount; dwIndex++) { if(pCertBuildCTLInfo->prgCertContext[dwIndex]) CertFreeCertificateContext(pCertBuildCTLInfo->prgCertContext[dwIndex]); } WizardFree(pCertBuildCTLInfo->prgCertContext); } pCertBuildCTLInfo->dwCertCount=0; pCertBuildCTLInfo->prgCertContext=NULL; } ////////////////////////////////////////////////////////////////////////////////////// // The winProc for the new oid dialogue ////////////////////////////////////////////////////////////////////////////////////// INT_PTR APIENTRY CTLOIDDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { DWORD i; char szText[MAX_STRING_SIZE]; LPSTR pszText=NULL; int intMsg=0; CERT_ENHKEY_USAGE KeyUsage; DWORD cbData = 0; LPSTR pszCheckOID=NULL; switch ( msg ) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (GetDlgItemTextA( hwndDlg, IDC_WIZARD_EDIT1, szText, MAX_STRING_SIZE-1)) { // // make sure there are not weird characters // for (i=0; i<(DWORD)strlen(szText); i++) { if (((szText[i] < '0') || (szText[i] > '9')) && (szText[i] != '.')) { intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK | MB_ICONERROR|MB_APPLMODAL); return FALSE; } } // // check the last char, and for the empty string // if ((szText[0] == '.') || (szText[strlen(szText)-1] == '.') || (strcmp(szText, "") == 0)) { intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK | MB_ICONERROR|MB_APPLMODAL); return FALSE; } //encode the OID to make sure the format of the OID is correct pszCheckOID = szText; KeyUsage.rgpszUsageIdentifier = &pszCheckOID; KeyUsage.cUsageIdentifier = 1; if (!CryptEncodeObject( X509_ASN_ENCODING, szOID_ENHANCED_KEY_USAGE, &KeyUsage, NULL, &cbData)) { intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK | MB_ICONERROR|MB_APPLMODAL); return FALSE; } // // allocate space for the string and pass the string back // pszText = (LPSTR) WizardAlloc(strlen(szText)+1); if (pszText != NULL) { strcpy(pszText, szText); } } EndDialog(hwndDlg, (INT_PTR)pszText); break; case IDCANCEL: EndDialog(hwndDlg, 0); break; } break; } return FALSE; } //----------------------------------------------------------------------- //Free the purpose array //----------------------------------------------------------------------- void FreePurposeInfo(ENROLL_PURPOSE_INFO **prgPurposeInfo, DWORD dwOIDCount) { DWORD dwIndex=0; if(dwOIDCount==0 || NULL==prgPurposeInfo) return; for(dwIndex=0; dwIndexfFreeOID) { if((prgPurposeInfo[dwIndex])->pszOID) WizardFree((prgPurposeInfo[dwIndex])->pszOID); } if(TRUE==prgPurposeInfo[dwIndex]->fFreeName) { //the name was obtained viz MkWstr if((prgPurposeInfo[dwIndex])->pwszName) FreeWStr((prgPurposeInfo[dwIndex])->pwszName); } WizardFree(prgPurposeInfo[dwIndex]); } } WizardFree(prgPurposeInfo); } //----------------------------------------------------------------------- //Search for the OID in the array //----------------------------------------------------------------------- BOOL SearchAndAddOID(LPSTR pszOID, DWORD *pdwCount, ENROLL_PURPOSE_INFO ***pprgPurposeInfo, BOOL *pfFound, BOOL fAllocateOID, BOOL fMarkAsSelectedNew, BOOL fMarkAsSelectedFound ) { DWORD dwIndex=0; if(NULL==pszOID || NULL==pdwCount || NULL==pprgPurposeInfo) return FALSE; for(dwIndex=0; dwIndex< *pdwCount; dwIndex++) { //no need to go on if we find a match if(0==strcmp(pszOID, (*pprgPurposeInfo)[dwIndex]->pszOID)) { if(pfFound) *pfFound=TRUE; //mark the selected option if(TRUE==fMarkAsSelectedFound) (*pprgPurposeInfo)[dwIndex]->fSelected=TRUE; return TRUE; } } //we did not find a match if(pfFound) *pfFound=FALSE; //now, we need to add the OID to the list (*pdwCount)++; //get more memory for the pointer list *pprgPurposeInfo=(ENROLL_PURPOSE_INFO **)WizardRealloc(*pprgPurposeInfo, (*pdwCount) * sizeof(ENROLL_PURPOSE_INFO *)); if(NULL==*pprgPurposeInfo) return FALSE; //wizardAlloc for each pointer (*pprgPurposeInfo)[*pdwCount-1]=(ENROLL_PURPOSE_INFO *)WizardAlloc(sizeof(ENROLL_PURPOSE_INFO)); if(NULL==(*pprgPurposeInfo)[*pdwCount-1]) return FALSE; memset((*pprgPurposeInfo)[*pdwCount-1], 0, sizeof(ENROLL_PURPOSE_INFO)); if(TRUE==fAllocateOID) { (*pprgPurposeInfo)[*pdwCount-1]->pszOID=(LPSTR)WizardAlloc(strlen(pszOID)+1); if(NULL!=(*pprgPurposeInfo)[*pdwCount-1]->pszOID) { strcpy((*pprgPurposeInfo)[*pdwCount-1]->pszOID, pszOID); (*pprgPurposeInfo)[*pdwCount-1]->fFreeOID=TRUE; } } else { (*pprgPurposeInfo)[*pdwCount-1]->pszOID=pszOID; (*pprgPurposeInfo)[*pdwCount-1]->fFreeOID=FALSE; } //get the name for the OID based on the oid string if((*pprgPurposeInfo)[*pdwCount-1]->pszOID) { (*pprgPurposeInfo)[*pdwCount-1]->pwszName=MkWStr(pszOID); (*pprgPurposeInfo)[*pdwCount-1]->fFreeName=TRUE; } //mark the OID as selected if specified if(TRUE==fMarkAsSelectedNew) (*pprgPurposeInfo)[*pdwCount-1]->fSelected=TRUE; else (*pprgPurposeInfo)[*pdwCount-1]->fSelected=FALSE; return TRUE; } //----------------------------------------------------------------------- //The call back function for enum //----------------------------------------------------------------------- static BOOL WINAPI EnumInfoCallback( IN PCCRYPT_OID_INFO pInfo, IN void *pvArg ) { PURPOSE_INFO_CALL_BACK *pCallBackInfo=NULL; DWORD dwError=0; pCallBackInfo=(PURPOSE_INFO_CALL_BACK *)pvArg; if(NULL==pvArg || NULL==pInfo) return FALSE; //increment the oid list (*(pCallBackInfo->pdwCount))++; //get more memory for the pointer list *(pCallBackInfo->pprgPurpose)=(ENROLL_PURPOSE_INFO **)WizardRealloc(*(pCallBackInfo->pprgPurpose), (*(pCallBackInfo->pdwCount)) * sizeof(ENROLL_PURPOSE_INFO *)); if(NULL==*(pCallBackInfo->pprgPurpose)) { dwError=GetLastError(); return FALSE; } //wizardAlloc for each pointer (*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]=(ENROLL_PURPOSE_INFO *)WizardAlloc(sizeof(ENROLL_PURPOSE_INFO)); if(NULL==(*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]) return FALSE; memset((*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1], 0, sizeof(ENROLL_PURPOSE_INFO)); (*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]->pszOID=(LPSTR)(pInfo->pszOID); (*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]->pwszName=(LPWSTR)(pInfo->pwszName); return TRUE; } //----------------------------------------------------------------------- //Initialize usage OID to display //----------------------------------------------------------------------- BOOL GetOIDForCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo, DWORD cUsageID, LPSTR *rgpszUsageID) { BOOL fResult=FALSE; PURPOSE_INFO_CALL_BACK PurposeCallBack; PCTL_INFO pCTLInfo=NULL; DWORD dwIndex=0; DWORD dwCount=0; ENROLL_PURPOSE_INFO **prgPurposeInfo=NULL; //init memset(&PurposeCallBack, 0, sizeof(PURPOSE_INFO_CALL_BACK)); if(NULL==pCertBuildCTLInfo) return FALSE; //init PurposeCallBack.pdwCount=&dwCount; PurposeCallBack.pprgPurpose=&prgPurposeInfo; //enum all the enhanced key usages if(!CryptEnumOIDInfo( CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, &PurposeCallBack, EnumInfoCallback)) goto CLEANUP; //add the existing ones in the old CTL if they do not exist //from the enum list if(pCertBuildCTLInfo->pSrcCTL) { if(pCertBuildCTLInfo->pSrcCTL->pCtlInfo) { pCTLInfo=pCertBuildCTLInfo->pSrcCTL->pCtlInfo; for(dwIndex=0; dwIndexSubjectUsage.cUsageIdentifier; dwIndex++) { if(!SearchAndAddOID(pCTLInfo->SubjectUsage.rgpszUsageIdentifier[dwIndex], &dwCount, &prgPurposeInfo, NULL, FALSE, TRUE, //mark as selected if new oid TRUE)) //mark as selected if existing oid goto CLEANUP; } } } else { //add the pre-defined OIDs if((0!=cUsageID) && (NULL!=rgpszUsageID)) { for(dwIndex=0; dwIndexdwPurposeCount=dwCount; pCertBuildCTLInfo->prgPurpose=prgPurposeInfo; } return fResult; } //----------------------------------------------------------------------- //Initialize the usage OID list //----------------------------------------------------------------------- BOOL InitBuildCTLOID(HWND hwndList, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { DWORD dwCount=0; ENROLL_PURPOSE_INFO **prgPurposeInfo=NULL; DWORD dwIndex=0; LV_ITEMW lvItem; LV_COLUMNW lvC; int dwMaxSize=0; if(!hwndList || !pCertBuildCTLInfo) return FALSE; //get the list of OIDs from the old CTL and all possibilities dwCount=pCertBuildCTLInfo->dwPurposeCount; prgPurposeInfo=pCertBuildCTLInfo->prgPurpose; //mark the list is selected by a check box ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); //get the max length of the column for(dwIndex=0; dwIndexpwszName)) dwMaxSize=wcslen((prgPurposeInfo[dwIndex])->pwszName); } //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(hwndList, 0, &lvC) == -1) return FALSE; //populate the list memset(&lvItem, 0, sizeof(LV_ITEMW)); lvItem.mask=LVIF_TEXT | LVIF_STATE; for(dwIndex=0; dwIndexpwszName; lvItem.cchTextMax=sizeof(WCHAR)*(1+wcslen((prgPurposeInfo[dwIndex])->pwszName)); lvItem.stateMask = LVIS_STATEIMAGEMASK; lvItem.state = (prgPurposeInfo[dwIndex])->fSelected ? 0x00002000 : 0x00001000; //insert the list // insert and set state ListView_SetItemState(hwndList, ListView_InsertItemU(hwndList, &lvItem), (prgPurposeInfo[dwIndex])->fSelected ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK); } //autosize the column ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); return TRUE; } //----------------------------------------------------------------------- //populate the list box in the order of //Purpose, FileName, StoreName, FriendlyName, //and any other things signing wizard display //----------------------------------------------------------------------- void DisplayBuildCTLConfirmation(HWND hwndControl, CERT_BUILDCTL_INFO *pCertBuildCTLInfo) { DWORD dwIndex=0; LPWSTR pwszStoreName=NULL; WCHAR wszNone[MAX_TITLE_LENGTH]; BOOL fNewItem=FALSE; DWORD dwSize=0; LPWSTR pwszValidityString=NULL; LV_COLUMNW lvC; LV_ITEMW lvItem; //pCertBuildCTLInfo has to be valid if(!pCertBuildCTLInfo) return; //delete all the old items in the listView ListView_DeleteAllItems(hwndControl); //load the string if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH)) *wszNone=L'\0'; //get the storename if(pCertBuildCTLInfo->hDesStore) { if(!CertGetStoreProperty( pCertBuildCTLInfo->hDesStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, &dwSize) || (0==dwSize)) { //Get the string pwszStoreName=(LPWSTR)WizardAlloc(MAX_TITLE_LENGTH * sizeof(WCHAR)); if(pwszStoreName) { *pwszStoreName=L'\0'; LoadStringU(g_hmodThisDll, IDS_UNKNOWN, pwszStoreName, MAX_TITLE_LENGTH); } } else { pwszStoreName=(LPWSTR)WizardAlloc(dwSize); if(pwszStoreName) { *pwszStoreName=L'\0'; CertGetStoreProperty( pCertBuildCTLInfo->hDesStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, pwszStoreName, &dwSize); } } } //insert row by row memset(&lvItem, 0, sizeof(LV_ITEMW)); // set up the fields in the list view item struct that don't change from item to item lvItem.mask = LVIF_TEXT | LVIF_STATE ; lvItem.state = 0; lvItem.stateMask = 0; lvItem.iItem=0; lvItem.iSubItem=0; //Purpose. We are guaranteed to have at least one item in the purpose list ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_PURPOSE, NULL); for(dwIndex=0; dwIndexdwPurposeCount; dwIndex++) { if(TRUE==((pCertBuildCTLInfo->prgPurpose)[dwIndex]->fSelected)) { if(TRUE==fNewItem) { //increase the row lvItem.iItem++; lvItem.pszText=L""; lvItem.iSubItem=0; ListView_InsertItemU(hwndControl, &lvItem); } else fNewItem=TRUE; lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, (pCertBuildCTLInfo->prgPurpose)[dwIndex]->pwszName); } } //list ID lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_ID, NULL); //content lvItem.iSubItem++; if(pCertBuildCTLInfo->pwszListID) ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszListID); else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone); //validity lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_VALIDITY, NULL); //content lvItem.iSubItem++; if(pCertBuildCTLInfo->dwValidMonths || pCertBuildCTLInfo->dwValidDays) { GetValidityString(pCertBuildCTLInfo->dwValidMonths, pCertBuildCTLInfo->dwValidDays, &pwszValidityString); ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pwszValidityString); } else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone); //only show the file name or store name if the destination page //is not skipped if(0 == (pCertBuildCTLInfo->dwFlag & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)) { //file name if(pCertBuildCTLInfo->pwszFileName && (TRUE==(pCertBuildCTLInfo->fSelectedFileName))) { lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_FILE_NAME, NULL); //content lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pCertBuildCTLInfo->pwszFileName); } //StoreName if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore)) { if(pwszStoreName) { lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_STORE_NAME, NULL); //content lvItem.iSubItem++; ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem, pwszStoreName); } } } //FriendlyName and descripton will be displayed if the hDesStore is not NULL // if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore)) // { //friendlyName lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_FRIENDLY_NAME, NULL); //content lvItem.iSubItem++; if(pCertBuildCTLInfo->pwszFriendlyName) ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszFriendlyName); else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone); //description lvItem.iItem++; lvItem.iSubItem=0; ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_DESCRIPTION, NULL); //content lvItem.iSubItem++; if(pCertBuildCTLInfo->pwszDescription) ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszDescription); else ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone); //} //autosize the columns ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); ListView_SetColumnWidth(hwndControl, 1, LVSCW_AUTOSIZE); //free the memory if(pwszStoreName) WizardFree(pwszStoreName); if(pwszValidityString) WizardFree(pwszValidityString); return; } //************************************************************************** // // The winProcs for the buildCtl wizard //************************************************************************** //----------------------------------------------------------------------- //BuildCTL_Welcome //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Welcome(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBigBold, hwndDlg,IDC_WIZARD_STATIC_BIG_BOLD1); SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1); break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //check if we need to skip the 1st page if(CRYPTUI_WIZ_BUILDCTL_SKIP_PURPOSE & pCertBuildCTLInfo->dwFlag) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_CERTS); } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //BuildCTL_Purpose //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Purpose(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; HWND hwndControl=NULL; DWORD dwCount=0; DWORD dwIndex=0; NM_LISTVIEW FAR * pnmv=NULL; int intMsg=0; LPSTR pszNewOID; BOOL fFound=FALSE; LV_ITEMW lvItem; DWORD dwChar=0; WCHAR wszMonth[BUILDCTL_DURATION_SIZE]; WCHAR wszDay[BUILDCTL_DURATION_SIZE]; BOOL fUserTypeDuration=FALSE; LPWSTR pwszDuration=NULL; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1); //initizialize the OID list InitBuildCTLOID(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), pCertBuildCTLInfo); //initialize the ListID if(pCertBuildCTLInfo->pwszListID) SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszListID); //mark that we are done with the init OID ListView //if user de-select OIDs from now on, they will be prompted for the //warning pCertBuildCTLInfo->fCompleteInit=TRUE; //init the dwValidMonth and dwValidDays if(pCertBuildCTLInfo->dwValidMonths != 0) { _ltow(pCertBuildCTLInfo->dwValidMonths, wszMonth, 10); SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_MONTH, wszMonth); } if(pCertBuildCTLInfo->dwValidDays != 0) { _ltow(pCertBuildCTLInfo->dwValidDays, wszDay, 10); SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_DAY, wszDay); } break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDC_WIZARD_BUTTON1: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //prompt user to enter the user OID pszNewOID = (LPSTR) DialogBoxU( g_hmodThisDll, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_USER_PURPOSE), hwndDlg, CTLOIDDialogProc); //add the OID to the list if(NULL != pszNewOID) { SearchAndAddOID( pszNewOID, &(pCertBuildCTLInfo->dwPurposeCount), &(pCertBuildCTLInfo->prgPurpose), &fFound, TRUE, TRUE, //mark as selected if new oid FALSE); //do not mark as selected if existing oid if(fFound==TRUE) { I_MessageBox(hwndDlg, IDS_EXISTING_OID, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL); } else { //add the item to the list view //populate the list memset(&lvItem, 0, sizeof(LV_ITEMW)); lvItem.mask=LVIF_TEXT | LVIF_STATE; lvItem.iItem=pCertBuildCTLInfo->dwPurposeCount-1; lvItem.pszText=(pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->pwszName; lvItem.cchTextMax=sizeof(WCHAR)*(1+wcslen ((pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->pwszName)); lvItem.stateMask = LVIS_STATEIMAGEMASK; lvItem.state = (pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->fSelected ? 0x00002000 : 0x00001000; // insert and set state //mark no warning for the user pCertBuildCTLInfo->fCompleteInit=FALSE; ListView_SetItemState(hwndControl, ListView_InsertItemU(hwndControl, &lvItem), (pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->fSelected ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK); //mark the end of setting pCertBuildCTLInfo->fCompleteInit=TRUE; //autosize the column ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); } } //free the pszNewOID if(pszNewOID) WizardFree(pszNewOID); break; } } break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: break; case LVN_ITEMCHANGING: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //the item has been chagned. pnmv = (NM_LISTVIEW FAR *) lParam; if(NULL==pnmv) break; //ingore if we have not complete the init yet if(NULL == pCertBuildCTLInfo->prgPurpose) //we allow change return FALSE; //ignore if we are not complete with the //init yet if(FALSE==pCertBuildCTLInfo->fCompleteInit) return FALSE; //see if the new item is de-selected if(pnmv->uChanged & LVIF_STATE) { if(FALSE==(((pnmv->uNewState & LVIS_STATEIMAGEMASK)>> 12) -1)) { if(TRUE==(pCertBuildCTLInfo->prgPurpose[pnmv->iItem])->fSelected) { //check to see if the user has selected any certs if(0!=pCertBuildCTLInfo->dwCertCount) { //ask user if they are sure to change the subject //of the CTL, thus the whole cert list will be gone intMsg=I_MessageBox(hwndDlg, IDS_SURE_CERT_GONE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_YESNO|MB_APPLMODAL); if(IDYES==intMsg) { //free all the certificate context and //clear the listView of the ceritificate pCertBuildCTLInfo->fClearCerts=TRUE; //we allow change return FALSE; } //we disallow the change SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } } } } //we allow the chagne return FALSE; break; case PSN_WIZNEXT: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the purpose list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //get the count of selected OIDs and mark them dwCount=0; for(dwIndex=0; dwIndexdwPurposeCount; dwIndex++) { //mark the selected OIDS. Keep track of //if the OID selections have been changed if(ListView_GetCheckState(hwndControl, dwIndex)) { ((pCertBuildCTLInfo->prgPurpose)[dwIndex])->fSelected=TRUE; dwCount++; } else { ((pCertBuildCTLInfo->prgPurpose)[dwIndex])->fSelected=FALSE; } } if(0==dwCount) { I_MessageBox(hwndDlg, IDS_NO_SELECTED_CTL_PURPOSE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } //get the list ID if user has specified it. if(pCertBuildCTLInfo->pwszListID) { WizardFree(pCertBuildCTLInfo->pwszListID); pCertBuildCTLInfo->pwszListID=NULL; } if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT1, WM_GETTEXTLENGTH, 0, 0))) { pCertBuildCTLInfo->pwszListID=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=pCertBuildCTLInfo->pwszListID) { GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszListID, dwChar+1); } else //we are out of memory and out of hope break; } //get the valid month and valid days that user specified if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT_MONTH, WM_GETTEXTLENGTH, 0, 0))) { fUserTypeDuration=TRUE; pwszDuration=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=pwszDuration) { GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_MONTH, pwszDuration, dwChar+1); } else //we are out of memory and out of hope break; //make sure the character are valid /*if(!ValidDuration(pwszDuration)) { I_MessageBox(hwndDlg, IDS_INVALID_MONTHS, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); WizardFree(pwszDuration); pwszDuration=NULL; //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; }*/ pCertBuildCTLInfo->dwValidMonths=_wtol(pwszDuration); /*if( (0 == pCertBuildCTLInfo->dwValidMonths && !ValidZero(pwszDuration)) || (0 > _wtol(pwszDuration)) ) { if(!ValidZero(pwszDuration)) { I_MessageBox(hwndDlg, IDS_INVALID_MONTHS, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); WizardFree(pwszDuration); pwszDuration=NULL; //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } */ } else pCertBuildCTLInfo->dwValidMonths=0; //Free the memory if(pwszDuration) { WizardFree(pwszDuration); pwszDuration=NULL; } //valid days if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT_DAY, WM_GETTEXTLENGTH, 0, 0))) { fUserTypeDuration=TRUE; pwszDuration=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=pwszDuration) { GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_DAY, pwszDuration, dwChar+1); } else //we are out of memory and out of hope break; //make sure the character are valid /*if(!ValidDuration(pwszDuration)) { I_MessageBox(hwndDlg, IDS_INVALID_DAYS, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); WizardFree(pwszDuration); pwszDuration=NULL; //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; }*/ pCertBuildCTLInfo->dwValidDays=_wtol(pwszDuration); /*if( (0 == pCertBuildCTLInfo->dwValidDays && !ValidZero(pwszDuration)) || (0 > _wtol(pwszDuration)) ) { I_MessageBox(hwndDlg, IDS_INVALID_DAYS, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); WizardFree(pwszDuration); pwszDuration=NULL; //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; }*/ } else pCertBuildCTLInfo->dwValidDays=0; //Free the memory if(pwszDuration) { WizardFree(pwszDuration); pwszDuration=NULL; } //make sure that user did type in some valid duration if(0 == pCertBuildCTLInfo->dwValidDays && 0 == pCertBuildCTLInfo->dwValidMonths && TRUE== fUserTypeDuration) { I_MessageBox(hwndDlg, IDS_INVALID_DURATION, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } //make sure that the dwValidMonth + dwValidDays //will not exceed 99 month + some extra days if(pCertBuildCTLInfo->dwValidDays || pCertBuildCTLInfo->dwValidMonths) { if(!DurationWithinLimit(pCertBuildCTLInfo->dwValidMonths, pCertBuildCTLInfo->dwValidDays)) { I_MessageBox(hwndDlg, IDS_EXCEED_LIMIT, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- //BuildCTL_Certs //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Certs(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; HCERTSTORE hCertStore=NULL; PCCERT_CONTEXT pCertContext=NULL; PCCERT_CONTEXT pPreCertContext=NULL; BOOL fSelfSigned=TRUE; BOOL fCTLUsage=TRUE; BOOL fEmptyStore=TRUE; BOOL fDuplicateCert=TRUE; HWND hwndControl=NULL; DWORD dwCount=0; DWORD dwIndex=0; int listIndex=0; WCHAR wszText[MAX_STRING_SIZE]; UINT rgIDS[]={IDS_COLUMN_SUBJECT, IDS_COLUMN_ISSUER, IDS_COLUMN_PURPOSE, IDS_COLUMN_EXPIRE}; LV_COLUMNW lvC; CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct; DWORD dwSortParam=0; LV_ITEM lvItem; NM_LISTVIEW FAR * pnmv=NULL; BOOL fErrorDisplayed=FALSE; int i; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) { break; } SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1); // set the style in the list view so that it highlights an entire line SendMessageA(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); //insert columns with headers into the listView control dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]); //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //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 = 145; // 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; dwIndexrgdwSortParam[0]; if(0!=dwSortParam) { //sort the 1st column SendDlgItemMessage(hwndDlg, IDC_WIZARD_LIST1, LVM_SORTITEMS, (WPARAM) (LPARAM) dwSortParam, (LPARAM) (PFNLVCOMPARE)CompareCertificate); } } else { //we reset the ordering order pCertBuildCTLInfo->rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_DESCEND; } //Disable the Buttons for View or Delete if no selection //has been made //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //get the selected item listIndex = ListView_GetNextItem( hwndControl, -1, LVNI_SELECTED ); if(-1 == listIndex) { EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), FALSE); } break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { //add a certificate from a store case IDC_WIZARD_BUTTON1: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //get the certificate from the stores if(hCertStore=GetCertsFromStore(hwndDlg, pCertBuildCTLInfo)) { pCertContext = NULL; while (NULL != (pCertContext = CertEnumCertificatesInStore( hCertStore, pCertContext))) { if(AddCertToBuildCTL( CertDuplicateCertificateContext(pCertContext), pCertBuildCTLInfo)) { //add the certificat to the window AddCertToList(hwndControl,pCertContext, pCertBuildCTLInfo->dwCertCount-1); } else if (!fErrorDisplayed) { fErrorDisplayed = TRUE; //warn the user that the certificate already exists I_MessageBox(hwndDlg, IDS_EXIT_CERT_IN_CTL, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL); } } CertCloseStore(hCertStore, 0); } break; //add a certificate from a file case IDC_WIZARD_BUTTON2: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //get the file name. Make sure the cert is correct if(hCertStore=GetCertStoreFromFile(hwndDlg, pCertBuildCTLInfo)) { while(pCertContext=CertEnumCertificatesInStore( hCertStore, pPreCertContext)) { fEmptyStore=FALSE; //make sure this is a valid certificate //make sure the pCertContext is a self-signed certificate if(!TrustIsCertificateSelfSigned(pCertContext, pCertContext->dwCertEncodingType, 0)) { if(fSelfSigned) { I_MessageBox(hwndDlg, IDS_SOME_NOT_SELF_SIGNED, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); //no need to pop up the information anymore fSelfSigned=FALSE; } pPreCertContext=pCertContext; continue; } //make sure the certifcate match what is defined on the CTL list if(!CertMatchCTL(pCertBuildCTLInfo, pCertContext)) { if(fCTLUsage) { I_MessageBox(hwndDlg, IDS_SOME_NO_MATCH_USAGE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); //no need to pop up the information anymore fCTLUsage=FALSE; } pPreCertContext=pCertContext; continue; } //get a duplicate copy pPreCertContext=CertDuplicateCertificateContext(pCertContext); if(NULL==pPreCertContext) { pPreCertContext=pCertContext; continue; } if(AddCertToBuildCTL(pPreCertContext, pCertBuildCTLInfo)) { //add the certificat to the window AddCertToList(hwndControl,pPreCertContext, pCertBuildCTLInfo->dwCertCount-1); } else { if(fDuplicateCert) { //warn the user that the certificate already exists I_MessageBox(hwndDlg, IDS_EXIT_CERT_IN_CTL, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONINFORMATION|MB_OK|MB_APPLMODAL); fDuplicateCert=FALSE; } CertFreeCertificateContext(pPreCertContext); } pPreCertContext=pCertContext; } //warn the user that the store is empty if(TRUE == fEmptyStore) { I_MessageBox(hwndDlg, IDS_EMPTY_CERT_IN_FILE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL); } } pPreCertContext=NULL; pCertContext=NULL; if(hCertStore) CertCloseStore(hCertStore, 0); hCertStore=NULL; break; //remove a certificate from the store case IDC_WIZARD_BUTTON3: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; memset(&lvItem, 0, sizeof(lvItem)); lvItem.mask = LVIF_STATE | LVIF_PARAM; lvItem.stateMask = LVIS_SELECTED; for (i=(ListView_GetItemCount(hwndControl) - 1); i >=0; i--) { lvItem.iItem = i; if (ListView_GetItem(hwndControl, &lvItem) && (lvItem.state & LVIS_SELECTED)) { if(DeleteCertFromBuildCTL(pCertBuildCTLInfo, (PCCERT_CONTEXT)(lvItem.lParam))) { //delete the item from the list ListView_DeleteItem(hwndControl, lvItem.iItem); } } } /* else //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL);*/ break; //view a certificate case IDC_WIZARD_BUTTON4: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) 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(pCertBuildCTLInfo->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; CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES; CryptUIDlgViewCertificate(&CertViewStruct, NULL); } } } else //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); break; default: break; } } break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { //the column has been clicked case LVN_COLUMNCLICK: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the purpose list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; pnmv = (NM_LISTVIEW FAR *) lParam; //get the column number dwSortParam=0; switch(pnmv->iSubItem) { case 0: case 1: case 2: case 3: dwSortParam=pCertBuildCTLInfo->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_WIZARD_LIST1, LVM_SORTITEMS, (WPARAM) (LPARAM) dwSortParam, (LPARAM) (PFNLVCOMPARE)CompareCertificate); pCertBuildCTLInfo->rgdwSortParam[pnmv->iSubItem]=dwSortParam; } break; case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //get the window handle of the purpose list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //see if we need to clear the certs if(TRUE==pCertBuildCTLInfo->fClearCerts) { pCertBuildCTLInfo->fClearCerts=FALSE; //clear the list view ListView_DeleteAllItems(hwndControl); //free all the certificate context FreeCerts(pCertBuildCTLInfo); } break; case PSN_WIZBACK: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //check if we need to skip the 1st page if(CRYPTUI_WIZ_BUILDCTL_SKIP_PURPOSE & pCertBuildCTLInfo->dwFlag) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_WELCOME); } break; case PSN_WIZNEXT: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } if(0==pCertBuildCTLInfo->dwCertCount) { I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //the page should stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); } break; case NM_DBLCLK: switch (((NMHDR FAR *) lParam)->idFrom) { case IDC_WIZARD_LIST1: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) 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(pCertBuildCTLInfo->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; CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES; CryptUIDlgViewCertificate(&CertViewStruct, NULL); } } } else //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); break; default: break; } break; /* case NM_CLICK: { switch (((NMHDR FAR *) lParam)->idFrom) { case IDC_WIZARD_LIST1: //get the window handle of the cert list view if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))) break; //get the selected item listIndex = ListView_GetNextItem( hwndControl, -1, LVNI_SELECTED ); if(-1 != listIndex) { EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), TRUE); } break; } } break; */ //the item has been selected case LVN_ITEMCHANGED: // // if an item is selected, then enable the remove button, otherwise // disable it // if (ListView_GetSelectedCount(GetDlgItem(hwndDlg,IDC_WIZARD_LIST1)) == 0) { EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), FALSE); } else { EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), TRUE); } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- // BuildCTL_Destination //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Destination(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; HWND hwndControl=NULL; OPENFILENAMEW OpenFileName; WCHAR szFileName[_MAX_PATH]; static WCHAR wszFileName[_MAX_PATH]; WCHAR szFilter[MAX_STRING_SIZE]; //"Certificate Trust List (*.ctl)\0*.ctl\0All Files\0*.*\0" DWORD dwSize=0; LPWSTR pwszStoreName=NULL; CRYPTUI_SELECTSTORE_STRUCT CertStoreSelect; STORENUMERATION_STRUCT StoreEnumerationStruct; STORESFORSELCTION_STRUCT StoresForSelectionStruct; DWORD dwChar=0; HCERTSTORE hCertStore=NULL; LV_COLUMNW lvC; LV_ITEMW lvItem; HDC hdc=NULL; COLORREF colorRef; BOOL fAppendExt=FALSE; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1); //getthe background color of the parent window //the background of the list view for store name is grayed /* if(hdc=GetWindowDC(hwndDlg)) { if(CLR_INVALID!=(colorRef=GetBkColor(hdc))) { ListView_SetBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE); ListView_SetTextBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE); } } */ //pre-set the selections for the destinations //set the store name if pre-selected if(pCertBuildCTLInfo->hDesStore) { //select the 1st radio button SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 1, 0); SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 0, 0); //disable the windows for select a file EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), FALSE); //set the store name if pre-selected //get the hwndControl for the list view hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1); if(hwndControl) SetStoreName(hwndControl,pCertBuildCTLInfo->hDesStore); } else { //select the 2nd radio button SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 0, 0); SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 1, 0); //disable the controls to select a store EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), FALSE); if(pCertBuildCTLInfo->pwszFileName) { //pre-initialize the file name SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFileName); } } //init memset(&wszFileName, 0, sizeof(wszFileName)); *wszFileName='\0'; break; case WM_COMMAND: if(HIWORD(wParam) == BN_CLICKED) { switch (LOWORD(wParam)) { case IDC_WIZARD_RADIO1: //select the 1st radio button SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 1, 0); //enable the controls to select a store EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), TRUE); //disable raio2 SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 0, 0); //disable controls to select a file EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), FALSE); break; case IDC_WIZARD_RADIO2: //disable the 1st radio button SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 0, 0); //disable the controls to select a store EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), FALSE); //enable raio2 SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 1, 0); //enable controls to select a file EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), TRUE); break; case IDC_WIZARD_BUTTON1: //the browse for store button is selected if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //get the hwndControl for the list view hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1); //call the store selection dialogue memset(&CertStoreSelect, 0, sizeof(CertStoreSelect)); memset(&StoresForSelectionStruct, 0, sizeof(StoresForSelectionStruct)); memset(&StoreEnumerationStruct, 0, sizeof(StoreEnumerationStruct)); StoreEnumerationStruct.dwFlags=CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_SYSTEM_STORE_CURRENT_USER; StoreEnumerationStruct.pvSystemStoreLocationPara=NULL; StoresForSelectionStruct.cEnumerationStructs = 1; StoresForSelectionStruct.rgEnumerationStructs = &StoreEnumerationStruct; CertStoreSelect.dwSize=sizeof(CRYPTUI_SELECTSTORE_STRUCT); CertStoreSelect.hwndParent=hwndDlg; CertStoreSelect.dwFlags=CRYPTUI_VALIDATE_STORES_AS_WRITABLE | CRYPTUI_ALLOW_PHYSICAL_STORE_VIEW | CRYPTUI_DISPLAY_WRITE_ONLY_STORES; CertStoreSelect.pStoresForSelection = &StoresForSelectionStruct; hCertStore=CryptUIDlgSelectStore(&CertStoreSelect); if(hCertStore) { //delete the old destination certificate store if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fFreeDesStore)) { CertCloseStore(pCertBuildCTLInfo->hDesStore, 0); pCertBuildCTLInfo->hDesStore=NULL; } pCertBuildCTLInfo->hDesStore=hCertStore; pCertBuildCTLInfo->fFreeDesStore=TRUE; //get the store name SetStoreName(hwndControl, pCertBuildCTLInfo->hDesStore); } break; case IDC_WIZARD_BUTTON2: //the browse file button is clicked. Open the FileOpen dialogue memset(&OpenFileName, 0, sizeof(OpenFileName)); *szFileName=L'\0'; OpenFileName.lStructSize = sizeof(OpenFileName); OpenFileName.hwndOwner = hwndDlg; OpenFileName.hInstance = NULL; //load the fileter string if(LoadFilterString(g_hmodThisDll, IDS_CTL_FILTER, szFilter, MAX_STRING_SIZE)) { OpenFileName.lpstrFilter = szFilter; } OpenFileName.lpstrCustomFilter = NULL; OpenFileName.nMaxCustFilter = 0; OpenFileName.nFilterIndex = 1; OpenFileName.lpstrFile = szFileName; OpenFileName.nMaxFile = _MAX_PATH; OpenFileName.lpstrFileTitle = NULL; OpenFileName.nMaxFileTitle = 0; OpenFileName.lpstrInitialDir = NULL; OpenFileName.lpstrTitle = NULL; OpenFileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; OpenFileName.nFileOffset = 0; OpenFileName.nFileExtension = 0; OpenFileName.lpstrDefExt = L"ctl"; OpenFileName.lCustData = NULL; OpenFileName.lpfnHook = NULL; OpenFileName.lpTemplateName = NULL; if (WizGetSaveFileName(&OpenFileName)) { //set the edit box SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, szFileName); //copy the selected file name wcscpy(wszFileName, szFileName); } break; default: break; } } break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; if(pCertBuildCTLInfo->pwszFileName) { //pre-initialize the file name since extension might have been added SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFileName); } break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //make sure that we have select some store if(TRUE==SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_GETCHECK, 0, 0)) { if(NULL==pCertBuildCTLInfo->hDesStore) { //output the message I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_STORE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //make the file page stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } else { //mark the hDesStore should be used pCertBuildCTLInfo->fSelectedDesStore=TRUE; pCertBuildCTLInfo->fSelectedFileName=FALSE; } } else { //make sure a file is selected if(0==(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT1, WM_GETTEXTLENGTH, 0, 0))) { I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_FILE, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_ICONERROR|MB_OK|MB_APPLMODAL); //make the file page stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } else { //mark the file name should be used pCertBuildCTLInfo->fSelectedDesStore=FALSE; pCertBuildCTLInfo->fSelectedFileName=TRUE; //get the file name if(pCertBuildCTLInfo->pwszFileName) { //delete the old file name if(TRUE==pCertBuildCTLInfo->fFreeFileName) { WizardFree(pCertBuildCTLInfo->pwszFileName); pCertBuildCTLInfo->pwszFileName=NULL; } } pCertBuildCTLInfo->pwszFileName=(LPWSTR)WizardAlloc((dwChar+1)*sizeof(WCHAR)); if(NULL==pCertBuildCTLInfo->pwszFileName) break; pCertBuildCTLInfo->fFreeFileName=TRUE; GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFileName, dwChar+1); //we append .ctl file extension if user has not specify it fAppendExt=FALSE; if(wcslen(pCertBuildCTLInfo->pwszFileName) < 4) fAppendExt=TRUE; else { if (_wcsicmp(L".stl", &(pCertBuildCTLInfo->pwszFileName[wcslen(pCertBuildCTLInfo->pwszFileName)-4])) != 0) fAppendExt=TRUE; else fAppendExt=FALSE; } if(TRUE == fAppendExt) { pCertBuildCTLInfo->pwszFileName = (LPWSTR)WizardRealloc(pCertBuildCTLInfo->pwszFileName, (wcslen(pCertBuildCTLInfo->pwszFileName) + 4 + 1) * sizeof(WCHAR)); if(NULL==pCertBuildCTLInfo->pwszFileName) break; wcscat(pCertBuildCTLInfo->pwszFileName, L".stl"); } //confirm to over write if(0 != _wcsicmp(wszFileName, pCertBuildCTLInfo->pwszFileName)) { if(FileExist(pCertBuildCTLInfo->pwszFileName)) { if(FALSE == CheckReplace(hwndDlg, pCertBuildCTLInfo->pwszFileName)) { //make the file page stay SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); break; } } } } } //decide if we need to skip to the friendly name page if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore)) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_NAME); } else { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_COMPLETION); } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- // BuildCTL_Name //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Name(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; HWND hwndControl=NULL; DWORD dwChar; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1); //set the FriedlyName and description field //if pwszFriendlyName is NULL, use the list ID if(pCertBuildCTLInfo->pwszFriendlyName) SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFriendlyName); else { if(pCertBuildCTLInfo->pwszListID) SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszListID); } if(pCertBuildCTLInfo->pwszDescription) SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT2, pCertBuildCTLInfo->pwszDescription); break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK); break; case PSN_WIZBACK: break; case PSN_WIZNEXT: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //free the friendly name and description if(pCertBuildCTLInfo->pwszFriendlyName) { WizardFree(pCertBuildCTLInfo->pwszFriendlyName); pCertBuildCTLInfo->pwszFriendlyName=NULL; } if(pCertBuildCTLInfo->pwszDescription) { WizardFree(pCertBuildCTLInfo->pwszDescription); pCertBuildCTLInfo->pwszDescription=NULL; } //get the friendly name if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT1, WM_GETTEXTLENGTH, 0, 0))) { pCertBuildCTLInfo->pwszFriendlyName=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=pCertBuildCTLInfo->pwszFriendlyName) { GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFriendlyName, dwChar+1); } else //we are out of memory and out of hope break; } //get the description if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg, IDC_WIZARD_EDIT2, WM_GETTEXTLENGTH, 0, 0))) { pCertBuildCTLInfo->pwszDescription=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1)); if(NULL!=pCertBuildCTLInfo->pwszDescription) { GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT2, pCertBuildCTLInfo->pwszDescription, dwChar+1); } else //we are out of memory and out of hope break; } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //----------------------------------------------------------------------- // BuildCTL_Completion //----------------------------------------------------------------------- INT_PTR APIENTRY BuildCTL_Completion(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL; PROPSHEETPAGEW *pPropSheet=NULL; HWND hwndControl=NULL; LV_COLUMNW lvC; HDC hdc=NULL; COLORREF colorRef; DWORD dwEncodedCTL=0; BYTE *pbEncodedCTL=NULL; DWORD cbEncodedCTL=0; UINT ids=0; switch (msg) { case WM_INITDIALOG: //set the wizard information so that it can be shared pPropSheet = (PROPSHEETPAGEW *) lParam; pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam); //make sure pCertBuildCTLInfo is a valid pointer if(NULL==pCertBuildCTLInfo) break; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo); SetControlFont(pCertBuildCTLInfo->hBigBold, hwndDlg,IDC_WIZARD_STATIC_BIG_BOLD1); //getthe background color of the parent window /* if(hdc=GetWindowDC(hwndDlg)) { if(CLR_INVALID!=(colorRef=GetBkColor(hdc))) { ListView_SetBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE); ListView_SetTextBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE); } } */ //insert two columns hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1); if(NULL==hwndControl) break; //1st one is the label for the confirmation memset(&lvC, 0, sizeof(LV_COLUMNW)); lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; // Left-align the column. lvC.cx = 20; // Width of the column, in pixels.We will autosize later lvC.pszText = L""; // The text for the column. lvC.iSubItem=0; if (ListView_InsertColumnU(hwndControl, 0, &lvC) == -1) break; //2nd column is the content memset(&lvC, 0, sizeof(LV_COLUMNW)); lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; // Left-align the column. lvC.cx = 10; //(dwMaxSize+2)*7; // Width of the column, in pixels. //the width will be autosized later lvC.pszText = L""; // The text for the column. lvC.iSubItem= 1; if (ListView_InsertColumnU(hwndControl, 1, &lvC) == -1) break; break; case WM_COMMAND: break; case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); return TRUE; break; case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK|PSWIZB_FINISH); if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //populate the list box in the order of //FileName, StoreName, Purpose, FriendlyName, Description //and any other things signing wizard display if(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)) DisplayBuildCTLConfirmation(hwndControl, pCertBuildCTLInfo); break; case PSN_WIZBACK: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) { break; } //no need to worry if the pages are not included in the wizards if(0==(pCertBuildCTLInfo->dwFlag & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)) { //skip the friendly name page if the desination does no include //a store if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore)) SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_NAME); else SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_DESTINATION); } break; case PSN_WIZFINISH: if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER))) break; //we need to build the CTL and return the pbEncoded and cbEncoded if(!I_BuildCTL(pCertBuildCTLInfo, &ids, &pbEncodedCTL, &cbEncodedCTL)) { if(ids!=0) I_MessageBox(hwndDlg, ids, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK|MB_ICONINFORMATION); } else { if(0!=cbEncodedCTL && NULL!=pbEncodedCTL) { //set up the signing information ((CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO *)(pCertBuildCTLInfo->pGetSignInfo->pDigitalSignInfo->pSignBlobInfo))->cbBlob=cbEncodedCTL; ((CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO *)(pCertBuildCTLInfo->pGetSignInfo->pDigitalSignInfo->pSignBlobInfo))->pbBlob=pbEncodedCTL; } } break; default: return FALSE; } break; default: return FALSE; } return TRUE; } //************************************************************************** // // The entry point for buildCTL wizard //************************************************************************** //---------------------------------------------------------------------------- // Check to see if the certificate is a valid signing CTL cert // //---------------------------------------------------------------------------- BOOL IsValidSigningCTLCert(PCCERT_CONTEXT pCertContext) { BOOL fResult=FALSE; int cNumOID=0; LPSTR *rgOID=NULL; DWORD cbOID=0; DWORD dwIndex=0; DWORD cbData=0; if(!pCertContext) return FALSE; //the certificate has to have the CERT_KEY_PROV_INFO_PROP_ID if(!CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbData)) return FALSE; if(0==cbData) return FALSE; //get the OIDs from the cert if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, NULL, &cbOID)) return FALSE; rgOID=(LPSTR *)WizardAlloc(cbOID); if(NULL==rgOID) return FALSE; if(!CertGetValidUsages( 1, &pCertContext, &cNumOID, rgOID, &cbOID)) goto CLEANUP; //-1 means the certiifcate is food for everything if(-1==cNumOID) { fResult=TRUE; goto CLEANUP; } for(dwIndex=0; dwIndex<(DWORD)cNumOID; dwIndex++) { //the only good cert is the one with CTL signing OID if(0==strcmp(szOID_KP_CTL_USAGE_SIGNING, rgOID[dwIndex])) { fResult=TRUE; goto CLEANUP; } } //we are hopeless at this point fResult=FALSE; CLEANUP: if(rgOID) WizardFree(rgOID); return fResult; } //---------------------------------------------------------------------------- // CallBack fro cert selection call back // //---------------------------------------------------------------------------- static BOOL WINAPI SelectCTLSignCertCallBack( PCCERT_CONTEXT pCertContext, BOOL *pfInitialSelectedCert, void *pvCallbackData) { if(!pCertContext) return FALSE; //make sure that this is a valid certificate return IsValidSigningCTLCert(pCertContext); } //----------------------------------------------------------------------- // // CryptUIWizBuildCTL // // Build a new CTL or modify an existing CTL. The UI for wizard will // always show in this case // // // dwFlags: IN Reserved: flags. Must be set 0 // hwndParnet: IN Optional: The parent window handle // pwszWizardTitle: IN Optional: The title of the wizard // pBuildCTLSrc: IN Optional: The source from which the CTL will be built // pBuildCTLDest: IN Optional: The desination where the newly // built CTL will be stored // ppCTLContext: OUT Optaionl: The newly build CTL // //------------------------------------------------------------------------ BOOL WINAPI CryptUIWizBuildCTL( DWORD dwFlags, HWND hwndParent, LPCWSTR pwszWizardTitle, PCCRYPTUI_WIZ_BUILDCTL_SRC_INFO pBuildCTLSrc, PCCRYPTUI_WIZ_BUILDCTL_DEST_INFO pBuildCTLDest, PCCTL_CONTEXT *ppCTLContext ) { BOOL fResult=FALSE; HRESULT hr=E_FAIL; DWORD dwError=0; CERT_BUILDCTL_INFO CertBuildCTLInfo; UINT ids=IDS_INVALID_WIZARD_INPUT; FILETIME CurrentFileTime; PROPSHEETPAGEW *prgBuildCTLSheet=NULL; PROPSHEETHEADERW buildCTLHeader; ENROLL_PAGE_INFO rgBuildCTLPageInfo[]= {(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_WELCOME), BuildCTL_Welcome, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_PURPOSE), BuildCTL_Purpose, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_CERTS), BuildCTL_Certs, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_DESTINATION), BuildCTL_Destination, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_NAME), BuildCTL_Name, (LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_COMPLETION), BuildCTL_Completion, }; DWORD dwIndex=0; DWORD dwPropCount=0; WCHAR wszTitle[MAX_TITLE_LENGTH]; PCCRYPT_OID_INFO pOIDInfo; PCCTL_CONTEXT pCTLContext=NULL; PCCTL_CONTEXT pBldCTL=NULL; PCCRYPTUI_WIZ_BUILDCTL_NEW_CTL_INFO pNewCTLInfo=NULL; LPWSTR pwszListID=NULL; PCERT_ENHKEY_USAGE pSubjectUsage=NULL; DWORD cbData=0; CRYPTUI_WIZ_GET_SIGN_PAGE_INFO GetSignInfo; DWORD dwPages=0; CRYPTUI_WIZ_DIGITAL_SIGN_INFO DigitalSignInfo; PROPSHEETPAGEW *pwPages=NULL; CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO SignBlob; CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO SignStoreInfo; GUID CTLGuid=CRYPT_SUBJTYPE_CTL_IMAGE; CRYPT_DATA_BLOB PropertyBlob; HCERTSTORE hMyStore=NULL; INT_PTR iReturn=-1; // CERT_STORE_LIST CertStoreList; //init memset(&CertBuildCTLInfo, 0, sizeof(CERT_BUILDCTL_INFO)); memset(&buildCTLHeader, 0, sizeof(PROPSHEETHEADERW)); memset(&GetSignInfo, 0, sizeof(CRYPTUI_WIZ_GET_SIGN_PAGE_INFO)); memset(&DigitalSignInfo, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO)); memset(&SignBlob, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO)); memset(&SignStoreInfo, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO)); memset(&PropertyBlob, 0, sizeof(CRYPT_DATA_BLOB)); //open all the system store system store //memset(&CertStoreList, 0, sizeof(CertStoreList)); //input checking if(ppCTLContext) *ppCTLContext=NULL; //get the basic information from the src info struct if(pBuildCTLSrc) { if(pBuildCTLSrc->dwSize != sizeof(CRYPTUI_WIZ_BUILDCTL_SRC_INFO)) goto InvalidArgErr; if(CRYPTUI_WIZ_BUILDCTL_SRC_EXISTING_CTL==pBuildCTLSrc->dwSourceChoice) { if(NULL==pBuildCTLSrc->pCTLContext) goto InvalidArgErr; pCTLContext=pBuildCTLSrc->pCTLContext; CertBuildCTLInfo.pSrcCTL=pCTLContext; } else { if(CRYPTUI_WIZ_BUILDCTL_SRC_NEW_CTL==pBuildCTLSrc->dwSourceChoice) { if(NULL==pBuildCTLSrc->pNewCTLInfo) goto InvalidArgErr; pNewCTLInfo=pBuildCTLSrc->pNewCTLInfo; } else goto InvalidArgErr; } } //init the private structure based on input parameters CertBuildCTLInfo.hwndParent=hwndParent; CertBuildCTLInfo.dwFlag=dwFlags; CertBuildCTLInfo.rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND; CertBuildCTLInfo.rgdwSortParam[1]=SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND; CertBuildCTLInfo.rgdwSortParam[2]=SORT_COLUMN_PURPOSE | SORT_COLUMN_DESCEND; CertBuildCTLInfo.rgdwSortParam[3]=SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND; //get the listIdentifier if(pCTLContext) { //copy the listID if it is the wchar format if(0!=(pCTLContext->pCtlInfo->ListIdentifier.cbData)) { //get the string presentation of the listID if(ValidString(&(pCTLContext->pCtlInfo->ListIdentifier))) { CertBuildCTLInfo.pwszListID=WizardAllocAndCopyWStr((LPWSTR)(pCTLContext->pCtlInfo->ListIdentifier.pbData)); if(NULL==CertBuildCTLInfo.pwszListID) goto MemoryErr; } else { //get the hex presentation of the listID cbData=0; if(CryptFormatObject( X509_ASN_ENCODING, 0, 0, NULL, 0, pCTLContext->pCtlInfo->ListIdentifier.pbData, pCTLContext->pCtlInfo->ListIdentifier.cbData, NULL, &cbData) && (0!= cbData)) { CertBuildCTLInfo.pwszListID=(LPWSTR)WizardAlloc(cbData); if(NULL==CertBuildCTLInfo.pwszListID) goto MemoryErr; if(!CryptFormatObject( X509_ASN_ENCODING, 0, 0, NULL, 0, pCTLContext->pCtlInfo->ListIdentifier.pbData, pCTLContext->pCtlInfo->ListIdentifier.cbData, CertBuildCTLInfo.pwszListID, &cbData)) goto Win32Err; } } } } else { if(pNewCTLInfo) { if(pNewCTLInfo->pwszListIdentifier) { CertBuildCTLInfo.pwszListID=WizardAllocAndCopyWStr(pNewCTLInfo->pwszListIdentifier); if(NULL==CertBuildCTLInfo.pwszListID) goto MemoryErr; } } } //get the hash algorithm and dwHashPropID from the source CTL if(pCTLContext) { //make sure we have the correct algorithm if(NULL==pCTLContext->pCtlInfo->SubjectAlgorithm.pszObjId) { ids=IDS_INVALID_ALGORITHM_IN_CTL; goto InvalidArgErr; } CertBuildCTLInfo.pszSubjectAlgorithm=(LPSTR)(pCTLContext->pCtlInfo->SubjectAlgorithm.pszObjId); } else { if(pNewCTLInfo) CertBuildCTLInfo.pszSubjectAlgorithm=(LPSTR)(pNewCTLInfo->pszSubjectAlgorithm); } if(CertBuildCTLInfo.pszSubjectAlgorithm) { pOIDInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, CertBuildCTLInfo.pszSubjectAlgorithm, CRYPT_HASH_ALG_OID_GROUP_ID); if(NULL==pOIDInfo) { ids=IDS_INVALID_ALGORITHM_IN_CTL; goto Crypt32Err; } if (pOIDInfo->Algid == CALG_MD5) { CertBuildCTLInfo.dwHashPropID=CERT_MD5_HASH_PROP_ID; } else { if (pOIDInfo->Algid == CALG_SHA1) { CertBuildCTLInfo.dwHashPropID=CERT_SHA1_HASH_PROP_ID; } else { ids=IDS_INVALID_ALGORITHM_IN_CTL; goto InvalidArgErr; } } } else CertBuildCTLInfo.dwHashPropID=CERT_SHA1_HASH_PROP_ID; //get the pSubjectUsage if(pNewCTLInfo) { if(pNewCTLInfo->pSubjectUsage) pSubjectUsage=pNewCTLInfo->pSubjectUsage; } //add the subject Usage and pre-select them from either //the exising CTL or the user defined ones if(!GetOIDForCTL(&CertBuildCTLInfo, (pSubjectUsage) ? pSubjectUsage->cUsageIdentifier : 0, (pSubjectUsage) ? pSubjectUsage->rgpszUsageIdentifier : NULL)) goto InvalidArgErr; //get the Certficate contexts from either the existing CTL //of the user defined one GetCertForCTL(hwndParent, TRUE, //always UI mode for now &CertBuildCTLInfo, (pNewCTLInfo)? pNewCTLInfo->hCertStore : NULL); //get the dwValidMonths and dwValidDays if(pCTLContext) CertBuildCTLInfo.pNextUpdate=&(pCTLContext->pCtlInfo->NextUpdate); else { if(pNewCTLInfo) CertBuildCTLInfo.pNextUpdate=(FILETIME *)(&(pNewCTLInfo->NextUpdate)); } //get the current FileTime GetSystemTimeAsFileTime(&CurrentFileTime); //get the difference if(CertBuildCTLInfo.pNextUpdate) { SubstractDurationFromFileTime( CertBuildCTLInfo.pNextUpdate, &CurrentFileTime, &(CertBuildCTLInfo.dwValidMonths), &(CertBuildCTLInfo.dwValidDays)); //we limit to 99 month if((CertBuildCTLInfo.dwValidMonths > 99) || (CertBuildCTLInfo.dwValidMonths == 99 && CertBuildCTLInfo.dwValidDays !=0)) { CertBuildCTLInfo.dwValidMonths=0; CertBuildCTLInfo.dwValidDays=0; } } //get the FriendlyName and Description if(pCTLContext) { //friendly Name cbData=0; if(CertGetCTLContextProperty( pCTLContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cbData) && (0!=cbData)) { CertBuildCTLInfo.pwszFriendlyName=(LPWSTR)WizardAlloc(cbData); if(NULL==CertBuildCTLInfo.pwszFriendlyName) goto MemoryErr; if(!CertGetCTLContextProperty( pCTLContext, CERT_FRIENDLY_NAME_PROP_ID, CertBuildCTLInfo.pwszFriendlyName, &cbData)) goto Win32Err; } //Description cbData=0; if(CertGetCTLContextProperty( pCTLContext, CERT_DESCRIPTION_PROP_ID, NULL, &cbData) && (0!=cbData)) { CertBuildCTLInfo.pwszDescription=(LPWSTR)WizardAlloc(cbData); if(NULL==CertBuildCTLInfo.pwszDescription) goto MemoryErr; if(!CertGetCTLContextProperty( pCTLContext, CERT_DESCRIPTION_PROP_ID, CertBuildCTLInfo.pwszDescription, &cbData)) goto Win32Err; } } else { if(pNewCTLInfo) { if(pNewCTLInfo->pwszFriendlyName) { CertBuildCTLInfo.pwszFriendlyName=WizardAllocAndCopyWStr(pNewCTLInfo->pwszFriendlyName); if(NULL==CertBuildCTLInfo.pwszFriendlyName) goto MemoryErr; } if(pNewCTLInfo->pwszDescription) { CertBuildCTLInfo.pwszDescription=WizardAllocAndCopyWStr(pNewCTLInfo->pwszDescription); if(NULL==CertBuildCTLInfo.pwszDescription) goto MemoryErr; } } } //get the destination if(pBuildCTLDest) { CertBuildCTLInfo.fKnownDes=TRUE; if(pBuildCTLDest->dwSize != sizeof(CRYPTUI_WIZ_BUILDCTL_DEST_INFO)) goto InvalidArgErr; switch(pBuildCTLDest->dwDestinationChoice) { case CRYPTUI_WIZ_BUILDCTL_DEST_CERT_STORE: if(NULL==pBuildCTLDest->hCertStore) goto InvalidArgErr; CertBuildCTLInfo.hDesStore=pBuildCTLDest->hCertStore; CertBuildCTLInfo.fFreeDesStore=FALSE; CertBuildCTLInfo.fSelectedDesStore=TRUE; break; case CRYPTUI_WIZ_BUILDCTL_DEST_FILE: if(NULL==pBuildCTLDest->pwszFileName) goto InvalidArgErr; CertBuildCTLInfo.pwszFileName=(LPWSTR)(pBuildCTLDest->pwszFileName); CertBuildCTLInfo.fFreeFileName=FALSE; CertBuildCTLInfo.fSelectedFileName=TRUE; break; default: goto InvalidArgErr; break; } } else CertBuildCTLInfo.fKnownDes=FALSE; //set up the fonts if(!SetupFonts(g_hmodThisDll, NULL, &(CertBuildCTLInfo.hBigBold), &(CertBuildCTLInfo.hBold))) { ids=IDS_FAIL_INIT_BUILDCTL; goto Win32Err; } //init the common control if(!WizardInit() || (sizeof(rgBuildCTLPageInfo)/sizeof(rgBuildCTLPageInfo[0])!=BUILDCTL_PROP_SHEET) ) { ids=IDS_FAIL_INIT_BUILDCTL; goto InvalidArgErr; } //set up the parameter to get a list of certificate //open the my store if(NULL == (hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W, g_dwMsgAndCertEncodingType, NULL, CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG, L"my"))) goto Win32Err; /* if (!CertEnumSystemStore( CERT_SYSTEM_STORE_CURRENT_USER, NULL, &CertStoreList, EnumSysStoreSignCertCallBack)) goto Win32Err; */ //set up GetSignInfo GetSignInfo.dwSize=sizeof(CRYPTUI_WIZ_GET_SIGN_PAGE_INFO); GetSignInfo.dwPageChoice=CRYPTUI_WIZ_DIGITAL_SIGN_MINIMAL_SIGNING_OPTION_PAGES; if(pwszWizardTitle) GetSignInfo.pwszPageTitle=(LPWSTR)pwszWizardTitle; else { if(LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0]))) GetSignInfo.pwszPageTitle=wszTitle; } GetSignInfo.pDigitalSignInfo=&DigitalSignInfo; //set up DigitalSignInfo DigitalSignInfo.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO); //we are always signing a BLOB DigitalSignInfo.dwSubjectChoice=CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB; DigitalSignInfo.pSignBlobInfo=&SignBlob; DigitalSignInfo.dwSigningCertChoice=CRYPTUI_WIZ_DIGITAL_SIGN_STORE; DigitalSignInfo.pSigningCertStore=&SignStoreInfo; DigitalSignInfo.dwAdditionalCertChoice=CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN; //set up SignStoreInfo SignStoreInfo.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO); SignStoreInfo.cCertStore=1; //CertStoreList.dwStoreCount; SignStoreInfo.rghCertStore=&hMyStore; //CertStoreList.prgStore; SignStoreInfo.pFilterCallback=SelectCTLSignCertCallBack; //set up SignBlobInfo SignBlob.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO); SignBlob.pGuidSubject=&CTLGuid; //copy the GetSignInfo into the private data CertBuildCTLInfo.pGetSignInfo=&GetSignInfo; //we set up the wizard in two ways: with the signing page or without the //signing page if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_SIGNING) { //set up the property sheet without signing prgBuildCTLSheet=(PROPSHEETPAGEW *)WizardAlloc(sizeof(PROPSHEETPAGEW) * BUILDCTL_PROP_SHEET); if(NULL==prgBuildCTLSheet) goto MemoryErr; memset(prgBuildCTLSheet, 0, sizeof(PROPSHEETPAGEW) * BUILDCTL_PROP_SHEET); dwPropCount=0; for(dwIndex=0; dwIndexdwDestinationChoice) continue; } else continue; } } } prgBuildCTLSheet[dwPropCount].dwSize=sizeof(prgBuildCTLSheet[dwPropCount]); if(pwszWizardTitle) prgBuildCTLSheet[dwPropCount].dwFlags=PSP_USETITLE; else prgBuildCTLSheet[dwPropCount].dwFlags=0; prgBuildCTLSheet[dwPropCount].hInstance=g_hmodThisDll; prgBuildCTLSheet[dwPropCount].pszTemplate=(LPCWSTR)(rgBuildCTLPageInfo[dwIndex].pszTemplate); if(pwszWizardTitle) { prgBuildCTLSheet[dwPropCount].pszTitle=pwszWizardTitle; } else prgBuildCTLSheet[dwPropCount].pszTitle=NULL; prgBuildCTLSheet[dwPropCount].pfnDlgProc=rgBuildCTLPageInfo[dwIndex].pfnDlgProc; prgBuildCTLSheet[dwPropCount].lParam=(LPARAM)&CertBuildCTLInfo; dwPropCount++; } } else { //get the pages if(!CryptUIWizGetDigitalSignPages(&GetSignInfo, &pwPages, &dwPages)) goto Win32Err; //set up the property sheet and the property header prgBuildCTLSheet=(PROPSHEETPAGEW *)WizardAlloc(sizeof(PROPSHEETPAGEW) * ( BUILDCTL_PROP_SHEET + dwPages)); if(NULL==prgBuildCTLSheet) goto MemoryErr; memset(prgBuildCTLSheet, 0, sizeof(PROPSHEETPAGEW) * (BUILDCTL_PROP_SHEET + dwPages)); dwPropCount=0; for(dwIndex=0; dwIndex=3 && dwIndex < (3+dwPages)) { memcpy(&(prgBuildCTLSheet[dwPropCount]), &(pwPages[dwPropCount-3]), sizeof(PROPSHEETPAGEW)); dwPropCount++; continue; } //skip the destination page is required if((3+dwPages) == dwIndex ) { if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION) continue; } //skip the friendly name page if the desination page is skipped and the destination //is a file name if((4+dwPages) == dwIndex) { if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION) { if(NULL==ppCTLContext) { if(pBuildCTLDest) { if(CRYPTUI_WIZ_BUILDCTL_DEST_FILE == pBuildCTLDest->dwDestinationChoice) continue; } else continue; } } } prgBuildCTLSheet[dwPropCount].dwSize=sizeof(prgBuildCTLSheet[dwPropCount]); if(pwszWizardTitle) prgBuildCTLSheet[dwPropCount].dwFlags=PSP_USETITLE; else prgBuildCTLSheet[dwPropCount].dwFlags=0; prgBuildCTLSheet[dwPropCount].hInstance=g_hmodThisDll; prgBuildCTLSheet[dwPropCount].pszTemplate=(LPCWSTR)(rgBuildCTLPageInfo[dwIndex >= 3 ? dwIndex-dwPages : dwIndex].pszTemplate); if(pwszWizardTitle) { prgBuildCTLSheet[dwPropCount].pszTitle=pwszWizardTitle; } else prgBuildCTLSheet[dwPropCount].pszTitle=NULL; prgBuildCTLSheet[dwPropCount].pfnDlgProc=rgBuildCTLPageInfo[dwIndex >= 3 ? dwIndex-dwPages : dwIndex].pfnDlgProc; prgBuildCTLSheet[dwPropCount].lParam=(LPARAM)&CertBuildCTLInfo; dwPropCount++; } } //set up the header information buildCTLHeader.dwSize=sizeof(buildCTLHeader); buildCTLHeader.dwFlags=PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW; buildCTLHeader.hwndParent=hwndParent; buildCTLHeader.hInstance=g_hmodThisDll; if(pwszWizardTitle) buildCTLHeader.pszCaption=pwszWizardTitle; else { if(LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0]))) buildCTLHeader.pszCaption=wszTitle; } buildCTLHeader.nPages=dwPropCount; buildCTLHeader.nStartPage=0; buildCTLHeader.ppsp=prgBuildCTLSheet; //create the wizard iReturn = PropertySheetU(&buildCTLHeader); if(-1 == iReturn) goto Win32Err; if(0 == iReturn) { //user clicks cancel fResult=TRUE; //no need to say anything if the wizard is cancelled ids=0; if(ppCTLContext) *ppCTLContext=NULL; goto CommonReturn; } //get the resulting nonsigned CTL or signed CTL if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_SIGNING) { //get the created BLOB of the CTL if( (0 == SignBlob.cbBlob) || (NULL==SignBlob.pbBlob) ) { //the error msg should have shown. ids=0; goto CTLBlobErr; } //the CTL context from the encoded CTL pBldCTL=CertCreateCTLContext( g_dwMsgAndCertEncodingType, SignBlob.pbBlob, SignBlob.cbBlob); } else { //get the signing result fResult=GetSignInfo.fResult; if(!fResult || !(GetSignInfo.pSignContext)) { ids=IDS_SIGN_CTL_FAILED; if(0 == GetSignInfo.dwError) GetSignInfo.dwError=E_FAIL; goto SignErr; } //the CTL context from the encoded CTL pBldCTL=CertCreateCTLContext( g_dwMsgAndCertEncodingType, (GetSignInfo.pSignContext)->pbBlob, (GetSignInfo.pSignContext)->cbBlob); } if(NULL==pBldCTL) goto Win32Err; //set the properties if(CertBuildCTLInfo.pwszFriendlyName) { PropertyBlob.cbData=sizeof(WCHAR)*(wcslen(CertBuildCTLInfo.pwszFriendlyName)+1); PropertyBlob.pbData=(BYTE *)(CertBuildCTLInfo.pwszFriendlyName); CertSetCTLContextProperty( pBldCTL, CERT_FRIENDLY_NAME_PROP_ID, 0, &PropertyBlob); } if(CertBuildCTLInfo.pwszDescription) { PropertyBlob.cbData=sizeof(WCHAR)*(wcslen(CertBuildCTLInfo.pwszDescription)+1); PropertyBlob.pbData=(BYTE *)(CertBuildCTLInfo.pwszDescription); CertSetCTLContextProperty( pBldCTL, CERT_DESCRIPTION_PROP_ID, 0, &PropertyBlob); } //save to the destination if(CertBuildCTLInfo.hDesStore && (TRUE==CertBuildCTLInfo.fSelectedDesStore)) { if(!CertAddCTLContextToStore(CertBuildCTLInfo.hDesStore, pBldCTL, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) { ids=IDS_FAIL_TO_ADD_CTL_TO_STORE; goto Win32Err; } } //save to the file if(CertBuildCTLInfo.pwszFileName && (TRUE==CertBuildCTLInfo.fSelectedFileName)) { if(S_OK != OpenAndWriteToFile( CertBuildCTLInfo.pwszFileName, pBldCTL->pbCtlEncoded, pBldCTL->cbCtlEncoded)) { ids=IDS_FAIL_TO_ADD_CTL_TO_FILE; goto Win32Err; } } if(ppCTLContext) { *ppCTLContext=pBldCTL; pBldCTL=NULL; } fResult=TRUE; ids=IDS_BUILDCTL_SUCCEEDED; CommonReturn: //preserve the last error dwError=GetLastError(); //pop up the confirmation box for failure if(ids) { //set the message of inable to gather enough info for PKCS10 if(IDS_BUILDCTL_SUCCEEDED == ids) I_MessageBox(hwndParent, ids, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK|MB_ICONINFORMATION); else I_MessageBox(hwndParent, ids, IDS_BUILDCTL_WIZARD_TITLE, NULL, MB_OK|MB_ICONERROR); } //free the BLOB to be signed. It is the encoded CTL BLOB without the //signature if(SignBlob.pbBlob) WizardFree(SignBlob.pbBlob); //free the signing context if(GetSignInfo.pSignContext) CryptUIWizFreeDigitalSignContext(GetSignInfo.pSignContext); //free the store lsit //free my store if(hMyStore) CertCloseStore(hMyStore, 0); /* if(CertStoreList.prgStore) { for(dwIndex=0; dwIndexprgCertContext) return FALSE; //now, we need to enum all the certs in the store for(dwIndex=0; dwIndexdwCertCount; dwIndex++) { if(NULL==pCertBuildCTLInfo->prgCertContext[dwIndex]) continue; //get the SHA1 hash of the certificate if(!CertGetCertificateContextProperty( pCertBuildCTLInfo->prgCertContext[dwIndex], pCertBuildCTLInfo->dwHashPropID, NULL,&cbData)) goto CLEANUP; pbData=(BYTE *)WizardAlloc(cbData); if(!pbData) goto CLEANUP; //get the SHA1 hash of the certificate if(!CertGetCertificateContextProperty( pCertBuildCTLInfo->prgCertContext[dwIndex], pCertBuildCTLInfo->dwHashPropID, pbData,&cbData)) goto CLEANUP; //add to our global list (*pdwCount)++; //re-alloc memory *prgpHash=(BYTE **)WizardRealloc(*prgpHash, sizeof(BYTE *)*(*pdwCount)); *prgcbHash=(DWORD *)WizardRealloc(*prgcbHash, sizeof(DWORD)*(*pdwCount)); if((!(*prgpHash)) || (!(*prgcbHash))) goto CLEANUP; (*prgpHash)[*pdwCount-1]=pbData; (*prgcbHash)[*pdwCount-1]=cbData; } fResult=TRUE; CLEANUP: if(!fResult) { if(*prgpHash) { for(dwIndex=0; dwIndex<*pdwCount; dwIndex++) WizardFree((*prgpHash)[dwIndex]); WizardFree(*prgpHash); *prgpHash=NULL; } if(*prgcbHash) { WizardFree(*prgcbHash); *prgcbHash=NULL; } } return fResult; } //----------------------------------------------------------------------- // // I_BuildCTL // // Build a new CTL or modify an existing CTL. //------------------------------------------------------------------------ BOOL I_BuildCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo, UINT *pIDS, BYTE **ppbEncodedCTL, DWORD *pcbEncodedCTL) { BOOL fResult=FALSE; CMSG_SIGNED_ENCODE_INFO sSignInfo; CTL_INFO CTLInfo; DWORD dwIndex=0; DWORD cbEncodedCTL=0; UINT ids=IDS_FAIL_TO_BUILD_CTL; GUID guid; PCCRYPT_OID_INFO pOIDInfo=NULL; ALG_ID AlgID=0; DWORD dwCount=0; BYTE **rgpHash=NULL; DWORD *rgcbHash=NULL; unsigned char * pGUID=NULL; LPWSTR pwszGUID=NULL; BYTE *pbEncodedCTL=NULL; //init memset(&sSignInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO)); sSignInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO); memset(&CTLInfo, 0, sizeof(CTL_INFO)); if(pbEncodedCTL) *pbEncodedCTL=NULL; //set up CTL CTLInfo.dwVersion=CTL_V1; //set up the subject Usage for(dwIndex=0; dwIndexdwPurposeCount; dwIndex++) { if(pCertBuildCTLInfo->prgPurpose[dwIndex]->fSelected) { CTLInfo.SubjectUsage.cUsageIdentifier++; CTLInfo.SubjectUsage.rgpszUsageIdentifier=(LPSTR *)WizardRealloc( CTLInfo.SubjectUsage.rgpszUsageIdentifier, sizeof(LPSTR) * CTLInfo.SubjectUsage.cUsageIdentifier); if(!CTLInfo.SubjectUsage.rgpszUsageIdentifier) goto MemoryErr; CTLInfo.SubjectUsage.rgpszUsageIdentifier[CTLInfo.SubjectUsage.cUsageIdentifier-1]= pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID; } } //Set up ListIdentifier //copy the listID if user has specified it if(NULL==pCertBuildCTLInfo->pwszListID) { if(RPC_S_OK != UuidCreate(&guid)) goto TraceErr; //make a wchar string out of the guid if(RPC_S_OK != UuidToString(&guid, &pGUID)) goto TraceErr; //conver the string to wchar pwszGUID=MkWStr((char *)pGUID); if(!pwszGUID) goto TraceErr; CTLInfo.ListIdentifier.cbData=sizeof(WCHAR)*(wcslen(pwszGUID)+1); CTLInfo.ListIdentifier.pbData=(BYTE *)WizardAlloc(CTLInfo.ListIdentifier.cbData); if(NULL==CTLInfo.ListIdentifier.pbData) goto MemoryErr; memcpy(CTLInfo.ListIdentifier.pbData, pwszGUID, CTLInfo.ListIdentifier.cbData); } else { CTLInfo.ListIdentifier.cbData=sizeof(WCHAR)*(wcslen(pCertBuildCTLInfo->pwszListID)+1); CTLInfo.ListIdentifier.pbData=(BYTE *)WizardAlloc(CTLInfo.ListIdentifier.cbData); if(NULL==CTLInfo.ListIdentifier.pbData) goto MemoryErr; memcpy(CTLInfo.ListIdentifier.pbData, pCertBuildCTLInfo->pwszListID, CTLInfo.ListIdentifier.cbData); } //This update field GetSystemTimeAsFileTime(&(CTLInfo.ThisUpdate)); //Next Update field //do not specify any value if user did not enter any if(pCertBuildCTLInfo->dwValidMonths != 0 || pCertBuildCTLInfo->dwValidDays != 0) { AddDurationToFileTime(pCertBuildCTLInfo->dwValidMonths, pCertBuildCTLInfo->dwValidDays, &(CTLInfo.ThisUpdate), &(CTLInfo.NextUpdate)); } //subject Algorithm if(pCertBuildCTLInfo->dwHashPropID==CERT_MD5_HASH_PROP_ID) AlgID=CALG_MD5; else AlgID=CALG_SHA1; pOIDInfo=CryptFindOIDInfo( CRYPT_OID_INFO_ALGID_KEY, &AlgID, CRYPT_HASH_ALG_OID_GROUP_ID); if(pOIDInfo) CTLInfo.SubjectAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID); else goto FailErr; //set up the list of entries //get the array of hash of the certificate if(!GetCertHash(pCertBuildCTLInfo, &rgpHash, &rgcbHash, &dwCount)) goto FailErr; CTLInfo.cCTLEntry=dwCount; CTLInfo.rgCTLEntry=(CTL_ENTRY *)WizardAlloc(sizeof(CTL_ENTRY)*dwCount); if(!(CTLInfo.rgCTLEntry)) goto MemoryErr; //memset memset(CTLInfo.rgCTLEntry, 0, sizeof(CTL_ENTRY)*dwCount); for(dwIndex=0; dwIndexdwCertCount; sSignInfo.rgCertEncoded=(PCERT_BLOB)WizardAlloc(sizeof(CERT_BLOB)* sSignInfo.cCertEncoded); if(NULL==sSignInfo.rgCertEncoded) goto MemoryErr; for(dwIndex=0; dwIndexprgCertContext[dwIndex]->cbCertEncoded; sSignInfo.rgCertEncoded[dwIndex].pbData=pCertBuildCTLInfo->prgCertContext[dwIndex]->pbCertEncoded; } //encode and sign the CTL if(!CryptMsgEncodeAndSignCTL(g_dwMsgAndCertEncodingType, &CTLInfo, &sSignInfo, 0, NULL, &cbEncodedCTL)) goto TraceErr; //memory allocation pbEncodedCTL=(BYTE *)WizardAlloc(cbEncodedCTL); if(!(pbEncodedCTL)) goto MemoryErr; if(!CryptMsgEncodeAndSignCTL(g_dwMsgAndCertEncodingType, &CTLInfo, &sSignInfo, 0, pbEncodedCTL, &cbEncodedCTL)) goto TraceErr; if(ppbEncodedCTL && pcbEncodedCTL) { *ppbEncodedCTL=pbEncodedCTL; *pcbEncodedCTL=cbEncodedCTL; pbEncodedCTL=NULL; } ids=IDS_BUILDCTL_SUCCEEDED; fResult=TRUE; CommonReturn: if(CTLInfo.ListIdentifier.pbData) WizardFree(CTLInfo.ListIdentifier.pbData); if(CTLInfo.SubjectUsage.rgpszUsageIdentifier) WizardFree(CTLInfo.SubjectUsage.rgpszUsageIdentifier); if(pGUID) RpcStringFree(&pGUID); if(pwszGUID) FreeWStr(pwszGUID); if(CTLInfo.rgCTLEntry) WizardFree(CTLInfo.rgCTLEntry); if(sSignInfo.rgCertEncoded) WizardFree(sSignInfo.rgCertEncoded); if(rgpHash) { for(dwIndex=0; dwIndexpwszName)+1) <= stringSize) { wcscpy(string, pOIDInfo->pwszName); } else { return FALSE; } } else { return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0); } return TRUE; } ////////////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////////// LPWSTR WizardAllocAndCopyWStr(LPWSTR pwsz) { LPWSTR pwszReturn; if (NULL == (pwszReturn = (LPWSTR) WizardAlloc((wcslen(pwsz)+1) * sizeof(WCHAR)))) { return NULL; } wcscpy(pwszReturn, pwsz); return(pwszReturn); } ////////////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////////// BOOL WizardFormatDateString(LPWSTR *ppString, FILETIME ft, BOOL fIncludeTime) { int cch=0; int cch2=0; LPWSTR psz=NULL; SYSTEMTIME st; FILETIME localTime; if (!FileTimeToLocalFileTime(&ft, &localTime)) { return FALSE; } if (!FileTimeToSystemTime(&localTime, &st)) { // // if the conversion to local time failed, then just use the original time // if (!FileTimeToSystemTime(&ft, &st)) { return FALSE; } } cch = (GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + GetDateFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5); if (NULL == (psz = (LPWSTR) WizardAlloc((cch+5) * sizeof(WCHAR)))) { return FALSE; } cch2 = GetDateFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, psz, cch); if (fIncludeTime) { psz[cch2-1] = ' '; GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, &psz[cch2], cch-cch2); } *ppString = psz; return TRUE; } //+------------------------------------------------------------------------- // Write a blob to a file //-------------------------------------------------------------------------- HRESULT OpenAndWriteToFile( LPCWSTR pwszFileName, PBYTE pb, DWORD cb ) { HRESULT hr=E_FAIL; HANDLE hFile=NULL; DWORD dwBytesWritten=0; if(!pwszFileName || !pb || (cb==0)) return E_INVALIDARG; hFile = ExpandAndCreateFileU(pwszFileName, GENERIC_WRITE, 0, // fdwShareMode NULL, // lpsa CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, // fdwAttrsAndFlags 0); // TemplateFile if (INVALID_HANDLE_VALUE == hFile) { hr=HRESULT_FROM_WIN32(GetLastError()); } else { if (!WriteFile( hFile, pb, cb, &dwBytesWritten, NULL // lpOverlapped )) { hr=HRESULT_FROM_WIN32(GetLastError()); } else { if(dwBytesWritten != cb) hr=E_FAIL; else hr=S_OK; } CloseHandle(hFile); } return hr; } //-------------------------------------------------------------------------------- // See if the DATA blob is a valid wchar string //-------------------------------------------------------------------------------- BOOL ValidString(CRYPT_DATA_BLOB *pDataBlob) { LPWSTR pwsz=NULL; DWORD dwIndex=0; if(NULL==pDataBlob) return FALSE; if(pDataBlob->cbData < sizeof(WCHAR)) return FALSE; //has to be NULL-terminated pwsz=(LPWSTR)((DWORD_PTR)(pDataBlob->pbData)+(pDataBlob->cbData)-sizeof(WCHAR)); if(*pwsz != '\0') return FALSE; //has to include the exact number of wchars if(0 != ((pDataBlob->cbData)%sizeof(WCHAR))) return FALSE; //each character, with exception of the last NULL terminater, //has to be printable (20-7e) range for(dwIndex=0; dwIndex<(pDataBlob->cbData)-sizeof(WCHAR); dwIndex=dwIndex+sizeof(WCHAR)) { pwsz=(LPWSTR)((DWORD_PTR)(pDataBlob->pbData)+dwIndex); if(0==iswprint(*pwsz)) return FALSE; } return TRUE; } //-------------------------------------------------------------------------------- // See if the user input is an 0 in the form of {white spaces}{sign}{0} // pwszInput has to be NULL terminated //-------------------------------------------------------------------------------- BOOL ValidZero(LPWSTR pwszInput) { BOOL fSpace=TRUE; BOOL fSign=TRUE; if(NULL==pwszInput) return FALSE; while(*pwszInput != L'\0') { if(iswspace(*pwszInput)) { if(fSpace) pwszInput++; else return FALSE; } else { if((L'+'==*pwszInput) || (L'-'==*pwszInput)) { if(fSign) { fSign=FALSE; fSpace=FALSE; pwszInput++; } else return FALSE; } else { if(L'0'==*pwszInput) { fSign=FALSE; fSpace=FALSE; pwszInput++; } else return FALSE; } } } return TRUE; } //-------------------------------------------------------------------------------- // Get the number of days in a particular month of a particular year //-------------------------------------------------------------------------------- DWORD DaysInMonth(DWORD dwYear, DWORD dwMonth) { switch (dwMonth) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; break; case 4: case 6: case 9: case 11: return 30; break; case 2: //leap year if((0 == dwYear % 4 && 0!= dwYear % 100) || 0 == dwYear % 400) return 29; else return 28; default: return 0; } return 0; } //-------------------------------------------------------------------------------- // Substract the next update time from the current time //-------------------------------------------------------------------------------- void SubstractDurationFromFileTime( FILETIME *pNextUpdateTime, FILETIME *pCurrentTime, DWORD *pdwValidMonths, DWORD *pdwValidDays) { SYSTEMTIME SystemNext; SYSTEMTIME SystemCurrent; *pdwValidMonths=0; *pdwValidDays=0; //return if the NextUpdateTime is NULL if(0 ==pNextUpdateTime->dwLowDateTime && 0==pNextUpdateTime->dwHighDateTime) return; //the NextUpateTime has to be more than the current time if((*(LONGLONG *)pNextUpdateTime) <= (*(LONGLONG *)pCurrentTime) ) return; //convert to system time if(!FileTimeToSystemTime(pNextUpdateTime, &SystemNext) || !FileTimeToSystemTime(pCurrentTime, &SystemCurrent)) return; //compute the difference between the two systemtime //in terms of month and days if(SystemNext.wDay >= SystemCurrent.wDay) *pdwValidDays=SystemNext.wDay - SystemCurrent.wDay; else { SystemNext.wMonth--; //consider the 1st month of the year if(0 == SystemNext.wMonth) { SystemNext.wMonth=12; SystemNext.wYear--; } *pdwValidDays=SystemNext.wDay + DaysInMonth(SystemNext.wYear, SystemNext.wMonth) - SystemCurrent.wDay; } *pdwValidMonths=(SystemNext.wYear * 12 + SystemNext.wMonth) - (SystemCurrent.wYear * 12 + SystemCurrent.wMonth); //if the resolution for day is too small, we just use one day if((*pdwValidDays == 0) && (*pdwValidMonths==0)) *pdwValidDays=1; } //-------------------------------------------------------------------------------- // GetDaysForMonth //-------------------------------------------------------------------------------- BOOL GetDaysForMonth(DWORD dwYear, DWORD dwMonth, DWORD *pdwDays) { BOOL fResult=FALSE; if(NULL == pdwDays) goto CLEANUP; *pdwDays=0; switch(dwMonth) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: *pdwDays=31; break; case 4: case 6: case 9: case 11: *pdwDays=30; break; case 2: if((dwYear % 4 == 0 && dwYear % 100 !=0 ) || (dwYear % 400 ==0)) *pdwDays=29; else *pdwDays=28; break; default: goto CLEANUP; } fResult=TRUE; CLEANUP: return fResult; } //-------------------------------------------------------------------------------- // Add the duration to the current fileTime //-------------------------------------------------------------------------------- void AddDurationToFileTime(DWORD dwValidMonths, DWORD dwValidDays, FILETIME *pCurrentFileTime, FILETIME *pNextFileTime) { SYSTEMTIME SystemCurrent; FILETIME FileAdded; LARGE_INTEGER dwSeconds; LARGE_INTEGER StartTime; DWORD dwActualdDays=0; //init memset(pNextFileTime, 0, sizeof(FILETIME)); //conver to the system time if(!FileTimeToSystemTime(pCurrentFileTime, &SystemCurrent)) return; //conver the month to year while(dwValidMonths >= 12) { SystemCurrent.wYear++; dwValidMonths=dwValidMonths-12; } SystemCurrent.wMonth = (WORD)(SystemCurrent.wMonth + dwValidMonths); if(SystemCurrent.wMonth > 12) { SystemCurrent.wYear++; SystemCurrent.wMonth = SystemCurrent.wMonth -12; } //make sure the number of days in a month is within the limit if(GetDaysForMonth(SystemCurrent.wYear, SystemCurrent.wMonth, &dwActualdDays)) { if(SystemCurrent.wDay > dwActualdDays) { SystemCurrent.wMonth++; SystemCurrent.wDay = SystemCurrent.wDay- (WORD)(dwActualdDays); } } //convert the system file to fileTime if(!SystemTimeToFileTime(&SystemCurrent, &FileAdded)) return; //convert the nan-seconds based on the file time //// FILETIME is in units of 100 nanoseconds (10**-7) dwSeconds.QuadPart=dwValidDays * 24 * 3600; dwSeconds.QuadPart=dwSeconds.QuadPart * 10000000; StartTime.LowPart=FileAdded.dwLowDateTime; StartTime.HighPart=FileAdded.dwHighDateTime; StartTime.QuadPart = StartTime.QuadPart + dwSeconds.QuadPart; //copy the fileAdded value to *pNextFileTime pNextFileTime->dwLowDateTime=StartTime.LowPart; pNextFileTime->dwHighDateTime=StartTime.HighPart; return; }