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.

1711 lines
58 KiB

  1. #include "pch.hxx"
  2. #ifndef WIN16
  3. #include <commctrl.h>
  4. #endif // !WIN16
  5. #include <stdio.h>
  6. #include <limits.h>
  7. #ifndef WIN16
  8. #include "wintrust.h"
  9. #endif // !WIN16
  10. #include "demand.h"
  11. #include <iehelpid.h>
  12. #ifndef WIN16
  13. // Fix a Win95 problem
  14. #undef TVM_SETITEM
  15. #define TVM_SETITEM TVM_SETITEMA
  16. #undef TVM_GETITEM
  17. #define TVM_GETITEM TVM_GETITEMA
  18. #endif // !WIN16
  19. extern HINSTANCE HinstDll;
  20. #ifndef MAC
  21. extern HMODULE HmodRichEdit;
  22. #endif // !MAC
  23. BOOL CertViewPropertiesX(PCERT_VIEWPROPERTIES_STRUCT_W pcvp);
  24. #define ARRAYSIZE(_rg) (sizeof(_rg)/sizeof(_rg[0]))
  25. #define VIEW_HELPER_SENTRY 0x424A4800
  26. typedef struct {
  27. DWORD dwSentry; // Must be set to value of VIEW_HELPER_SENTRY
  28. PCERT_VIEWPROPERTIES_STRUCT_W pcvp;
  29. DWORD ccf; // Count of frames
  30. PCCertFrame rgpcf[20]; // Array of frames
  31. HTREEITEM hItem; // Leaf item in trust view
  32. HANDLE hWVTState; // WinVerifyTrust state handle
  33. // CryptUI version only
  34. PCCERT_CONTEXT pccert; // Cert context goes here
  35. ULONG icf; // index in rgpcf of this cert.
  36. } VIEW_HELPER;
  37. typedef struct {
  38. DLGPROC pfnDlgProc;
  39. LPARAM lParam;
  40. } VIEW_CALLBACK_HELPER;
  41. const HELPMAP RgctxGeneral[] = {
  42. {IDC_FINE_PRINT, IDH_CERTVWPROP_GEN_FINEPRINT}
  43. };
  44. const HELPMAP RgctxDetails[] = {
  45. {IDC_ISSUED_BY, IDH_CERTVWPROP_DET_ISSUER_CERT},
  46. {IDC_FRIENDLY_NAME, IDH_CERTVWPROP_DET_FRIENDLY},
  47. {IDC_TRUST_IMAGE, IDH_CERTVWPROP_DET_STATUS},
  48. {IDC_IS_TRUSTED, IDH_CERTVWPROP_DET_STATUS},
  49. {IDC_IS_VALID, IDH_CERTVWPROP_DET_STATUS}
  50. };
  51. const HELPMAP RgctxTrust[] = {
  52. {IDC_TRUST_LIST, IDH_CERTVWPROP_TRUST_PURPOSE},
  53. {IDC_TRUST_TREE, IDH_CERTVWPROP_TRUST_HIERAR},
  54. {IDC_TRUST_VIEW, IDH_CERTVWPROP_TRUST_VIEWCERT},
  55. {IDC_TRUST_INHERIT, IDH_CERTVWPROP_TRUST_INHERIT},
  56. {IDC_TRUST_YES, IDH_CERTVWPROP_TRUST_EXPLICIT_TRUST},
  57. {IDC_TRUST_NO, IDH_CERTVWPROP_TRUST_EXPLICIT_DISTRUST}
  58. };
  59. const HELPMAP RgctxAdvanced[] = {
  60. {IDC_LIST1, IDH_CERTVWPROP_ADV_FIELD},
  61. {IDC_EDIT1, IDH_CERTVWPROP_ADV_DETAILS}
  62. };
  63. ////////////////////////////////////////////////////////
  64. VIEW_HELPER * GetViewHelperFromPropSheetPage(PROPSHEETPAGE *ps) {
  65. VIEW_HELPER * pviewhelp;
  66. ULONG i;
  67. pviewhelp = (VIEW_HELPER *)(ps->lParam);
  68. if (pviewhelp->dwSentry != VIEW_HELPER_SENTRY) {
  69. // Assume that CryptUI has passed us a wrapped lparam/cert pair
  70. // typedef struct tagCRYPTUI_INITDIALOG_STRUCT {
  71. // LPARAM lParam;
  72. // PCCERT_CONTEXT pCertContext;
  73. // } CRYPTUI_INITDIALOG_STRUCT, *PCRYPTUI_INITDIALOG_STRUCT;
  74. PCRYPTUI_INITDIALOG_STRUCT pCryptUIInitDialog = (PCRYPTUI_INITDIALOG_STRUCT)pviewhelp;
  75. pviewhelp = (VIEW_HELPER *)pCryptUIInitDialog->lParam;
  76. if (pviewhelp->dwSentry != VIEW_HELPER_SENTRY) {
  77. // Bad lparam
  78. return(NULL);
  79. }
  80. pviewhelp->pccert = pCryptUIInitDialog->pCertContext;
  81. // Find the correct frame in the array
  82. pviewhelp->icf = 0;
  83. for (i = 0; i < pviewhelp->ccf; i++) {
  84. if (CertCompareCertificate(X509_ASN_ENCODING,
  85. pviewhelp->rgpcf[i]->m_pccert->pCertInfo, pviewhelp->pccert->pCertInfo)) {
  86. pviewhelp->icf = i;
  87. break;
  88. }
  89. }
  90. }
  91. return(pviewhelp);
  92. }
  93. void ShowHelp(HWND hwnd, VIEW_HELPER * pviewhelp) {
  94. if (FIsWin95) {
  95. WinHelpA(hwnd, (LPSTR)pviewhelp->pcvp->szHelpFileName, HELP_CONTEXT,
  96. pviewhelp->pcvp->dwHelpId);
  97. }
  98. #if !defined( MAC ) && !defined( WIN16 )
  99. else {
  100. WinHelpW(hwnd, pviewhelp->pcvp->szHelpFileName, HELP_CONTEXT,
  101. pviewhelp->pcvp->dwHelpId);
  102. }
  103. #endif // !MAC && !WIN16
  104. }
  105. INT_PTR CALLBACK ViewPageGeneral(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  106. {
  107. BOOL fTrust;
  108. HANDLE hGraphic;
  109. int i1;
  110. DWORD i;
  111. PCCERT_CONTEXT pccert;
  112. ENLINK * penlink;
  113. PROPSHEETPAGE * ps;
  114. VIEW_HELPER * pviewhelp;
  115. LPWSTR pwsz;
  116. WCHAR rgwch[200];
  117. LPWSTR rgpwsz[4];
  118. UINT rguiStrings[7];
  119. switch ( msg ) {
  120. case WM_INITDIALOG:
  121. //
  122. // Stash the item in the header
  123. //
  124. ps = (PROPSHEETPAGE *) lParam;
  125. pviewhelp = GetViewHelperFromPropSheetPage(ps);
  126. if (! pviewhelp) {
  127. return(FALSE);
  128. }
  129. pccert = pviewhelp->pcvp->pCertContext;
  130. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pviewhelp);
  131. //
  132. // Pick up and format the general message texts
  133. //
  134. rguiStrings[0] = IDS_GENERAL_DESC;
  135. rguiStrings[1] = IDS_GENERAL_DESC2;
  136. rguiStrings[2] = IDS_GENERAL_DESC3;
  137. rguiStrings[3] = IDS_GENERAL_DESC4;
  138. rguiStrings[4] = IDS_GENERAL_DESC5;
  139. rguiStrings[5] = IDS_GENERAL_DESC6;
  140. rguiStrings[6] = UINT_MAX;
  141. LoadStringsInWindow(hwndDlg, IDC_GENERAL_DESC, HinstDll, rguiStrings);
  142. rgpwsz[0] = PrettySubject(pccert);
  143. rgpwsz[1] = PrettyIssuer(pccert);
  144. // rgpwsz[2] = FindURL(pccert);
  145. rgpwsz[2] = NULL;
  146. rgpwsz[3] = (LPWSTR) -1; // Sentinal Value
  147. LoadString(HinstDll, IDS_GENERAL_INFO, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  148. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  149. FORMAT_MESSAGE_FROM_STRING |
  150. FORMAT_MESSAGE_ARGUMENT_ARRAY, rgwch,
  151. 0, 0, (LPWSTR) &pwsz, 0, (va_list *) rgpwsz);
  152. SetDlgItemText(hwndDlg, IDC_TEXT, pwsz);
  153. if (rgpwsz[2] != NULL) {
  154. i1 = (int) (wcsstr(pwsz, rgpwsz[1]) - pwsz);
  155. if (i1 >= 0) {
  156. CHARFORMATA cf = {sizeof(cf), CFM_UNDERLINE | CFM_LINK,
  157. CFE_UNDERLINE | CFE_LINK};
  158. SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETSEL,
  159. i1, i1+wcslen(rgpwsz[1]));
  160. SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETCHARFORMAT,
  161. SCF_SELECTION, (LPARAM) &cf);
  162. SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETEVENTMASK, 0,
  163. ENM_LINK);
  164. SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETSEL, 0, 0);
  165. }
  166. }
  167. // Grey out the rich edit box
  168. SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETBKGNDCOLOR, 0,
  169. GetSysColor(COLOR_3DFACE));
  170. //
  171. // Now that we have determined what the trust status is, display the
  172. // correct string and image
  173. //
  174. if (pviewhelp->rgpcf[0]->m_dwFlags == 0) {
  175. if (pviewhelp->pcvp->cArrayPurposes == 0) {
  176. fTrust = TRUE;
  177. }
  178. else {
  179. for (i=0, fTrust = TRUE; i<pviewhelp->pcvp->cArrayPurposes; i++) {
  180. fTrust &= pviewhelp->rgpcf[0]->m_rgTrust[i].fTrust;
  181. }
  182. }
  183. }
  184. else {
  185. fTrust = FALSE;
  186. }
  187. #ifndef WIN16
  188. hGraphic = LoadImageA(HinstDll, (LPSTR) MAKEINTRESOURCE(IDB_TICK+!fTrust),
  189. IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  190. #else
  191. hGraphic = LoadBitmap(HinstDll,
  192. (LPSTR) MAKEINTRESOURCE(IDB_TICK+!fTrust));
  193. #endif
  194. SendDlgItemMessageA(hwndDlg, IDC_CERT_STATUS_IMAGE, STM_SETIMAGE,
  195. IMAGE_BITMAP, (LPARAM) hGraphic);
  196. LoadStringInWindow(hwndDlg, IDC_CERT_STATUS, HinstDll,
  197. IDS_GENERAL_TICK + !fTrust);
  198. //
  199. // Free out the buffers
  200. #ifndef WIN16
  201. LocalFree(pwsz);
  202. #else
  203. LocalFree((HLOCAL)pwsz);
  204. #endif
  205. if (rgpwsz[0])
  206. free(rgpwsz[0]);
  207. if (rgpwsz[1])
  208. free(rgpwsz[1]);
  209. if (rgpwsz[2])
  210. free(rgpwsz[2]);
  211. return TRUE;
  212. case WM_NOTIFY:
  213. switch (((NMHDR FAR *) lParam)->code) {
  214. case EN_LINK:
  215. penlink = (ENLINK *) lParam;
  216. if (penlink->msg == WM_LBUTTONUP) {
  217. break;
  218. }
  219. break;
  220. case PSN_SETACTIVE:
  221. break;
  222. case PSN_APPLY:
  223. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
  224. break;
  225. case PSN_KILLACTIVE:
  226. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  227. return TRUE;
  228. case PSN_RESET:
  229. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  230. break;
  231. case PSN_HELP:
  232. pviewhelp = (VIEW_HELPER *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  233. ShowHelp(hwndDlg, pviewhelp);
  234. return TRUE;
  235. }
  236. case WM_COMMAND:
  237. if (LOWORD(wParam) == IDC_FINE_PRINT) {
  238. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  239. FinePrint(pviewhelp->pcvp->pCertContext, hwndDlg);
  240. return TRUE;
  241. }
  242. else if (LOWORD(wParam) == IDHELP) {
  243. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  244. ShowHelp(hwndDlg, pviewhelp);
  245. return TRUE;
  246. }
  247. break;
  248. #ifndef MAC
  249. case WM_HELP:
  250. case WM_CONTEXTMENU:
  251. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxGeneral);
  252. #endif // !MAC
  253. }
  254. return FALSE;
  255. }
  256. INT_PTR CALLBACK ViewPageDetails(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  257. {
  258. CRYPT_DATA_BLOB blob;
  259. DWORD cch;
  260. BOOL fNotTrust;
  261. BOOL fInvalid;
  262. BOOL f;
  263. HANDLE h;
  264. PCCERT_CONTEXT pccert;
  265. PROPSHEETPAGE * ps;
  266. VIEW_HELPER * pviewhelp;
  267. LPWSTR pwsz;
  268. switch ( msg ) {
  269. case WM_INITDIALOG:
  270. ps = (PROPSHEETPAGE *) lParam;
  271. pviewhelp = GetViewHelperFromPropSheetPage(ps);
  272. if (! pviewhelp) {
  273. return(FALSE);
  274. }
  275. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pviewhelp);
  276. pccert = pviewhelp->pcvp->pCertContext;
  277. FormatSubject(hwndDlg, IDC_ISSUED_TO, pccert);
  278. FormatIssuer(hwndDlg, IDC_ISSUED_BY, pccert);
  279. FormatValidity(hwndDlg, IDC_VALIDITY, pccert);
  280. FormatAlgorithm(hwndDlg, IDC_ALGORITHM, pccert);
  281. FormatSerialNo(hwndDlg, IDC_SERIAL_NUMBER, pccert);
  282. FormatThumbprint(hwndDlg, IDC_THUMBPRINT, pccert);
  283. pwsz = PrettySubject(pccert);
  284. SetDlgItemText(hwndDlg, IDC_FRIENDLY_NAME, pwsz);
  285. free(pwsz);
  286. if (pviewhelp->pcvp->dwFlags & CM_NO_NAMECHANGE) {
  287. SendDlgItemMessageA(hwndDlg, IDC_FRIENDLY_NAME, EM_SETREADONLY,
  288. 1, 0);
  289. }
  290. //
  291. // Play with the validity and trust items at the bottom of the page.
  292. //
  293. fInvalid = (pviewhelp->rgpcf[0]->m_dwFlags != 0);
  294. if (pviewhelp->rgpcf[0]->m_rgTrust == NULL) {
  295. fNotTrust = FALSE;
  296. ShowWindow(GetDlgItem(hwndDlg, IDC_IS_TRUSTED), FALSE);
  297. ShowWindow(GetDlgItem(hwndDlg, IDC_IS_TRUSTED), FALSE);
  298. }
  299. else {
  300. fNotTrust = !pviewhelp->rgpcf[0]->m_rgTrust[0].fTrust;
  301. }
  302. #ifndef WIN16
  303. h = LoadImageA(HinstDll,
  304. (LPSTR) MAKEINTRESOURCE(IDB_TICK+(fNotTrust||fInvalid)),
  305. IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  306. #else
  307. h = LoadBitmap(HinstDll,
  308. (LPSTR) MAKEINTRESOURCE(IDB_TICK+(fNotTrust||fInvalid)));
  309. #endif
  310. SendDlgItemMessageA(hwndDlg, IDC_TRUST_IMAGE, STM_SETIMAGE,
  311. IMAGE_BITMAP, (LPARAM) h);
  312. LoadStringInWindow(hwndDlg, IDC_IS_VALID, HinstDll,
  313. IDS_DETAIL_VALID_TICK + fInvalid);
  314. LoadStringInWindow(hwndDlg, IDC_IS_TRUSTED, HinstDll,
  315. IDS_DETAIL_TRUST_TICK + fNotTrust);
  316. #ifdef MAC
  317. if (fInvalid) {
  318. HWND hwnd;
  319. hwnd = CreateWindowA(TOOLTIPS_CLASSA, NULL, TTS_ALWAYSTIP,
  320. CW_USEDEFAULT, CW_USEDEFAULT,
  321. CW_USEDEFAULT, CW_USEDEFAULT,
  322. hwndDlg, NULL, HinstDll, NULL);
  323. TOOLINFO ti;
  324. ti.cbSize = sizeof(TOOLINFO);
  325. ti.uFlags = TTF_SUBCLASS;
  326. ti.hwnd = hwndDlg;
  327. ti.hinst = HinstDll;
  328. GetWindowRect(GetDlgItem(hwndDlg, IDC_TRUST_GROUP), &ti.rect);
  329. ti.uId = 0;
  330. ti.lpszText = FormatValidityFailures(pviewhelp->rgpcf[0]->m_dwFlags);
  331. SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM) &ti);
  332. }
  333. if (pviewhelp->ccf < 2) {
  334. EnableWindow(GetDlgItem(hwndDlg, IDC_VIEW_ISSUER), FALSE);
  335. }
  336. SendDlgItemMessageA(hwndDlg, IDC_ISSUED_TO, EM_SETSEL, 0,0);
  337. #else // !MAC
  338. if (fInvalid) {
  339. HWND hwnd;
  340. hwnd = CreateWindow(TOOLTIPS_CLASS, NULL, TTS_ALWAYSTIP,
  341. CW_USEDEFAULT, CW_USEDEFAULT,
  342. CW_USEDEFAULT, CW_USEDEFAULT,
  343. hwndDlg, NULL, HinstDll, NULL);
  344. TOOLINFO ti;
  345. ti.cbSize = sizeof(TOOLINFO);
  346. ti.uFlags = TTF_SUBCLASS;
  347. ti.hwnd = hwndDlg;
  348. ti.hinst = HinstDll;
  349. GetWindowRect(GetDlgItem(hwndDlg, IDC_TRUST_GROUP), &ti.rect);
  350. ti.uId = 0;
  351. ti.lpszText = FormatValidityFailures(pviewhelp->rgpcf[0]->m_dwFlags);
  352. SendMessage(hwnd, TTM_ADDTOOL, 0, (LPARAM) &ti);
  353. }
  354. if (pviewhelp->ccf < 2) {
  355. EnableWindow(GetDlgItem(hwndDlg, IDC_VIEW_ISSUER), FALSE);
  356. }
  357. SendDlgItemMessage(hwndDlg, IDC_ISSUED_TO, EM_SETSEL, 0,0);
  358. #endif // MAC
  359. SetFocus(GetDlgItem(hwndDlg, IDC_FRIENDLY_NAME));
  360. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  361. return FALSE;
  362. case WM_NOTIFY:
  363. switch (((NMHDR FAR *) lParam)->code) {
  364. case PSN_SETACTIVE:
  365. break;
  366. case PSN_APPLY:
  367. // Only thing to do is to write back the Friendly name
  368. f = FALSE;
  369. cch = (DWORD) SendDlgItemMessage(hwndDlg, IDC_FRIENDLY_NAME,
  370. WM_GETTEXTLENGTH, 0, 0);
  371. if (cch) {
  372. // Must have a name!
  373. pwsz = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  374. if (pwsz) {
  375. GetDlgItemText(hwndDlg, IDC_FRIENDLY_NAME, pwsz, cch+1);
  376. pccert = ((VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER))->pcvp->pCertContext;
  377. if (pccert) {
  378. blob.pbData = (LPBYTE) pwsz;
  379. blob.cbData = (cch+1)*sizeof(WCHAR);
  380. f = CertSetCertificateContextProperty(pccert,
  381. CERT_FRIENDLY_NAME_PROP_ID, 0,
  382. &blob);
  383. }
  384. free(pwsz);
  385. }
  386. }
  387. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR) f);
  388. break;
  389. case PSN_KILLACTIVE:
  390. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  391. return TRUE;
  392. case PSN_RESET:
  393. // Only thing to do is to write back the Friendly name
  394. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  395. #if 0
  396. pccert = ((VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER))->pcvp->pCertContext;
  397. pwsz = PrettySubject(pccert);
  398. SetDlgItemText(hwndDlg, IDC_FRIENDLY_NAME, pwsz);
  399. free(pwsz);
  400. #endif // 0
  401. break;
  402. case PSN_HELP:
  403. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  404. ShowHelp(hwndDlg, pviewhelp);
  405. return TRUE;
  406. }
  407. case WM_COMMAND:
  408. switch (LOWORD(wParam)) {
  409. case IDC_FRIENDLY_NAME:
  410. // If they edit the friendly name, let us know
  411. if (HIWORD(wParam) == EN_CHANGE) {
  412. PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
  413. }
  414. break;
  415. case IDC_VIEW_ISSUER:
  416. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  417. if (FIsWin95) {
  418. CERT_VIEWPROPERTIES_STRUCT_A cvps;
  419. memcpy(&cvps, pviewhelp->pcvp, sizeof(cvps));
  420. cvps.hwndParent = hwndDlg;
  421. cvps.pCertContext = pviewhelp->rgpcf[1]->m_pccert;
  422. CertViewPropertiesA(&cvps);
  423. }
  424. #ifndef WIN16
  425. #ifndef MAC
  426. else {
  427. CERT_VIEWPROPERTIES_STRUCT_W cvps;
  428. memcpy(&cvps, pviewhelp->pcvp, sizeof(cvps));
  429. cvps.hwndParent = hwndDlg;
  430. cvps.pCertContext = pviewhelp->rgpcf[1]->m_pccert;
  431. CertViewPropertiesW(&cvps);
  432. }
  433. #endif // !MAC
  434. #endif // !WIN16
  435. return TRUE;
  436. case IDC_WHY:
  437. break;
  438. case IDHELP:
  439. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  440. ShowHelp(hwndDlg, pviewhelp);
  441. return TRUE;
  442. }
  443. break;
  444. #ifndef MAC
  445. case WM_HELP:
  446. case WM_CONTEXTMENU:
  447. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxDetails);
  448. #endif // !MAC
  449. }
  450. return FALSE;
  451. }
  452. INT_PTR CALLBACK ViewPageTrust(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  453. {
  454. DWORD cb;
  455. BOOL f;
  456. HBITMAP hBmp;
  457. HIMAGELIST hIml;
  458. HTREEITEM hItem;
  459. int i;
  460. PCCERT_CONTEXT pccert;
  461. PROPSHEETPAGE * ps;
  462. VIEW_HELPER * pviewhelp;
  463. LPWSTR pwsz;
  464. TV_ITEM tvi;
  465. TV_INSERTSTRUCT tvins;
  466. UINT rguiStrings[5];
  467. WCHAR rgwch[256];
  468. switch ( msg ) {
  469. case WM_INITDIALOG:
  470. // Pick up the parameter so we have all of the data
  471. ps = (PROPSHEETPAGE *) lParam;
  472. pviewhelp = GetViewHelperFromPropSheetPage(ps);
  473. if (! pviewhelp) {
  474. return(FALSE);
  475. }
  476. pccert = pviewhelp->pcvp->pCertContext;
  477. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pviewhelp);
  478. // Put the long text into the window
  479. rguiStrings[0] = IDS_TRUST_DESC;
  480. rguiStrings[1] = IDS_TRUST_DESC2;
  481. rguiStrings[2] = IDS_TRUST_DESC4;
  482. rguiStrings[3] = IDS_TRUST_DESC4;
  483. rguiStrings[4] = UINT_MAX;
  484. LoadStringsInWindow(hwndDlg, IDC_TRUST_DESC, HinstDll, rguiStrings);
  485. // Populate the trust line
  486. if (pviewhelp->pcvp->cArrayPurposes == 1) {
  487. cb = sizeof(rgwch);
  488. f = CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
  489. pviewhelp->pcvp->arrayPurposes[0],
  490. NULL, 0, rgwch, &cb);
  491. if (f && (rgwch[0] != 0)) {
  492. SetDlgItemText(hwndDlg, IDC_TRUST_EDIT, rgwch);
  493. }
  494. else {
  495. SetDlgItemTextA(hwndDlg, IDC_TRUST_EDIT,
  496. pviewhelp->pcvp->arrayPurposes[0]);
  497. }
  498. }
  499. else {
  500. ShowWindow(GetDlgItem(hwndDlg, IDC_TRUST_LIST), SW_SHOW);
  501. ShowWindow(GetDlgItem(hwndDlg, IDC_TRUST_EDIT), SW_HIDE);
  502. }
  503. // Build up the image list for the control
  504. hIml = ImageList_Create(16, 16, FALSE, 6, 0);
  505. hBmp = LoadBitmapA(HinstDll, (LPSTR) MAKEINTRESOURCE(IDB_TREE_IMAGES));
  506. ImageList_Add(hIml, hBmp, NULL);
  507. DeleteObject(hBmp);
  508. TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_TRUST_TREE), hIml, 0);
  509. // Populate the tree control
  510. tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  511. hItem = TVI_ROOT;
  512. for (i=pviewhelp->ccf-1; i>= 0; i--) {
  513. tvins.hParent = hItem;
  514. tvins.hInsertAfter = TVI_FIRST;
  515. pwsz = PrettySubject(pviewhelp->rgpcf[i]->m_pccert);
  516. tvins.item.pszText = pwsz;
  517. tvins.item.cchTextMax = lstrlen(pwsz);
  518. if (pviewhelp->rgpcf[i]->m_rgTrust[0].fTrust) {
  519. tvins.item.iImage = 2;
  520. }
  521. else if (pviewhelp->rgpcf[i]->m_rgTrust[0].fDistrust) {
  522. tvins.item.iImage = 0;
  523. }
  524. else {
  525. tvins.item.iImage = 1;
  526. }
  527. if (pviewhelp->rgpcf[i]->m_fSelfSign) {
  528. tvins.item.iImage += 3;
  529. }
  530. tvins.item.iSelectedImage = tvins.item.iImage;
  531. tvins.item.lParam = (LPARAM) pviewhelp->rgpcf[i]->m_pccert;
  532. hItem = (HTREEITEM) SendDlgItemMessage(hwndDlg, IDC_TRUST_TREE,
  533. TVM_INSERTITEM, 0,
  534. (LPARAM) &tvins);
  535. if (i != (int) (pviewhelp->ccf-1)) {
  536. TreeView_Expand(GetDlgItem(hwndDlg, IDC_TRUST_TREE),
  537. tvins.hParent, TVE_EXPAND);
  538. }
  539. }
  540. pviewhelp->hItem = hItem;
  541. //
  542. // If the leaf cert is in the root store, then disable all items
  543. //
  544. if (pviewhelp->rgpcf[0]->m_fRootStore) {
  545. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_NO), FALSE);
  546. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_YES), FALSE);
  547. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_INHERIT), FALSE);
  548. }
  549. else {
  550. //
  551. // Populate the radio button from the leaf cert
  552. //
  553. if (pviewhelp->rgpcf[0]->m_rgTrust[0].fExplicitDistrust) {
  554. SendDlgItemMessage(hwndDlg, IDC_TRUST_NO, BM_SETCHECK, 1, 0);
  555. }
  556. else if (pviewhelp->rgpcf[0]->m_rgTrust[0].fExplicitTrust) {
  557. SendDlgItemMessage(hwndDlg, IDC_TRUST_YES, BM_SETCHECK, 1, 0);
  558. }
  559. else {
  560. SendDlgItemMessage(hwndDlg, IDC_TRUST_INHERIT, BM_SETCHECK, 1, 0);
  561. if (pviewhelp->rgpcf[0]->m_fSelfSign) {
  562. pviewhelp->rgpcf[0]->m_rgTrust[0].newTrust = 4;
  563. }
  564. }
  565. if (pviewhelp->rgpcf[0]->m_fSelfSign) {
  566. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_INHERIT), FALSE);
  567. }
  568. }
  569. return TRUE;
  570. case WM_NOTIFY:
  571. switch (((NMHDR FAR *) lParam)->code) {
  572. case PSN_SETACTIVE:
  573. break;
  574. case PSN_APPLY:
  575. //
  576. // We have been asked to save any changes we have. The only possible
  577. // item that the trust on the leaf has been changed. Check to see
  578. // if this was done and do the appropriate thing
  579. //
  580. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  581. if (pviewhelp->rgpcf[0]->m_rgTrust[0].newTrust != 0) {
  582. if (pviewhelp->rgpcf[0]->m_rgTrust[0].newTrust == 4) {
  583. f = FALSE;
  584. }
  585. else {
  586. f = FModifyTrust(hwndDlg, pviewhelp->rgpcf[0]->m_pccert,
  587. pviewhelp->rgpcf[0]->m_rgTrust[0].newTrust,
  588. pviewhelp->pcvp->arrayPurposes[0]);
  589. }
  590. }
  591. else {
  592. f = TRUE;
  593. }
  594. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR) f);
  595. break;
  596. case PSN_KILLACTIVE:
  597. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  598. return TRUE;
  599. case PSN_RESET:
  600. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  601. break;
  602. case TVN_SELCHANGEDA:
  603. #ifndef WIN16
  604. case TVN_SELCHANGEDW:
  605. #endif // !WIN16
  606. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  607. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_VIEW),
  608. ((NM_TREEVIEW *) lParam)->itemNew.hItem != pviewhelp->hItem);
  609. break;
  610. case PSN_HELP:
  611. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  612. ShowHelp(hwndDlg, pviewhelp);
  613. return TRUE;
  614. }
  615. break;
  616. case WM_COMMAND:
  617. switch (LOWORD(wParam)) {
  618. case IDC_TRUST_INHERIT:
  619. case IDC_TRUST_NO:
  620. case IDC_TRUST_YES:
  621. //
  622. // The explicit trust has been changed for the leaf, make the
  623. // appropriate change to the tree control for the modification
  624. //
  625. if (HIWORD(wParam) == BN_CLICKED) {
  626. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  627. pviewhelp->rgpcf[0]->m_rgTrust[0].newTrust = (LOWORD(wParam) -
  628. IDC_TRUST_NO) + 1;
  629. PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
  630. tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_HANDLE;
  631. tvi.hItem = pviewhelp->hItem;
  632. if (LOWORD(wParam) == IDC_TRUST_INHERIT) {
  633. if (pviewhelp->rgpcf[0]->m_rgTrust[0].fTrust) {
  634. tvi.iImage = 2;
  635. }
  636. else if (pviewhelp->rgpcf[0]->m_rgTrust[0].fDistrust) {
  637. tvi.iImage = 0;
  638. }
  639. else {
  640. tvi.iImage = 1;
  641. }
  642. }
  643. else if (LOWORD(wParam) == IDC_TRUST_YES) {
  644. tvi.iImage = 2;
  645. }
  646. else {
  647. tvi.iImage = 0;
  648. }
  649. tvi.iSelectedImage = tvi.iImage;
  650. TreeView_SetItem(GetDlgItem(hwndDlg, IDC_TRUST_TREE), &tvi);
  651. }
  652. break;
  653. case IDC_TRUST_VIEW:
  654. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  655. hItem = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_TRUST_TREE));
  656. tvi.mask = TVIF_HANDLE | TVIF_PARAM;
  657. tvi.hItem = hItem;
  658. TreeView_GetItem(GetDlgItem(hwndDlg, IDC_TRUST_TREE), &tvi);
  659. #ifndef MAC
  660. if (FIsWin95) {
  661. #endif // !MAC
  662. CERT_VIEWPROPERTIES_STRUCT_A cvps;
  663. memcpy(&cvps, pviewhelp->pcvp, sizeof(cvps));
  664. cvps.hwndParent = hwndDlg;
  665. cvps.pCertContext = (PCCERT_CONTEXT) tvi.lParam;
  666. i = CertViewPropertiesA(&cvps);
  667. #ifndef MAC
  668. }
  669. #ifndef WIN16
  670. else {
  671. CERT_VIEWPROPERTIES_STRUCT_W cvps;
  672. memcpy(&cvps, pviewhelp->pcvp, sizeof(cvps));
  673. cvps.hwndParent = hwndDlg;
  674. cvps.pCertContext = (PCCERT_CONTEXT) tvi.lParam;
  675. i = CertViewPropertiesW(&cvps);
  676. }
  677. #endif // !WIN16
  678. #endif // !MAC
  679. //
  680. if (i) {
  681. // M00BUG -- must rebuild all trust lists
  682. }
  683. return TRUE;
  684. case IDHELP:
  685. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  686. ShowHelp(hwndDlg, pviewhelp);
  687. return TRUE;
  688. }
  689. break;
  690. #ifndef MAC
  691. case WM_HELP:
  692. case WM_CONTEXTMENU:
  693. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxTrust);
  694. #endif // !MAC
  695. }
  696. return FALSE;
  697. }
  698. INT_PTR CALLBACK ViewPageAdvanced(HWND hwndDlg, UINT msg, WPARAM wParam,
  699. LPARAM lParam)
  700. {
  701. DWORD cb;
  702. BOOL f;
  703. DWORD i;
  704. PROPSHEETPAGE * ps;
  705. PCCERT_CONTEXT pccert;
  706. VIEW_HELPER * pviewhelp;
  707. LPWSTR pwsz;
  708. WCHAR rgwch[200];
  709. switch ( msg ) {
  710. case WM_INITDIALOG:
  711. ps = (PROPSHEETPAGE *) lParam;
  712. pviewhelp = GetViewHelperFromPropSheetPage(ps);
  713. if (! pviewhelp) {
  714. return(FALSE);
  715. }
  716. pccert = pviewhelp->pcvp->pCertContext;
  717. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pccert);
  718. //
  719. // Stick the "normal" items into the list
  720. //
  721. for (i=IDS_ADV_VERSION; i<= IDS_ADV_PUBKEY; i++) {
  722. LoadString(HinstDll, i, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  723. SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0,
  724. (LPARAM) rgwch);
  725. }
  726. //
  727. // Stick the extensions into the list
  728. //
  729. for (i=0; i<pccert->pCertInfo->cExtension; i++) {
  730. if (FIsWin95) {
  731. SendDlgItemMessageA(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0,
  732. (LPARAM) pccert->pCertInfo->rgExtension[i].pszObjId);
  733. }
  734. #ifndef MAC
  735. else {
  736. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  737. pccert->pCertInfo->rgExtension[i].pszObjId, -1,
  738. rgwch, sizeof(rgwch)/sizeof(WCHAR));
  739. SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0,
  740. (LPARAM) rgwch);
  741. }
  742. #endif // !MAC
  743. }
  744. SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_SETCURSEL, 0, 0);
  745. ViewPageAdvanced(hwndDlg, WM_COMMAND,
  746. MAKELONG(IDC_LIST1, LBN_SELCHANGE), 0);
  747. SendDlgItemMessage(hwndDlg, IDC_EDIT1, EM_SETEVENTMASK, 0, ENM_LINK);
  748. return TRUE;
  749. case WM_NOTIFY:
  750. switch (((NMHDR FAR *) lParam)->code) {
  751. case PSN_SETACTIVE:
  752. break;
  753. case PSN_APPLY:
  754. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
  755. break;
  756. case PSN_KILLACTIVE:
  757. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  758. return TRUE;
  759. case PSN_RESET:
  760. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  761. break;
  762. case EN_LINK:
  763. if (((ENLINK FAR *) lParam)->msg == WM_LBUTTONDOWN) {
  764. f = FNoteDlgNotifyLink(hwndDlg, (ENLINK *) lParam, NULL);
  765. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR) f);
  766. return f;
  767. }
  768. break;
  769. case PSN_HELP:
  770. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  771. ShowHelp(hwndDlg, pviewhelp);
  772. return TRUE;
  773. }
  774. case WM_COMMAND:
  775. switch (LOWORD(wParam)) {
  776. case IDC_LIST1:
  777. if (HIWORD(wParam) == LBN_SELCHANGE) {
  778. pccert = (PCERT_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
  779. i = (int) SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_GETCARETINDEX,
  780. 0, 0);
  781. if (i <= IDS_ADV_PUBKEY - IDS_ADV_VERSION) {
  782. switch (i + IDS_ADV_VERSION) {
  783. case IDS_ADV_VERSION: // Version
  784. rgwch[0] = L'V';
  785. rgwch[1] = (WCHAR) ('0' + pccert->pCertInfo->dwVersion+1);
  786. rgwch[2] = 0;
  787. SetDlgItemText(hwndDlg, IDC_EDIT1, rgwch);
  788. break;
  789. case IDS_ADV_SER_NUM: // Serial Number
  790. FormatSerialNo(hwndDlg, IDC_EDIT1, pccert);
  791. break;
  792. case IDS_ADV_SIG_ALG: // Signature Alg
  793. FormatAlgorithm(hwndDlg, IDC_EDIT1, pccert);
  794. break;
  795. case IDS_ADV_ISSUER: // Issuer
  796. FormatIssuer(hwndDlg, IDC_EDIT1, pccert,
  797. CERT_X500_NAME_STR);
  798. break;
  799. case IDS_ADV_SUBJECT: // Subject
  800. FormatSubject(hwndDlg, IDC_EDIT1, pccert,
  801. CERT_X500_NAME_STR);
  802. break;
  803. case IDS_ADV_PUBKEY: // Public Key
  804. FormatBinary(hwndDlg, IDC_EDIT1,
  805. pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  806. pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
  807. break;
  808. case IDS_ADV_NOTBEFORE: // Effective Date
  809. FormatDate(hwndDlg, IDC_EDIT1,
  810. pccert->pCertInfo->NotBefore);
  811. break;
  812. case IDS_ADV_NOTAFTER: // Expiration Date
  813. FormatDate(hwndDlg, IDC_EDIT1,
  814. pccert->pCertInfo->NotAfter);
  815. break;
  816. }
  817. }
  818. else {
  819. i -= (IDS_ADV_PUBKEY - IDS_ADV_VERSION + 1);
  820. // Assert( i < pccert->pCertInfo->cExtension );
  821. cb = 0;
  822. f = CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
  823. pccert->pCertInfo->rgExtension[i].pszObjId,
  824. pccert->pCertInfo->rgExtension[i].Value.pbData,
  825. pccert->pCertInfo->rgExtension[i].Value.cbData,
  826. 0, &cb);
  827. if (f && (cb > 0)) {
  828. pwsz = (LPWSTR) malloc(cb * sizeof(WCHAR));
  829. pwsz[0] = 0;
  830. CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
  831. pccert->pCertInfo->rgExtension[i].pszObjId,
  832. pccert->pCertInfo->rgExtension[i].Value.pbData,
  833. pccert->pCertInfo->rgExtension[i].Value.cbData,
  834. pwsz, &cb);
  835. SetDlgItemText(hwndDlg, IDC_EDIT1, pwsz);
  836. RecognizeURLs(GetDlgItem(hwndDlg, IDC_EDIT1));
  837. free(pwsz);
  838. }
  839. else {
  840. SetDlgItemTextA(hwndDlg, IDC_EDIT1, "");
  841. }
  842. }
  843. }
  844. break;
  845. case IDHELP:
  846. pviewhelp = (VIEW_HELPER *) GetWindowLongPtr(hwndDlg, DWLP_USER);
  847. ShowHelp(hwndDlg, pviewhelp);
  848. return TRUE;
  849. }
  850. #ifndef MAC
  851. case WM_HELP:
  852. case WM_CONTEXTMENU:
  853. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxAdvanced);
  854. #endif // !MAC
  855. }
  856. return FALSE;
  857. }
  858. INT_PTR CALLBACK ViewPageTrustCryptUI(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  859. {
  860. DWORD cb;
  861. BOOL f;
  862. PROPSHEETPAGE * ps;
  863. VIEW_HELPER * pviewhelp;
  864. UINT rguiStrings[5];
  865. WCHAR rgwch[256];
  866. switch ( msg ) {
  867. case WM_INITDIALOG:
  868. // Pick up the parameter so we have all of the data
  869. ps = (PROPSHEETPAGE *)lParam;
  870. pviewhelp = GetViewHelperFromPropSheetPage(ps);
  871. if (! pviewhelp) {
  872. return(FALSE);
  873. }
  874. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pviewhelp);
  875. // Put the long text into the window
  876. rguiStrings[0] = IDS_TRUST_DESC;
  877. rguiStrings[1] = IDS_TRUST_DESC2;
  878. rguiStrings[2] = IDS_TRUST_DESC4;
  879. rguiStrings[3] = IDS_TRUST_DESC4;
  880. rguiStrings[4] = UINT_MAX;
  881. LoadStringsInWindow(hwndDlg, IDC_TRUST_DESC, HinstDll, rguiStrings);
  882. // Populate the trust line
  883. if (pviewhelp->pcvp->cArrayPurposes == 1) {
  884. cb = sizeof(rgwch);
  885. f = CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
  886. pviewhelp->pcvp->arrayPurposes[0],
  887. NULL, 0, rgwch, &cb);
  888. if (f && (rgwch[0] != 0)) {
  889. SetDlgItemText(hwndDlg, IDC_TRUST_EDIT, rgwch);
  890. }
  891. else {
  892. SetDlgItemTextA(hwndDlg, IDC_TRUST_EDIT,
  893. pviewhelp->pcvp->arrayPurposes[0]);
  894. }
  895. }
  896. else {
  897. ShowWindow(GetDlgItem(hwndDlg, IDC_TRUST_LIST), SW_SHOW);
  898. ShowWindow(GetDlgItem(hwndDlg, IDC_TRUST_EDIT), SW_HIDE);
  899. }
  900. //
  901. // If the leaf cert is in the root store, then disable all items
  902. //
  903. if (pviewhelp->rgpcf[pviewhelp->icf]->m_fRootStore ||
  904. !pviewhelp->rgpcf[pviewhelp->icf]->m_fLeaf) {
  905. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_NO), FALSE);
  906. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_YES), FALSE);
  907. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_INHERIT), FALSE);
  908. }
  909. else {
  910. //
  911. // Populate the radio button from the leaf cert
  912. //
  913. if (pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].fExplicitDistrust) {
  914. SendDlgItemMessage(hwndDlg, IDC_TRUST_NO, BM_SETCHECK, 1, 0);
  915. }
  916. else if (pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].fExplicitTrust) {
  917. SendDlgItemMessage(hwndDlg, IDC_TRUST_YES, BM_SETCHECK, 1, 0);
  918. }
  919. else {
  920. SendDlgItemMessage(hwndDlg, IDC_TRUST_INHERIT, BM_SETCHECK, 1, 0);
  921. if (pviewhelp->rgpcf[pviewhelp->icf]->m_fSelfSign) {
  922. pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].newTrust = 4;
  923. }
  924. }
  925. if (pviewhelp->rgpcf[pviewhelp->icf]->m_fSelfSign) {
  926. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_INHERIT), FALSE);
  927. }
  928. if (pviewhelp->rgpcf[pviewhelp->icf]->m_fExpired) {
  929. EnableWindow(GetDlgItem(hwndDlg, IDC_TRUST_YES), FALSE);
  930. }
  931. }
  932. return TRUE;
  933. case WM_NOTIFY:
  934. switch (((NMHDR FAR *) lParam)->code) {
  935. case PSN_SETACTIVE:
  936. break;
  937. case PSN_APPLY:
  938. //
  939. // We have been asked to save any changes we have. The only possible
  940. // item that the trust on the leaf has been changed. Check to see
  941. // if this was done and do the appropriate thing
  942. //
  943. pviewhelp = (VIEW_HELPER *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  944. if (pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].newTrust != 0) {
  945. if (pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].newTrust == 4) {
  946. f = FALSE;
  947. }
  948. else {
  949. f = FModifyTrust(hwndDlg, pviewhelp->rgpcf[pviewhelp->icf]->m_pccert,
  950. pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].newTrust,
  951. pviewhelp->pcvp->arrayPurposes[0]);
  952. }
  953. }
  954. else {
  955. f = TRUE;
  956. }
  957. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR) f);
  958. break;
  959. case PSN_KILLACTIVE:
  960. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  961. return TRUE;
  962. case PSN_RESET:
  963. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  964. break;
  965. case PSN_HELP:
  966. pviewhelp = (VIEW_HELPER *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  967. ShowHelp(hwndDlg, pviewhelp);
  968. return TRUE;
  969. }
  970. break;
  971. case WM_COMMAND:
  972. switch (LOWORD(wParam)) {
  973. case IDC_TRUST_INHERIT:
  974. case IDC_TRUST_NO:
  975. case IDC_TRUST_YES:
  976. //
  977. // The explicit trust has been changed for the cert.
  978. //
  979. if (HIWORD(wParam) == BN_CLICKED) {
  980. pviewhelp = (VIEW_HELPER *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  981. pviewhelp->rgpcf[pviewhelp->icf]->m_rgTrust[0].newTrust = (LOWORD(wParam) - IDC_TRUST_NO) + 1;
  982. PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
  983. }
  984. break;
  985. case IDHELP:
  986. pviewhelp = (VIEW_HELPER *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  987. ShowHelp(hwndDlg, pviewhelp);
  988. return TRUE;
  989. }
  990. break;
  991. #ifndef MAC
  992. case WM_HELP:
  993. case WM_CONTEXTMENU:
  994. return OnContextHelp(hwndDlg, msg, wParam, lParam, RgctxTrust);
  995. #endif // !MAC
  996. }
  997. return FALSE;
  998. }
  999. HRESULT HrDoViewPropsTrustWork(PCERT_VIEWPROPERTIES_STRUCT_W pcvp,
  1000. VIEW_HELPER * pviewhelp, BOOL fGetState) {
  1001. HRESULT hr;
  1002. CCertFrame * pcfRoot = NULL;
  1003. pviewhelp->pcvp = pcvp;
  1004. //
  1005. // Lets go out and try to find out what we can on the trust and validity
  1006. // of this message. This is done by calling the trust provider that is
  1007. // around and going to town with it
  1008. //
  1009. hr = HrDoTrustWork(pcvp->pCertContext,
  1010. (CERT_TRUST_DO_FULL_SEARCH |
  1011. (pcvp->dwFlags &
  1012. (CM_ADD_CERT_STORES | ~CM_VIEWFLAGS_MASK))),
  1013. // Why would we want to mask out these errors ?????
  1014. (DWORD) (CERT_VALIDITY_CRL_OUT_OF_DATE |
  1015. CERT_VALIDITY_UNKNOWN_CRITICAL_EXTENSION |
  1016. CERT_VALIDITY_NO_CRL_FOUND // |
  1017. // CERT_VALIDITY_NO_TRUST_DATA
  1018. ),
  1019. pcvp->cArrayPurposes, pcvp->arrayPurposes, pcvp->hprov,
  1020. pcvp->cRootStores, pcvp->rghstoreRoots,
  1021. pcvp->cStores, pcvp->rghstoreCAs,
  1022. pcvp->cTrustStores, pcvp->rghstoreTrust, NULL, 0, &pcfRoot,
  1023. &pviewhelp->ccf, pviewhelp->rgpcf,
  1024. fGetState ? &pviewhelp->hWVTState : NULL);
  1025. if (pcfRoot) {
  1026. delete pcfRoot;
  1027. }
  1028. return(hr);
  1029. }
  1030. BOOL LoadRichEdit(void) {
  1031. // We use the common controls -- so make sure they have been loaded
  1032. if (HmodRichEdit == NULL) {
  1033. HmodRichEdit = LoadLibraryA("RichEd32.dll");
  1034. if (HmodRichEdit == NULL) {
  1035. return(FALSE);
  1036. }
  1037. }
  1038. return(TRUE);
  1039. }
  1040. BOOL CertViewPropertiesX(PCERT_VIEWPROPERTIES_STRUCT_W pcvp);
  1041. INT_PTR CALLBACK CertViewPageSubClassProc(HWND hWndDlg, UINT nMsg,
  1042. WPARAM wParam, LPARAM lParam)
  1043. {
  1044. INT_PTR iReturn = FALSE;
  1045. CRYPTUI_INITDIALOG_STRUCT* pcids;
  1046. PROPSHEETPAGEW* ppsp;
  1047. PROPSHEETPAGEW pspTemp;
  1048. VIEW_CALLBACK_HELPER* pviewcbhelp;
  1049. // For WM_INITDIALOG make sure the property sheet gets what it expects
  1050. // as the lParam
  1051. if (WM_INITDIALOG == nMsg) {
  1052. ppsp = (PROPSHEETPAGE*)lParam;
  1053. pcids = (CRYPTUI_INITDIALOG_STRUCT*)(ppsp->lParam);
  1054. pviewcbhelp = (VIEW_CALLBACK_HELPER*)(pcids->lParam);
  1055. memcpy(&pspTemp, ppsp, sizeof(pspTemp));
  1056. pspTemp.pfnDlgProc = pviewcbhelp->pfnDlgProc;
  1057. pspTemp.lParam = pviewcbhelp->lParam;
  1058. iReturn = pviewcbhelp->pfnDlgProc(hWndDlg, nMsg, wParam,
  1059. (LPARAM)&pspTemp);
  1060. SetWindowLongPtr(hWndDlg, DWLP_DLGPROC, (LONG_PTR)pviewcbhelp->pfnDlgProc);
  1061. }
  1062. return iReturn;
  1063. }
  1064. BOOL CertViewUI(BOOL fWide, PCERT_VIEWPROPERTIES_STRUCT_W pcvp)
  1065. {
  1066. ULONG cPages = pcvp->cArrayPropSheetPages + 1;
  1067. CRYPTUI_VIEWCERTIFICATE_STRUCTW cvcs = {0};
  1068. HRESULT hrTrust = E_FAIL;
  1069. DWORD i;
  1070. DWORD iPage;
  1071. PROPSHEETPAGEW * ppsp;
  1072. BOOL ret;
  1073. VIEW_HELPER viewhelp = {0};
  1074. VIEW_CALLBACK_HELPER* pviewcbhelp = NULL;
  1075. VIEW_CALLBACK_HELPER* pviewcbhelp2;
  1076. // Allocate space to hold the property sheet information to hand to
  1077. // CryptUI
  1078. ppsp = (PROPSHEETPAGEW *) malloc(cPages * sizeof(PROPSHEETPAGEW));
  1079. // CryptUI insists on passing back a CRYPTUI_INITDIALOG_STRUCT when
  1080. // it calls the property sheet pages which breaks the existing
  1081. // CryptDlg implementations. To get around this we force everything
  1082. // that says it knows nothing of CryptUI to call through a local DlgProc
  1083. // first so that we can safely forward the lParam onto the real
  1084. // property pages DlgProc.
  1085. // Allocate space to hold the re-direction information
  1086. if (!(pcvp->dwFlags & CERTVIEW_CRYPTUI_LPARAM)) {
  1087. pviewcbhelp = (VIEW_CALLBACK_HELPER*)malloc(cPages *
  1088. sizeof(VIEW_CALLBACK_HELPER));
  1089. }
  1090. // Fill out the property sheet information
  1091. if ((NULL != ppsp) &&
  1092. ((pcvp->dwFlags & CERTVIEW_CRYPTUI_LPARAM) || (NULL != pviewcbhelp))) {
  1093. viewhelp.dwSentry = VIEW_HELPER_SENTRY;
  1094. hrTrust = HrDoViewPropsTrustWork(pcvp, &viewhelp, TRUE);
  1095. if (FAILED(hrTrust)) {
  1096. return FALSE;
  1097. }
  1098. if (pcvp->cArrayPurposes == 0) {
  1099. pcvp->dwFlags |= CM_HIDE_TRUSTPAGE;
  1100. }
  1101. memset(ppsp, 0, cPages * sizeof(PROPSHEETPAGEW));
  1102. iPage = 0;
  1103. cPages = 0;
  1104. if (!(pcvp->dwFlags & CM_HIDE_TRUSTPAGE)) {
  1105. ppsp[iPage].dwSize = sizeof(ppsp[0]);
  1106. ppsp[iPage].dwFlags = 0; // fHelp ? PSP_HASHELP : 0;
  1107. ppsp[iPage].hInstance = HinstDll;
  1108. ppsp[iPage].pszTemplate = MAKEINTRESOURCE(IDD_CRYPTUI_CERTPROP_TRUST);
  1109. ppsp[iPage].hIcon = 0;
  1110. ppsp[iPage].pszTitle = NULL;
  1111. ppsp[iPage].pfnDlgProc = ViewPageTrustCryptUI;
  1112. ppsp[iPage].lParam = (LPARAM)&viewhelp;
  1113. ppsp[iPage].pfnCallback = 0;
  1114. ppsp[iPage].pcRefParent = NULL;
  1115. iPage++;
  1116. cPages++;
  1117. }
  1118. //
  1119. // Copy over the users pages
  1120. //
  1121. if (pcvp->cArrayPropSheetPages) {
  1122. memcpy(&ppsp[iPage], pcvp->arrayPropSheetPages,
  1123. pcvp->cArrayPropSheetPages * sizeof(PROPSHEETPAGEW));
  1124. cPages += pcvp->cArrayPropSheetPages;
  1125. }
  1126. // If the user knows nothing about the CryptUI structures, subclass
  1127. // the DlgProc so that they get what they expect.
  1128. if (!(pcvp->dwFlags & CERTVIEW_CRYPTUI_LPARAM)) {
  1129. for (pviewcbhelp2 = pviewcbhelp; iPage < cPages;
  1130. iPage++, pviewcbhelp2++) {
  1131. pviewcbhelp2->pfnDlgProc = ppsp[iPage].pfnDlgProc;
  1132. pviewcbhelp2->lParam = ppsp[iPage].lParam;
  1133. ppsp[iPage].pfnDlgProc = CertViewPageSubClassProc;
  1134. ppsp[iPage].lParam = (LPARAM)pviewcbhelp2;
  1135. }
  1136. }
  1137. }
  1138. else {
  1139. // That's an error, but we'll ignore it and just not use them
  1140. cPages = 0;
  1141. }
  1142. cvcs.dwSize = sizeof(cvcs);
  1143. cvcs.hwndParent = pcvp->hwndParent;
  1144. cvcs.dwFlags = CRYPTUI_DISABLE_ADDTOSTORE;
  1145. if (!(pcvp->dwFlags & CM_NO_NAMECHANGE)) {
  1146. cvcs.dwFlags |= CRYPTUI_ENABLE_EDITPROPERTIES;
  1147. }
  1148. cvcs.szTitle = pcvp->szTitle;
  1149. cvcs.pCertContext = pcvp->pCertContext;
  1150. cvcs.cPurposes = pcvp->cArrayPurposes;
  1151. cvcs.rgszPurposes = (LPCSTR *) pcvp->arrayPurposes;
  1152. cvcs.hWVTStateData = viewhelp.hWVTState;
  1153. cvcs.fpCryptProviderDataTrustedUsage = hrTrust;
  1154. // cvcs.idxSigner = 0;
  1155. // cvcs.idxCert = 0;
  1156. // cvcs.fCounterSigner = FALSE;
  1157. // cvcs.idxCounterSigner = 0;
  1158. cvcs.cStores = pcvp->cStores;
  1159. cvcs.rghStores = pcvp->rghstoreCAs;
  1160. cvcs.cPropSheetPages = cPages;
  1161. cvcs.rgPropSheetPages = ppsp;
  1162. // Pages are:
  1163. // 0 - General - 0
  1164. // 1 - Detail - 1
  1165. // 2 - Edit Trust - 0x8000
  1166. // 3 - Advanced - 2
  1167. switch (pcvp->nStartPage) {
  1168. case 0:
  1169. case 1:
  1170. cvcs.nStartPage = pcvp->nStartPage;
  1171. break;
  1172. case 3:
  1173. cvcs.nStartPage = 2;
  1174. break;
  1175. case 2:
  1176. cvcs.nStartPage = 0x8000;
  1177. break;
  1178. default:
  1179. // Add-on page, set the high bit
  1180. if (pcvp->dwFlags & CM_HIDE_TRUSTPAGE) {
  1181. cvcs.nStartPage = (pcvp->nStartPage - 2) | 0x8000;
  1182. }
  1183. else {
  1184. cvcs.nStartPage = (pcvp->nStartPage - 3) | 0x8000;
  1185. }
  1186. break;
  1187. }
  1188. // BUGBUG: CryptUI does not allow for these CryptDlg parameters:
  1189. // pcvp->cRootStores
  1190. // pcvp->rghstoreRoots
  1191. // pcvp->cTrustStores
  1192. // pcvp->rghstoreTrust
  1193. // pcvp->hprov
  1194. // pcvp->lCustData
  1195. // pcvp->szHelpFileName
  1196. // pcvp->szHelpId
  1197. if (fWide) {
  1198. ret = CryptUIDlgViewCertificateW(&cvcs, NULL);
  1199. }
  1200. else {
  1201. ret = CryptUIDlgViewCertificateA((PCRYPTUI_VIEWCERTIFICATE_STRUCTA) &cvcs, NULL);
  1202. }
  1203. FreeWVTHandle(viewhelp.hWVTState);
  1204. if (ppsp) {
  1205. free(ppsp);
  1206. }
  1207. if (pviewcbhelp) {
  1208. free(pviewcbhelp);
  1209. }
  1210. if (viewhelp.rgpcf != NULL) {
  1211. for (i=0; i<viewhelp.ccf; i++) {
  1212. delete viewhelp.rgpcf[i];
  1213. }
  1214. }
  1215. return ret;
  1216. }
  1217. BOOL APIENTRY CertViewPropertiesA(PCERT_VIEWPROPERTIES_STRUCT_A pcvp)
  1218. {
  1219. if (CryptUIAvailable()) {
  1220. return CertViewUI(FALSE, (PCERT_VIEWPROPERTIES_STRUCT_W) pcvp);
  1221. }
  1222. #ifndef MAC
  1223. DWORD cch;
  1224. #endif // !MAC
  1225. BOOL ret = FALSE;
  1226. CERT_VIEWPROPERTIES_STRUCT_W cvpw = {0};
  1227. if (! (LoadRichEdit())) {
  1228. return(FALSE);
  1229. }
  1230. //
  1231. // Need to do some Wide Charactoring to move to unicode
  1232. //
  1233. memcpy(&cvpw, pcvp, pcvp->dwSize);
  1234. #ifndef MAC
  1235. if (!FIsWin95) {
  1236. if (cvpw.szTitle != NULL) {
  1237. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcvp->szTitle, -1,
  1238. NULL, 0);
  1239. cvpw.szTitle = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  1240. if (cvpw.szTitle == NULL) {
  1241. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1242. goto ExitW;
  1243. }
  1244. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcvp->szTitle, -1,
  1245. (LPWSTR) cvpw.szTitle, cch+1);
  1246. }
  1247. if (cvpw.szHelpFileName != NULL) {
  1248. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcvp->szHelpFileName, -1,
  1249. NULL, 0);
  1250. cvpw.szHelpFileName = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  1251. if (cvpw.szHelpFileName == NULL) {
  1252. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1253. goto ExitW;
  1254. }
  1255. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcvp->szHelpFileName, -1,
  1256. (LPWSTR) cvpw.szHelpFileName, cch+1);
  1257. }
  1258. }
  1259. #endif // !MAC
  1260. ret = CertViewPropertiesX(&cvpw);
  1261. #ifndef MAC
  1262. ExitW:
  1263. if (!FIsWin95)
  1264. {
  1265. if (cvpw.szTitle != NULL) free((LPWSTR) cvpw.szTitle);
  1266. if (cvpw.szHelpFileName != NULL) free((LPWSTR) cvpw.szHelpFileName);
  1267. }
  1268. #endif // !MAC
  1269. return ret;
  1270. }
  1271. #ifndef WIN16
  1272. #ifndef MAC
  1273. //// CertViewPropertiesW
  1274. //
  1275. // Description:
  1276. // This routine will display the property view dialog for the given
  1277. // certificate
  1278. //
  1279. BOOL CertViewPropertiesW(PCERT_VIEWPROPERTIES_STRUCT_W pcvp)
  1280. {
  1281. if (CryptUIAvailable()) {
  1282. return CertViewUI(TRUE, pcvp);
  1283. }
  1284. if (! (LoadRichEdit())) {
  1285. return(FALSE);
  1286. }
  1287. return CertViewPropertiesX(pcvp);
  1288. }
  1289. #endif // !MAC
  1290. #endif // !WIN16
  1291. BOOL CertViewPropertiesX(PCERT_VIEWPROPERTIES_STRUCT_W pcvp)
  1292. {
  1293. int cPages = 4;
  1294. BOOL fHelp;
  1295. BOOL fRetValue = FALSE;
  1296. HRESULT hr;
  1297. PROPSHEETPAGE * ppage = NULL;
  1298. int ret;
  1299. WCHAR rgwch[100];
  1300. VIEW_HELPER viewhelp = {0};
  1301. #ifndef MAC
  1302. #ifndef WIN16
  1303. INITCOMMONCONTROLSEX initcomm = {
  1304. sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES
  1305. };
  1306. #else
  1307. INITCOMMONCONTROLSEX initcomm = {
  1308. sizeof(initcomm), ICC_LISTVIEW_CLASSES
  1309. };
  1310. #endif // !WIN16
  1311. #endif // !MAC
  1312. if (pcvp->dwSize < sizeof(CERT_VIEWPROPERTIES_STRUCT_W)) {
  1313. return FALSE;
  1314. }
  1315. viewhelp.dwSentry = VIEW_HELPER_SENTRY;
  1316. //
  1317. hr = HrDoViewPropsTrustWork(pcvp, &viewhelp, FALSE);
  1318. if (FAILED(hr)) {
  1319. return FALSE;
  1320. }
  1321. if (pcvp->cArrayPurposes == 0) {
  1322. pcvp->dwFlags |= CM_HIDE_TRUSTPAGE;
  1323. }
  1324. //
  1325. fHelp = pcvp->dwFlags & CM_SHOW_HELP;
  1326. //
  1327. // Deal with some DBCS issues
  1328. //
  1329. #ifndef MAC
  1330. InitCommonControlsEx(&initcomm);
  1331. #endif // !MAC
  1332. //
  1333. // Build up the list of pages we are going to use in the dialog
  1334. //
  1335. cPages += pcvp->cArrayPropSheetPages;
  1336. ppage = (PROPSHEETPAGE *) malloc(cPages * sizeof(PROPSHEETPAGE));
  1337. if (ppage == NULL) {
  1338. goto Exit;
  1339. }
  1340. memset(ppage, 0, cPages * sizeof(PROPSHEETPAGE));
  1341. ppage[0].dwSize = sizeof(ppage[0]);
  1342. ppage[0].dwFlags = fHelp ? PSP_HASHELP : 0;
  1343. ppage[0].hInstance = HinstDll;
  1344. ppage[0].pszTemplate = MAKEINTRESOURCE(IDD_CERTPROP_GENERAL);
  1345. ppage[0].hIcon = 0;
  1346. ppage[0].pszTitle = NULL;
  1347. ppage[0].pfnDlgProc = ViewPageGeneral;
  1348. ppage[0].lParam = (LPARAM) &viewhelp;
  1349. ppage[0].pfnCallback = 0;
  1350. ppage[0].pcRefParent = NULL;
  1351. cPages = 1;
  1352. if (!(pcvp->dwFlags & CM_HIDE_DETAILPAGE)) {
  1353. ppage[cPages].dwSize = sizeof(ppage[0]);
  1354. ppage[cPages].dwFlags = fHelp ? PSP_HASHELP : 0;
  1355. ppage[cPages].hInstance = HinstDll;
  1356. ppage[cPages].pszTemplate = MAKEINTRESOURCE(IDD_CERTPROP_DETAILS);
  1357. ppage[cPages].hIcon = 0;
  1358. ppage[cPages].pszTitle = NULL;
  1359. ppage[cPages].pfnDlgProc = ViewPageDetails;
  1360. ppage[cPages].lParam = (LPARAM) &viewhelp;
  1361. ppage[cPages].pfnCallback = 0;
  1362. ppage[cPages].pcRefParent = NULL;
  1363. cPages += 1;
  1364. }
  1365. if (!(pcvp->dwFlags & CM_HIDE_TRUSTPAGE)) {
  1366. ppage[cPages].dwSize = sizeof(ppage[0]);
  1367. ppage[cPages].dwFlags = fHelp ? PSP_HASHELP : 0;
  1368. ppage[cPages].hInstance = HinstDll;
  1369. ppage[cPages].pszTemplate = MAKEINTRESOURCE(IDD_CERTPROP_TRUST);
  1370. ppage[cPages].hIcon = 0;
  1371. ppage[cPages].pszTitle = NULL;
  1372. ppage[cPages].pfnDlgProc = ViewPageTrust;
  1373. ppage[cPages].lParam = (LPARAM) &viewhelp;
  1374. ppage[cPages].pfnCallback = 0;
  1375. ppage[cPages].pcRefParent = NULL;
  1376. cPages += 1;
  1377. }
  1378. if (!(pcvp->dwFlags & CM_HIDE_ADVANCEPAGE)) {
  1379. ppage[cPages].dwSize = sizeof(ppage[0]);
  1380. ppage[cPages].dwFlags = fHelp ? PSP_HASHELP : 0;
  1381. ppage[cPages].hInstance = HinstDll;
  1382. ppage[cPages].pszTemplate = MAKEINTRESOURCE(IDD_CERTPROP_ADVANCED);
  1383. ppage[cPages].hIcon = 0;
  1384. ppage[cPages].pszTitle = NULL;
  1385. ppage[cPages].pfnDlgProc = ViewPageAdvanced;
  1386. ppage[cPages].lParam = (LPARAM) &viewhelp;
  1387. ppage[cPages].pfnCallback = 0;
  1388. ppage[cPages].pcRefParent = NULL;
  1389. cPages += 1;
  1390. }
  1391. //
  1392. // Copy over the users pages
  1393. //
  1394. memcpy(&ppage[cPages], pcvp->arrayPropSheetPages,
  1395. pcvp->cArrayPropSheetPages * sizeof(PROPSHEETPAGE));
  1396. cPages += pcvp->cArrayPropSheetPages;
  1397. #ifndef MAC
  1398. if (FIsWin95) {
  1399. #endif // !MAC
  1400. PROPSHEETHEADERA hdr;
  1401. memset(&hdr, 0, sizeof(hdr));
  1402. hdr.dwSize = /*sizeof(hdr)*/ 0x28;
  1403. hdr.dwFlags = PSH_PROPSHEETPAGE;
  1404. hdr.hwndParent = pcvp->hwndParent;
  1405. hdr.hInstance = HinstDll;
  1406. hdr.hIcon = NULL;
  1407. if (pcvp->szTitle != NULL) {
  1408. hdr.pszCaption = (LPSTR) pcvp->szTitle;
  1409. }
  1410. else {
  1411. LoadStringA(HinstDll, IDS_VIEW_TITLE, (LPSTR) rgwch, ARRAYSIZE(rgwch));
  1412. hdr.pszCaption = (LPSTR) rgwch;
  1413. }
  1414. hdr.nPages = cPages;
  1415. hdr.nStartPage = pcvp->nStartPage;
  1416. hdr.ppsp = (PROPSHEETPAGEA *) ppage;
  1417. hdr.pfnCallback = NULL;
  1418. ret = (int) PropertySheetA(&hdr);
  1419. #ifndef MAC
  1420. }
  1421. #ifndef WIN16
  1422. else {
  1423. PROPSHEETHEADERW hdr;
  1424. memset(&hdr, 0, sizeof(hdr));
  1425. hdr.dwSize = /*sizeof(hdr)*/ 0x28;
  1426. hdr.dwFlags = PSH_PROPSHEETPAGE;
  1427. hdr.hwndParent = pcvp->hwndParent;
  1428. hdr.hInstance = HinstDll;
  1429. hdr.hIcon = NULL;
  1430. if (pcvp->szTitle != NULL) {
  1431. hdr.pszCaption = pcvp->szTitle;
  1432. }
  1433. else {
  1434. LoadStringW(HinstDll, IDS_VIEW_TITLE, rgwch, ARRAYSIZE(rgwch));
  1435. hdr.pszCaption = rgwch;
  1436. }
  1437. hdr.nPages = cPages;
  1438. hdr.nStartPage = pcvp->nStartPage;
  1439. hdr.ppsp = ppage;
  1440. hdr.pfnCallback = NULL;
  1441. ret = (int) PropertySheetW(&hdr);
  1442. }
  1443. #endif // !WIN16
  1444. #endif // !MAC
  1445. fRetValue = (ret == IDOK);
  1446. Exit:
  1447. if (ppage)
  1448. free(ppage);
  1449. return fRetValue;
  1450. }