windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/ui/wizards/mgrcert.cpp

3921 lines
125 KiB
C++
Raw Normal View History

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