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.

1048 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: trustdlg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // PersonalTrustDialog.cpp
  12. //
  13. // Implementation of the dialog that manages the personal trust database editing.
  14. //
  15. #include "global.hxx"
  16. #include "cryptreg.h"
  17. #include "pkialloc.h"
  18. #include "pertrust.h"
  19. #include "resource.h"
  20. #include "cryptui.h"
  21. #include <ole2.h>
  22. #include <commctrl.h>
  23. #include "secauth.h"
  24. #include <md5.h>
  25. inline LONG Width(const RECT& rc)
  26. {
  27. return rc.right - rc.left;
  28. }
  29. inline LONG Height(const RECT& rc)
  30. {
  31. return rc.bottom - rc.top;
  32. }
  33. inline POINT Center(const RECT& rc)
  34. {
  35. POINT pt;
  36. pt.x = (rc.left + rc.right) / 2;
  37. pt.y = (rc.top + rc.bottom) / 2;
  38. return pt;
  39. }
  40. void EnsureOnScreen(HWND hwnd)
  41. //
  42. // Ensure the window is on the screen
  43. //
  44. {
  45. RECT rcScreen, rcWindow;
  46. if (SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, 0)
  47. && GetWindowRect(hwnd, &rcWindow))
  48. {
  49. int dx = 0;
  50. int dy = 0;
  51. if (rcWindow.top < rcScreen.top)
  52. dy = rcScreen.top - rcWindow.top; // move down
  53. else if (rcWindow.bottom > rcScreen.bottom)
  54. dy = rcScreen.bottom - rcWindow.bottom; // move up
  55. if (rcWindow.left < rcScreen.left)
  56. dx = rcScreen.left - rcWindow.left; // move right
  57. else if (rcWindow.right > rcScreen.right)
  58. dx = rcScreen.right - rcWindow.right; // move left
  59. if (dx || dy)
  60. {
  61. SetWindowPos(hwnd,
  62. NULL,
  63. rcWindow.left+dx,
  64. rcWindow.top+dy,
  65. 0,0,
  66. SWP_NOSIZE | SWP_NOZORDER
  67. );
  68. }
  69. }
  70. }
  71. /////////////////////////////////////////////////
  72. class CDialogTrustDB
  73. {
  74. private:
  75. HWND m_hWnd;
  76. HWND m_hWndParent;
  77. IPersonalTrustDB* m_pdb;
  78. BOOL m_fPropertySheet;
  79. ULONG m_cTrust;
  80. TRUSTLISTENTRY* m_rgTrust;
  81. public:
  82. CDialogTrustDB(BOOL fPropSheet = TRUE, HWND hWndParent = NULL);
  83. ~CDialogTrustDB();
  84. void OnInitDialog();
  85. HWND GetWindow();
  86. void SetWindow(HWND);
  87. void OnOK();
  88. void OnCancel();
  89. void OnApplyNow();
  90. void NotifySheetOfChange();
  91. void NoteIrrevocableChange();
  92. void RemoveSelectedTrustEntries();
  93. private:
  94. HWND WindowOf(UINT id);
  95. void RefreshTrustList();
  96. void FreeTrustList();
  97. HRESULT Init();
  98. };
  99. /////////////////////////////////////////////////
  100. int __cdecl CompareTrustListEntries(const void*pelem1, const void* pelem2)
  101. {
  102. TRUSTLISTENTRY* p1 = (TRUSTLISTENTRY*)pelem1;
  103. TRUSTLISTENTRY* p2 = (TRUSTLISTENTRY*)pelem2;
  104. return _wcsicmp(p1->szDisplayName, p2->szDisplayName);
  105. }
  106. /////////////////////////////////////////////////
  107. void CDialogTrustDB::OnInitDialog()
  108. {
  109. //
  110. // Initialize our internals
  111. //
  112. if (Init() != S_OK)
  113. return;
  114. //
  115. // Set the state of our commercial checkbox per the current registry setting
  116. //
  117. ::SendMessage(
  118. WindowOf(IDC_TRUSTCOMMERCIAL),
  119. BM_SETCHECK,
  120. (m_pdb->AreCommercialPublishersTrusted()==S_OK) ? BST_CHECKED : BST_UNCHECKED,
  121. 0L);
  122. //
  123. // If we are a property sheet, then hide the OK & Cancel buttons and
  124. // make the banter wider
  125. //
  126. if (m_fPropertySheet)
  127. {
  128. RECT rcBanter, rcOk;
  129. GetWindowRect(WindowOf(IDC_BANTER), &rcBanter); // get in screen coords
  130. GetWindowRect(WindowOf(IDOK ), &rcOk); // get in screen coords
  131. ::SetWindowPos(WindowOf(IDC_BANTER), NULL,
  132. 0, 0, Width(rcBanter) + (rcOk.right - rcBanter.right), Height(rcBanter),
  133. SWP_NOMOVE | SWP_NOZORDER);
  134. ::ShowWindow(WindowOf(IDOK), SW_HIDE);
  135. ::ShowWindow(WindowOf(IDCANCEL), SW_HIDE);
  136. }
  137. else
  138. {
  139. //
  140. // We are the modal dialog variation. Center ourselves in our
  141. // parent window
  142. //
  143. RECT rcParent, rcMe;
  144. ::GetWindowRect(m_hWndParent, &rcParent);
  145. ::GetWindowRect(GetWindow(), &rcMe);
  146. POINT ptParent = Center(rcParent);
  147. POINT ptMe = Center(rcMe);
  148. POINT pt;
  149. pt.x = ptParent.x - ptMe.x + rcMe.left;
  150. pt.y = ptParent.y - ptMe.y + rcMe.top;
  151. ::SetWindowPos
  152. (
  153. GetWindow(),
  154. NULL,
  155. pt.x,
  156. pt.y,
  157. 0,
  158. 0,
  159. SWP_NOZORDER | SWP_NOSIZE
  160. );
  161. //
  162. // Make sure we're on the screen
  163. //
  164. EnsureOnScreen(GetWindow());
  165. }
  166. //
  167. // Add the one column to list view control
  168. //
  169. LV_COLUMNW lvC;
  170. WCHAR szText[512];
  171. lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  172. lvC.fmt = LVCFMT_LEFT; // Left-align the column.
  173. lvC.iSubItem = 0;
  174. lvC.cx = 250;
  175. lvC.pszText = szText;
  176. LoadStringU(hinst, IDS_COLUMN_HEADER, szText, 512);
  177. if (ListView_InsertColumnU(WindowOf(IDC_TRUSTLIST), 0, &lvC) == -1)
  178. {
  179. // error
  180. }
  181. //
  182. // Populate our list box
  183. //
  184. RefreshTrustList();
  185. }
  186. void CDialogTrustDB::RefreshTrustList()
  187. {
  188. //
  189. // Remove all the entries presently in the trust list and on the display
  190. //
  191. FreeTrustList();
  192. HWND hwndList = WindowOf(IDC_TRUSTLIST);
  193. ListView_DeleteAllItems(hwndList);
  194. ::SendMessage(GetWindow(), WM_NEXTDLGCTL, 0 , (LPARAM) FALSE);
  195. EnableWindow(WindowOf(IDC_TRUSTREMOVE), FALSE);
  196. //
  197. // Populate our listbox with the current list of trusted publishers
  198. //
  199. if (m_pdb->GetTrustList(1, TRUE, &m_rgTrust, &m_cTrust) == S_OK)
  200. {
  201. //
  202. // Sort the trust entries alphabetically
  203. //
  204. if (m_cTrust > 1)
  205. {
  206. qsort(m_rgTrust, m_cTrust, sizeof(TRUSTLISTENTRY), CompareTrustListEntries);
  207. }
  208. //
  209. // Add them to the list box
  210. //
  211. LV_ITEMW lvI;
  212. memset(&lvI, 0, sizeof(lvI));
  213. lvI.mask = LVIF_TEXT | LVIF_STATE;
  214. lvI.state = 0;
  215. lvI.stateMask = 0;
  216. lvI.iSubItem = 0;
  217. lvI.iItem = 0;
  218. for (ULONG i=0; i < m_cTrust; i++)
  219. {
  220. lvI.pszText = m_rgTrust[i].szDisplayName;
  221. lvI.cchTextMax = wcslen(m_rgTrust[i].szDisplayName);
  222. ListView_InsertItemU(hwndList, &lvI);
  223. lvI.iItem++;
  224. }
  225. EnableWindow(WindowOf(IDC_TRUSTREMOVE), m_cTrust > 0);
  226. }
  227. }
  228. //////////////////////////////////////////////////////////////////////
  229. void CDialogTrustDB::OnApplyNow()
  230. {
  231. //
  232. // Update the registry settings per the current commercial checkbox setting
  233. //
  234. m_pdb->SetCommercialPublishersTrust(
  235. ::SendMessage
  236. (
  237. WindowOf(IDC_TRUSTCOMMERCIAL),
  238. BM_GETCHECK, 0, 0L
  239. ) == BST_CHECKED
  240. );
  241. }
  242. void CDialogTrustDB::OnOK()
  243. {
  244. OnApplyNow();
  245. ::EndDialog(GetWindow(), IDOK);
  246. }
  247. void CDialogTrustDB::OnCancel()
  248. {
  249. ::EndDialog(GetWindow(), IDCANCEL);
  250. }
  251. //////////////////////////////////////////////////////////////////////
  252. void CDialogTrustDB::RemoveSelectedTrustEntries()
  253. {
  254. //
  255. // Remove from trust those items that are presently selected
  256. //
  257. HWND hwndList = WindowOf(IDC_TRUSTLIST);
  258. int itemIndex = -1;
  259. if (ListView_GetSelectedCount(hwndList) >= 1)
  260. {
  261. while (-1 != (itemIndex = ListView_GetNextItem(hwndList, itemIndex, LVNI_SELECTED)))
  262. {
  263. m_pdb->RemoveTrustToken
  264. (
  265. &m_rgTrust[itemIndex].szToken[0],
  266. m_rgTrust[itemIndex].iLevel,
  267. FALSE
  268. );
  269. }
  270. //
  271. // Update the display
  272. //
  273. RefreshTrustList();
  274. //
  275. // Note the change
  276. //
  277. NoteIrrevocableChange();
  278. }
  279. }
  280. void CDialogTrustDB::NoteIrrevocableChange()
  281. //
  282. // An irrevocable change has taken place in the UI. Note that
  283. // as appropriate
  284. //
  285. {
  286. if (!m_fPropertySheet)
  287. {
  288. //
  289. // Change 'cancel' to 'close'
  290. //
  291. WCHAR sz[30];
  292. ::LoadStringU(hinst, IDS_CLOSE, &sz[0], 30);
  293. ::SetWindowTextU(WindowOf(IDCANCEL), sz);
  294. }
  295. }
  296. void CDialogTrustDB::NotifySheetOfChange()
  297. //
  298. // Inform our sheet that something on this page has changed
  299. //
  300. {
  301. HWND hwndSheet = ::GetParent(GetWindow());
  302. PropSheet_Changed(hwndSheet, GetWindow());
  303. }
  304. /////////////////////////////////////////////////
  305. INT_PTR CALLBACK TrustPropSheetDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  306. {
  307. CDialogTrustDB* This = (CDialogTrustDB*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  308. switch (uMsg)
  309. {
  310. case WM_INITDIALOG:
  311. {
  312. PROPSHEETPAGE* ppsp = (PROPSHEETPAGE*)lParam;
  313. This = (CDialogTrustDB*)ppsp->lParam;
  314. This->SetWindow(hwnd);
  315. This->OnInitDialog();
  316. break;
  317. }
  318. case WM_NOTIFY:
  319. {
  320. // Property sheet notifications are sent to us by the property
  321. // sheet using the WM_NOTIFY message
  322. //
  323. switch (((NMHDR*)lParam)->code)
  324. {
  325. case PSN_APPLY:
  326. // The user chose OK or Apply Now and wants all changes to take effect
  327. This->OnApplyNow();
  328. }
  329. break;
  330. }
  331. case WM_COMMAND:
  332. {
  333. WORD wNotifyCode = HIWORD(wParam); // notification code
  334. UINT wID = LOWORD(wParam); // item, control, or accelerator identifier
  335. HWND hwndCtl = (HWND) lParam; // handle of control
  336. if (wID==IDC_TRUSTCOMMERCIAL && wNotifyCode == BN_CLICKED)
  337. {
  338. // If something on our page changes then inform the property sheet
  339. // so that it can enable the Apply Now button.
  340. //
  341. This->NotifySheetOfChange();
  342. }
  343. if (wID==IDC_TRUSTREMOVE && wNotifyCode == BN_CLICKED)
  344. {
  345. // If the user clicks the 'Remove' button then remove
  346. // the selected entries from the trust data base.
  347. //
  348. This->RemoveSelectedTrustEntries();
  349. }
  350. break;
  351. }
  352. default:
  353. return FALSE; // I did not process the message
  354. }
  355. return TRUE; // I did process the message
  356. }
  357. /////////////////////////////////////////////////
  358. UINT CALLBACK TrustPropSheetDialogReleaseProc(
  359. HWND hwnd, // reserved, must be null
  360. UINT uMsg, // PSPCB_CREATE or PSPCB_RELEASE
  361. LPPROPSHEETPAGEW ppsp // the page being created or destroyed
  362. ){
  363. if (uMsg==PSPCB_RELEASE)
  364. {
  365. CDialogTrustDB* pdlg = (CDialogTrustDB*)(ppsp->lParam);
  366. delete pdlg;
  367. ppsp->lParam = NULL;
  368. }
  369. return TRUE; // significant only in the PSPCB_CREATE case
  370. }
  371. /////////////////////////////////////////////////
  372. INT_PTR CALLBACK TrustModalDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  373. {
  374. CDialogTrustDB* This = (CDialogTrustDB*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  375. switch (uMsg)
  376. {
  377. case WM_HELP:
  378. case WM_CONTEXTMENU:
  379. {
  380. // Define an array of dword pairs,
  381. // where the first of each pair is the control ID,
  382. // and the second is the context ID for a help topic,
  383. // which is used in the help file.
  384. static const DWORD aMenuHelpIDs[] =
  385. {
  386. IDC_TRUSTCOMMERCIAL, IDH_TRUSTCOMMERCIAL,
  387. IDC_TRUSTLIST, IDH_TRUSTLIST,
  388. IDC_TRUSTREMOVE, IDH_TRUSTREMOVE,
  389. 0, 0
  390. };
  391. if (uMsg == WM_HELP)
  392. {
  393. LPHELPINFO lphi;
  394. lphi = (LPHELPINFO)lParam;
  395. if (lphi->iContextType == HELPINFO_WINDOW) // must be for a control
  396. {
  397. WinHelp
  398. (
  399. (HWND)(lphi->hItemHandle),
  400. SECAUTH_HELPFILENAME,
  401. HELP_WM_HELP,
  402. (ULONG_PTR)(LPVOID)aMenuHelpIDs
  403. );
  404. }
  405. }
  406. else
  407. {
  408. WinHelp
  409. (
  410. (HWND) wParam,
  411. SECAUTH_HELPFILENAME,
  412. HELP_CONTEXTMENU,
  413. (ULONG_PTR)(LPVOID)aMenuHelpIDs
  414. );
  415. }
  416. return TRUE;
  417. }
  418. case WM_INITDIALOG:
  419. {
  420. This = (CDialogTrustDB*)lParam;
  421. This->SetWindow(hwnd);
  422. This->OnInitDialog();
  423. break;
  424. }
  425. case WM_COMMAND:
  426. {
  427. WORD wNotifyCode = HIWORD(wParam); // notification code
  428. UINT wID = LOWORD(wParam); // item, control, or accelerator identifier
  429. HWND hwndCtl = (HWND) lParam; // handle of control
  430. if (wNotifyCode == BN_CLICKED)
  431. {
  432. if (wID==IDC_TRUSTREMOVE)
  433. {
  434. // If the user clicks the 'Remove' button then remove
  435. // the selected entries from the trust data base.
  436. //
  437. This->RemoveSelectedTrustEntries();
  438. }
  439. else if (wID == IDOK)
  440. {
  441. // The user clicked the OK button
  442. This->OnOK();
  443. }
  444. else if (wID == IDCANCEL)
  445. {
  446. // The user clicked the Cancel button
  447. This->OnCancel();
  448. }
  449. }
  450. break;
  451. }
  452. default:
  453. return FALSE; // I did not process the message
  454. }
  455. return TRUE; // I did process the message
  456. }
  457. /////////////////////////////////////////////////////////////////////////////
  458. //
  459. // The version of the trust db dialog that brings it up
  460. // as a property sheet.
  461. extern "C" BOOL CALLBACK AddPersonalTrustDBPages(
  462. //
  463. // Add the pages of our trust database editor to the indicated property
  464. // sheet by using the indicated callback function. Return success or failure
  465. //
  466. LPVOID lpv,
  467. LPFNADDPROPSHEETPAGE lpfnAddPage,
  468. LPARAM lParam
  469. ) {
  470. PROPSHEETPAGEW psp;
  471. CDialogTrustDB* pdlg = new CDialogTrustDB;
  472. if (!pdlg)
  473. return FALSE;
  474. psp.dwSize = sizeof(psp); // no extra data
  475. psp.dwFlags = PSP_USECALLBACK | PSP_USETITLE;
  476. psp.hInstance = hinst;
  477. psp.pszTemplate = (LPWSTR) MAKEINTRESOURCE(IDD_TRUSTDIALOG);
  478. psp.pfnDlgProc = TrustPropSheetDialogProc;
  479. psp.pfnCallback = TrustPropSheetDialogReleaseProc;
  480. psp.lParam = (LPARAM)pdlg;
  481. psp.pszTitle = (LPWSTR) MAKEINTRESOURCE(IDS_TRUSTDIALOG);
  482. BOOL fSuccess = TRUE;
  483. // The following APIs are in DELAYLOAD'ed comctl32.dll. If the
  484. // DELAYLOAD fails an exception is raised.
  485. __try {
  486. HPROPSHEETPAGE hpage = CreatePropertySheetPageU(&psp);
  487. if (hpage)
  488. {
  489. if (!lpfnAddPage(hpage, lParam))
  490. {
  491. DestroyPropertySheetPage(hpage);
  492. fSuccess = FALSE;
  493. }
  494. }
  495. else
  496. fSuccess = FALSE;
  497. } __except(EXCEPTION_EXECUTE_HANDLER) {
  498. DWORD dwExceptionCode = GetExceptionCode();
  499. fSuccess = FALSE;
  500. }
  501. return fSuccess;
  502. }
  503. /////////////////////////////////////////////////////////////////////////////
  504. //
  505. // The version of the trust dialog that brings it up as a
  506. // simple modal dialog
  507. //
  508. #define REGPATH_LEGACY_TRUSTED_PUBLISHER REGPATH_WINTRUST_POLICY_FLAGS \
  509. L"\\Trust Database\\0"
  510. // Convert the bytes into some string form.
  511. // Needs (cb * 2 + 1) * sizeof(WCHAR) bytes of space in sz
  512. void Legacy_BytesToString(
  513. ULONG cb,
  514. void* pv,
  515. LPWSTR sz
  516. )
  517. {
  518. BYTE* pb = (BYTE*)pv;
  519. for (ULONG i = 0; i<cb; i++)
  520. {
  521. int b = *pb;
  522. *sz++ = (((b & 0xF0)>>4) + L'a');
  523. *sz++ = ((b & 0x0F) + L'a');
  524. pb++;
  525. }
  526. *sz++ = 0;
  527. }
  528. //
  529. // X500 names can have VERY long encodings, so we can't just
  530. // do a literal vanilla encoding
  531. //
  532. // There must be CBX500NAME characters of space in the destination
  533. //
  534. // NOTE: We rely on the lack of collision in the hash values.
  535. // Chance of a collision for a set of 'p' names is approx:
  536. //
  537. // p^2 / n
  538. //
  539. // (if p<<n) where n (with MD5) is 2^128. An amazingly small chance.
  540. //
  541. HRESULT Legacy_X500NAMEToString(
  542. ULONG cb,
  543. void *pv,
  544. LPWSTR szDest
  545. )
  546. {
  547. #define CBHASH 16 // MD5
  548. #define CBX500NAME (2*CBHASH + 1)
  549. BYTE rgb[CBHASH];
  550. MD5_CTX md5ctx;
  551. MD5Init( &md5ctx );
  552. MD5Update( &md5ctx, (BYTE*)pv, cb );
  553. MD5Final( &md5ctx );
  554. assert(CBHASH == MD5DIGESTLEN);
  555. memcpy(rgb, md5ctx.digest, CBHASH);
  556. Legacy_BytesToString(CBHASH, rgb, szDest);
  557. return S_OK;
  558. }
  559. // Convert the issuer and serial number to some reasonable string form.
  560. HRESULT Legacy_GetIssuerSerialString(
  561. PCCERT_CONTEXT pCert,
  562. LPWSTR *ppsz
  563. )
  564. {
  565. HRESULT hr = S_OK;
  566. PCERT_INFO pCertInfo = pCert->pCertInfo;
  567. ULONG cbIssuer = CBX500NAME * sizeof(WCHAR);
  568. ULONG cbSerial = (pCertInfo->SerialNumber.cbData*2+1) * sizeof(WCHAR);
  569. WCHAR* sz = (WCHAR*)PkiZeroAlloc(cbSerial + sizeof(WCHAR) + cbIssuer);
  570. if (sz)
  571. {
  572. if (S_OK == (hr = Legacy_X500NAMEToString(
  573. pCertInfo->Issuer.cbData,
  574. pCertInfo->Issuer.pbData,
  575. sz
  576. )))
  577. {
  578. WCHAR* szNext = &sz[CBX500NAME-1];
  579. *szNext++ = L' ';
  580. Legacy_BytesToString(
  581. pCertInfo->SerialNumber.cbData,
  582. pCertInfo->SerialNumber.pbData,
  583. szNext
  584. );
  585. }
  586. else
  587. {
  588. PkiFree(sz);
  589. sz = NULL;
  590. }
  591. }
  592. else
  593. {
  594. hr = E_OUTOFMEMORY;
  595. }
  596. *ppsz = sz;
  597. return hr;
  598. }
  599. BOOL ConvertAndAddLegacyPublisherCertificate(
  600. IN HKEY hLegacyKey,
  601. IN PCCERT_CONTEXT pPubCert
  602. )
  603. {
  604. BOOL fResult = TRUE;
  605. DWORD dwLastErr = 0;
  606. HRESULT hr;
  607. LONG lErr;
  608. LPWSTR pwszValueName = NULL;
  609. LPWSTR pwszPubName = NULL;
  610. hr = Legacy_GetIssuerSerialString(pPubCert, &pwszValueName);
  611. if (FAILED(hr))
  612. goto GetIssuerSerialStringError;
  613. pwszPubName = spGetPublisherNameOfCert(pPubCert);
  614. if (NULL == pwszPubName) {
  615. hr = E_UNEXPECTED;
  616. goto GetPublisherNameOfCertError;
  617. }
  618. if (ERROR_SUCCESS != (lErr = RegSetValueExU(
  619. hLegacyKey,
  620. pwszValueName,
  621. NULL,
  622. REG_SZ,
  623. (BYTE *) pwszPubName,
  624. (wcslen(pwszPubName) + 1) * sizeof(WCHAR)
  625. )))
  626. goto RegSetValueError;
  627. CommonReturn:
  628. if (pwszValueName)
  629. PkiFree(pwszValueName);
  630. if (pwszPubName)
  631. delete pwszPubName;
  632. if (dwLastErr)
  633. SetLastError(dwLastErr);
  634. return fResult;
  635. ErrorReturn:
  636. fResult = FALSE;
  637. dwLastErr = GetLastError();
  638. goto CommonReturn;
  639. SET_ERROR_VAR_EX(DBG_SS, GetIssuerSerialStringError, hr)
  640. SET_ERROR_VAR_EX(DBG_SS, GetPublisherNameOfCertError, hr)
  641. SET_ERROR_VAR_EX(DBG_SS, RegSetValueError, lErr)
  642. }
  643. BOOL WriteTrustedPublisherLegacyRegistry()
  644. {
  645. BOOL fResult = TRUE;
  646. DWORD dwLastErr = 0;
  647. LONG lErr;
  648. HCERTSTORE hPubStore = NULL;
  649. HKEY hLegacyKey = NULL;
  650. DWORD dwDisposition;
  651. PCCERT_CONTEXT pCert;
  652. hPubStore = CertOpenStore(
  653. CERT_STORE_PROV_SYSTEM_W,
  654. 0,
  655. NULL,
  656. CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
  657. (const void *) L"TrustedPublisher"
  658. );
  659. if (NULL == hPubStore)
  660. goto OpenTrustedPublisherStoreError;
  661. // Delete the legacy registry key to remove any existing publishers
  662. if (ERROR_SUCCESS != (lErr = RegDeleteKeyU(
  663. HKEY_CURRENT_USER,
  664. REGPATH_LEGACY_TRUSTED_PUBLISHER
  665. ))) {
  666. if (ERROR_FILE_NOT_FOUND != lErr) {
  667. fResult = FALSE;
  668. if (0 == dwLastErr)
  669. dwLastErr = (DWORD) lErr;
  670. }
  671. }
  672. // Create the legacy registry key
  673. if (ERROR_SUCCESS != (lErr = RegCreateKeyExU(
  674. HKEY_CURRENT_USER,
  675. REGPATH_LEGACY_TRUSTED_PUBLISHER,
  676. 0, // dwReserved
  677. NULL, // lpClass
  678. REG_OPTION_NON_VOLATILE,
  679. KEY_ALL_ACCESS,
  680. NULL, // lpSecurityAttributes
  681. &hLegacyKey,
  682. &dwDisposition
  683. )))
  684. goto CreateLegacyKeyError;
  685. // Loop through the TrustedPublisher certs: convert and add to
  686. // the legacy registry subkey
  687. pCert = NULL;
  688. while (pCert = CertEnumCertificatesInStore(hPubStore, pCert)) {
  689. if (!ConvertAndAddLegacyPublisherCertificate(
  690. hLegacyKey,
  691. pCert
  692. )) {
  693. fResult = FALSE;
  694. if (0 == dwLastErr)
  695. dwLastErr = GetLastError();
  696. }
  697. }
  698. CommonReturn:
  699. if (hPubStore)
  700. CertCloseStore(hPubStore, 0);
  701. if (hLegacyKey)
  702. RegCloseKey(hLegacyKey);
  703. if (dwLastErr)
  704. SetLastError(dwLastErr);
  705. return fResult;
  706. ErrorReturn:
  707. fResult = FALSE;
  708. dwLastErr = GetLastError();
  709. goto CommonReturn;
  710. TRACE_ERROR_EX(DBG_SS, OpenTrustedPublisherStoreError)
  711. SET_ERROR_VAR_EX(DBG_SS, CreateLegacyKeyError, lErr)
  712. }
  713. BOOL WriteTrustedPublisher_IEAKStore()
  714. {
  715. BOOL fResult = TRUE;
  716. DWORD dwLastErr = 0;
  717. HCERTSTORE hPubStore = NULL;
  718. HCERTSTORE hIEAKStore = NULL;
  719. PCCERT_CONTEXT pCert;
  720. hPubStore = CertOpenStore(
  721. CERT_STORE_PROV_SYSTEM_W,
  722. 0,
  723. NULL,
  724. CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
  725. (const void *) L"TrustedPublisher"
  726. );
  727. if (NULL == hPubStore)
  728. goto OpenTrustedPublisherStoreError;
  729. hIEAKStore = CertOpenStore(
  730. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  731. 0,
  732. NULL,
  733. CERT_SYSTEM_STORE_CURRENT_USER,
  734. (const void *) L"TrustedPublisher_IEAK"
  735. );
  736. if (NULL == hIEAKStore)
  737. goto OpenTrustedPublisher_IEAKStoreError;
  738. // Remove any existing certs that may already exist in the IEAK store
  739. pCert = NULL;
  740. while (pCert = CertEnumCertificatesInStore(hIEAKStore, pCert)) {
  741. PCCERT_CONTEXT pDeleteCert = CertDuplicateCertificateContext(pCert);
  742. if (!CertDeleteCertificateFromStore(pDeleteCert)) {
  743. fResult = FALSE;
  744. if (0 == dwLastErr)
  745. dwLastErr = GetLastError();
  746. }
  747. }
  748. // Copy all certs from the logical TrustedPublisher to the IEAK registry
  749. // store
  750. pCert = NULL;
  751. while (pCert = CertEnumCertificatesInStore(hPubStore, pCert)) {
  752. if (!CertAddCertificateContextToStore(
  753. hIEAKStore,
  754. pCert,
  755. CERT_STORE_ADD_USE_EXISTING,
  756. NULL // ppStoreContext
  757. )) {
  758. fResult = FALSE;
  759. if (0 == dwLastErr)
  760. dwLastErr = GetLastError();
  761. }
  762. }
  763. CommonReturn:
  764. if (hPubStore)
  765. CertCloseStore(hPubStore, 0);
  766. if (hIEAKStore)
  767. CertCloseStore(hIEAKStore, 0);
  768. if (dwLastErr)
  769. SetLastError(dwLastErr);
  770. return fResult;
  771. ErrorReturn:
  772. fResult = FALSE;
  773. dwLastErr = GetLastError();
  774. goto CommonReturn;
  775. TRACE_ERROR_EX(DBG_SS, OpenTrustedPublisherStoreError)
  776. TRACE_ERROR_EX(DBG_SS, OpenTrustedPublisher_IEAKStoreError)
  777. }
  778. typedef BOOL (WINAPI *PFN_CRYPTUI_DLG_CERT_MGR)(
  779. IN PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
  780. );
  781. extern "C" BOOL WINAPI OpenPersonalTrustDBDialogEx(
  782. IN OPTIONAL HWND hwndParent,
  783. IN DWORD dwFlags,
  784. IN OUT OPTIONAL PVOID *pvReserved
  785. )
  786. {
  787. DWORD dwLastErr = 0;
  788. BOOL fResult = TRUE;
  789. HMODULE hDll = NULL;
  790. if (!(dwFlags & WT_TRUSTDBDIALOG_NO_UI_FLAG)) {
  791. PFN_CRYPTUI_DLG_CERT_MGR pfnCryptUIDlgCertMgr;
  792. CRYPTUI_CERT_MGR_STRUCT CertMgrStruct;
  793. if (NULL == (hDll = LoadLibraryA("cryptui.dll")))
  794. goto LoadCryptUIDllError;
  795. if (NULL == (pfnCryptUIDlgCertMgr =
  796. (PFN_CRYPTUI_DLG_CERT_MGR) GetProcAddress(hDll,
  797. "CryptUIDlgCertMgr")))
  798. goto CryptUICertMgrProcAddressError;
  799. memset(&CertMgrStruct, 0, sizeof(CRYPTUI_CERT_MGR_STRUCT));
  800. CertMgrStruct.dwSize=sizeof(CRYPTUI_CERT_MGR_STRUCT);
  801. CertMgrStruct.hwndParent = hwndParent;
  802. CertMgrStruct.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
  803. if (dwFlags & WT_TRUSTDBDIALOG_ONLY_PUB_TAB_FLAG)
  804. CertMgrStruct.dwFlags |= CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG;
  805. if (!pfnCryptUIDlgCertMgr(&CertMgrStruct)) {
  806. fResult = FALSE;
  807. if (0 == dwLastErr)
  808. dwLastErr = GetLastError();
  809. }
  810. }
  811. // else
  812. // Being called to only write the TrustedPublisher store to the
  813. // registry and/or IEAK store
  814. if (dwFlags & WT_TRUSTDBDIALOG_WRITE_LEGACY_REG_FLAG) {
  815. if (!WriteTrustedPublisherLegacyRegistry()) {
  816. fResult = FALSE;
  817. if (0 == dwLastErr)
  818. dwLastErr = GetLastError();
  819. }
  820. }
  821. if (dwFlags & WT_TRUSTDBDIALOG_WRITE_IEAK_STORE_FLAG) {
  822. if (!WriteTrustedPublisher_IEAKStore()) {
  823. fResult = FALSE;
  824. if (0 == dwLastErr)
  825. dwLastErr = GetLastError();
  826. }
  827. }
  828. CommonReturn:
  829. if (hDll)
  830. FreeLibrary(hDll);
  831. if (dwLastErr)
  832. SetLastError(dwLastErr);
  833. return fResult;
  834. ErrorReturn:
  835. fResult = FALSE;
  836. dwLastErr = GetLastError();
  837. goto CommonReturn;
  838. TRACE_ERROR_EX(DBG_SS, LoadCryptUIDllError)
  839. TRACE_ERROR_EX(DBG_SS, CryptUICertMgrProcAddressError)
  840. }
  841. extern "C" BOOL WINAPI OpenPersonalTrustDBDialog(
  842. IN OPTIONAL HWND hwndParent
  843. )
  844. {
  845. return OpenPersonalTrustDBDialogEx(
  846. hwndParent,
  847. 0, // dwFlags
  848. NULL // pvReserved
  849. );
  850. }
  851. /////////////////////////////////////////////////////////////////////////////
  852. HWND CDialogTrustDB::WindowOf(UINT id)
  853. // Return the HWND of this control of ours
  854. {
  855. return ::GetDlgItem(GetWindow(), id);
  856. }
  857. HWND CDialogTrustDB::GetWindow()
  858. {
  859. return m_hWnd;
  860. }
  861. void CDialogTrustDB::SetWindow(HWND hwnd)
  862. {
  863. m_hWnd = hwnd;
  864. SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)this);
  865. }
  866. CDialogTrustDB::CDialogTrustDB(BOOL fPropSheet, HWND hWndParent) :
  867. m_hWnd(NULL),
  868. m_pdb(NULL),
  869. m_fPropertySheet(fPropSheet),
  870. m_rgTrust(NULL),
  871. m_hWndParent(hWndParent),
  872. m_cTrust(0)
  873. {
  874. INITCOMMONCONTROLSEX initcomm = {
  875. sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES
  876. };
  877. InitCommonControlsEx(&initcomm);
  878. }
  879. void CDialogTrustDB::FreeTrustList()
  880. {
  881. if (m_rgTrust)
  882. {
  883. CoTaskMemFree(m_rgTrust);
  884. m_rgTrust = NULL;
  885. }
  886. }
  887. CDialogTrustDB::~CDialogTrustDB()
  888. {
  889. if (m_pdb)
  890. m_pdb->Release();
  891. FreeTrustList();
  892. }
  893. HRESULT CDialogTrustDB::Init()
  894. {
  895. HRESULT hr = OpenTrustDB(NULL, IID_IPersonalTrustDB, (LPVOID*)&m_pdb);
  896. return hr;
  897. }