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.

558 lines
20 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. };
  59. STDAPI CPassportWizard_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  60. {
  61. CPassportWizard *pPPW = new CPassportWizard();
  62. if (!pPPW)
  63. return E_OUTOFMEMORY;
  64. HRESULT hr = pPPW->QueryInterface(IID_PPV_ARG(IUnknown, ppunk));
  65. pPPW->Release();
  66. return hr;
  67. }
  68. CPassportWizard::CPassportWizard() :
  69. _cRef(1)
  70. {}
  71. CPassportWizard::~CPassportWizard()
  72. {
  73. ATOMICRELEASE(_ppb);
  74. ATOMICRELEASE(_pwwe);
  75. }
  76. // IUnknown
  77. ULONG CPassportWizard::AddRef()
  78. {
  79. return InterlockedIncrement(&_cRef);
  80. }
  81. ULONG CPassportWizard::Release()
  82. {
  83. ASSERT( 0 != _cRef );
  84. ULONG cRef = InterlockedDecrement(&_cRef);
  85. if ( 0 == cRef )
  86. {
  87. delete this;
  88. }
  89. return cRef;
  90. }
  91. HRESULT CPassportWizard::QueryInterface(REFIID riid, void **ppv)
  92. {
  93. static const QITAB qit[] =
  94. {
  95. QITABENT(CPassportWizard, IServiceProvider), // IID_IServiceProvider
  96. QITABENT(CPassportWizard, IWizardSite), // IID_IWizardSite
  97. QITABENT(CPassportWizard, IModalWindow), // IID_IModalWindow
  98. QITABENT(CPassportWizard, IPassportWizard), // IID_IModalWindow
  99. {0, 0 },
  100. };
  101. return QISearch(this, qit, riid, ppv);
  102. }
  103. // IWizardSite
  104. STDMETHODIMP CPassportWizard::GetNextPage(HPROPSHEETPAGE *phPage)
  105. {
  106. *phPage = _rgWizPages[WIZPAGE_FINISH];
  107. return S_OK;
  108. }
  109. STDMETHODIMP CPassportWizard::GetPreviousPage(HPROPSHEETPAGE *phPage)
  110. {
  111. *phPage = _rgWizPages[WIZPAGE_WELCOME];
  112. return S_OK;
  113. }
  114. // IServiceProvider
  115. STDMETHODIMP CPassportWizard::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  116. {
  117. HRESULT hr = E_FAIL;
  118. *ppv = NULL; // no result yet
  119. if (guidService == SID_WebWizardHost)
  120. {
  121. if (riid == IID_IPropertyBag)
  122. hr = _ppb->QueryInterface(riid, ppv);
  123. }
  124. return hr;
  125. }
  126. // IModalWindow
  127. #define WIZDLG(name, dlgproc, dwFlags) \
  128. { MAKEINTRESOURCE(IDD_GETPP_##name##), dlgproc, MAKEINTRESOURCE(IDS_GETPP_HEADER_##name##), MAKEINTRESOURCE(IDS_GETPP_SUBHEADER_##name##), dwFlags }
  129. HRESULT CPassportWizard::_CreateWizardPages(void)
  130. {
  131. static const WIZPAGE c_wpPages[] =
  132. {
  133. WIZDLG(WELCOME, CPassportWizard::s_WelcomePageProc, PSP_HIDEHEADER),
  134. WIZDLG(FINISH, CPassportWizard::s_FinishPageProc, PSP_HIDEHEADER),
  135. };
  136. // if we haven't created the pages yet, then lets initialize our array of handlers.
  137. if (!_rgWizPages[0])
  138. {
  139. INITCOMMONCONTROLSEX iccex = { 0 };
  140. iccex.dwSize = sizeof (iccex);
  141. iccex.dwICC = ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_LINK_CLASS;
  142. InitCommonControlsEx(&iccex);
  143. LinkWindow_RegisterClass();
  144. for (int i = 0; i < ARRAYSIZE(c_wpPages) ; i++ )
  145. {
  146. PROPSHEETPAGE psp = { 0 };
  147. psp.dwSize = SIZEOF(PROPSHEETPAGE);
  148. psp.hInstance = g_hinst;
  149. psp.lParam = (LPARAM)this;
  150. psp.dwFlags = PSP_USETITLE | PSP_DEFAULT |
  151. PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE |
  152. c_wpPages[i].dwFlags;
  153. psp.pszTemplate = c_wpPages[i].idPage;
  154. psp.pfnDlgProc = c_wpPages[i].pDlgProc;
  155. psp.pszTitle = MAKEINTRESOURCE(IDS_GETPP_CAPTION);
  156. psp.pszHeaderTitle = c_wpPages[i].pHeading;
  157. psp.pszHeaderSubTitle = c_wpPages[i].pSubHeading;
  158. _rgWizPages[i] = CreatePropertySheetPage(&psp);
  159. if (!_rgWizPages[i])
  160. {
  161. return E_FAIL;
  162. }
  163. }
  164. }
  165. return S_OK;
  166. }
  167. HRESULT CPassportWizard::_SetURLFromNexus()
  168. {
  169. WCHAR szURL[INTERNET_MAX_URL_LENGTH];
  170. HRESULT hr = PassportGetURL(PASSPORTURL_REGISTRATION, szURL, ARRAYSIZE(szURL));
  171. if (SUCCEEDED(hr))
  172. {
  173. hr = _pwwe->SetInitialURL(szURL);
  174. }
  175. else
  176. {
  177. // Cause the webserviceerror to appear since we can't get a good URL
  178. hr = _pwwe->SetInitialURL(L"");
  179. }
  180. return hr;
  181. }
  182. HRESULT CPassportWizard::Show(HWND hwndParent)
  183. {
  184. // create our wizard pages, these are required before we do anything
  185. HRESULT hr = _CreateWizardPages();
  186. if (SUCCEEDED(hr))
  187. {
  188. // we interface with the wizard host via a property bag, so lets create an
  189. // initialize that before we proceed.
  190. hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_PPV_ARG(IPropertyBag, &_ppb));
  191. if (SUCCEEDED(hr))
  192. {
  193. // Provide a property telling Passport if MSN Explorer is available as an e-mail client
  194. // in the start menu
  195. SHPropertyBag_WriteBOOL(_ppb, PROPERTY_PASSPORTMARSAVAILABLE, _IsMSNExplorerAvailableForEmail());
  196. // create the object which will host the HTML wizard pages, these are shown in the frame
  197. hr = CoCreateInstance(CLSID_WebWizardHost, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWebWizardExtension, &_pwwe));
  198. if (SUCCEEDED(hr))
  199. {
  200. IUnknown_SetSite(_pwwe, SAFECAST(this, IServiceProvider*));
  201. UINT cExtnPages = 0;
  202. hr = _pwwe->AddPages(_rgWizPages + WIZPAGE_STARTOFEXT, WIZPAGE_MAX - WIZPAGE_STARTOFEXT, &cExtnPages);
  203. if (SUCCEEDED(hr))
  204. {
  205. PROPSHEETHEADER psh = { 0 };
  206. psh.hwndParent = hwndParent;
  207. psh.dwSize = SIZEOF(PROPSHEETHEADER);
  208. psh.hInstance = g_hinst;
  209. psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_STRETCHWATERMARK | PSH_HEADER | PSH_WATERMARK;
  210. psh.pszbmHeader = MAKEINTRESOURCE(IDB_GETPP_BANNER);
  211. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_GETPP_WATERMARK);
  212. psh.phpage = _rgWizPages;
  213. psh.nPages = (cExtnPages + WIZPAGE_STARTOFEXT);
  214. psh.nStartPage = WIZPAGE_WELCOME;
  215. // Return S_FALSE on cancel; otherwise S_OK;
  216. hr = PropertySheet(&psh) ? S_OK : S_FALSE;
  217. }
  218. IUnknown_SetSite(_pwwe, NULL);
  219. ATOMICRELEASE(_pwwe);
  220. }
  221. }
  222. ATOMICRELEASE(_ppb);
  223. }
  224. return hr;
  225. }
  226. HRESULT CPassportWizard::SetOptions(DWORD dwOptions)
  227. {
  228. // Options are ignored
  229. return S_OK;
  230. }
  231. CPassportWizard* CPassportWizard::s_GetPPW(HWND hwnd, UINT uMsg, LPARAM lParam)
  232. {
  233. if (uMsg == WM_INITDIALOG)
  234. {
  235. PROPSHEETPAGE *ppsp = (PROPSHEETPAGE*)lParam;
  236. SetWindowLongPtr(hwnd, GWLP_USERDATA, ppsp->lParam);
  237. return (CPassportWizard*)ppsp->lParam;
  238. }
  239. return (CPassportWizard*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  240. }
  241. INT_PTR CPassportWizard::_WizardNext(HWND hwnd, int iPage)
  242. {
  243. PropSheet_SetCurSel(GetParent(hwnd), _rgWizPages[iPage], -1);
  244. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  245. return TRUE;
  246. }
  247. INT_PTR CPassportWizard::_WelcomePageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  248. {
  249. switch (uMsg)
  250. {
  251. case WM_INITDIALOG:
  252. {
  253. SendDlgItemMessage(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  254. BoldControl(hwnd, IDC_BOLD1);
  255. // Increment "NumRegistrationRuns" value in the registry
  256. HKEY hkey;
  257. if (NO_ERROR == RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_PASSPORT_INTERNET_SETTINGS, NULL, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &hkey, NULL))
  258. {
  259. DWORD dwType;
  260. DWORD nRuns;
  261. DWORD cb = sizeof (nRuns);
  262. if ((NO_ERROR != RegQueryValueEx(hkey, REGVAL_PASSPORT_NUMBEROFWIZARDRUNS, NULL, &dwType, (LPBYTE) &nRuns, &cb)) ||
  263. (REG_DWORD != dwType))
  264. {
  265. nRuns = 0;
  266. }
  267. nRuns ++;
  268. RegSetValueEx(hkey, REGVAL_PASSPORT_NUMBEROFWIZARDRUNS, NULL, REG_DWORD, (const BYTE *) &nRuns, sizeof (nRuns));
  269. RegCloseKey(hkey);
  270. }
  271. }
  272. return TRUE;
  273. case WM_NOTIFY:
  274. {
  275. LPNMHDR pnmh = (LPNMHDR) lParam;
  276. switch (pnmh->code)
  277. {
  278. case PSN_SETACTIVE:
  279. PropSheet_SetWizButtons(pnmh->hwndFrom, PSWIZB_NEXT);
  280. return TRUE;
  281. case PSN_WIZNEXT:
  282. {
  283. // we need ICW to have executed before we navigate to webbased UI
  284. LaunchICW();
  285. if (SUCCEEDED(_SetURLFromNexus()))
  286. {
  287. HPROPSHEETPAGE hpageNext;
  288. if (SUCCEEDED(_pwwe->GetFirstPage(&hpageNext)))
  289. {
  290. PropSheet_SetCurSel(GetParent(hwnd), hpageNext, -1);
  291. }
  292. }
  293. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LONG_PTR) -1);
  294. return TRUE;
  295. }
  296. case NM_CLICK:
  297. case NM_RETURN:
  298. switch ((int) wParam)
  299. {
  300. case IDC_PRIVACYLINK:
  301. {
  302. WCHAR szURL[INTERNET_MAX_URL_LENGTH];
  303. HRESULT hr = PassportGetURL(PASSPORTURL_PRIVACY, szURL, ARRAYSIZE(szURL));
  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. // Previous page is the web wizard host.
  425. if (SUCCEEDED(_SetURLFromNexus()))
  426. {
  427. HPROPSHEETPAGE hpageNext;
  428. if (SUCCEEDED(_pwwe->GetFirstPage(&hpageNext)))
  429. {
  430. PropSheet_SetCurSel(GetParent(hwnd), hpageNext, -1);
  431. }
  432. }
  433. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, (LPARAM)-1);
  434. return TRUE;
  435. case PSN_WIZFINISH:
  436. _ApplyChanges(hwnd);
  437. return TRUE;
  438. }
  439. break;
  440. }
  441. }
  442. return FALSE;
  443. }
  444. // Help requires a rundll entrypoint to run passport wizard
  445. void APIENTRY PassportWizardRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  446. {
  447. HRESULT hr = CoInitialize(NULL);
  448. if (SUCCEEDED(hr))
  449. {
  450. IPassportWizard* pPW = NULL;
  451. hr = CoCreateInstance(CLSID_PassportWizard, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPassportWizard, &pPW));
  452. if (SUCCEEDED(hr))
  453. {
  454. pPW->SetOptions(PPW_LAUNCHEDBYUSER);
  455. pPW->Show(hwndStub);
  456. pPW->Release();
  457. }
  458. CoUninitialize();
  459. }
  460. }
  461. void BoldControl(HWND hwnd, int id)
  462. {
  463. HWND hwndTitle = GetDlgItem(hwnd, id);
  464. // Get the existing font
  465. HFONT hfontOld = (HFONT) SendMessage(hwndTitle, WM_GETFONT, 0, 0);
  466. LOGFONT lf = {0};
  467. if (GetObject(hfontOld, sizeof(lf), &lf))
  468. {
  469. lf.lfWeight = FW_BOLD;
  470. HFONT hfontNew = CreateFontIndirect(&lf);
  471. if (hfontNew)
  472. {
  473. SendMessage(hwndTitle, WM_SETFONT, (WPARAM) hfontNew, FALSE);
  474. // Don't do this, its shared.
  475. // DeleteObject(hfontOld);
  476. }
  477. }
  478. }