1390 lines
43 KiB
C++
1390 lines
43 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
|
//
|
||
|
// File: selcert.cpp
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include "global.hxx"
|
||
|
#include <dbgdef.h>
|
||
|
|
||
|
extern HINSTANCE HinstDll;
|
||
|
extern HMODULE HmodRichEdit;
|
||
|
|
||
|
#define MAX_SIZE_OF_COLUMNS 400
|
||
|
|
||
|
static const HELPMAP helpmap[] = {
|
||
|
{IDC_SELECTCERT_VIEWCERT_BUTTON,IDH_SELECTCERTIFICATE_VIEWCERT_BUTTON},
|
||
|
{IDC_SELECTCERT_CERTLIST, IDH_SELECTCERTIFICATE_CERTIFICATE_LIST}
|
||
|
};
|
||
|
|
||
|
|
||
|
class CertContextList {
|
||
|
public:
|
||
|
CertContextList() : m_head(NULL) { }
|
||
|
~CertContextList();
|
||
|
|
||
|
HRESULT Add(IN PCCERT_CONTEXT pCertContext,
|
||
|
OUT BOOL *pfReplacedExisting) ;
|
||
|
|
||
|
HRESULT SyncWithStore(HCERTSTORE hStore, DWORD dwFlags);
|
||
|
|
||
|
private:
|
||
|
typedef struct _CertContextListEle {
|
||
|
PCCERT_CONTEXT pCertContext;
|
||
|
struct _CertContextListEle * pNext;
|
||
|
} CertContextListEle;
|
||
|
|
||
|
CertContextListEle * m_head;
|
||
|
};
|
||
|
|
||
|
typedef struct _CERT_SELECT_HELPER
|
||
|
{
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
|
||
|
PCCERT_CONTEXT pSelectedCert;
|
||
|
DWORD rgdwSortParam[6];
|
||
|
BOOL fCertListDblClick;
|
||
|
CertContextList *pCertsFromDS;
|
||
|
} CERT_SELECT_HELPER, *PCERT_SELECT_HELPER;
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
static void AddCertToList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp, PCCERT_CONTEXT pCertContext, int itemIndex)
|
||
|
{
|
||
|
LPWSTR pwszText;
|
||
|
DWORD cbText;
|
||
|
WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
|
||
|
int subItemIndex;
|
||
|
LV_ITEMW lvI;
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
|
||
|
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
|
||
|
//
|
||
|
// set up the fields in the list view item
|
||
|
//
|
||
|
lvI.mask = LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
|
||
|
lvI.state = 0;
|
||
|
lvI.stateMask = 0;
|
||
|
lvI.iSubItem = 0;
|
||
|
lvI.iImage = 0;
|
||
|
lvI.lParam = (LPARAM) CertDuplicateCertificateContext(pCertContext);
|
||
|
lvI.iItem = itemIndex;
|
||
|
ListView_InsertItemU(hWndListView, &lvI);
|
||
|
|
||
|
subItemIndex = 0;
|
||
|
|
||
|
//
|
||
|
// issued to
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
|
||
|
{
|
||
|
CertGetNameStringW(
|
||
|
pCertContext,
|
||
|
CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
||
|
0,//CERT_NAME_ISSUER_FLAG,
|
||
|
NULL,
|
||
|
szText,
|
||
|
ARRAYSIZE(szText));
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// issued by
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
|
||
|
{
|
||
|
CertGetNameStringW(
|
||
|
pCertContext,
|
||
|
CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
||
|
CERT_NAME_ISSUER_FLAG,
|
||
|
NULL,
|
||
|
szText,
|
||
|
ARRAYSIZE(szText));
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// intended use
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
|
||
|
{
|
||
|
if (FormatEnhancedKeyUsageString(&pwszText, pCertContext, FALSE, FALSE))
|
||
|
{
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex, pwszText);
|
||
|
free(pwszText);
|
||
|
}
|
||
|
subItemIndex++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// friendly name
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
|
||
|
{
|
||
|
cbText = 0;
|
||
|
if (CertGetCertificateContextProperty( pCertContext,
|
||
|
CERT_FRIENDLY_NAME_PROP_ID,
|
||
|
NULL,
|
||
|
&cbText) &&
|
||
|
(NULL != (pwszText = (LPWSTR) malloc(cbText))))
|
||
|
{
|
||
|
CertGetCertificateContextProperty( pCertContext,
|
||
|
CERT_FRIENDLY_NAME_PROP_ID,
|
||
|
pwszText,
|
||
|
&cbText);
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
|
||
|
free(pwszText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_FRIENDLYNAME_NONE, szText, ARRAYSIZE(szText));
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// expiration
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
|
||
|
{
|
||
|
if (!FormatDateString(&pwszText, pCertContext->pCertInfo->NotAfter, FALSE, FALSE, hWndListView))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_NOTAVAILABLE, szText, ARRAYSIZE(szText));
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
|
||
|
free(pwszText);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// location
|
||
|
//
|
||
|
if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
|
||
|
{
|
||
|
pwszText = (LPWSTR) GetStoreName(pCertContext->hCertStore, TRUE);
|
||
|
if (pwszText == NULL)
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_NOTAVAILABLE, szText, ARRAYSIZE(szText));
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
|
||
|
free(pwszText);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static int ReplaceCertInList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp, PCCERT_CONTEXT pCertContext)
|
||
|
{
|
||
|
int nIndex = -1;
|
||
|
LV_ITEM lvitem;
|
||
|
|
||
|
while (-1 != (nIndex = ListView_GetNextItem(hWndListView, nIndex, LVNI_ALL)))
|
||
|
{
|
||
|
//DSIE: Bug 420717
|
||
|
memset(&lvitem, 0, sizeof(lvitem));
|
||
|
|
||
|
lvitem.iItem = nIndex;
|
||
|
lvitem.mask = LVIF_PARAM;
|
||
|
if (ListView_GetItem(hWndListView, &lvitem))
|
||
|
{
|
||
|
PCCERT_CONTEXT pCurrent = (PCCERT_CONTEXT)lvitem.lParam;
|
||
|
if (pCurrent->dwCertEncodingType == pCertContext->dwCertEncodingType)
|
||
|
{
|
||
|
if (CertCompareCertificate(pCertContext->dwCertEncodingType,
|
||
|
pCertContext->pCertInfo,
|
||
|
pCurrent->pCertInfo))
|
||
|
{
|
||
|
// Found a match, replace the certificate.
|
||
|
CertFreeCertificateContext(pCurrent);
|
||
|
ListView_DeleteItem(hWndListView, nIndex);
|
||
|
// Now, add our new certificate at this index.
|
||
|
AddCertToList(hWndListView, pviewhelp, pCertContext, nIndex);
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// No match, nothing to replace, just append to the list.
|
||
|
AddCertToList(hWndListView, pviewhelp, pCertContext, ListView_GetItemCount(hWndListView));
|
||
|
|
||
|
CommonReturn:
|
||
|
return nIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
// DSIE: Bug 207106
|
||
|
BOOL SupportEncryptedFileSystem(PCCERT_CONTEXT pCertContext)
|
||
|
{
|
||
|
BOOL fSuccess = FALSE;
|
||
|
DWORD cbUsage = 0;
|
||
|
PCERT_ENHKEY_USAGE pUsage = NULL;
|
||
|
|
||
|
if (!pCertContext)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &cbUsage))
|
||
|
goto CleanUp;
|
||
|
|
||
|
if (NULL == (pUsage = (PCERT_ENHKEY_USAGE) malloc(cbUsage)))
|
||
|
goto CleanUp;
|
||
|
|
||
|
if (!CertGetEnhancedKeyUsage(pCertContext, 0, pUsage, &cbUsage))
|
||
|
goto CleanUp;
|
||
|
|
||
|
if (0 == pUsage->cUsageIdentifier)
|
||
|
{
|
||
|
if (CRYPT_E_NOT_FOUND == GetLastError())
|
||
|
{
|
||
|
fSuccess = TRUE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (DWORD i = 0; i < pUsage->cUsageIdentifier; i++)
|
||
|
{
|
||
|
if (0 == strcmp(szOID_ENHANCED_KEY_USAGE, pUsage->rgpszUsageIdentifier[i]))
|
||
|
{
|
||
|
fSuccess = TRUE;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CleanUp:
|
||
|
if (pUsage)
|
||
|
free(pUsage);
|
||
|
|
||
|
return fSuccess;
|
||
|
}
|
||
|
|
||
|
|
||
|
//DSIE: Bug 314005. Major change to switch over to use Object Picker.
|
||
|
HRESULT AddFromDS(HWND hwndDlg, PCERT_SELECT_HELPER pviewhelp)
|
||
|
{
|
||
|
static const int SCOPE_INIT_COUNT = 1;
|
||
|
IDsObjectPicker * pDsObjectPicker = NULL;
|
||
|
IDataObject * pdo = NULL;
|
||
|
DSOP_SCOPE_INIT_INFO aScopeInit[SCOPE_INIT_COUNT];
|
||
|
DSOP_INIT_INFO InitInfo;
|
||
|
UINT cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
|
||
|
HWND hWndListView = NULL;
|
||
|
|
||
|
BOOL fGotStgMedium = FALSE;
|
||
|
PDS_SELECTION_LIST pDsSelList = NULL;
|
||
|
STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL, NULL};
|
||
|
FORMATETC formatetc = {(CLIPFORMAT) cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
||
|
|
||
|
HRESULT hr;
|
||
|
HCERTSTORE hDSCertStore = NULL;
|
||
|
|
||
|
PCCERT_CONTEXT pCertContext = NULL;
|
||
|
PCCERT_CONTEXT pCertContextPrev = NULL;
|
||
|
CertContextList * pCertContextList = NULL;
|
||
|
|
||
|
WCHAR errorString[512];
|
||
|
WCHAR errorTitle[512];
|
||
|
BOOL fInitialSelectedCert = FALSE;
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc = NULL;
|
||
|
|
||
|
// Input validation:
|
||
|
if (NULL == hwndDlg ||
|
||
|
NULL == pviewhelp ||
|
||
|
NULL == pviewhelp->pcsc ||
|
||
|
NULL == pviewhelp->pCertsFromDS)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
// Init:
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
pCertContextList = pviewhelp->pCertsFromDS;
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
CoInitialize(NULL);
|
||
|
hr = CoCreateInstance(CLSID_DsObjectPicker,
|
||
|
NULL,
|
||
|
CLSCTX_INPROC_SERVER,
|
||
|
IID_IDsObjectPicker,
|
||
|
(void **) &pDsObjectPicker);
|
||
|
if (FAILED(hr) || NULL == pDsObjectPicker)
|
||
|
goto ComError;
|
||
|
|
||
|
// Initialize the DSOP_SCOPE_INIT_INFO array.
|
||
|
ZeroMemory(aScopeInit, sizeof(DSOP_SCOPE_INIT_INFO) * SCOPE_INIT_COUNT);
|
||
|
|
||
|
// Combine multiple scope types in a single array entry.
|
||
|
aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
|
||
|
aScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
|
||
|
| DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
|
||
|
|
||
|
// Set uplevel and downlevel filters to include only computer objects.
|
||
|
// Uplevel filters apply to both mixed and native modes.
|
||
|
// Notice that the uplevel and downlevel flags are different.
|
||
|
aScopeInit[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
|
||
|
aScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
|
||
|
|
||
|
// Initialize the DSOP_INIT_INFO structure.
|
||
|
ZeroMemory(&InitInfo, sizeof(InitInfo));
|
||
|
InitInfo.cbSize = sizeof(InitInfo);
|
||
|
InitInfo.pwzTargetComputer = NULL; // Target is the local computer.
|
||
|
InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
|
||
|
InitInfo.aDsScopeInfos = aScopeInit;
|
||
|
//InitInfo.flOptions = DSOP_FLAG_MULTISELECT;
|
||
|
|
||
|
// You can call Initialize multiple times; last call wins.
|
||
|
// Note that object picker makes its own copy of InitInfo.
|
||
|
hr = pDsObjectPicker->Initialize(&InitInfo);
|
||
|
if (FAILED(hr))
|
||
|
goto ComError;
|
||
|
|
||
|
// Invoke the modal dialog.
|
||
|
hr = pDsObjectPicker->InvokeDialog(hwndDlg, &pdo);
|
||
|
if (FAILED(hr))
|
||
|
goto ComError;
|
||
|
|
||
|
// User pressed Cancel.
|
||
|
if (hr == S_FALSE)
|
||
|
{
|
||
|
hr = E_ABORT;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
// Get the global memory block containing the user's selections.
|
||
|
hr = pdo->GetData(&formatetc, &stgmedium);
|
||
|
if (FAILED(hr))
|
||
|
goto ComError;
|
||
|
|
||
|
fGotStgMedium = TRUE;
|
||
|
|
||
|
// Retrieve pointer to DS_SELECTION_LIST structure.
|
||
|
pDsSelList = (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
|
||
|
if (!pDsSelList)
|
||
|
goto ComError;
|
||
|
|
||
|
// Loop through DS_SELECTION array of selected objects.
|
||
|
for (ULONG i = 0; i < pDsSelList->cItems; i++)
|
||
|
{
|
||
|
WCHAR pwszLdapUrl[2048];
|
||
|
LPWSTR pTemp = pDsSelList->aDsSelection[i].pwzADsPath;
|
||
|
|
||
|
BOOL fReplacedExisting;
|
||
|
BOOL fHasEFSCerts = FALSE;
|
||
|
|
||
|
// Now is the time to get the certificate
|
||
|
LPCWSTR szCertAttr = L"?userCertificate";
|
||
|
|
||
|
// Check if our buffer is too small to hold the query.
|
||
|
if (wcslen(pTemp) + wcslen(szCertAttr) + 1 > (sizeof(pwszLdapUrl) / sizeof(pwszLdapUrl[0])))
|
||
|
goto UnexpectedErr;
|
||
|
|
||
|
wcscpy(pwszLdapUrl, pTemp);
|
||
|
wcscat(pwszLdapUrl, szCertAttr);
|
||
|
|
||
|
// Now open the DS store using LDAP provider.
|
||
|
hDSCertStore = CertOpenStore(sz_CERT_STORE_PROV_LDAP,
|
||
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||
|
NULL,
|
||
|
CERT_STORE_READONLY_FLAG,
|
||
|
(void*) pwszLdapUrl);
|
||
|
if (NULL == hDSCertStore)
|
||
|
goto CertCliError;
|
||
|
|
||
|
// We get the certificate store
|
||
|
pCertContext = NULL;
|
||
|
pCertContextPrev = NULL;
|
||
|
int nItemIndex;
|
||
|
|
||
|
while (NULL != (pCertContext = CertEnumCertificatesInStore(hDSCertStore, pCertContextPrev)))
|
||
|
{
|
||
|
// Apply our filter callback function to see if we should display this certificate.
|
||
|
BOOL fAllowCert = FALSE;
|
||
|
|
||
|
if (pcsc->pFilterCallback)
|
||
|
fAllowCert = (*(pcsc->pFilterCallback))(pCertContext, &fInitialSelectedCert, pcsc->pvCallbackData);
|
||
|
|
||
|
fAllowCert |= SupportEncryptedFileSystem(pCertContext);
|
||
|
|
||
|
if (fAllowCert)
|
||
|
{
|
||
|
fHasEFSCerts = TRUE;
|
||
|
|
||
|
if (S_OK != (hr = pCertContextList->Add(pCertContext, &fReplacedExisting)))
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
nItemIndex = ReplaceCertInList(hWndListView, pviewhelp, pCertContext);
|
||
|
|
||
|
// if the select cert dialog caller said that this should be the initially
|
||
|
// selected cert then make it so.
|
||
|
if (fInitialSelectedCert)
|
||
|
ListView_SetItemState(hWndListView, nItemIndex, LVIS_SELECTED, LVIS_SELECTED);
|
||
|
}
|
||
|
|
||
|
pCertContextPrev = pCertContext;
|
||
|
}
|
||
|
|
||
|
// We didn't reach the end of the enumeration. This is an error.
|
||
|
if (GetLastError() != CRYPT_E_NOT_FOUND)
|
||
|
goto CertCliError;
|
||
|
|
||
|
// We didn't find any EFS certs: display an error message and pop up the window again.
|
||
|
if (!fHasEFSCerts)
|
||
|
goto NoEfsError;
|
||
|
}
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
cleanup:
|
||
|
if (hDSCertStore)
|
||
|
{
|
||
|
CertCloseStore(hDSCertStore, 0);
|
||
|
}
|
||
|
|
||
|
if (NULL != pCertContext)
|
||
|
{
|
||
|
CertFreeCertificateContext(pCertContext);
|
||
|
}
|
||
|
|
||
|
if (pDsSelList)
|
||
|
{
|
||
|
GlobalUnlock(stgmedium.hGlobal);
|
||
|
}
|
||
|
|
||
|
if (fGotStgMedium)
|
||
|
{
|
||
|
ReleaseStgMedium(&stgmedium);
|
||
|
}
|
||
|
|
||
|
if (pdo)
|
||
|
{
|
||
|
pdo->Release();
|
||
|
}
|
||
|
|
||
|
if (pDsObjectPicker)
|
||
|
{
|
||
|
pDsObjectPicker->Release();
|
||
|
}
|
||
|
|
||
|
CoUninitialize();
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
ErrorReturn:
|
||
|
{
|
||
|
WCHAR wszText[MAX_STRING_SIZE];
|
||
|
WCHAR errorTitle2[MAX_STRING_SIZE];
|
||
|
LPWSTR pwszErrorMsg = NULL;
|
||
|
|
||
|
//get the text string
|
||
|
if(LoadStringU(HinstDll, IDS_INTERNAL_ERROR, wszText, sizeof(wszText) / sizeof(wszText[0])))
|
||
|
{
|
||
|
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL,
|
||
|
hr,
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||
|
(LPWSTR) &pwszErrorMsg,
|
||
|
0,
|
||
|
NULL))
|
||
|
{
|
||
|
if (LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle2, ARRAYSIZE(errorTitle2))) {
|
||
|
MessageBoxU(hwndDlg, pwszErrorMsg, errorTitle2, MB_ICONERROR|MB_OK|MB_APPLMODAL);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != pwszErrorMsg) { LocalFree(pwszErrorMsg); }
|
||
|
}
|
||
|
goto cleanup;
|
||
|
|
||
|
CertCliError:
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
ComError:
|
||
|
goto ErrorReturn;
|
||
|
|
||
|
NoEfsError:
|
||
|
LoadStringU(HinstDll, IDS_SELECT_CERT_NO_CERT_ERROR, errorString, ARRAYSIZE(errorString));
|
||
|
if (pcsc->szTitle != NULL)
|
||
|
{
|
||
|
MessageBoxU(hwndDlg, errorString, pcsc->szTitle, MB_OK | MB_ICONWARNING);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle, ARRAYSIZE(errorTitle));
|
||
|
MessageBoxU(hwndDlg, errorString, errorTitle, MB_OK | MB_ICONWARNING);
|
||
|
}
|
||
|
hr = AddFromDS(hwndDlg, pviewhelp);
|
||
|
goto cleanup;
|
||
|
|
||
|
UnexpectedErr:
|
||
|
hr = E_UNEXPECTED;
|
||
|
goto ErrorReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
static void AddCertsToList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp)
|
||
|
{
|
||
|
DWORD i;
|
||
|
PCCERT_CONTEXT pCertContext;
|
||
|
int itemIndex = 0;
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
|
||
|
BOOL fInitialSelectedCert = FALSE;
|
||
|
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
|
||
|
//
|
||
|
// loop for each store and display the certs in each store
|
||
|
//
|
||
|
for (i=0; i<pcsc->cDisplayStores; i++)
|
||
|
{
|
||
|
//
|
||
|
// loop for each cert in the store
|
||
|
//
|
||
|
pCertContext = NULL;
|
||
|
while (NULL != (pCertContext = CertEnumCertificatesInStore(pcsc->rghDisplayStores[i], pCertContext)))
|
||
|
{
|
||
|
fInitialSelectedCert = FALSE;
|
||
|
|
||
|
if ((pcsc->pFilterCallback == NULL) ||
|
||
|
((*(pcsc->pFilterCallback))(pCertContext, &fInitialSelectedCert, pcsc->pvCallbackData) == TRUE))
|
||
|
{
|
||
|
AddCertToList(hWndListView, pviewhelp, pCertContext, itemIndex);
|
||
|
|
||
|
//
|
||
|
// if the select cert dialog caller said that this should be the initially
|
||
|
// selected cert then make it so.
|
||
|
//
|
||
|
if (fInitialSelectedCert)
|
||
|
{
|
||
|
ListView_SetItemState(hWndListView, itemIndex, LVIS_SELECTED, LVIS_SELECTED);
|
||
|
}
|
||
|
|
||
|
itemIndex++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
static int CalculateColumnWidth(DWORD dwDontUseColumn)
|
||
|
{
|
||
|
int numColumns = 0;
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (!(dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
|
||
|
{
|
||
|
numColumns++;
|
||
|
}
|
||
|
|
||
|
if (numColumns >= 2)
|
||
|
{
|
||
|
return (MAX_SIZE_OF_COLUMNS / numColumns);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return MAX_SIZE_OF_COLUMNS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
INT_PTR APIENTRY SelectCertDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
|
||
|
HWND hWndListView;
|
||
|
LV_COLUMNW lvC;
|
||
|
int iCol = 0;
|
||
|
LV_ITEMW lvI;
|
||
|
int listIndex;
|
||
|
LPNMLISTVIEW pnmv;
|
||
|
PCERT_SELECT_HELPER pviewhelp;
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
|
||
|
WCHAR errorString[CRYPTUI_MAX_STRING_SIZE];
|
||
|
WCHAR errorTitle[CRYPTUI_MAX_STRING_SIZE];
|
||
|
HWND hwnd;
|
||
|
HIMAGELIST hIml;
|
||
|
DWORD dwSortParam;
|
||
|
int SortParamIndex;
|
||
|
|
||
|
switch ( msg ) {
|
||
|
|
||
|
case WM_INITDIALOG:
|
||
|
pviewhelp = (PCERT_SELECT_HELPER) lParam;
|
||
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR) pviewhelp);
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
|
||
|
//
|
||
|
// set the dialog title and the display string
|
||
|
//
|
||
|
if (pcsc->szTitle != NULL)
|
||
|
{
|
||
|
SetWindowTextU(hwndDlg, pcsc->szTitle);
|
||
|
}
|
||
|
|
||
|
if (pcsc->szDisplayString != NULL)
|
||
|
{
|
||
|
SetDlgItemTextU(hwndDlg, IDC_SELECTCERT_DISPLAYSTRING, pcsc->szDisplayString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT)
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_SELECT_MULTIPLE_CERT_DEFAULT, szText, ARRAYSIZE(szText));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_SELECT_CERT_DEFAULT, szText, ARRAYSIZE(szText));
|
||
|
}
|
||
|
SetDlgItemTextU(hwndDlg, IDC_SELECTCERT_DISPLAYSTRING, szText);
|
||
|
}
|
||
|
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
//
|
||
|
// initialize the image list for the list view
|
||
|
//
|
||
|
hIml = ImageList_LoadImage(HinstDll, MAKEINTRESOURCE(IDB_CERT), 0, 1, RGB(255,0,255), IMAGE_BITMAP, 0);
|
||
|
ListView_SetImageList(hWndListView, hIml, LVSIL_SMALL);
|
||
|
|
||
|
//
|
||
|
// add the colums to the list view
|
||
|
//
|
||
|
|
||
|
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;// | LVCF_SUBITEM;
|
||
|
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
|
||
|
lvC.pszText = szText; // The text for the column.
|
||
|
lvC.cx = CalculateColumnWidth(pviewhelp->pcsc->dwDontUseColumn);
|
||
|
|
||
|
memset(&(pviewhelp->rgdwSortParam[0]), 0, ARRAYSIZE(pviewhelp->rgdwSortParam));
|
||
|
SortParamIndex = 0;
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_ISSUEDTO2, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND;
|
||
|
}
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_ISSUEDBY2, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND;
|
||
|
}
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_INTENDED_PURPOSE, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] =SORT_COLUMN_PURPOSE | SORT_COLUMN_DESCEND;
|
||
|
}
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_CERTIFICATE_NAME, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_NAME | SORT_COLUMN_DESCEND;
|
||
|
}
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_EXPIRATION_DATE, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND;
|
||
|
}
|
||
|
|
||
|
if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_LOCATION, szText, ARRAYSIZE(szText));
|
||
|
if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
|
||
|
{
|
||
|
// error
|
||
|
}
|
||
|
|
||
|
pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_LOCATION | SORT_COLUMN_DESCEND;
|
||
|
}
|
||
|
|
||
|
AddCertsToList(hWndListView, pviewhelp);
|
||
|
|
||
|
//
|
||
|
// if there is no cert selected initially disable the "view cert button"
|
||
|
//
|
||
|
if (ListView_GetSelectedCount(hWndListView) == 0)
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set the style in the list view so that it highlights an entire line
|
||
|
//
|
||
|
SendMessageA(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
|
||
|
|
||
|
#if (1) // DSIE: bug 338852.
|
||
|
HWND hwndFindUser;
|
||
|
|
||
|
if (hwndFindUser = GetDlgItem(hwndDlg, IDC_SELECTCERT_ADDFROMDS_BUTTON))
|
||
|
{
|
||
|
LPBYTE pDCName = NULL;
|
||
|
|
||
|
DWORD dwError = NetGetDCName(NULL, NULL, &pDCName);
|
||
|
|
||
|
if (NERR_Success == dwError)
|
||
|
{
|
||
|
NetApiBufferFree(pDCName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EnableWindow(hwndFindUser, FALSE);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
ListView_SetItemState(hWndListView,
|
||
|
0,
|
||
|
LVIS_FOCUSED | LVIS_SELECTED,
|
||
|
LVIS_FOCUSED | LVIS_SELECTED);
|
||
|
SetFocus(hWndListView);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
switch (((NMHDR FAR *) lParam)->code)
|
||
|
{
|
||
|
|
||
|
case NM_DBLCLK:
|
||
|
|
||
|
switch (((NMHDR FAR *) lParam)->idFrom)
|
||
|
{
|
||
|
case IDC_SELECTCERT_CERTLIST:
|
||
|
|
||
|
if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON)))
|
||
|
{
|
||
|
pviewhelp->fCertListDblClick = TRUE;
|
||
|
|
||
|
SendMessage(
|
||
|
hwndDlg,
|
||
|
WM_COMMAND,
|
||
|
MAKELONG(IDC_SELECTCERT_VIEWCERT_BUTTON, BN_CLICKED),
|
||
|
(LPARAM) GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case LVN_ITEMCHANGING:
|
||
|
|
||
|
pnmv = (LPNMLISTVIEW) lParam;
|
||
|
|
||
|
switch (((NMHDR FAR *) lParam)->idFrom)
|
||
|
{
|
||
|
case IDC_SELECTCERT_CERTLIST:
|
||
|
|
||
|
if (!(pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT))
|
||
|
{
|
||
|
if (pnmv->uNewState & LVIS_SELECTED)
|
||
|
{
|
||
|
ListView_SetItemState(
|
||
|
hWndListView,
|
||
|
ListView_GetNextItem(hWndListView, -1, LVNI_SELECTED),
|
||
|
~LVIS_SELECTED,
|
||
|
LVIS_SELECTED);
|
||
|
|
||
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case LVN_ITEMCHANGED:
|
||
|
|
||
|
pnmv = (LPNMLISTVIEW) lParam;
|
||
|
|
||
|
switch (((NMHDR FAR *) lParam)->idFrom)
|
||
|
{
|
||
|
case IDC_SELECTCERT_CERTLIST:
|
||
|
|
||
|
if (ListView_GetSelectedCount(hWndListView) == 1)
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case NM_SETFOCUS:
|
||
|
|
||
|
switch (((NMHDR FAR *) lParam)->idFrom)
|
||
|
{
|
||
|
|
||
|
case IDC_SELECTCERT_CERTLIST:
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
if ((ListView_GetItemCount(hWndListView) != 0) &&
|
||
|
(ListView_GetNextItem(hWndListView, -1, LVNI_SELECTED) == -1))
|
||
|
{
|
||
|
memset(&lvI, 0, sizeof(lvI));
|
||
|
lvI.mask = LVIF_STATE;
|
||
|
lvI.iItem = 0;
|
||
|
lvI.state = LVIS_FOCUSED;
|
||
|
lvI.stateMask = LVIS_FOCUSED;
|
||
|
ListView_SetItem(hWndListView, &lvI);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
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:
|
||
|
case 5:
|
||
|
dwSortParam = pviewhelp->rgdwSortParam[pnmv->iSubItem];
|
||
|
break;
|
||
|
default:
|
||
|
dwSortParam = 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (0 != dwSortParam)
|
||
|
{
|
||
|
//
|
||
|
// 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_SELECTCERT_CERTLIST,
|
||
|
LVM_SORTITEMS,
|
||
|
(WPARAM) (LPARAM) dwSortParam,
|
||
|
(LPARAM) (PFNLVCOMPARE)CompareCertificate);
|
||
|
|
||
|
pviewhelp->rgdwSortParam[pnmv->iSubItem] = dwSortParam;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
|
||
|
pcsc = pviewhelp->pcsc;
|
||
|
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
switch (LOWORD(wParam))
|
||
|
{
|
||
|
|
||
|
case IDC_SELECTCERT_ADDFROMDS_BUTTON:
|
||
|
{
|
||
|
HRESULT hr = AddFromDS(hwndDlg, pviewhelp);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
// Error
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IDC_SELECTCERT_VIEWCERT_BUTTON:
|
||
|
CRYPTUI_VIEWCERTIFICATE_STRUCTW cvps;
|
||
|
BOOL fPropertiesChanged;
|
||
|
|
||
|
listIndex = ListView_GetNextItem(
|
||
|
hWndListView,
|
||
|
-1,
|
||
|
LVNI_SELECTED
|
||
|
);
|
||
|
|
||
|
if (listIndex != -1)
|
||
|
{
|
||
|
memset(&lvI, 0, sizeof(lvI));
|
||
|
lvI.iItem = listIndex;
|
||
|
lvI.mask = LVIF_PARAM;
|
||
|
if (ListView_GetItemU(hWndListView, &lvI))
|
||
|
{
|
||
|
//
|
||
|
// if the caller handed in a callback call them to see if they
|
||
|
// want to handle the display of the cert, otherwise display the cert
|
||
|
//
|
||
|
if ((pcsc->pDisplayCallback != NULL) &&
|
||
|
((*(pcsc->pDisplayCallback))((PCCERT_CONTEXT) lvI.lParam, hwndDlg, pcsc->pvCallbackData) == TRUE))
|
||
|
{
|
||
|
//
|
||
|
// set the fPropertiesChanged bool to true so that the cert will
|
||
|
// get refreshed in the display. this doesn't hurt anything even
|
||
|
// if the cert didn't change
|
||
|
//
|
||
|
fPropertiesChanged = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memset(&cvps, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW));
|
||
|
cvps.dwSize = sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW);
|
||
|
cvps.hwndParent = hwndDlg;
|
||
|
cvps.pCertContext = (PCCERT_CONTEXT) lvI.lParam;
|
||
|
cvps.cStores = pviewhelp->pcsc->cStores;
|
||
|
cvps.rghStores = pviewhelp->pcsc->rghStores;
|
||
|
cvps.cPropSheetPages = pviewhelp->pcsc->cPropSheetPages;
|
||
|
cvps.rgPropSheetPages = pviewhelp->pcsc->rgPropSheetPages;
|
||
|
CryptUIDlgViewCertificateW(&cvps, &fPropertiesChanged);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// if the properties changed then refresh the cert in the list
|
||
|
//
|
||
|
if (fPropertiesChanged)
|
||
|
{
|
||
|
ListView_DeleteItem(hWndListView, listIndex);
|
||
|
AddCertToList(hWndListView, pviewhelp, (PCCERT_CONTEXT) lvI.lParam, listIndex);
|
||
|
ListView_SetItemState(hWndListView, listIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
||
|
}
|
||
|
|
||
|
if (!pviewhelp->fCertListDblClick)
|
||
|
{
|
||
|
SetFocus(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON));
|
||
|
}
|
||
|
|
||
|
pviewhelp->fCertListDblClick = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case IDOK:
|
||
|
listIndex = ListView_GetNextItem(
|
||
|
hWndListView,
|
||
|
-1,
|
||
|
LVNI_SELECTED
|
||
|
);
|
||
|
|
||
|
if (listIndex != -1)
|
||
|
{
|
||
|
memset(&lvI, 0, sizeof(lvI));
|
||
|
lvI.iItem = listIndex;
|
||
|
lvI.mask = LVIF_PARAM;
|
||
|
|
||
|
if (!(pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT))
|
||
|
{
|
||
|
if (ListView_GetItemU(hWndListView, &lvI))
|
||
|
{
|
||
|
pviewhelp->pSelectedCert = CertDuplicateCertificateContext((PCCERT_CONTEXT) lvI.lParam);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ListView_GetItemU(hWndListView, &lvI))
|
||
|
{
|
||
|
CertAddCertificateContextToStore(
|
||
|
pcsc->hSelectedCertStore,
|
||
|
(PCCERT_CONTEXT) lvI.lParam,
|
||
|
CERT_STORE_ADD_ALWAYS,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
while (-1 != (listIndex = ListView_GetNextItem(
|
||
|
hWndListView,
|
||
|
listIndex,
|
||
|
LVNI_SELECTED
|
||
|
)))
|
||
|
{
|
||
|
lvI.iItem = listIndex;
|
||
|
if (ListView_GetItemU(hWndListView, &lvI))
|
||
|
{
|
||
|
CertAddCertificateContextToStore(
|
||
|
pcsc->hSelectedCertStore,
|
||
|
(PCCERT_CONTEXT) lvI.lParam,
|
||
|
CERT_STORE_ADD_ALWAYS,
|
||
|
NULL);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_SELECT_CERT_ERROR, errorString, ARRAYSIZE(errorString));
|
||
|
if (pcsc->szTitle != NULL)
|
||
|
{
|
||
|
MessageBoxU(hwndDlg, errorString, pcsc->szTitle, MB_OK | MB_ICONWARNING);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle, ARRAYSIZE(errorTitle));
|
||
|
MessageBoxU(hwndDlg, errorString, errorTitle, MB_OK | MB_ICONWARNING);
|
||
|
}
|
||
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LRESULT)TRUE);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
EndDialog(hwndDlg, NULL);
|
||
|
break;
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog(hwndDlg, NULL);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
|
||
|
hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
|
||
|
|
||
|
memset(&lvI, 0, sizeof(lvI));
|
||
|
lvI.iItem = ListView_GetItemCount(hWndListView) - 1;
|
||
|
lvI.mask = LVIF_PARAM;
|
||
|
while (lvI.iItem >= 0)
|
||
|
{
|
||
|
if (ListView_GetItemU(hWndListView, &lvI))
|
||
|
{
|
||
|
CertFreeCertificateContext((PCCERT_CONTEXT) lvI.lParam);
|
||
|
}
|
||
|
lvI.iItem--;
|
||
|
}
|
||
|
|
||
|
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, IDOK)) &&
|
||
|
(hwnd != GetDlgItem(hwndDlg, IDCANCEL)) &&
|
||
|
(hwnd != GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON)) &&
|
||
|
(hwnd != GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST)))
|
||
|
{
|
||
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LRESULT)TRUE);
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return OnContextHelp(hwndDlg, msg, wParam, lParam, helpmap);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
PCCERT_CONTEXT
|
||
|
WINAPI
|
||
|
CryptUIDlgSelectCertificateW(
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
|
||
|
)
|
||
|
{
|
||
|
CERT_SELECT_HELPER viewhelper;
|
||
|
WORD wDialogID;
|
||
|
|
||
|
if (CommonInit() == FALSE)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if ((pcsc->dwSize != sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW)) &&
|
||
|
(pcsc->dwSize != offsetof(CRYPTUI_SELECTCERTIFICATE_STRUCTW, hSelectedCertStore))) {
|
||
|
SetLastError(E_INVALIDARG);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
wDialogID =
|
||
|
pcsc->dwFlags & CRYPTUI_SELECTCERT_ADDFROMDS ?
|
||
|
IDD_SELECTCERT_DIALOG_WITH_DSPICKER :
|
||
|
IDD_SELECTCERT_DIALOG;
|
||
|
|
||
|
viewhelper.pcsc = pcsc;
|
||
|
viewhelper.pSelectedCert = NULL;
|
||
|
viewhelper.fCertListDblClick = FALSE;
|
||
|
viewhelper.pCertsFromDS = new CertContextList;
|
||
|
if (NULL == viewhelper.pCertsFromDS)
|
||
|
{
|
||
|
SetLastError(E_OUTOFMEMORY);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (DialogBoxParamU(
|
||
|
HinstDll,
|
||
|
(LPWSTR) MAKEINTRESOURCE(wDialogID),
|
||
|
(pcsc->hwndParent != NULL) ? pcsc->hwndParent : GetDesktopWindow(),
|
||
|
SelectCertDialogProc,
|
||
|
(LPARAM) &viewhelper) != -1)
|
||
|
{
|
||
|
SetLastError(0);
|
||
|
}
|
||
|
|
||
|
delete viewhelper.pCertsFromDS;
|
||
|
|
||
|
if (pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return(viewhelper.pSelectedCert);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
PCCERT_CONTEXT
|
||
|
WINAPI
|
||
|
CryptUIDlgSelectCertificateA(
|
||
|
PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
|
||
|
)
|
||
|
{
|
||
|
CRYPTUI_SELECTCERTIFICATE_STRUCTW cscW;
|
||
|
PCCERT_CONTEXT pReturnCert = NULL;
|
||
|
|
||
|
memcpy(&cscW, pcsc, sizeof(cscW));
|
||
|
|
||
|
if (!ConvertToPropPageW(
|
||
|
pcsc->rgPropSheetPages,
|
||
|
pcsc->cPropSheetPages,
|
||
|
&(cscW.rgPropSheetPages)))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (pcsc->szTitle)
|
||
|
{
|
||
|
cscW.szTitle = CertUIMkWStr(pcsc->szTitle);
|
||
|
}
|
||
|
|
||
|
if (pcsc->szDisplayString)
|
||
|
{
|
||
|
cscW.szDisplayString = CertUIMkWStr(pcsc->szDisplayString);
|
||
|
}
|
||
|
|
||
|
pReturnCert = CryptUIDlgSelectCertificateW(&cscW);
|
||
|
|
||
|
FreePropSheetPagesW((LPPROPSHEETPAGEW) cscW.rgPropSheetPages, cscW.cPropSheetPages);
|
||
|
|
||
|
if (cscW.szTitle)
|
||
|
{
|
||
|
free((void *) cscW.szTitle);
|
||
|
}
|
||
|
|
||
|
if (cscW.szDisplayString)
|
||
|
{
|
||
|
free((void *) cscW.szDisplayString);
|
||
|
}
|
||
|
|
||
|
return(pReturnCert);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Implementation of utility class: CertContextList
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////
|
||
|
|
||
|
CertContextList::~CertContextList()
|
||
|
{
|
||
|
CertContextListEle *pListEle;
|
||
|
CertContextListEle *pListEleNext;
|
||
|
|
||
|
for (pListEle = m_head; pListEle != NULL; pListEle = pListEleNext)
|
||
|
{
|
||
|
pListEleNext = pListEle->pNext;
|
||
|
if (pListEle->pCertContext != NULL) { CertFreeCertificateContext(pListEle->pCertContext); }
|
||
|
delete pListEle;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CertContextList::Add(IN PCCERT_CONTEXT pCertContext,
|
||
|
OUT BOOL *pfReplacedExisting)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
CertContextListEle *pListEle = NULL;
|
||
|
CertContextListEle *pListElePrev = NULL;
|
||
|
|
||
|
if (pCertContext == NULL || pfReplacedExisting == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
for (pListEle = m_head; pListEle != NULL; pListEle = pListEle->pNext)
|
||
|
{
|
||
|
PCCERT_CONTEXT pCurrent = pListEle->pCertContext;
|
||
|
|
||
|
if (pCurrent->dwCertEncodingType == pCertContext->dwCertEncodingType)
|
||
|
{
|
||
|
if (CertCompareCertificate
|
||
|
(pCertContext->dwCertEncodingType,
|
||
|
pCertContext->pCertInfo,
|
||
|
pCurrent->pCertInfo))
|
||
|
{
|
||
|
// We're replacing an existing element.
|
||
|
*pfReplacedExisting = TRUE;
|
||
|
CertFreeCertificateContext(pListEle->pCertContext);
|
||
|
pListEle->pCertContext = CertDuplicateCertificateContext(pCertContext);
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pListElePrev = pListEle;
|
||
|
}
|
||
|
|
||
|
// Didn't find the cert in the list, append it.
|
||
|
if (pListElePrev == NULL)
|
||
|
{
|
||
|
// Special case: this is the first cert we've added.
|
||
|
pListElePrev = new CertContextListEle;
|
||
|
if (pListElePrev == NULL)
|
||
|
goto MemoryErr;
|
||
|
pListEle = pListElePrev;
|
||
|
m_head = pListEle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pListElePrev->pNext = new CertContextListEle;
|
||
|
if (pListElePrev->pNext == NULL)
|
||
|
goto MemoryErr;
|
||
|
pListEle = pListElePrev->pNext;
|
||
|
}
|
||
|
|
||
|
pListEle->pCertContext = CertDuplicateCertificateContext(pCertContext);
|
||
|
pListEle->pNext = NULL;
|
||
|
|
||
|
CommonReturn:
|
||
|
return hr;
|
||
|
|
||
|
MemoryErr:
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto CommonReturn;
|
||
|
}
|
||
|
|
||
|
HRESULT CertContextList::SyncWithStore(HCERTSTORE hStore, DWORD dwFlags)
|
||
|
{
|
||
|
CertContextListEle * pListEle;
|
||
|
|
||
|
for (pListEle = m_head; pListEle != NULL; pListEle = pListEle->pNext)
|
||
|
{
|
||
|
if (!CertAddCertificateContextToStore
|
||
|
(hStore,
|
||
|
pListEle->pCertContext,
|
||
|
dwFlags,
|
||
|
NULL))
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|