Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1388 lines
44 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: selcert.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "global.hxx"
  11. #include <dbgdef.h>
  12. extern HINSTANCE HinstDll;
  13. extern HMODULE HmodRichEdit;
  14. #define MAX_SIZE_OF_COLUMNS 400
  15. static const HELPMAP helpmap[] = {
  16. {IDC_SELECTCERT_VIEWCERT_BUTTON,IDH_SELECTCERTIFICATE_VIEWCERT_BUTTON},
  17. {IDC_SELECTCERT_CERTLIST, IDH_SELECTCERTIFICATE_CERTIFICATE_LIST}
  18. };
  19. class CertContextList {
  20. public:
  21. CertContextList() : m_head(NULL) { }
  22. ~CertContextList();
  23. HRESULT Add(IN PCCERT_CONTEXT pCertContext,
  24. OUT BOOL *pfReplacedExisting) ;
  25. HRESULT SyncWithStore(HCERTSTORE hStore, DWORD dwFlags);
  26. private:
  27. typedef struct _CertContextListEle {
  28. PCCERT_CONTEXT pCertContext;
  29. struct _CertContextListEle * pNext;
  30. } CertContextListEle;
  31. CertContextListEle * m_head;
  32. };
  33. typedef struct _CERT_SELECT_HELPER
  34. {
  35. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
  36. PCCERT_CONTEXT pSelectedCert;
  37. DWORD rgdwSortParam[6];
  38. BOOL fCertListDblClick;
  39. CertContextList *pCertsFromDS;
  40. } CERT_SELECT_HELPER, *PCERT_SELECT_HELPER;
  41. //////////////////////////////////////////////////////////////////////////////////////
  42. //
  43. //////////////////////////////////////////////////////////////////////////////////////
  44. static void AddCertToList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp, PCCERT_CONTEXT pCertContext, int itemIndex)
  45. {
  46. LPWSTR pwszText;
  47. DWORD cbText;
  48. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  49. int subItemIndex;
  50. LV_ITEMW lvI;
  51. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
  52. pcsc = pviewhelp->pcsc;
  53. //
  54. // set up the fields in the list view item
  55. //
  56. lvI.mask = LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
  57. lvI.state = 0;
  58. lvI.stateMask = 0;
  59. lvI.iSubItem = 0;
  60. lvI.iImage = 0;
  61. lvI.lParam = (LPARAM) CertDuplicateCertificateContext(pCertContext);
  62. lvI.iItem = itemIndex;
  63. ListView_InsertItemU(hWndListView, &lvI);
  64. subItemIndex = 0;
  65. //
  66. // issued to
  67. //
  68. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
  69. {
  70. CertGetNameStringW(
  71. pCertContext,
  72. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  73. 0,//CERT_NAME_ISSUER_FLAG,
  74. NULL,
  75. szText,
  76. ARRAYSIZE(szText));
  77. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
  78. }
  79. //
  80. // issued by
  81. //
  82. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
  83. {
  84. CertGetNameStringW(
  85. pCertContext,
  86. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  87. CERT_NAME_ISSUER_FLAG,
  88. NULL,
  89. szText,
  90. ARRAYSIZE(szText));
  91. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
  92. }
  93. //
  94. // intended use
  95. //
  96. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
  97. {
  98. if (FormatEnhancedKeyUsageString(&pwszText, pCertContext, FALSE, FALSE))
  99. {
  100. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex, pwszText);
  101. free(pwszText);
  102. }
  103. subItemIndex++;
  104. }
  105. //
  106. // friendly name
  107. //
  108. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
  109. {
  110. cbText = 0;
  111. if (CertGetCertificateContextProperty( pCertContext,
  112. CERT_FRIENDLY_NAME_PROP_ID,
  113. NULL,
  114. &cbText) &&
  115. (NULL != (pwszText = (LPWSTR) malloc(cbText))))
  116. {
  117. CertGetCertificateContextProperty( pCertContext,
  118. CERT_FRIENDLY_NAME_PROP_ID,
  119. pwszText,
  120. &cbText);
  121. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
  122. free(pwszText);
  123. }
  124. else
  125. {
  126. LoadStringU(HinstDll, IDS_FRIENDLYNAME_NONE, szText, ARRAYSIZE(szText));
  127. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
  128. }
  129. }
  130. //
  131. // expiration
  132. //
  133. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
  134. {
  135. if (!FormatDateString(&pwszText, pCertContext->pCertInfo->NotAfter, FALSE, FALSE, hWndListView))
  136. {
  137. LoadStringU(HinstDll, IDS_NOTAVAILABLE, szText, ARRAYSIZE(szText));
  138. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
  139. }
  140. else
  141. {
  142. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
  143. free(pwszText);
  144. }
  145. }
  146. //
  147. // location
  148. //
  149. if (!(pcsc->dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
  150. {
  151. pwszText = (LPWSTR) GetStoreName(pCertContext->hCertStore, TRUE);
  152. if (pwszText == NULL)
  153. {
  154. LoadStringU(HinstDll, IDS_NOTAVAILABLE, szText, ARRAYSIZE(szText));
  155. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, szText);
  156. }
  157. else
  158. {
  159. ListView_SetItemTextU(hWndListView, itemIndex , subItemIndex++, pwszText);
  160. free(pwszText);
  161. }
  162. }
  163. }
  164. static int ReplaceCertInList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp, PCCERT_CONTEXT pCertContext)
  165. {
  166. int nIndex = -1;
  167. LV_ITEM lvitem;
  168. while (-1 != (nIndex = ListView_GetNextItem(hWndListView, nIndex, LVNI_ALL)))
  169. {
  170. //DSIE: Bug 420717
  171. memset(&lvitem, 0, sizeof(lvitem));
  172. lvitem.iItem = nIndex;
  173. lvitem.mask = LVIF_PARAM;
  174. if (ListView_GetItem(hWndListView, &lvitem))
  175. {
  176. PCCERT_CONTEXT pCurrent = (PCCERT_CONTEXT)lvitem.lParam;
  177. if (pCurrent->dwCertEncodingType == pCertContext->dwCertEncodingType)
  178. {
  179. if (CertCompareCertificate(pCertContext->dwCertEncodingType,
  180. pCertContext->pCertInfo,
  181. pCurrent->pCertInfo))
  182. {
  183. // Found a match, replace the certificate.
  184. CertFreeCertificateContext(pCurrent);
  185. ListView_DeleteItem(hWndListView, nIndex);
  186. // Now, add our new certificate at this index.
  187. AddCertToList(hWndListView, pviewhelp, pCertContext, nIndex);
  188. goto CommonReturn;
  189. }
  190. }
  191. }
  192. }
  193. // No match, nothing to replace, just append to the list.
  194. AddCertToList(hWndListView, pviewhelp, pCertContext, ListView_GetItemCount(hWndListView));
  195. CommonReturn:
  196. return nIndex;
  197. }
  198. BOOL SupportEncryptedFileSystem(PCCERT_CONTEXT pCertContext)
  199. {
  200. BOOL fSuccess = FALSE;
  201. DWORD cbUsage = 0;
  202. PCERT_ENHKEY_USAGE pUsage = NULL;
  203. if (!pCertContext)
  204. return FALSE;
  205. if (!CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &cbUsage))
  206. goto CleanUp;
  207. if (NULL == (pUsage = (PCERT_ENHKEY_USAGE) malloc(cbUsage)))
  208. goto CleanUp;
  209. if (!CertGetEnhancedKeyUsage(pCertContext, 0, pUsage, &cbUsage))
  210. goto CleanUp;
  211. if (0 == pUsage->cUsageIdentifier)
  212. {
  213. if (CRYPT_E_NOT_FOUND == GetLastError())
  214. {
  215. fSuccess = TRUE;
  216. }
  217. }
  218. else
  219. {
  220. for (DWORD i = 0; i < pUsage->cUsageIdentifier; i++)
  221. {
  222. if (0 == strcmp(szOID_KP_EFS, pUsage->rgpszUsageIdentifier[i]))
  223. {
  224. fSuccess = TRUE;
  225. goto CleanUp;
  226. }
  227. }
  228. }
  229. CleanUp:
  230. if (pUsage)
  231. free(pUsage);
  232. return fSuccess;
  233. }
  234. HRESULT AddFromDS(HWND hwndDlg, PCERT_SELECT_HELPER pviewhelp)
  235. {
  236. static const int SCOPE_INIT_COUNT = 1;
  237. IDsObjectPicker * pDsObjectPicker = NULL;
  238. IDataObject * pdo = NULL;
  239. DSOP_SCOPE_INIT_INFO aScopeInit[SCOPE_INIT_COUNT];
  240. DSOP_INIT_INFO InitInfo;
  241. UINT cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  242. HWND hWndListView = NULL;
  243. BOOL fGotStgMedium = FALSE;
  244. PDS_SELECTION_LIST pDsSelList = NULL;
  245. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL, NULL};
  246. FORMATETC formatetc = {(CLIPFORMAT) cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  247. HRESULT hr;
  248. HCERTSTORE hDSCertStore = NULL;
  249. PCCERT_CONTEXT pCertContext = NULL;
  250. PCCERT_CONTEXT pCertContextPrev = NULL;
  251. CertContextList * pCertContextList = NULL;
  252. WCHAR errorString[512];
  253. WCHAR errorTitle[512];
  254. BOOL fInitialSelectedCert = FALSE;
  255. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc = NULL;
  256. // Input validation:
  257. if (NULL == hwndDlg ||
  258. NULL == pviewhelp ||
  259. NULL == pviewhelp->pcsc ||
  260. NULL == pviewhelp->pCertsFromDS)
  261. return E_INVALIDARG;
  262. // Init:
  263. pcsc = pviewhelp->pcsc;
  264. pCertContextList = pviewhelp->pCertsFromDS;
  265. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  266. CoInitialize(NULL);
  267. hr = CoCreateInstance(CLSID_DsObjectPicker,
  268. NULL,
  269. CLSCTX_INPROC_SERVER,
  270. IID_IDsObjectPicker,
  271. (void **) &pDsObjectPicker);
  272. if (FAILED(hr) || NULL == pDsObjectPicker)
  273. goto ComError;
  274. // Initialize the DSOP_SCOPE_INIT_INFO array.
  275. ZeroMemory(aScopeInit, sizeof(DSOP_SCOPE_INIT_INFO) * SCOPE_INIT_COUNT);
  276. // Combine multiple scope types in a single array entry.
  277. aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  278. aScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
  279. | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  280. // Set uplevel and downlevel filters to include only computer objects.
  281. // Uplevel filters apply to both mixed and native modes.
  282. // Notice that the uplevel and downlevel flags are different.
  283. aScopeInit[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  284. aScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  285. // Initialize the DSOP_INIT_INFO structure.
  286. ZeroMemory(&InitInfo, sizeof(InitInfo));
  287. InitInfo.cbSize = sizeof(InitInfo);
  288. InitInfo.pwzTargetComputer = NULL; // Target is the local computer.
  289. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  290. InitInfo.aDsScopeInfos = aScopeInit;
  291. //InitInfo.flOptions = DSOP_FLAG_MULTISELECT;
  292. // You can call Initialize multiple times; last call wins.
  293. // Note that object picker makes its own copy of InitInfo.
  294. hr = pDsObjectPicker->Initialize(&InitInfo);
  295. if (FAILED(hr))
  296. goto ComError;
  297. // Invoke the modal dialog.
  298. hr = pDsObjectPicker->InvokeDialog(hwndDlg, &pdo);
  299. if (FAILED(hr))
  300. goto ComError;
  301. // User pressed Cancel.
  302. if (hr == S_FALSE)
  303. {
  304. hr = E_ABORT;
  305. goto cleanup;
  306. }
  307. // Get the global memory block containing the user's selections.
  308. hr = pdo->GetData(&formatetc, &stgmedium);
  309. if (FAILED(hr))
  310. goto ComError;
  311. fGotStgMedium = TRUE;
  312. // Retrieve pointer to DS_SELECTION_LIST structure.
  313. pDsSelList = (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
  314. if (!pDsSelList)
  315. goto ComError;
  316. // Loop through DS_SELECTION array of selected objects.
  317. for (ULONG i = 0; i < pDsSelList->cItems; i++)
  318. {
  319. WCHAR pwszLdapUrl[2048];
  320. LPWSTR pTemp = pDsSelList->aDsSelection[i].pwzADsPath;
  321. BOOL fReplacedExisting;
  322. BOOL fHasEFSCerts = FALSE;
  323. // Now is the time to get the certificate
  324. LPCWSTR szCertAttr = L"?userCertificate";
  325. // Check if our buffer is too small to hold the query.
  326. if (wcslen(pTemp) + wcslen(szCertAttr) + 1 > (sizeof(pwszLdapUrl) / sizeof(pwszLdapUrl[0])))
  327. goto UnexpectedErr;
  328. wcscpy(pwszLdapUrl, pTemp);
  329. wcscat(pwszLdapUrl, szCertAttr);
  330. // Now open the DS store using LDAP provider.
  331. hDSCertStore = CertOpenStore(sz_CERT_STORE_PROV_LDAP,
  332. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  333. NULL,
  334. CERT_STORE_READONLY_FLAG,
  335. (void*) pwszLdapUrl);
  336. if (NULL == hDSCertStore)
  337. goto CertCliError;
  338. // We get the certificate store
  339. pCertContext = NULL;
  340. pCertContextPrev = NULL;
  341. int nItemIndex;
  342. while (NULL != (pCertContext = CertEnumCertificatesInStore(hDSCertStore, pCertContextPrev)))
  343. {
  344. // Apply our filter callback function to see if we should display this certificate.
  345. BOOL fAllowCert = FALSE;
  346. if (pcsc->pFilterCallback)
  347. fAllowCert = (*(pcsc->pFilterCallback))(pCertContext, &fInitialSelectedCert, pcsc->pvCallbackData);
  348. if (!fAllowCert)
  349. fAllowCert = SupportEncryptedFileSystem(pCertContext);
  350. if (fAllowCert)
  351. {
  352. fHasEFSCerts = TRUE;
  353. if (S_OK != (hr = pCertContextList->Add(pCertContext, &fReplacedExisting)))
  354. goto ErrorReturn;
  355. nItemIndex = ReplaceCertInList(hWndListView, pviewhelp, pCertContext);
  356. // if the select cert dialog caller said that this should be the initially
  357. // selected cert then make it so.
  358. if (fInitialSelectedCert)
  359. ListView_SetItemState(hWndListView, nItemIndex, LVIS_SELECTED, LVIS_SELECTED);
  360. }
  361. pCertContextPrev = pCertContext;
  362. }
  363. // We didn't reach the end of the enumeration. This is an error.
  364. if (GetLastError() != CRYPT_E_NOT_FOUND)
  365. goto CertCliError;
  366. // We didn't find any EFS certs: display an error message and pop up the window again.
  367. if (!fHasEFSCerts)
  368. goto NoEfsError;
  369. }
  370. hr = S_OK;
  371. cleanup:
  372. if (hDSCertStore)
  373. {
  374. CertCloseStore(hDSCertStore, 0);
  375. }
  376. if (NULL != pCertContext)
  377. {
  378. CertFreeCertificateContext(pCertContext);
  379. }
  380. if (pDsSelList)
  381. {
  382. GlobalUnlock(stgmedium.hGlobal);
  383. }
  384. if (fGotStgMedium)
  385. {
  386. ReleaseStgMedium(&stgmedium);
  387. }
  388. if (pdo)
  389. {
  390. pdo->Release();
  391. }
  392. if (pDsObjectPicker)
  393. {
  394. pDsObjectPicker->Release();
  395. }
  396. CoUninitialize();
  397. return hr;
  398. ErrorReturn:
  399. {
  400. WCHAR wszText[MAX_STRING_SIZE];
  401. WCHAR errorTitle2[MAX_STRING_SIZE];
  402. LPWSTR pwszErrorMsg = NULL;
  403. //get the text string
  404. if(LoadStringU(HinstDll, IDS_INTERNAL_ERROR, wszText, sizeof(wszText) / sizeof(wszText[0])))
  405. {
  406. if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  407. FORMAT_MESSAGE_FROM_SYSTEM |
  408. FORMAT_MESSAGE_IGNORE_INSERTS,
  409. NULL,
  410. hr,
  411. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  412. (LPWSTR) &pwszErrorMsg,
  413. 0,
  414. NULL))
  415. {
  416. if (LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle2, ARRAYSIZE(errorTitle2))) {
  417. MessageBoxU(hwndDlg, pwszErrorMsg, errorTitle2, MB_ICONERROR|MB_OK|MB_APPLMODAL);
  418. }
  419. }
  420. }
  421. if (NULL != pwszErrorMsg) { LocalFree(pwszErrorMsg); }
  422. }
  423. goto cleanup;
  424. CertCliError:
  425. hr = HRESULT_FROM_WIN32(GetLastError());
  426. goto ErrorReturn;
  427. ComError:
  428. goto ErrorReturn;
  429. NoEfsError:
  430. LoadStringU(HinstDll, IDS_SELECT_CERT_NO_CERT_ERROR, errorString, ARRAYSIZE(errorString));
  431. if (pcsc->szTitle != NULL)
  432. {
  433. MessageBoxU(hwndDlg, errorString, pcsc->szTitle, MB_OK | MB_ICONWARNING);
  434. }
  435. else
  436. {
  437. LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle, ARRAYSIZE(errorTitle));
  438. MessageBoxU(hwndDlg, errorString, errorTitle, MB_OK | MB_ICONWARNING);
  439. }
  440. hr = AddFromDS(hwndDlg, pviewhelp);
  441. goto cleanup;
  442. UnexpectedErr:
  443. hr = E_UNEXPECTED;
  444. goto ErrorReturn;
  445. }
  446. //////////////////////////////////////////////////////////////////////////////////////
  447. //
  448. //////////////////////////////////////////////////////////////////////////////////////
  449. static void AddCertsToList(HWND hWndListView, PCERT_SELECT_HELPER pviewhelp)
  450. {
  451. DWORD i;
  452. PCCERT_CONTEXT pCertContext;
  453. int itemIndex = 0;
  454. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
  455. BOOL fInitialSelectedCert = FALSE;
  456. pcsc = pviewhelp->pcsc;
  457. //
  458. // loop for each store and display the certs in each store
  459. //
  460. for (i=0; i<pcsc->cDisplayStores; i++)
  461. {
  462. //
  463. // loop for each cert in the store
  464. //
  465. pCertContext = NULL;
  466. while (NULL != (pCertContext = CertEnumCertificatesInStore(pcsc->rghDisplayStores[i], pCertContext)))
  467. {
  468. fInitialSelectedCert = FALSE;
  469. if ((pcsc->pFilterCallback == NULL) ||
  470. ((*(pcsc->pFilterCallback))(pCertContext, &fInitialSelectedCert, pcsc->pvCallbackData) == TRUE))
  471. {
  472. AddCertToList(hWndListView, pviewhelp, pCertContext, itemIndex);
  473. //
  474. // if the select cert dialog caller said that this should be the initially
  475. // selected cert then make it so.
  476. //
  477. if (fInitialSelectedCert)
  478. {
  479. ListView_SetItemState(hWndListView, itemIndex, LVIS_SELECTED, LVIS_SELECTED);
  480. }
  481. itemIndex++;
  482. }
  483. }
  484. }
  485. }
  486. //////////////////////////////////////////////////////////////////////////////////////
  487. //
  488. //////////////////////////////////////////////////////////////////////////////////////
  489. static int CalculateColumnWidth(DWORD dwDontUseColumn)
  490. {
  491. int numColumns = 0;
  492. if (!(dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
  493. {
  494. numColumns++;
  495. }
  496. if (!(dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
  497. {
  498. numColumns++;
  499. }
  500. if (!(dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
  501. {
  502. numColumns++;
  503. }
  504. if (!(dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
  505. {
  506. numColumns++;
  507. }
  508. if (!(dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
  509. {
  510. numColumns++;
  511. }
  512. if (!(dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
  513. {
  514. numColumns++;
  515. }
  516. if (numColumns >= 2)
  517. {
  518. return (MAX_SIZE_OF_COLUMNS / numColumns);
  519. }
  520. else
  521. {
  522. return MAX_SIZE_OF_COLUMNS;
  523. }
  524. }
  525. //////////////////////////////////////////////////////////////////////////////////////
  526. //
  527. //////////////////////////////////////////////////////////////////////////////////////
  528. INT_PTR APIENTRY SelectCertDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  529. {
  530. WCHAR szText[CRYPTUI_MAX_STRING_SIZE];
  531. HWND hWndListView;
  532. LV_COLUMNW lvC;
  533. int iCol = 0;
  534. LV_ITEMW lvI;
  535. int listIndex;
  536. LPNMLISTVIEW pnmv;
  537. PCERT_SELECT_HELPER pviewhelp;
  538. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc;
  539. WCHAR errorString[CRYPTUI_MAX_STRING_SIZE];
  540. WCHAR errorTitle[CRYPTUI_MAX_STRING_SIZE];
  541. HWND hwnd;
  542. HIMAGELIST hIml;
  543. DWORD dwSortParam;
  544. int SortParamIndex;
  545. switch ( msg ) {
  546. case WM_INITDIALOG:
  547. pviewhelp = (PCERT_SELECT_HELPER) lParam;
  548. SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR) pviewhelp);
  549. pcsc = pviewhelp->pcsc;
  550. //
  551. // set the dialog title and the display string
  552. //
  553. if (pcsc->szTitle != NULL)
  554. {
  555. SetWindowTextU(hwndDlg, pcsc->szTitle);
  556. }
  557. if (pcsc->szDisplayString != NULL)
  558. {
  559. SetDlgItemTextU(hwndDlg, IDC_SELECTCERT_DISPLAYSTRING, pcsc->szDisplayString);
  560. }
  561. else
  562. {
  563. if (pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT)
  564. {
  565. LoadStringU(HinstDll, IDS_SELECT_MULTIPLE_CERT_DEFAULT, szText, ARRAYSIZE(szText));
  566. }
  567. else
  568. {
  569. LoadStringU(HinstDll, IDS_SELECT_CERT_DEFAULT, szText, ARRAYSIZE(szText));
  570. }
  571. SetDlgItemTextU(hwndDlg, IDC_SELECTCERT_DISPLAYSTRING, szText);
  572. }
  573. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  574. //
  575. // initialize the image list for the list view
  576. //
  577. hIml = ImageList_LoadImage(HinstDll, MAKEINTRESOURCE(IDB_CERT), 0, 1, RGB(255,0,255), IMAGE_BITMAP, 0);
  578. ListView_SetImageList(hWndListView, hIml, LVSIL_SMALL);
  579. //
  580. // add the colums to the list view
  581. //
  582. lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;// | LVCF_SUBITEM;
  583. lvC.fmt = LVCFMT_LEFT; // Left-align the column.
  584. lvC.pszText = szText; // The text for the column.
  585. lvC.cx = CalculateColumnWidth(pviewhelp->pcsc->dwDontUseColumn);
  586. memset(&(pviewhelp->rgdwSortParam[0]), 0, ARRAYSIZE(pviewhelp->rgdwSortParam));
  587. SortParamIndex = 0;
  588. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDTO_COLUMN))
  589. {
  590. LoadStringU(HinstDll, IDS_ISSUEDTO2, szText, ARRAYSIZE(szText));
  591. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  592. {
  593. // error
  594. }
  595. pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND;
  596. }
  597. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_ISSUEDBY_COLUMN))
  598. {
  599. LoadStringU(HinstDll, IDS_ISSUEDBY2, szText, ARRAYSIZE(szText));
  600. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  601. {
  602. // error
  603. }
  604. pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND;
  605. }
  606. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_INTENDEDUSE_COLUMN))
  607. {
  608. LoadStringU(HinstDll, IDS_INTENDED_PURPOSE, szText, ARRAYSIZE(szText));
  609. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  610. {
  611. // error
  612. }
  613. pviewhelp->rgdwSortParam[SortParamIndex++] =SORT_COLUMN_PURPOSE | SORT_COLUMN_DESCEND;
  614. }
  615. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_FRIENDLYNAME_COLUMN))
  616. {
  617. LoadStringU(HinstDll, IDS_CERTIFICATE_NAME, szText, ARRAYSIZE(szText));
  618. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  619. {
  620. // error
  621. }
  622. pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_NAME | SORT_COLUMN_DESCEND;
  623. }
  624. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_EXPIRATION_COLUMN))
  625. {
  626. LoadStringU(HinstDll, IDS_EXPIRATION_DATE, szText, ARRAYSIZE(szText));
  627. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  628. {
  629. // error
  630. }
  631. pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND;
  632. }
  633. if (!(pviewhelp->pcsc->dwDontUseColumn & CRYPTUI_SELECT_LOCATION_COLUMN))
  634. {
  635. LoadStringU(HinstDll, IDS_LOCATION, szText, ARRAYSIZE(szText));
  636. if (ListView_InsertColumnU(hWndListView, iCol++, &lvC) == -1)
  637. {
  638. // error
  639. }
  640. pviewhelp->rgdwSortParam[SortParamIndex++] = SORT_COLUMN_LOCATION | SORT_COLUMN_DESCEND;
  641. }
  642. AddCertsToList(hWndListView, pviewhelp);
  643. //
  644. // if there is no cert selected initially disable the "view cert button"
  645. //
  646. if (ListView_GetSelectedCount(hWndListView) == 0)
  647. {
  648. EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), FALSE);
  649. }
  650. //
  651. // set the style in the list view so that it highlights an entire line
  652. //
  653. SendMessageA(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  654. #if (1) // DSIE: bug 338852.
  655. HWND hwndFindUser;
  656. if (hwndFindUser = GetDlgItem(hwndDlg, IDC_SELECTCERT_ADDFROMDS_BUTTON))
  657. {
  658. LPBYTE pDCName = NULL;
  659. DWORD dwError = NetGetDCName(NULL, NULL, &pDCName);
  660. if (NERR_Success == dwError)
  661. {
  662. NetApiBufferFree(pDCName);
  663. }
  664. else
  665. {
  666. EnableWindow(hwndFindUser, FALSE);
  667. }
  668. }
  669. #endif
  670. ListView_SetItemState(hWndListView,
  671. 0,
  672. LVIS_FOCUSED | LVIS_SELECTED,
  673. LVIS_FOCUSED | LVIS_SELECTED);
  674. SetFocus(hWndListView);
  675. break;
  676. case WM_NOTIFY:
  677. pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
  678. pcsc = pviewhelp->pcsc;
  679. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  680. switch (((NMHDR FAR *) lParam)->code)
  681. {
  682. case NM_DBLCLK:
  683. switch (((NMHDR FAR *) lParam)->idFrom)
  684. {
  685. case IDC_SELECTCERT_CERTLIST:
  686. if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON)))
  687. {
  688. pviewhelp->fCertListDblClick = TRUE;
  689. SendMessage(
  690. hwndDlg,
  691. WM_COMMAND,
  692. MAKELONG(IDC_SELECTCERT_VIEWCERT_BUTTON, BN_CLICKED),
  693. (LPARAM) GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON));
  694. }
  695. break;
  696. }
  697. break;
  698. case LVN_ITEMCHANGING:
  699. pnmv = (LPNMLISTVIEW) lParam;
  700. switch (((NMHDR FAR *) lParam)->idFrom)
  701. {
  702. case IDC_SELECTCERT_CERTLIST:
  703. if (!(pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT))
  704. {
  705. if (pnmv->uNewState & LVIS_SELECTED)
  706. {
  707. ListView_SetItemState(
  708. hWndListView,
  709. ListView_GetNextItem(hWndListView, -1, LVNI_SELECTED),
  710. ~LVIS_SELECTED,
  711. LVIS_SELECTED);
  712. EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), TRUE);
  713. }
  714. }
  715. break;
  716. }
  717. break;
  718. case LVN_ITEMCHANGED:
  719. pnmv = (LPNMLISTVIEW) lParam;
  720. switch (((NMHDR FAR *) lParam)->idFrom)
  721. {
  722. case IDC_SELECTCERT_CERTLIST:
  723. if (ListView_GetSelectedCount(hWndListView) == 1)
  724. {
  725. EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), TRUE);
  726. }
  727. else
  728. {
  729. EnableWindow(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON), FALSE);
  730. }
  731. }
  732. break;
  733. case NM_SETFOCUS:
  734. switch (((NMHDR FAR *) lParam)->idFrom)
  735. {
  736. case IDC_SELECTCERT_CERTLIST:
  737. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  738. if ((ListView_GetItemCount(hWndListView) != 0) &&
  739. (ListView_GetNextItem(hWndListView, -1, LVNI_SELECTED) == -1))
  740. {
  741. memset(&lvI, 0, sizeof(lvI));
  742. lvI.mask = LVIF_STATE;
  743. lvI.iItem = 0;
  744. lvI.state = LVIS_FOCUSED;
  745. lvI.stateMask = LVIS_FOCUSED;
  746. ListView_SetItem(hWndListView, &lvI);
  747. }
  748. break;
  749. }
  750. break;
  751. case LVN_COLUMNCLICK:
  752. pnmv = (NM_LISTVIEW FAR *) lParam;
  753. //
  754. // get the column number
  755. //
  756. dwSortParam = 0;
  757. switch (pnmv->iSubItem)
  758. {
  759. case 0:
  760. case 1:
  761. case 2:
  762. case 3:
  763. case 4:
  764. case 5:
  765. dwSortParam = pviewhelp->rgdwSortParam[pnmv->iSubItem];
  766. break;
  767. default:
  768. dwSortParam = 0;
  769. break;
  770. }
  771. if (0 != dwSortParam)
  772. {
  773. //
  774. // flip the ascend ording
  775. //
  776. if (dwSortParam & SORT_COLUMN_ASCEND)
  777. {
  778. dwSortParam &= 0x0000FFFF;
  779. dwSortParam |= SORT_COLUMN_DESCEND;
  780. }
  781. else
  782. {
  783. if (dwSortParam & SORT_COLUMN_DESCEND)
  784. {
  785. dwSortParam &= 0x0000FFFF;
  786. dwSortParam |= SORT_COLUMN_ASCEND;
  787. }
  788. }
  789. //
  790. // sort the column
  791. //
  792. SendDlgItemMessage(hwndDlg,
  793. IDC_SELECTCERT_CERTLIST,
  794. LVM_SORTITEMS,
  795. (WPARAM) (LPARAM) dwSortParam,
  796. (LPARAM) (PFNLVCOMPARE)CompareCertificate);
  797. pviewhelp->rgdwSortParam[pnmv->iSubItem] = dwSortParam;
  798. }
  799. break;
  800. }
  801. break;
  802. case WM_COMMAND:
  803. pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
  804. pcsc = pviewhelp->pcsc;
  805. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  806. switch (LOWORD(wParam))
  807. {
  808. case IDC_SELECTCERT_ADDFROMDS_BUTTON:
  809. {
  810. HRESULT hr = AddFromDS(hwndDlg, pviewhelp);
  811. if (FAILED(hr))
  812. {
  813. // Error
  814. }
  815. break;
  816. }
  817. case IDC_SELECTCERT_VIEWCERT_BUTTON:
  818. CRYPTUI_VIEWCERTIFICATE_STRUCTW cvps;
  819. BOOL fPropertiesChanged;
  820. listIndex = ListView_GetNextItem(
  821. hWndListView,
  822. -1,
  823. LVNI_SELECTED
  824. );
  825. if (listIndex != -1)
  826. {
  827. memset(&lvI, 0, sizeof(lvI));
  828. lvI.iItem = listIndex;
  829. lvI.mask = LVIF_PARAM;
  830. if (ListView_GetItemU(hWndListView, &lvI))
  831. {
  832. //
  833. // if the caller handed in a callback call them to see if they
  834. // want to handle the display of the cert, otherwise display the cert
  835. //
  836. if ((pcsc->pDisplayCallback != NULL) &&
  837. ((*(pcsc->pDisplayCallback))((PCCERT_CONTEXT) lvI.lParam, hwndDlg, pcsc->pvCallbackData) == TRUE))
  838. {
  839. //
  840. // set the fPropertiesChanged bool to true so that the cert will
  841. // get refreshed in the display. this doesn't hurt anything even
  842. // if the cert didn't change
  843. //
  844. fPropertiesChanged = TRUE;
  845. }
  846. else
  847. {
  848. memset(&cvps, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW));
  849. cvps.dwSize = sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW);
  850. cvps.hwndParent = hwndDlg;
  851. cvps.pCertContext = (PCCERT_CONTEXT) lvI.lParam;
  852. cvps.cStores = pviewhelp->pcsc->cStores;
  853. cvps.rghStores = pviewhelp->pcsc->rghStores;
  854. cvps.cPropSheetPages = pviewhelp->pcsc->cPropSheetPages;
  855. cvps.rgPropSheetPages = pviewhelp->pcsc->rgPropSheetPages;
  856. CryptUIDlgViewCertificateW(&cvps, &fPropertiesChanged);
  857. }
  858. //
  859. // if the properties changed then refresh the cert in the list
  860. //
  861. if (fPropertiesChanged)
  862. {
  863. ListView_DeleteItem(hWndListView, listIndex);
  864. AddCertToList(hWndListView, pviewhelp, (PCCERT_CONTEXT) lvI.lParam, listIndex);
  865. ListView_SetItemState(hWndListView, listIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  866. }
  867. if (!pviewhelp->fCertListDblClick)
  868. {
  869. SetFocus(GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON));
  870. }
  871. pviewhelp->fCertListDblClick = FALSE;
  872. }
  873. }
  874. break;
  875. case IDOK:
  876. listIndex = ListView_GetNextItem(
  877. hWndListView,
  878. -1,
  879. LVNI_SELECTED
  880. );
  881. if (listIndex != -1)
  882. {
  883. memset(&lvI, 0, sizeof(lvI));
  884. lvI.iItem = listIndex;
  885. lvI.mask = LVIF_PARAM;
  886. if (!(pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT))
  887. {
  888. if (ListView_GetItemU(hWndListView, &lvI))
  889. {
  890. pviewhelp->pSelectedCert = CertDuplicateCertificateContext((PCCERT_CONTEXT) lvI.lParam);
  891. }
  892. }
  893. else
  894. {
  895. if (ListView_GetItemU(hWndListView, &lvI))
  896. {
  897. CertAddCertificateContextToStore(
  898. pcsc->hSelectedCertStore,
  899. (PCCERT_CONTEXT) lvI.lParam,
  900. CERT_STORE_ADD_ALWAYS,
  901. NULL);
  902. }
  903. while (-1 != (listIndex = ListView_GetNextItem(
  904. hWndListView,
  905. listIndex,
  906. LVNI_SELECTED
  907. )))
  908. {
  909. lvI.iItem = listIndex;
  910. if (ListView_GetItemU(hWndListView, &lvI))
  911. {
  912. CertAddCertificateContextToStore(
  913. pcsc->hSelectedCertStore,
  914. (PCCERT_CONTEXT) lvI.lParam,
  915. CERT_STORE_ADD_ALWAYS,
  916. NULL);
  917. }
  918. }
  919. }
  920. }
  921. else
  922. {
  923. LoadStringU(HinstDll, IDS_SELECT_CERT_ERROR, errorString, ARRAYSIZE(errorString));
  924. if (pcsc->szTitle != NULL)
  925. {
  926. MessageBoxU(hwndDlg, errorString, pcsc->szTitle, MB_OK | MB_ICONWARNING);
  927. }
  928. else
  929. {
  930. LoadStringU(HinstDll, IDS_SELECT_CERTIFICATE_TITLE, errorTitle, ARRAYSIZE(errorTitle));
  931. MessageBoxU(hwndDlg, errorString, errorTitle, MB_OK | MB_ICONWARNING);
  932. }
  933. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LRESULT)TRUE);
  934. return TRUE;
  935. }
  936. EndDialog(hwndDlg, NULL);
  937. break;
  938. case IDCANCEL:
  939. EndDialog(hwndDlg, NULL);
  940. break;
  941. }
  942. break;
  943. case WM_DESTROY:
  944. pviewhelp = (PCERT_SELECT_HELPER) GetWindowLongPtr(hwndDlg, DWLP_USER);
  945. hWndListView = GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST);
  946. memset(&lvI, 0, sizeof(lvI));
  947. lvI.iItem = ListView_GetItemCount(hWndListView) - 1;
  948. lvI.mask = LVIF_PARAM;
  949. while (lvI.iItem >= 0)
  950. {
  951. if (ListView_GetItemU(hWndListView, &lvI))
  952. {
  953. CertFreeCertificateContext((PCCERT_CONTEXT) lvI.lParam);
  954. }
  955. lvI.iItem--;
  956. }
  957. break;
  958. case WM_HELP:
  959. case WM_CONTEXTMENU:
  960. if (msg == WM_HELP)
  961. {
  962. hwnd = GetDlgItem(hwndDlg, ((LPHELPINFO)lParam)->iCtrlId);
  963. }
  964. else
  965. {
  966. hwnd = (HWND) wParam;
  967. }
  968. if ((hwnd != GetDlgItem(hwndDlg, IDOK)) &&
  969. (hwnd != GetDlgItem(hwndDlg, IDCANCEL)) &&
  970. (hwnd != GetDlgItem(hwndDlg, IDC_SELECTCERT_VIEWCERT_BUTTON)) &&
  971. (hwnd != GetDlgItem(hwndDlg, IDC_SELECTCERT_CERTLIST)))
  972. {
  973. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LRESULT)TRUE);
  974. return TRUE;
  975. }
  976. else
  977. {
  978. return OnContextHelp(hwndDlg, msg, wParam, lParam, helpmap);
  979. }
  980. }
  981. return FALSE;
  982. }
  983. //////////////////////////////////////////////////////////////////////////////////////
  984. //
  985. //////////////////////////////////////////////////////////////////////////////////////
  986. PCCERT_CONTEXT
  987. WINAPI
  988. CryptUIDlgSelectCertificateW(
  989. PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
  990. )
  991. {
  992. CERT_SELECT_HELPER viewhelper;
  993. WORD wDialogID;
  994. if (CommonInit() == FALSE)
  995. {
  996. return NULL;
  997. }
  998. if ((pcsc->dwSize != sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCTW)) &&
  999. (pcsc->dwSize != offsetof(CRYPTUI_SELECTCERTIFICATE_STRUCTW, hSelectedCertStore))) {
  1000. SetLastError(E_INVALIDARG);
  1001. return FALSE;
  1002. }
  1003. wDialogID =
  1004. pcsc->dwFlags & CRYPTUI_SELECTCERT_ADDFROMDS ?
  1005. IDD_SELECTCERT_DIALOG_WITH_DSPICKER :
  1006. IDD_SELECTCERT_DIALOG;
  1007. viewhelper.pcsc = pcsc;
  1008. viewhelper.pSelectedCert = NULL;
  1009. viewhelper.fCertListDblClick = FALSE;
  1010. viewhelper.pCertsFromDS = new CertContextList;
  1011. if (NULL == viewhelper.pCertsFromDS)
  1012. {
  1013. SetLastError(E_OUTOFMEMORY);
  1014. return FALSE;
  1015. }
  1016. if (DialogBoxParamU(
  1017. HinstDll,
  1018. (LPWSTR) MAKEINTRESOURCE(wDialogID),
  1019. (pcsc->hwndParent != NULL) ? pcsc->hwndParent : GetDesktopWindow(),
  1020. SelectCertDialogProc,
  1021. (LPARAM) &viewhelper) != -1)
  1022. {
  1023. SetLastError(0);
  1024. }
  1025. delete viewhelper.pCertsFromDS;
  1026. if (pcsc->dwFlags & CRYPTUI_SELECTCERT_MULTISELECT)
  1027. {
  1028. return NULL;
  1029. }
  1030. else
  1031. {
  1032. return(viewhelper.pSelectedCert);
  1033. }
  1034. }
  1035. //////////////////////////////////////////////////////////////////////////////////////
  1036. //
  1037. //////////////////////////////////////////////////////////////////////////////////////
  1038. PCCERT_CONTEXT
  1039. WINAPI
  1040. CryptUIDlgSelectCertificateA(
  1041. PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
  1042. )
  1043. {
  1044. CRYPTUI_SELECTCERTIFICATE_STRUCTW cscW;
  1045. PCCERT_CONTEXT pReturnCert = NULL;
  1046. memcpy(&cscW, pcsc, sizeof(cscW));
  1047. if (!ConvertToPropPageW(
  1048. pcsc->rgPropSheetPages,
  1049. pcsc->cPropSheetPages,
  1050. &(cscW.rgPropSheetPages)))
  1051. {
  1052. return NULL;
  1053. }
  1054. if (pcsc->szTitle)
  1055. {
  1056. cscW.szTitle = CertUIMkWStr(pcsc->szTitle);
  1057. }
  1058. if (pcsc->szDisplayString)
  1059. {
  1060. cscW.szDisplayString = CertUIMkWStr(pcsc->szDisplayString);
  1061. }
  1062. pReturnCert = CryptUIDlgSelectCertificateW(&cscW);
  1063. FreePropSheetPagesW((LPPROPSHEETPAGEW) cscW.rgPropSheetPages, cscW.cPropSheetPages);
  1064. if (cscW.szTitle)
  1065. {
  1066. free((void *) cscW.szTitle);
  1067. }
  1068. if (cscW.szDisplayString)
  1069. {
  1070. free((void *) cscW.szDisplayString);
  1071. }
  1072. return(pReturnCert);
  1073. }
  1074. ////////////////////////////////////////////////////////////
  1075. //
  1076. // Implementation of utility class: CertContextList
  1077. //
  1078. ////////////////////////////////////////////////////////////
  1079. CertContextList::~CertContextList()
  1080. {
  1081. CertContextListEle *pListEle;
  1082. CertContextListEle *pListEleNext;
  1083. for (pListEle = m_head; pListEle != NULL; pListEle = pListEleNext)
  1084. {
  1085. pListEleNext = pListEle->pNext;
  1086. if (pListEle->pCertContext != NULL) { CertFreeCertificateContext(pListEle->pCertContext); }
  1087. delete pListEle;
  1088. }
  1089. }
  1090. HRESULT CertContextList::Add(IN PCCERT_CONTEXT pCertContext,
  1091. OUT BOOL *pfReplacedExisting)
  1092. {
  1093. HRESULT hr = S_OK;
  1094. CertContextListEle *pListEle = NULL;
  1095. CertContextListEle *pListElePrev = NULL;
  1096. if (pCertContext == NULL || pfReplacedExisting == NULL)
  1097. return E_INVALIDARG;
  1098. for (pListEle = m_head; pListEle != NULL; pListEle = pListEle->pNext)
  1099. {
  1100. PCCERT_CONTEXT pCurrent = pListEle->pCertContext;
  1101. if (pCurrent->dwCertEncodingType == pCertContext->dwCertEncodingType)
  1102. {
  1103. if (CertCompareCertificate
  1104. (pCertContext->dwCertEncodingType,
  1105. pCertContext->pCertInfo,
  1106. pCurrent->pCertInfo))
  1107. {
  1108. // We're replacing an existing element.
  1109. *pfReplacedExisting = TRUE;
  1110. CertFreeCertificateContext(pListEle->pCertContext);
  1111. pListEle->pCertContext = CertDuplicateCertificateContext(pCertContext);
  1112. goto CommonReturn;
  1113. }
  1114. }
  1115. pListElePrev = pListEle;
  1116. }
  1117. // Didn't find the cert in the list, append it.
  1118. if (pListElePrev == NULL)
  1119. {
  1120. // Special case: this is the first cert we've added.
  1121. pListElePrev = new CertContextListEle;
  1122. if (pListElePrev == NULL)
  1123. goto MemoryErr;
  1124. pListEle = pListElePrev;
  1125. m_head = pListEle;
  1126. }
  1127. else
  1128. {
  1129. pListElePrev->pNext = new CertContextListEle;
  1130. if (pListElePrev->pNext == NULL)
  1131. goto MemoryErr;
  1132. pListEle = pListElePrev->pNext;
  1133. }
  1134. pListEle->pCertContext = CertDuplicateCertificateContext(pCertContext);
  1135. pListEle->pNext = NULL;
  1136. CommonReturn:
  1137. return hr;
  1138. MemoryErr:
  1139. hr = E_OUTOFMEMORY;
  1140. goto CommonReturn;
  1141. }
  1142. HRESULT CertContextList::SyncWithStore(HCERTSTORE hStore, DWORD dwFlags)
  1143. {
  1144. CertContextListEle * pListEle;
  1145. for (pListEle = m_head; pListEle != NULL; pListEle = pListEle->pNext)
  1146. {
  1147. if (!CertAddCertificateContextToStore
  1148. (hStore,
  1149. pListEle->pCertContext,
  1150. dwFlags,
  1151. NULL))
  1152. return HRESULT_FROM_WIN32(GetLastError());
  1153. }
  1154. return S_OK;
  1155. }