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.

1018 lines
31 KiB

  1. //
  2. // File: select.cpp
  3. //
  4. // Description: This file contains the implmentation code for the
  5. // "Certificate Select" dialog.
  6. //
  7. //
  8. // M00BUG -- Mutli-Select is not implemented
  9. //
  10. #include "pch.hxx"
  11. #include "demand.h"
  12. #define REIDK_PRIVATE TRUE
  13. #define ARRAYSIZE(_rg) (sizeof(_rg)/sizeof(_rg[0]))
  14. #pragma warning (disable: 4201) // nameless struct/union
  15. #pragma warning (disable: 4514) // remove inline functions
  16. #pragma warning (disable: 4127) // conditional expression is constant
  17. //#include <wchar.h>
  18. #ifdef MAC
  19. #include <stdio.h>
  20. #else // !MAC
  21. HMODULE HmodRichEdit = NULL;
  22. #endif // !MAC
  23. HINSTANCE HinstDll;
  24. BOOL FIsWin95 = TRUE;
  25. const HELPMAP RgctxSelect[] = {
  26. {IDC_CS_CERTLIST, IDH_CS_CERTLIST},
  27. {IDC_CS_PROPERTIES, IDH_CS_PROPERTIES},
  28. {IDC_CS_ALGORITHM, IDH_CS_ALGORITHM}};
  29. #ifdef WIN16
  30. #define LPCDLGTEMPLATE_X HGLOBAL
  31. #else
  32. #define LPCDLGTEMPLATE_X LPCDLGTEMPLATE
  33. #endif
  34. //
  35. // Generic DLL Main function, we need to get our own hinstance handle.
  36. //
  37. // We don't need to get thread attaches however.
  38. #ifndef WIN16
  39. #ifdef MAC
  40. BOOL WINAPI FormatPKIXEmailProtection(
  41. DWORD /*dwCertEncodingType*/, DWORD /*dwFormatType*/,
  42. DWORD /*dwFormatStrType*/, void * /*pFormatStruct*/,
  43. LPCSTR /*lpszStructType*/, const BYTE * /*pbEncoded*/,
  44. DWORD /*cbEncoded*/, void * pbFormat, DWORD * pcbFormat);
  45. static const CRYPT_OID_FUNC_ENTRY SpcFormatFuncTable[] =
  46. {
  47. szOID_PKIX_KP_EMAIL_PROTECTION, FormatPKIXEmailProtection,
  48. };
  49. #define SPC_FORMAT_FUNC_COUNT (sizeof(SpcFormatFuncTable) / sizeof(SpcFormatFuncTable[0]))
  50. BOOL WINAPI CryptDlgASNDllMain(HINSTANCE hInst, ULONG ulReason,
  51. LPVOID)
  52. {
  53. BOOL fRet = TRUE;
  54. switch (ulReason) {
  55. case DLL_PROCESS_ATTACH:
  56. fRet = CryptInstallOIDFunctionAddress(hInst, X509_ASN_ENCODING,
  57. CRYPT_OID_FORMAT_OBJECT_FUNC,
  58. SPC_FORMAT_FUNC_COUNT,
  59. SpcFormatFuncTable, 0);
  60. break;
  61. case DLL_PROCESS_DETACH:
  62. case DLL_THREAD_DETACH:
  63. default:
  64. break;
  65. }
  66. return fRet;
  67. }
  68. #endif // MAC
  69. // DLL Entry point
  70. #ifdef MAC
  71. EXTERN_C BOOL WINAPI CryptDlg_DllMain(HANDLE hInst, ULONG ulReason, LPVOID pv)
  72. #else // !MAC
  73. extern
  74. BOOL
  75. WINAPI
  76. WXP_CertTrustDllMain(
  77. HINSTANCE hInst,
  78. ULONG ulReason,
  79. LPVOID
  80. );
  81. BOOL WINAPI DllMain(HANDLE hInst, ULONG ulReason, LPVOID pv)
  82. #endif // MAC
  83. {
  84. switch( ulReason ) {
  85. case DLL_PROCESS_ATTACH:
  86. HinstDll = (HINSTANCE) hInst;
  87. // Kill all thread attach and detach messages
  88. DisableThreadLibraryCalls(HinstDll);
  89. #ifndef MAC
  90. // Are we running in Win95 or something equally bad
  91. FIsWin95 = IsWin95();
  92. InitDemandLoadedLibs();
  93. #endif // !MAC
  94. break;
  95. case DLL_PROCESS_DETACH:
  96. #ifndef MAC
  97. FreeDemandLoadedLibs();
  98. // If the rich edit dll was loaded, then unload it now
  99. if (HmodRichEdit != NULL) {
  100. FreeLibrary(HmodRichEdit);
  101. }
  102. #endif // !MAC
  103. break;
  104. }
  105. #ifndef MAC
  106. return WXP_CertTrustDllMain((HINSTANCE) hInst, ulReason, pv);
  107. #else // MAC
  108. // Handle the ASN OID functions
  109. return CryptDlgASNDllMain((HINSTANCE)hInst, ulReason, pv);
  110. #endif // !MAC
  111. }
  112. #else // WIN16
  113. BOOL FAR PASCAL
  114. LibMain (HINSTANCE hDll,
  115. WORD wDataSeg,
  116. WORD cbHeapSize,
  117. LPSTR lpszCmdLine)
  118. {
  119. HinstDll = (HINSTANCE) hDll;
  120. InitDemandLoadedLibs();
  121. // Done
  122. return TRUE;
  123. }
  124. int CALLBACK WEP(int x)
  125. {
  126. FreeDemandLoadedLibs();
  127. // If the rich edit dll was loaded, then unload it now
  128. if (HmodRichEdit != NULL) {
  129. FreeLibrary(HmodRichEdit);
  130. }
  131. return 1;
  132. }
  133. #endif // !WIN16
  134. #ifndef WIN16
  135. DWORD ComputeExtent(HWND hwnd, int id)
  136. {
  137. int c;
  138. ULONG cb;
  139. ULONG cbMax = 0;
  140. DWORD dwExtent;
  141. DWORD dwExtentMax = 0;
  142. HDC hdc;
  143. HFONT hfontOld;
  144. HFONT hfontNew;
  145. int i;
  146. LPWSTR psz = NULL;
  147. SIZE sz;
  148. #ifndef MAC
  149. TEXTMETRICW tmW={0};
  150. #endif // !MAC
  151. TEXTMETRICA tmA={0};
  152. hdc = GetDC(hwnd);
  153. hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL);
  154. hfontOld = (HFONT) SelectObject(hdc, hfontNew);
  155. if (FIsWin95) {
  156. GetTextMetricsA(hdc, &tmA);
  157. }
  158. #ifndef MAC
  159. else {
  160. GetTextMetricsW(hdc, &tmW);
  161. }
  162. #endif // !MAC
  163. c = (int) SendDlgItemMessage(hwnd, id, LB_GETCOUNT, 0, 0);
  164. for (i=0; i<c; i++) {
  165. cb = (ULONG) SendDlgItemMessage(hwnd, id, LB_GETTEXTLEN, i, 0);
  166. if (cb > cbMax) {
  167. free(psz);
  168. cbMax = cb + 100;
  169. psz = (LPWSTR) malloc(cbMax*sizeof(WCHAR));
  170. if (psz == NULL) {
  171. break;
  172. }
  173. }
  174. #ifndef MAC
  175. if (FIsWin95) {
  176. #endif // !MAC
  177. SendDlgItemMessageA(hwnd, id, LB_GETTEXT, i, (LPARAM) psz);
  178. GetTextExtentPointA(hdc, (LPSTR) psz, strlen((LPSTR) psz), &sz);
  179. dwExtent = sz.cx + tmA.tmAveCharWidth;
  180. #ifndef MAC
  181. }
  182. else {
  183. SendDlgItemMessageW(hwnd, id, LB_GETTEXT, i, (LPARAM) psz);
  184. GetTextExtentPointW(hdc, psz, wcslen(psz), &sz);
  185. dwExtent = sz.cx + tmW.tmAveCharWidth;
  186. }
  187. #endif // !MAC
  188. if (dwExtent > dwExtentMax) {
  189. dwExtentMax = dwExtent;
  190. }
  191. }
  192. free(psz);
  193. SelectObject(hdc, hfontOld);
  194. ReleaseDC(hwnd, hdc);
  195. return dwExtentMax;
  196. }
  197. #else // WIN16
  198. DWORD ComputeExtent(HWND hwnd, int id)
  199. {
  200. int c;
  201. int cb;
  202. int cbMax = 0;
  203. DWORD dwExtent;
  204. DWORD dwExtentMax = 0;
  205. HDC hdc;
  206. HFONT hfontOld;
  207. HFONT hfontNew;
  208. int i;
  209. LPWSTR psz = NULL;
  210. SIZE sz;
  211. TEXTMETRIC tm;
  212. hdc = GetDC(hwnd);
  213. hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL);
  214. hfontOld = (HFONT) SelectObject(hdc, hfontNew);
  215. GetTextMetrics(hdc, &tm);
  216. c = SendDlgItemMessage(hwnd, id, LB_GETCOUNT, 0, 0);
  217. for (i=0; i<c; i++) {
  218. cb = SendDlgItemMessage(hwnd, id, LB_GETTEXTLEN, i, 0);
  219. if (cb > cbMax) {
  220. free(psz);
  221. cbMax = cb + 100;
  222. psz = (LPWSTR) malloc(cbMax*sizeof(WCHAR));
  223. if (psz == NULL) {
  224. break;
  225. }
  226. }
  227. SendDlgItemMessage(hwnd, id, LB_GETTEXT, i, (LONG) psz);
  228. GetTextExtentPoint(hdc, (LPSTR) psz, strlen((LPSTR) psz), &sz);
  229. dwExtent = sz.cx + tm.tmAveCharWidth;
  230. if (dwExtent > dwExtentMax) {
  231. dwExtentMax = dwExtent;
  232. }
  233. }
  234. free(psz);
  235. SelectObject(hdc, hfontOld);
  236. ReleaseDC(hwnd, hdc);
  237. return dwExtentMax;
  238. }
  239. #endif // !WIN16
  240. BOOL FillInFields(HWND hwnd, PCCERT_CONTEXT pccert)
  241. {
  242. LPWSTR pwsz;
  243. WCHAR rgwch[200];
  244. LPWSTR rgpwsz[3];
  245. rgpwsz[2] = (LPWSTR)-1; // Sentinal Value
  246. FormatAlgorithm(hwnd, IDC_CS_ALGORITHM, pccert);
  247. FormatSerialNo(hwnd, IDC_CS_SERIAL_NUMBER, pccert);
  248. FormatThumbprint(hwnd, IDC_CS_THUMBPRINT, pccert);
  249. FormatValidity(hwnd, IDC_CS_VALIDITY, pccert);
  250. rgpwsz[0] = PrettySubject(pccert);
  251. rgpwsz[1] = PrettyIssuer(pccert);
  252. LoadString(HinstDll, IDS_SELECT_INFO, rgwch, ARRAYSIZE(rgwch));
  253. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  254. FORMAT_MESSAGE_FROM_STRING |
  255. FORMAT_MESSAGE_ARGUMENT_ARRAY, rgwch, 0, 0,
  256. (LPWSTR) &pwsz, 0, (va_list *) rgpwsz);
  257. #ifndef WIN16
  258. TruncateToWindowW(hwnd, IDC_CS_INFO, pwsz);
  259. #else
  260. TruncateToWindowA(hwnd, IDC_CS_INFO, pwsz);
  261. #endif // !WIN16
  262. SetDlgItemText(hwnd, IDC_CS_INFO, pwsz);
  263. free(rgpwsz[0]);
  264. free(rgpwsz[1]);
  265. LocalFree((HLOCAL)pwsz);
  266. return TRUE;
  267. }
  268. INT_PTR CALLBACK SelectCertDlgProc(HWND hwndDlg, UINT msg,
  269. WPARAM wParam, LPARAM lParam)
  270. {
  271. int c;
  272. CTL_USAGE ctlUsage;
  273. PCERT_CONTEXT pcertctx;
  274. BOOL f;
  275. int i;
  276. DWORD iStore;
  277. LPWSTR pwsz;
  278. PCCERT_CONTEXT pccert;
  279. PCERT_SELECT_STRUCT pcss;
  280. pcss = (PCERT_SELECT_STRUCT) GetWindowLongPtr(hwndDlg, DWLP_USER);
  281. //
  282. // If a hook proc has been registered for this dialog, then we need
  283. // to call the hook proc. Notice that if the hook proc returns TRUE
  284. // then we don't do normal processing
  285. //
  286. if ((pcss != NULL) && (pcss->dwFlags & CSS_ENABLEHOOK) &&
  287. (pcss->pfnHook != 0)) {
  288. f = pcss->pfnHook(hwndDlg, msg, wParam, lParam);
  289. if (f) {
  290. return f;
  291. }
  292. }
  293. //
  294. switch (msg) {
  295. case WM_INITDIALOG:
  296. // Center the dialog on its parent
  297. // CenterThisDialog(hwndDlg);
  298. // Save the pointer to the control structure for later use.
  299. SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
  300. //
  301. pcss = (PCERT_SELECT_STRUCT) lParam;
  302. //
  303. // Is there a title to be displayed?
  304. //
  305. if (pcss->szTitle != NULL) {
  306. if (FIsWin95) {
  307. SendMessageA(hwndDlg, WM_SETTEXT, 0, (LPARAM) pcss->szTitle);
  308. }
  309. #ifndef WIN16
  310. #ifndef MAC
  311. else {
  312. SendMessageW(hwndDlg, WM_SETTEXT, 0, (LPARAM) pcss->szTitle);
  313. }
  314. #endif // !MAC
  315. #endif // !WIN16
  316. }
  317. //
  318. // If we want a help button, then show it
  319. //
  320. if (pcss->dwFlags & CSS_SHOW_HELP) {
  321. ShowWindow(GetDlgItem(hwndDlg, IDHELP), SW_SHOW);
  322. }
  323. //
  324. // Check to see if the properties button should be suppressed
  325. //
  326. if (pcss->dwFlags & CSS_HIDE_PROPERTIES) {
  327. ShowWindow(GetDlgItem(hwndDlg, IDC_CS_PROPERTIES), SW_HIDE);
  328. }
  329. //
  330. // Let populate the list box, walk through the list of stores
  331. // to populate the list
  332. //
  333. if (pcss->szPurposeOid != NULL) {
  334. ctlUsage.cUsageIdentifier = 1;
  335. ctlUsage.rgpszUsageIdentifier = (LPSTR *) &pcss->szPurposeOid;
  336. }
  337. for (iStore = 0; iStore < pcss->cCertStore; iStore++) {
  338. pccert = NULL;
  339. if (!pcss->arrayCertStore[iStore])
  340. continue;
  341. while (TRUE) {
  342. //
  343. // Get the next certificate in the current store. If
  344. // we are finished then move on to the next store
  345. //
  346. if (pcss->szPurposeOid != NULL) {
  347. pccert = CertFindCertificateInStore(
  348. pcss->arrayCertStore[iStore],
  349. CRYPT_ASN_ENCODING,
  350. CERT_FIND_OPTIONAL_CTL_USAGE_FLAG,
  351. CERT_FIND_CTL_USAGE, &ctlUsage, pccert);
  352. }
  353. else {
  354. pccert = CertEnumCertificatesInStore(
  355. pcss->arrayCertStore[iStore],
  356. pccert);
  357. }
  358. if (pccert == NULL) {
  359. break;
  360. }
  361. //
  362. // Filter the certificate according to the purpse desired
  363. //
  364. //
  365. // If we have a filter set, then call back and see if
  366. // the filter approves the certificate. If it is not
  367. // approved then move onto the next certificate in this
  368. // store.
  369. //
  370. if (pcss->pfnFilter != NULL) {
  371. if (!pcss->pfnFilter(pccert, pcss->lCustData, 0, 0)) {
  372. continue;
  373. }
  374. }
  375. //
  376. // If there is no filter function, then kill all V1 certs
  377. //
  378. else {
  379. if (pccert->pCertInfo->dwVersion < 2) {
  380. continue;
  381. }
  382. }
  383. //
  384. // Convert the certificate subject to a name
  385. //
  386. pwsz = PrettySubjectIssuer(pccert);
  387. if (NULL != pwsz) {
  388. i = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_ADDSTRING, 0,
  389. (LPARAM) pwsz);
  390. SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_SETITEMDATA, i,
  391. (LPARAM) CertDuplicateCertificateContext(pccert));
  392. free(pwsz);
  393. }
  394. }
  395. }
  396. SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_SETHORIZONTALEXTENT,
  397. ComputeExtent(hwndDlg, IDC_CS_CERTLIST), 0);
  398. c = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCOUNT, 0, 0);
  399. if (c != 0 && pcss->arrayCertContext[0] != NULL) {
  400. for (i=0; i<c; i++) {
  401. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA,
  402. i, 0);
  403. if (CertCompareCertificate(X509_ASN_ENCODING,
  404. pcss->arrayCertContext[0]->pCertInfo,
  405. pcertctx->pCertInfo)) {
  406. SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_SETCURSEL,
  407. i, 0);
  408. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST,
  409. LB_GETITEMDATA, i, 0);
  410. FillInFields(hwndDlg, pcertctx);
  411. break;
  412. }
  413. }
  414. }
  415. else {
  416. // no certs at all or no default certificate,
  417. // so there is no selection in the listbox
  418. EnableWindow(GetDlgItem(hwndDlg, IDC_CS_PROPERTIES), FALSE);
  419. EnableWindow(GetDlgItem(hwndDlg, IDC_CS_FINEPRINT), FALSE);
  420. EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
  421. }
  422. if ((pcss->dwFlags & CSS_ENABLEHOOK) && (pcss->pfnHook != 0)) {
  423. f = pcss->pfnHook(hwndDlg, msg, wParam, lParam);
  424. if (f) {
  425. return f;
  426. }
  427. }
  428. return TRUE;
  429. case WM_COMMAND:
  430. switch (LOWORD(wParam)) {
  431. case IDOK:
  432. i = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCURSEL, 0, 0);
  433. if (i != LB_ERR) {
  434. // Free the old cert if there is one
  435. if (pcss->arrayCertContext[0] != NULL) {
  436. CertFreeCertificateContext(pcss->arrayCertContext[0]);
  437. }
  438. // Get the new cert from the system.
  439. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA,
  440. i, 0);
  441. // Put the new cert into the location
  442. pcss->cCertContext = 1;
  443. pcss->arrayCertContext[0] =
  444. CertDuplicateCertificateContext(pcertctx);
  445. }
  446. else {
  447. pcss->cCertContext = 0;
  448. }
  449. EndDialog(hwndDlg, IDOK);
  450. return TRUE;
  451. case IDCANCEL:
  452. EndDialog(hwndDlg, IDCANCEL);
  453. return TRUE;
  454. case IDHELP:
  455. if (FIsWin95) {
  456. WinHelpA(hwndDlg, (LPSTR) pcss->szHelpFileName,
  457. HELP_CONTEXT, pcss->dwHelpId);
  458. }
  459. #ifndef MAC
  460. else {
  461. WinHelp(hwndDlg, pcss->szHelpFileName,
  462. HELP_CONTEXT, pcss->dwHelpId);
  463. }
  464. #endif // !MAC
  465. return TRUE;
  466. case IDC_CS_PROPERTIES:
  467. i = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCURSEL, 0, 0);
  468. if (i == LB_ERR) {
  469. return TRUE;
  470. }
  471. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA,
  472. i, 0);
  473. f = TRUE;
  474. if (FIsWin95) {
  475. CERT_VIEWPROPERTIES_STRUCT_A cvps;
  476. memset(&cvps, 0, sizeof(cvps));
  477. cvps.dwSize = sizeof(cvps);
  478. cvps.hwndParent = hwndDlg;
  479. cvps.pCertContext = pcertctx;
  480. pcss = (PCERT_SELECT_STRUCT) GetWindowLongPtr(hwndDlg, DWLP_USER);
  481. if (pcss->szPurposeOid != NULL) {
  482. cvps.cArrayPurposes = 1;
  483. cvps.arrayPurposes = (LPSTR *) &pcss->szPurposeOid;
  484. }
  485. if (pcss->dwSize > (DWORD_PTR) &((PCERT_SELECT_STRUCT_A) 0)->hprov) {
  486. cvps.hprov = pcss->hprov;
  487. }
  488. f = CertViewPropertiesA(&cvps);
  489. }
  490. #ifndef WIN16
  491. #ifndef MAC
  492. else {
  493. CERT_VIEWPROPERTIES_STRUCT_W cvps;
  494. memset(&cvps, 0, sizeof(cvps));
  495. cvps.dwSize = sizeof(cvps);
  496. cvps.hwndParent = hwndDlg;
  497. cvps.pCertContext = pcertctx;
  498. pcss = (PCERT_SELECT_STRUCT) GetWindowLongPtr(hwndDlg, DWLP_USER);
  499. if (pcss->szPurposeOid != NULL) {
  500. cvps.cArrayPurposes = 1;
  501. cvps.arrayPurposes = (LPSTR *) &pcss->szPurposeOid;
  502. }
  503. if (pcss->dwSize > (DWORD_PTR) &((PCERT_SELECT_STRUCT_W) 0)->hprov) {
  504. cvps.hprov = pcss->hprov;
  505. }
  506. f = CertViewPropertiesW(&cvps);
  507. }
  508. #endif // !MAC
  509. #endif // !WIN16
  510. if (f) {
  511. // M00BUG -- repopulate the line. The friendly name
  512. // may have changed.
  513. }
  514. return TRUE;
  515. case IDC_CS_FINEPRINT:
  516. i = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCURSEL, 0, 0);
  517. if (i == LB_ERR) {
  518. return TRUE;
  519. }
  520. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA,
  521. i, 0);
  522. FinePrint(pcertctx, hwndDlg);
  523. return TRUE;
  524. case IDC_CS_CERTLIST:
  525. if (HIWORD(wParam) == LBN_SELCHANGE) {
  526. i = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCARETINDEX,
  527. 0, 0);
  528. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA,
  529. i, 0);
  530. FillInFields(hwndDlg, pcertctx);
  531. if (!(pcss->dwFlags & CSS_HIDE_PROPERTIES)) {
  532. EnableWindow(GetDlgItem(hwndDlg, IDC_CS_PROPERTIES), TRUE);
  533. }
  534. EnableWindow(GetDlgItem(hwndDlg, IDC_CS_FINEPRINT), TRUE);
  535. EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
  536. }
  537. return TRUE;
  538. }
  539. break;
  540. #ifndef MAC
  541. case WM_HELP:
  542. case WM_CONTEXTMENU:
  543. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxSelect);
  544. #endif // !MAC
  545. case WM_DESTROY:
  546. c = (int) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETCOUNT, 0, 0);
  547. for (i=0; i<c; i++) {
  548. pcertctx = (PCERT_CONTEXT) SendDlgItemMessage(hwndDlg, IDC_CS_CERTLIST, LB_GETITEMDATA, i, 0);
  549. CertFreeCertificateContext(pcertctx);
  550. }
  551. return FALSE;
  552. //
  553. // Use the default handler -- we don't do anything for it
  554. //
  555. default:
  556. return FALSE;
  557. }
  558. return TRUE;
  559. } // SelectCertDialogProc()
  560. BOOL WINAPI MyCryptFilter(PCCERT_CONTEXT pccert, BOOL * pfSelect, void * pv)
  561. {
  562. PCERT_SELECT_STRUCT_W pcssW = (PCERT_SELECT_STRUCT_W) pv;
  563. PCERT_EXTENSION pExt;
  564. // Test purpose
  565. if (pcssW->szPurposeOid != NULL) {
  566. pExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  567. pccert->pCertInfo->cExtension,
  568. pccert->pCertInfo->rgExtension);
  569. if (pExt != NULL) {
  570. BOOL f;
  571. DWORD i;
  572. PCERT_ENHKEY_USAGE pUsage;
  573. pUsage = (PCERT_ENHKEY_USAGE) PVCryptDecode(szOID_ENHANCED_KEY_USAGE,
  574. pExt->Value.cbData,
  575. pExt->Value.pbData);
  576. if (pUsage == NULL) {
  577. return FALSE;
  578. }
  579. for (i=0, f=FALSE; i<pUsage->cUsageIdentifier; i++) {
  580. if (strcmp(pcssW->szPurposeOid, pUsage->rgpszUsageIdentifier[i]) == 0) {
  581. break;
  582. }
  583. }
  584. if (i == pUsage->cUsageIdentifier) {
  585. free(pUsage);
  586. return FALSE;
  587. }
  588. free(pUsage);
  589. }
  590. }
  591. // Let them filter if they want
  592. if (pcssW->pfnFilter != NULL) {
  593. if (!pcssW->pfnFilter(pccert, pcssW->lCustData, 0, 0)) {
  594. return FALSE;
  595. }
  596. }
  597. else if (pccert->pCertInfo->dwVersion < 2) {
  598. return FALSE;
  599. }
  600. if ((pfSelect != NULL) && (pcssW->arrayCertContext[0] != NULL)) {
  601. *pfSelect = CertCompareCertificate(X509_ASN_ENCODING, pccert->pCertInfo,
  602. pcssW->arrayCertContext[0]->pCertInfo);
  603. }
  604. return TRUE;
  605. }
  606. BOOL WINAPI MyDisplay(PCCERT_CONTEXT pccert, HWND hwnd, void * pv)
  607. {
  608. CERT_VIEWPROPERTIES_STRUCT_A cvps = {0};
  609. PCERT_SELECT_STRUCT_W pcss = (PCERT_SELECT_STRUCT_W) pv;
  610. cvps.dwSize = sizeof(cvps);
  611. cvps.hwndParent = hwnd;
  612. cvps.pCertContext = pccert;
  613. if (pcss->szPurposeOid != NULL) {
  614. cvps.cArrayPurposes = 1;
  615. cvps.arrayPurposes = (LPSTR *) &pcss->szPurposeOid;
  616. }
  617. if (pcss->dwSize > (DWORD_PTR) &((PCERT_SELECT_STRUCT_A) 0)->hprov) {
  618. cvps.hprov = pcss->hprov;
  619. }
  620. CertViewPropertiesA(&cvps);
  621. return TRUE;
  622. }
  623. BOOL CallCryptUISelect(BOOL fWide, PCERT_SELECT_STRUCT_W pcssW)
  624. {
  625. CRYPTUI_SELECTCERTIFICATE_STRUCTW cscs = {0};
  626. PCCERT_CONTEXT pccert;
  627. cscs.dwSize = sizeof(cscs);
  628. cscs.hwndParent = pcssW->hwndParent;
  629. // cscs.dwFlags = 0;
  630. cscs.szTitle = pcssW->szTitle;
  631. if (pcssW->szPurposeOid != NULL) {
  632. cscs.dwDontUseColumn = /*CRYPTUI_SELECT_INTENDEDUSE_COLUMN |*/
  633. CRYPTUI_SELECT_LOCATION_COLUMN;
  634. }
  635. else {
  636. cscs.dwDontUseColumn = CRYPTUI_SELECT_LOCATION_COLUMN;
  637. }
  638. // cscs.szDisplayString = NULL;
  639. cscs.pFilterCallback = MyCryptFilter;
  640. cscs.pDisplayCallback = MyDisplay;
  641. cscs.pvCallbackData = pcssW;
  642. cscs.cDisplayStores = pcssW->cCertStore;
  643. cscs.rghDisplayStores = pcssW->arrayCertStore;
  644. // cscs.cStores = 0;
  645. // cscs.rghStores = NULL;
  646. // cscs.cPropSheetPages = 0;
  647. // cscs.rgPropSheetPages = NULL;
  648. if (fWide) {
  649. pccert = CryptUIDlgSelectCertificateW(&cscs);
  650. }
  651. else {
  652. pccert = CryptUIDlgSelectCertificateA((PCRYPTUI_SELECTCERTIFICATE_STRUCTA) &cscs);
  653. }
  654. if (pccert != NULL) {
  655. if (pcssW->cCertContext == 1) {
  656. CertFreeCertificateContext(pcssW->arrayCertContext[0]);
  657. }
  658. pcssW->cCertContext = 1;
  659. pcssW->arrayCertContext[0] = pccert;
  660. return TRUE;
  661. }
  662. return FALSE;
  663. }
  664. extern "C" BOOL APIENTRY CertSelectCertificateA(PCERT_SELECT_STRUCT_A pcssA)
  665. {
  666. if (CryptUIAvailable()) {
  667. return CallCryptUISelect(FALSE, (PCERT_SELECT_STRUCT_W) pcssA);
  668. }
  669. HCERTSTORE hCertStore = NULL;
  670. int ret = FALSE;
  671. CERT_SELECT_STRUCT_W cssW = {0};
  672. #ifndef MAC
  673. int cch;
  674. INITCOMMONCONTROLSEX initcomm = {
  675. sizeof(initcomm), ICC_LISTVIEW_CLASSES
  676. #ifndef WIN16
  677. | ICC_NATIVEFNTCTL_CLASS
  678. #endif // ! WIN16
  679. };
  680. #endif // ! MAC
  681. if (pcssA->cCertStore == 0) {
  682. hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING,
  683. NULL, CERT_SYSTEM_STORE_CURRENT_USER,
  684. L"MY");
  685. if (hCertStore == NULL) {
  686. ret = -1;
  687. goto Exit;
  688. }
  689. pcssA->cCertStore = 1;
  690. pcssA->arrayCertStore = &hCertStore;
  691. }
  692. //
  693. // Size of the object must be acceptable in order to copy it over
  694. //
  695. if (pcssA->dwSize > sizeof(cssW)) {
  696. SetLastError(ERROR_INVALID_PARAMETER);
  697. return FALSE;
  698. }
  699. if (FIsWin95) {
  700. //
  701. // Deal with some DBCS issues
  702. //
  703. #ifndef MAC
  704. InitCommonControlsEx(&initcomm);
  705. #endif // !MAC
  706. //
  707. // Launch the dialog
  708. //
  709. if (pcssA->dwFlags & CSS_ENABLETEMPLATEHANDLE) {
  710. ret = (int) DialogBoxIndirectParamA(pcssA->hInstance,
  711. (LPCDLGTEMPLATE_X) pcssA->pTemplateName,
  712. pcssA->hwndParent, SelectCertDlgProc,
  713. (LPARAM) pcssA);
  714. }
  715. else if (pcssA->dwFlags & CSS_ENABLETEMPLATE) {
  716. ret = (int) DialogBoxParamA(pcssA->hInstance, pcssA->pTemplateName,
  717. pcssA->hwndParent, SelectCertDlgProc,
  718. (LPARAM) pcssA);
  719. }
  720. else {
  721. ret = (int) DialogBoxParamA(HinstDll,
  722. (LPSTR) MAKEINTRESOURCE(IDD_SELECT_DIALOG),
  723. pcssA->hwndParent, SelectCertDlgProc,
  724. (LPARAM) pcssA);
  725. }
  726. }
  727. #if ! defined(WIN16) && ! defined (MAC)
  728. else {
  729. //
  730. // Do a bulk copy of the passed in structure then we fix up the
  731. // individual fields to go from the A to the W version of the structure
  732. //
  733. //Assert(pcssA->dwSize <= sizeof(cssW));
  734. memcpy(&cssW, pcssA, (int)min(pcssA->dwSize, sizeof(cssW)));
  735. if (pcssA->szTitle != NULL) {
  736. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcssA->szTitle, -1,
  737. NULL, 0);
  738. cssW.szTitle = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  739. if (cssW.szTitle == NULL) {
  740. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  741. goto ExitW;
  742. }
  743. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcssA->szTitle, -1,
  744. (LPWSTR) cssW.szTitle, cch+1);
  745. }
  746. if (pcssA->szHelpFileName != NULL) {
  747. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  748. pcssA->szHelpFileName, -1, NULL, 0);
  749. cssW.szHelpFileName = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  750. if (cssW.szHelpFileName == NULL) {
  751. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  752. goto ExitW;
  753. }
  754. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcssA->szHelpFileName, -1,
  755. (LPWSTR) cssW.szHelpFileName, cch+1);
  756. }
  757. if (pcssA->dwFlags & CSS_ENABLETEMPLATE) {
  758. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  759. pcssA->pTemplateName, -1, NULL, 0);
  760. cssW.pTemplateName = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  761. if (cssW.pTemplateName == NULL) {
  762. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  763. goto ExitW;
  764. }
  765. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcssA->pTemplateName, -1,
  766. (LPWSTR) cssW.pTemplateName, cch+1);
  767. }
  768. //
  769. // Call Wide char version of the function now
  770. //
  771. ret = CertSelectCertificateW(&cssW);
  772. pcssA->cCertContext = cssW.cCertContext;
  773. //
  774. // If we allocated buffers to hold data, free them now
  775. //
  776. ExitW:
  777. if (cssW.szTitle != NULL) free((LPWSTR) cssW.szTitle);
  778. if (cssW.szHelpFileName != NULL) free((LPWSTR) cssW.szHelpFileName);
  779. if (pcssA->dwFlags & CSS_ENABLETEMPLATE) {
  780. free((LPWSTR) cssW.pTemplateName);
  781. }
  782. //
  783. // return the return value of the original function
  784. //
  785. }
  786. #endif // !WIN16 and !MAC
  787. Exit:
  788. if (hCertStore != NULL) {
  789. CertCloseStore(hCertStore, 0);
  790. pcssA->cCertStore = 0;
  791. pcssA->arrayCertStore = NULL;
  792. }
  793. return (ret == IDOK);
  794. }
  795. #ifndef WIN16
  796. #ifndef MAC
  797. BOOL APIENTRY CertSelectCertificateW(PCERT_SELECT_STRUCT_W pcssW)
  798. {
  799. if (CryptUIAvailable()) {
  800. return CallCryptUISelect(TRUE, pcssW);
  801. }
  802. HCERTSTORE hCertStore = NULL;
  803. int ret = FALSE;
  804. #ifndef MAC
  805. INITCOMMONCONTROLSEX initcomm = {
  806. sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES
  807. };
  808. #endif // !MAC
  809. //
  810. // If cCertStore == 0, then default to using the "MY" cert store
  811. //
  812. if (pcssW->cCertStore == 0) {
  813. hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING,
  814. NULL, CERT_SYSTEM_STORE_CURRENT_USER,
  815. L"MY");
  816. if (hCertStore == NULL) {
  817. ret = -1;
  818. goto Exit;
  819. }
  820. pcssW->cCertStore = 1;
  821. pcssW->arrayCertStore = &hCertStore;
  822. }
  823. //
  824. // Deal with some DBCS issues
  825. //
  826. InitCommonControlsEx(&initcomm);
  827. //
  828. // Launch the dialog
  829. //
  830. if (pcssW->dwFlags & CSS_ENABLETEMPLATEHANDLE) {
  831. ret = (int) DialogBoxIndirectParam(pcssW->hInstance,
  832. (LPCDLGTEMPLATE_X) pcssW->pTemplateName,
  833. pcssW->hwndParent, SelectCertDlgProc,
  834. (LPARAM) pcssW);
  835. }
  836. else if (pcssW->dwFlags & CSS_ENABLETEMPLATE) {
  837. ret = (int) DialogBoxParam(pcssW->hInstance, pcssW->pTemplateName,
  838. pcssW->hwndParent, SelectCertDlgProc,
  839. (LPARAM) pcssW);
  840. }
  841. else {
  842. ret = (int) DialogBoxParam(HinstDll, MAKEINTRESOURCE(IDD_SELECT_DIALOG),
  843. pcssW->hwndParent, SelectCertDlgProc,
  844. (LPARAM) pcssW);
  845. }
  846. Exit:
  847. if (hCertStore != NULL) {
  848. CertCloseStore(hCertStore, 0);
  849. pcssW->cCertStore = 0;
  850. pcssW->arrayCertStore = NULL;
  851. }
  852. return (ret == IDOK);
  853. }
  854. #endif // !MAC
  855. #endif // !WIN16