Source code of Windows XP (NT5)
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.

561 lines
19 KiB

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #define PROPERTY_PASSPORTUSER L"PassportUser"
  4. #define PROPERTY_PASSPORTPASSWORD L"PassportPassword"
  5. #define PROPERTY_PASSPORTREMEMBERPASSWORD L"PassportRememberPassword"
  6. #define PROPERTY_PASSPORTUSEMSNEMAIL L"PassportUseMSNExplorerEmail"
  7. #define PROPERTY_PASSPORTMARSAVAILABLE L"PassportMSNExplorerAvailable"
  8. // Wizard pages
  9. #define WIZPAGE_WELCOME 0
  10. #define WIZPAGE_FINISH 1
  11. #define WIZPAGE_STARTOFEXT 2 // First webwizard extension page
  12. #define WIZPAGE_MAX 10
  13. #define REGKEY_PASSPORT_INTERNET_SETTINGS L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport"
  14. #define REGVAL_PASSPORT_WIZARDCOMPLETE L"RegistrationCompleted"
  15. #define REGVAL_PASSPORT_NUMBEROFWIZARDRUNS L"NumRegistrationRuns"
  16. void BoldControl(HWND hwnd, int id);
  17. class CPassportWizard : public IWizardSite, IServiceProvider, IPassportWizard
  18. {
  19. public:
  20. CPassportWizard();
  21. ~CPassportWizard();
  22. // IUnknown
  23. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
  24. STDMETHOD_(ULONG,AddRef)(void);
  25. STDMETHOD_(ULONG,Release)(void);
  26. // IWizardSite
  27. STDMETHODIMP GetPreviousPage(HPROPSHEETPAGE *phPage);
  28. STDMETHODIMP GetNextPage(HPROPSHEETPAGE *phPage);
  29. STDMETHODIMP GetCancelledPage(HPROPSHEETPAGE *phPage)
  30. { return E_NOTIMPL; }
  31. // IServiceProvider
  32. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
  33. // IPassportWizard
  34. STDMETHODIMP Show(HWND hwndParent);
  35. STDMETHODIMP SetOptions(DWORD dwOptions);
  36. protected:
  37. static CPassportWizard* s_GetPPW(HWND hwnd, UINT uMsg, LPARAM lParam);
  38. // Page Procs
  39. static INT_PTR CALLBACK s_WelcomePageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  40. { CPassportWizard *ppw = s_GetPPW(hwnd, uMsg, lParam); return ppw->_WelcomePageProc(hwnd, uMsg, wParam, lParam); }
  41. static INT_PTR CALLBACK s_FinishPageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  42. { CPassportWizard *ppw = s_GetPPW(hwnd, uMsg, lParam); return ppw->_FinishPageProc(hwnd, uMsg, wParam, lParam); }
  43. INT_PTR _WelcomePageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  44. INT_PTR _FinishPageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  45. HRESULT _CreateMyWebDocumentsLink();
  46. HRESULT _ApplyChanges(HWND hwnd);
  47. HRESULT _CreateWizardPages(void);
  48. HRESULT _SetURLFromNexus();
  49. HRESULT _GetCurrentPassport();
  50. HRESULT _LaunchHotmailRegistration();
  51. BOOL _IsMSNExplorerAvailableForEmail();
  52. HRESULT _UseMSNExplorerForEmail();
  53. INT_PTR _WizardNext(HWND hwnd, int iPage);
  54. LONG _cRef;
  55. IPropertyBag* _ppb; // Property Bag
  56. IWebWizardExtension* _pwwe; // Wizard host - used for HTML pages
  57. HPROPSHEETPAGE _rgWizPages[WIZPAGE_MAX];
  58. DWORD _dwOptions; // Option flags for the passport wizard
  59. };
  60. STDAPI CPassportWizard_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  61. {
  62. CPassportWizard *pPPW = new CPassportWizard();
  63. if (!pPPW)
  64. return E_OUTOFMEMORY;
  65. HRESULT hr = pPPW->QueryInterface(IID_PPV_ARG(IUnknown, ppunk));
  66. pPPW->Release();
  67. return hr;
  68. }
  69. CPassportWizard::CPassportWizard() :
  70. _cRef(1)
  71. {}
  72. CPassportWizard::~CPassportWizard()
  73. {
  74. ATOMICRELEASE(_ppb);
  75. ATOMICRELEASE(_pwwe);
  76. }
  77. // IUnknown
  78. ULONG CPassportWizard::AddRef()
  79. {
  80. return InterlockedIncrement(&_cRef);
  81. }
  82. ULONG CPassportWizard::Release()
  83. {
  84. if (InterlockedDecrement(&_cRef))
  85. return _cRef;
  86. delete this;
  87. return 0;
  88. }
  89. HRESULT CPassportWizard::QueryInterface(REFIID riid, void **ppv)
  90. {
  91. static const QITAB qit[] =
  92. {
  93. QITABENT(CPassportWizard, IServiceProvider), // IID_IServiceProvider
  94. QITABENT(CPassportWizard, IWizardSite), // IID_IWizardSite
  95. QITABENT(CPassportWizard, IModalWindow), // IID_IModalWindow
  96. QITABENT(CPassportWizard, IPassportWizard), // IID_IModalWindow
  97. {0, 0 },
  98. };
  99. return QISearch(this, qit, riid, ppv);
  100. }
  101. // IWizardSite
  102. STDMETHODIMP CPassportWizard::GetNextPage(HPROPSHEETPAGE *phPage)
  103. {
  104. *phPage = _rgWizPages[WIZPAGE_FINISH];
  105. return S_OK;
  106. }
  107. STDMETHODIMP CPassportWizard::GetPreviousPage(HPROPSHEETPAGE *phPage)
  108. {
  109. *phPage = _rgWizPages[WIZPAGE_WELCOME];
  110. return S_OK;
  111. }
  112. // IServiceProvider
  113. STDMETHODIMP CPassportWizard::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  114. {
  115. HRESULT hr = E_FAIL;
  116. *ppv = NULL; // no result yet
  117. if (guidService == SID_WebWizardHost)
  118. {
  119. if (riid == IID_IPropertyBag)
  120. hr = _ppb->QueryInterface(riid, ppv);
  121. }
  122. return hr;
  123. }
  124. // IModalWindow
  125. #define WIZDLG(name, dlgproc, dwFlags) \
  126. { MAKEINTRESOURCE(IDD_GETPP_##name##), dlgproc, MAKEINTRESOURCE(IDS_GETPP_HEADER_##name##), MAKEINTRESOURCE(IDS_GETPP_SUBHEADER_##name##), dwFlags }
  127. HRESULT CPassportWizard::_CreateWizardPages(void)
  128. {
  129. static const WIZPAGE c_wpPages[] =
  130. {
  131. WIZDLG(WELCOME, CPassportWizard::s_WelcomePageProc, PSP_HIDEHEADER),
  132. WIZDLG(FINISH, CPassportWizard::s_FinishPageProc, PSP_HIDEHEADER),
  133. };
  134. // if we haven't created the pages yet, then lets initialize our array of handlers.
  135. if (!_rgWizPages[0])
  136. {
  137. INITCOMMONCONTROLSEX iccex = { 0 };
  138. iccex.dwSize = sizeof (iccex);
  139. iccex.dwICC = ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_LINK_CLASS;
  140. InitCommonControlsEx(&iccex);
  141. LinkWindow_RegisterClass();
  142. for (int i = 0; i < ARRAYSIZE(c_wpPages) ; i++ )
  143. {
  144. PROPSHEETPAGE psp = { 0 };
  145. psp.dwSize = SIZEOF(PROPSHEETPAGE);
  146. psp.hInstance = g_hinst;
  147. psp.lParam = (LPARAM)this;
  148. psp.dwFlags = PSP_USETITLE | PSP_DEFAULT |
  149. PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE |
  150. c_wpPages[i].dwFlags;
  151. psp.pszTemplate = c_wpPages[i].idPage;
  152. psp.pfnDlgProc = c_wpPages[i].pDlgProc;
  153. psp.pszTitle = MAKEINTRESOURCE(IDS_GETPP_CAPTION);
  154. psp.pszHeaderTitle = c_wpPages[i].pHeading;
  155. psp.pszHeaderSubTitle = c_wpPages[i].pSubHeading;
  156. _rgWizPages[i] = CreatePropertySheetPage(&psp);
  157. if (!_rgWizPages[i])
  158. {
  159. return E_FAIL;
  160. }
  161. }
  162. }
  163. return S_OK;
  164. }
  165. HRESULT CPassportWizard::_SetURLFromNexus()
  166. {
  167. WCHAR szURL[INTERNET_MAX_URL_LENGTH];
  168. DWORD cch = ARRAYSIZE(szURL) - 1;
  169. HRESULT hr = PassportGetURL(PASSPORTURL_REGISTRATION, szURL, &cch);
  170. if (SUCCEEDED(hr))
  171. {
  172. hr = _pwwe->SetInitialURL(szURL);
  173. }
  174. else
  175. {
  176. // Cause the webserviceerror to appear since we can't get a good URL
  177. hr = _pwwe->SetInitialURL(L"");
  178. }
  179. return hr;
  180. }
  181. HRESULT CPassportWizard::Show(HWND hwndParent)
  182. {
  183. // create our wizard pages, these are required before we do anything
  184. HRESULT hr = _CreateWizardPages();
  185. if (SUCCEEDED(hr))
  186. {
  187. // we interface with the wizard host via a property bag, so lets create an
  188. // initialize that before we proceed.
  189. hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_PPV_ARG(IPropertyBag, &_ppb));
  190. if (SUCCEEDED(hr))
  191. {
  192. // Provide a property telling Passport if MSN Explorer is available as an e-mail client
  193. // in the start menu
  194. SHPropertyBag_WriteBOOL(_ppb, PROPERTY_PASSPORTMARSAVAILABLE, _IsMSNExplorerAvailableForEmail());
  195. // create the object which will host the HTML wizard pages, these are shown in the frame
  196. hr = CoCreateInstance(CLSID_WebWizardHost, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWebWizardExtension, &_pwwe));
  197. if (SUCCEEDED(hr))
  198. {
  199. IUnknown_SetSite(_pwwe, SAFECAST(this, IServiceProvider*));
  200. UINT cExtnPages = 0;
  201. hr = _pwwe->AddPages(_rgWizPages + WIZPAGE_STARTOFEXT, WIZPAGE_MAX - WIZPAGE_STARTOFEXT, &cExtnPages);
  202. if (SUCCEEDED(hr))
  203. {
  204. PROPSHEETHEADER psh = { 0 };
  205. psh.hwndParent = hwndParent;
  206. psh.dwSize = SIZEOF(PROPSHEETHEADER);
  207. psh.hInstance = g_hinst;
  208. psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_STRETCHWATERMARK | PSH_HEADER | PSH_WATERMARK;
  209. psh.pszbmHeader = MAKEINTRESOURCE(IDB_GETPP_BANNER);
  210. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_GETPP_WATERMARK);
  211. psh.phpage = _rgWizPages;
  212. psh.nPages = (cExtnPages + WIZPAGE_STARTOFEXT);
  213. psh.nStartPage = WIZPAGE_WELCOME;
  214. // Return S_FALSE on cancel; otherwise S_OK;
  215. hr = PropertySheet(&psh) ? S_OK : S_FALSE;
  216. }
  217. IUnknown_SetSite(_pwwe, NULL);
  218. ATOMICRELEASE(_pwwe);
  219. }
  220. }
  221. ATOMICRELEASE(_ppb);
  222. }
  223. return hr;
  224. }
  225. HRESULT CPassportWizard::SetOptions(DWORD dwOptions)
  226. {
  227. _dwOptions = dwOptions;
  228. return S_OK;
  229. }
  230. CPassportWizard* CPassportWizard::s_GetPPW(HWND hwnd, UINT uMsg, LPARAM lParam)
  231. {
  232. if (uMsg == WM_INITDIALOG)
  233. {
  234. PROPSHEETPAGE *ppsp = (PROPSHEETPAGE*)lParam;
  235. SetWindowLongPtr(hwnd, GWLP_USERDATA, ppsp->lParam);
  236. return (CPassportWizard*)ppsp->lParam;
  237. }
  238. return (CPassportWizard*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  239. }
  240. INT_PTR CPassportWizard::_WizardNext(HWND hwnd, int iPage)
  241. {
  242. PropSheet_SetCurSel(GetParent(hwnd), _rgWizPages[iPage], -1);
  243. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  244. return TRUE;
  245. }
  246. INT_PTR CPassportWizard::_WelcomePageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  247. {
  248. switch (uMsg)
  249. {
  250. case WM_INITDIALOG:
  251. {
  252. SendDlgItemMessage(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  253. BoldControl(hwnd, IDC_BOLD1);
  254. // Increment "NumRegistrationRuns" value in the registry
  255. HKEY hkey;
  256. if (NO_ERROR == RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_PASSPORT_INTERNET_SETTINGS, NULL, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &hkey, NULL))
  257. {
  258. DWORD dwType;
  259. DWORD nRuns;
  260. DWORD cb = sizeof (nRuns);
  261. if ((NO_ERROR != RegQueryValueEx(hkey, REGVAL_PASSPORT_NUMBEROFWIZARDRUNS, NULL, &dwType, (LPBYTE) &nRuns, &cb)) ||
  262. (REG_DWORD != dwType))
  263. {
  264. nRuns = 0;
  265. }
  266. nRuns ++;
  267. RegSetValueEx(hkey, REGVAL_PASSPORT_NUMBEROFWIZARDRUNS, NULL, REG_DWORD, (const BYTE *) &nRuns, sizeof (nRuns));
  268. RegCloseKey(hkey);
  269. }
  270. }
  271. return TRUE;
  272. case WM_NOTIFY:
  273. {
  274. LPNMHDR pnmh = (LPNMHDR) lParam;
  275. switch (pnmh->code)
  276. {
  277. case PSN_SETACTIVE:
  278. PropSheet_SetWizButtons(pnmh->hwndFrom, PSWIZB_NEXT);
  279. return TRUE;
  280. case PSN_WIZNEXT:
  281. {
  282. // we need ICW to have executed before we navigate to webbased UI
  283. LaunchICW();
  284. if (SUCCEEDED(_SetURLFromNexus()))
  285. {
  286. HPROPSHEETPAGE hpageNext;
  287. if (SUCCEEDED(_pwwe->GetFirstPage(&hpageNext)))
  288. {
  289. PropSheet_SetCurSel(GetParent(hwnd), hpageNext, -1);
  290. }
  291. }
  292. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR) -1);
  293. return TRUE;
  294. }
  295. case NM_CLICK:
  296. case NM_RETURN:
  297. switch ((int) wParam)
  298. {
  299. case IDC_PRIVACYLINK:
  300. {
  301. WCHAR szURL[INTERNET_MAX_URL_LENGTH];
  302. DWORD cch = ARRAYSIZE(szURL) - 1;
  303. HRESULT hr = PassportGetURL(PASSPORTURL_PRIVACY, szURL, &cch);
  304. if (SUCCEEDED(hr))
  305. {
  306. WCHAR szURLWithLCID[INTERNET_MAX_URL_LENGTH];
  307. LPCWSTR pszFormat = StrChr(szURL, L'?') ? L"%s&pplcid=%d":L"%s?pplcid=%d";
  308. if (wnsprintf(szURLWithLCID, ARRAYSIZE(szURLWithLCID), pszFormat, szURL, GetUserDefaultLCID()) > 0)
  309. {
  310. // Open the browser to the privacy policy site
  311. SHELLEXECUTEINFO shexinfo = {0};
  312. shexinfo.cbSize = sizeof (shexinfo);
  313. shexinfo.fMask = SEE_MASK_FLAG_NO_UI;
  314. shexinfo.nShow = SW_SHOWNORMAL;
  315. shexinfo.lpFile = szURL;
  316. shexinfo.lpVerb = TEXT("open");
  317. ShellExecuteEx(&shexinfo);
  318. }
  319. }
  320. }
  321. return TRUE;
  322. }
  323. }
  324. return FALSE;
  325. }
  326. }
  327. return FALSE;
  328. }
  329. // Make sure MSN Explorer exists as an email client
  330. BOOL CPassportWizard::_IsMSNExplorerAvailableForEmail()
  331. {
  332. BOOL fAvailable = FALSE;
  333. HKEY hkeyMSNEmail;
  334. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Clients\\Mail\\MSN Explorer", 0, KEY_READ, &hkeyMSNEmail))
  335. {
  336. fAvailable = TRUE;
  337. RegCloseKey(hkeyMSNEmail);
  338. }
  339. return fAvailable;
  340. }
  341. HRESULT CPassportWizard::_UseMSNExplorerForEmail()
  342. {
  343. HRESULT hr = E_FAIL;
  344. if (_IsMSNExplorerAvailableForEmail())
  345. {
  346. HKEY hkeyDefaultEmail;
  347. // Change the default email program for the current user only
  348. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Clients\\Mail", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeyDefaultEmail, NULL))
  349. {
  350. static WCHAR szMSNExplorer[] = L"MSN Explorer";
  351. if (ERROR_SUCCESS == RegSetValueEx(hkeyDefaultEmail, L"", 0, REG_SZ, (BYTE*) szMSNExplorer, sizeof(szMSNExplorer)))
  352. {
  353. hr = S_OK;
  354. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)TEXT("Software\\Clients\\Mail"));
  355. }
  356. RegCloseKey(hkeyDefaultEmail);
  357. }
  358. }
  359. return hr;
  360. }
  361. HRESULT CPassportWizard::_ApplyChanges(HWND hwnd)
  362. {
  363. // Read user, password, and auth DA.
  364. WCHAR szPassportUser[1024];
  365. HRESULT hr = SHPropertyBag_ReadStr(_ppb, PROPERTY_PASSPORTUSER, szPassportUser, ARRAYSIZE(szPassportUser));
  366. if (SUCCEEDED(hr) && *szPassportUser)
  367. {
  368. WCHAR szPassportPassword[256];
  369. hr = SHPropertyBag_ReadStr(_ppb, PROPERTY_PASSPORTPASSWORD, szPassportPassword, ARRAYSIZE(szPassportPassword));
  370. if (SUCCEEDED(hr) && *szPassportPassword)
  371. {
  372. BOOL fRememberPW = SHPropertyBag_ReadBOOLDefRet(_ppb, PROPERTY_PASSPORTREMEMBERPASSWORD, FALSE);
  373. if (ERROR_SUCCESS == CredUIStoreSSOCredW(NULL, szPassportUser, szPassportPassword, fRememberPW))
  374. {
  375. hr = S_OK;
  376. // Write "RegistrationCompleted" value into the registry
  377. DWORD dwValue = 1;
  378. SHSetValue(HKEY_CURRENT_USER, REGKEY_PASSPORT_INTERNET_SETTINGS, REGVAL_PASSPORT_WIZARDCOMPLETE, REG_DWORD, &dwValue, sizeof (dwValue));
  379. #if 0
  380. if (BST_CHECKED == SendDlgItemMessage(hwnd, IDC_MYWEBDOCUMENTSLINK, BM_GETCHECK, 0, 0))
  381. {
  382. // Temporarily commented out - _CreateMyWebDocumentsLink();
  383. }
  384. #endif
  385. }
  386. else
  387. {
  388. hr = E_FAIL;
  389. }
  390. if (SHPropertyBag_ReadBOOLDefRet(_ppb, PROPERTY_PASSPORTUSEMSNEMAIL, FALSE))
  391. {
  392. _UseMSNExplorerForEmail();
  393. }
  394. }
  395. }
  396. return hr;
  397. }
  398. INT_PTR CPassportWizard::_FinishPageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  399. {
  400. switch (uMsg)
  401. {
  402. case WM_INITDIALOG:
  403. SendDlgItemMessage(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  404. return TRUE;
  405. case WM_NOTIFY:
  406. {
  407. LPNMHDR pnmh = (LPNMHDR) lParam;
  408. switch (pnmh->code)
  409. {
  410. case PSN_SETACTIVE:
  411. {
  412. // Temporarily commented out - SendDlgItemMessage(hwnd, IDC_MYWEBDOCUMENTSLINK, BM_SETCHECK, (WPARAM) BST_CHECKED, 0);
  413. WCHAR szPassportUser[1024];
  414. // Try to get the passport user name... we may have to add an error page if this fails... TODO
  415. HRESULT hr = SHPropertyBag_ReadStr(_ppb, PROPERTY_PASSPORTUSER, szPassportUser, ARRAYSIZE(szPassportUser));
  416. if (SUCCEEDED(hr) && *szPassportUser)
  417. {
  418. SetDlgItemText(hwnd, IDC_YOURPASSPORT, szPassportUser);
  419. }
  420. PropSheet_SetWizButtons(pnmh->hwndFrom, PSWIZB_BACK | PSWIZB_FINISH);
  421. return TRUE;
  422. }
  423. case PSN_WIZBACK:
  424. // The next page is the web wizard host. We show different pages depending whether or not
  425. // the user has an email account (or passport) or not.
  426. if (SUCCEEDED(_SetURLFromNexus()))
  427. {
  428. HPROPSHEETPAGE hpageNext;
  429. if (SUCCEEDED(_pwwe->GetFirstPage(&hpageNext)))
  430. {
  431. PropSheet_SetCurSel(GetParent(hwnd), hpageNext, -1);
  432. }
  433. }
  434. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  435. return TRUE;
  436. case PSN_WIZFINISH:
  437. _ApplyChanges(hwnd);
  438. return TRUE;
  439. }
  440. break;
  441. }
  442. }
  443. return FALSE;
  444. }
  445. // Help requires a rundll entrypoint to run passport wizard
  446. void APIENTRY PassportWizardRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  447. {
  448. HRESULT hr = CoInitialize(NULL);
  449. if (SUCCEEDED(hr))
  450. {
  451. IPassportWizard* pPW = NULL;
  452. hr = CoCreateInstance(CLSID_PassportWizard, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPassportWizard, &pPW));
  453. if (SUCCEEDED(hr))
  454. {
  455. pPW->SetOptions(PPW_LAUNCHEDBYUSER);
  456. pPW->Show(hwndStub);
  457. pPW->Release();
  458. }
  459. CoUninitialize();
  460. }
  461. }
  462. void BoldControl(HWND hwnd, int id)
  463. {
  464. HWND hwndTitle = GetDlgItem(hwnd, id);
  465. // Get the existing font
  466. HFONT hfontOld = (HFONT) SendMessage(hwndTitle, WM_GETFONT, 0, 0);
  467. LOGFONT lf = {0};
  468. if (GetObject(hfontOld, sizeof(lf), &lf))
  469. {
  470. lf.lfWeight = FW_BOLD;
  471. HFONT hfontNew = CreateFontIndirect(&lf);
  472. if (hfontNew)
  473. {
  474. SendMessage(hwndTitle, WM_SETFONT, (WPARAM) hfontNew, FALSE);
  475. // Don't do this, its shared.
  476. // DeleteObject(hfontOld);
  477. }
  478. }
  479. }