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.

678 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: firstpin.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.h"
  11. #pragma hdrstop
  12. #include "firstpin.h"
  13. #include "folder.h"
  14. #include "idlhelp.h"
  15. #include "msgbox.h"
  16. #include "cscst.h"
  17. #include "syncmgr.h"
  18. #include "strings.h"
  19. //
  20. // Base class for all "first pin" wizard pages.
  21. // Contains the single dialog proc used for all pages. Specialization
  22. // for individual pages is achieved through deriviation and implementing
  23. // virtual functions.
  24. //
  25. class CWizardPage
  26. {
  27. public:
  28. enum { WM_WIZARDFINISHED = (WM_USER + 1) };
  29. CWizardPage(HINSTANCE hInstance,
  30. UINT idDlgTemplate,
  31. UINT idsHdrTitle,
  32. UINT idsHdrSubtitle,
  33. DWORD dwPgFlags,
  34. DWORD dwBtnFlags);
  35. virtual ~CWizardPage(void);
  36. UINT GetDlgTemplate(void) const
  37. { return m_idDlgTemplate; }
  38. UINT GetHeaderTitle(void) const
  39. { return m_idsHdrTitle; }
  40. UINT GetHeaderSubtitle(void) const
  41. { return m_idsHdrSubtitle; }
  42. DWORD GetPageFlags(void) const
  43. { return m_dwPgFlags; }
  44. DWORD GetBtnFlags(void) const
  45. { return m_dwBtnFlags; }
  46. DLGPROC GetDlgProc(void) const
  47. { return DlgProc; }
  48. virtual BOOL OnInitDialog(WPARAM wParam, LPARAM lParam)
  49. { return TRUE; }
  50. virtual BOOL OnPSNSetActive(void);
  51. virtual BOOL OnPSNWizFinish(void)
  52. { SetWindowLong(m_hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); return FALSE; }
  53. virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
  54. { return FALSE; }
  55. virtual BOOL OnWizardFinished(void) { return FALSE; }
  56. protected:
  57. HINSTANCE m_hInstance;
  58. HWND m_hwndDlg;
  59. HFONT m_hTitleFont; // Used only by cover and finish pages.
  60. UINT m_cyTitleFontHt; // Title font height in pts.
  61. int FontPtsToHt(HWND hwnd, int pts);
  62. BOOL FormatTitleFont(UINT idcTitle);
  63. private:
  64. UINT m_idDlgTemplate; // Dialog resource template.
  65. UINT m_idsHdrTitle; // String ID for pg header title.
  66. UINT m_idsHdrSubtitle; // String ID for pg header subtitle.
  67. DWORD m_dwBtnFlags; // PSB_WIZXXXXX flags.
  68. DWORD m_dwPgFlags; // PSP_XXXX flags.
  69. static INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  70. };
  71. //
  72. // Welcome page.
  73. //
  74. class CWizardPgWelcome : public CWizardPage
  75. {
  76. public:
  77. CWizardPgWelcome(HINSTANCE hInstance,
  78. UINT idDlgTemplate,
  79. UINT idsHdrTitle,
  80. UINT idsHdrSubtitle,
  81. DWORD dwPgFlags,
  82. DWORD dwBtnFlags
  83. ) : CWizardPage(hInstance,
  84. idDlgTemplate,
  85. idsHdrTitle,
  86. idsHdrSubtitle,
  87. dwPgFlags,
  88. dwBtnFlags)
  89. { }
  90. BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
  91. };
  92. //
  93. // Pinning page.
  94. //
  95. class CWizardPgPin : public CWizardPage
  96. {
  97. public:
  98. CWizardPgPin(HINSTANCE hInstance,
  99. UINT idDlgTemplate,
  100. UINT idsHdrTitle,
  101. UINT idsHdrSubtitle,
  102. DWORD dwPgFlags,
  103. DWORD dwBtnFlags
  104. ) : CWizardPage(hInstance,
  105. idDlgTemplate,
  106. idsHdrTitle,
  107. idsHdrSubtitle,
  108. dwPgFlags,
  109. dwBtnFlags) { }
  110. BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
  111. BOOL OnWizardFinished(void);
  112. };
  113. //
  114. // Offline page.
  115. //
  116. class CWizardPgOffline : public CWizardPage
  117. {
  118. public:
  119. CWizardPgOffline(HINSTANCE hInstance,
  120. UINT idDlgTemplate,
  121. UINT idsHdrTitle,
  122. UINT idsHdrSubtitle,
  123. DWORD dwPgFlags,
  124. DWORD dwBtnFlags
  125. ) : CWizardPage(hInstance,
  126. idDlgTemplate,
  127. idsHdrTitle,
  128. idsHdrSubtitle,
  129. dwPgFlags,
  130. dwBtnFlags) { }
  131. BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
  132. BOOL OnPSNWizFinish(void);
  133. BOOL OnWizardFinished(void);
  134. };
  135. //
  136. // Class encapsulating the functionality of the entire wizard.
  137. // It contains member instances of each of the page types.
  138. //
  139. class CFirstPinWizard
  140. {
  141. public:
  142. CFirstPinWizard(HINSTANCE hInstance, HWND hwndParent);
  143. HRESULT Run(void);
  144. private:
  145. enum { PG_WELCOME,
  146. PG_PIN,
  147. PG_OFFLINE,
  148. PG_NUMPAGES };
  149. HINSTANCE m_hInstance;
  150. HWND m_hwndParent;
  151. CWizardPgWelcome m_PgWelcome;
  152. CWizardPgPin m_PgPin;
  153. CWizardPgOffline m_PgOffline;
  154. CWizardPage *m_rgpWizPages[PG_NUMPAGES];
  155. };
  156. //
  157. // CWizardPage members --------------------------------------------------------
  158. //
  159. CWizardPage::CWizardPage(
  160. HINSTANCE hInstance,
  161. UINT idDlgTemplate,
  162. UINT idsHdrTitle,
  163. UINT idsHdrSubtitle,
  164. DWORD dwPgFlags,
  165. DWORD dwBtnFlags
  166. ) : m_hInstance(hInstance),
  167. m_idDlgTemplate(idDlgTemplate),
  168. m_idsHdrTitle(idsHdrTitle),
  169. m_idsHdrSubtitle(idsHdrSubtitle),
  170. m_dwPgFlags(dwPgFlags),
  171. m_dwBtnFlags(dwBtnFlags),
  172. m_cyTitleFontHt(12),
  173. m_hwndDlg(NULL),
  174. m_hTitleFont(NULL)
  175. {
  176. //
  177. // Get the title font height from a resource string. That way localizers can
  178. // play with the font dimensions if necessary.
  179. //
  180. TCHAR szFontHt[20];
  181. if (0 < LoadString(m_hInstance, IDS_FIRSTPIN_FONTHT_PTS, szFontHt, ARRAYSIZE(szFontHt)))
  182. {
  183. m_cyTitleFontHt = StrToInt(szFontHt);
  184. }
  185. }
  186. CWizardPage::~CWizardPage(
  187. void
  188. )
  189. {
  190. if (NULL != m_hTitleFont)
  191. {
  192. DeleteObject(m_hTitleFont);
  193. }
  194. }
  195. //
  196. // PSN_SETACTIVE handler.
  197. //
  198. BOOL
  199. CWizardPage::OnPSNSetActive(
  200. void
  201. )
  202. {
  203. PropSheet_SetWizButtons(GetParent(m_hwndDlg), m_dwBtnFlags);
  204. return FALSE;
  205. }
  206. //
  207. // Dialog proc used by all pages in this wizard.
  208. //
  209. INT_PTR CALLBACK
  210. CWizardPage::DlgProc(
  211. HWND hwnd,
  212. UINT uMsg,
  213. WPARAM wParam,
  214. LPARAM lParam
  215. )
  216. {
  217. CWizardPage *pPage = (CWizardPage *)GetWindowLongPtr(hwnd, DWLP_USER);
  218. BOOL bResult = FALSE;
  219. switch(uMsg)
  220. {
  221. case WM_INITDIALOG:
  222. {
  223. PROPSHEETPAGE *ppsp = (PROPSHEETPAGE *)lParam;
  224. pPage = (CWizardPage *)ppsp->lParam;
  225. TraceAssert(NULL != pPage);
  226. SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pPage);
  227. pPage->m_hwndDlg = hwnd;
  228. bResult = pPage->OnInitDialog(wParam, lParam);
  229. break;
  230. }
  231. case WM_COMMAND:
  232. if (NULL != pPage)
  233. bResult = pPage->OnCommand(wParam, lParam);
  234. break;
  235. case WM_NOTIFY:
  236. switch(((LPNMHDR)lParam)->code)
  237. {
  238. case PSN_SETACTIVE:
  239. bResult = pPage->OnPSNSetActive();
  240. break;
  241. case PSN_WIZFINISH:
  242. bResult = pPage->OnPSNWizFinish();
  243. break;
  244. }
  245. break;
  246. case PSM_QUERYSIBLINGS:
  247. if (CWizardPage::WM_WIZARDFINISHED == wParam)
  248. bResult = pPage->OnWizardFinished();
  249. break;
  250. default:
  251. break;
  252. }
  253. return bResult;
  254. }
  255. //
  256. // Helper function to convert a font point size to a height value
  257. // used in a LOGFONT structure.
  258. //
  259. int
  260. CWizardPage::FontPtsToHt(
  261. HWND hwnd,
  262. int pts
  263. )
  264. {
  265. int ht = 10;
  266. HDC hdc = GetDC(hwnd);
  267. if (NULL != hdc)
  268. {
  269. ht = -MulDiv(pts, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  270. ReleaseDC(hwnd, hdc);
  271. }
  272. return ht;
  273. }
  274. //
  275. // The title text on the cover and finish pages is enlarged and bold.
  276. // This code modifies the text in the dialog accordingly.
  277. // On return, m_hTitleFont contains the handle to the title font.
  278. //
  279. BOOL
  280. CWizardPage::FormatTitleFont(
  281. UINT idcTitle
  282. )
  283. {
  284. BOOL bResult = FALSE;
  285. HWND hwndTitle = GetDlgItem(m_hwndDlg, idcTitle);
  286. HFONT hFont = (HFONT)SendMessage(hwndTitle, WM_GETFONT, 0, 0);
  287. if (NULL != hFont)
  288. {
  289. if (NULL == m_hTitleFont)
  290. {
  291. LOGFONT lf;
  292. if (GetObject(hFont, sizeof(lf), &lf))
  293. {
  294. lf.lfHeight = FontPtsToHt(hwndTitle, m_cyTitleFontHt);
  295. m_hTitleFont = CreateFontIndirect(&lf);
  296. }
  297. }
  298. if (NULL != m_hTitleFont)
  299. {
  300. SendMessage(hwndTitle, WM_SETFONT, (WPARAM)m_hTitleFont, 0);
  301. bResult = TRUE;
  302. }
  303. }
  304. return bResult;
  305. }
  306. //
  307. // CWizardPgWelcome members -----------------------------------------------------
  308. //
  309. //
  310. // WM_INITDIALOG handler.
  311. //
  312. BOOL
  313. CWizardPgWelcome::OnInitDialog(
  314. WPARAM wParam,
  315. LPARAM lParam
  316. )
  317. {
  318. FormatTitleFont(IDC_TXT_FIRSTPIN_WELCOME_TITLE);
  319. return CWizardPage::OnInitDialog(wParam, lParam);
  320. }
  321. //
  322. // CWizardPgPin members -------------------------------------------------------
  323. //
  324. //
  325. // WM_INITDIALOG handler.
  326. //
  327. BOOL
  328. CWizardPgPin::OnInitDialog(
  329. WPARAM wParam,
  330. LPARAM lParam
  331. )
  332. {
  333. HRESULT hr = IsRegisteredForSyncAtLogonAndLogoff();
  334. CheckDlgButton(m_hwndDlg,
  335. IDC_CBX_FIRSTPIN_AUTOSYNC,
  336. S_OK == hr ? BST_CHECKED : BST_UNCHECKED);
  337. return CWizardPage::OnInitDialog(wParam, lParam);
  338. }
  339. //
  340. // PSN_WIZFINISH handler.
  341. //
  342. BOOL
  343. CWizardPgPin::OnWizardFinished(
  344. void
  345. )
  346. {
  347. HRESULT hr;
  348. RegisterSyncMgrHandler(TRUE);
  349. if (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_FIRSTPIN_AUTOSYNC))
  350. {
  351. const DWORD dwFlags = SYNCMGRREGISTERFLAG_CONNECT | SYNCMGRREGISTERFLAG_PENDINGDISCONNECT;
  352. hr = RegisterForSyncAtLogonAndLogoff(dwFlags, dwFlags);
  353. if (SUCCEEDED(hr))
  354. {
  355. SetSyncMgrInitialized();
  356. }
  357. else
  358. {
  359. CscMessageBox(m_hwndDlg,
  360. MB_OK | MB_ICONERROR,
  361. Win32Error(HRESULT_CODE(hr)),
  362. m_hInstance,
  363. IDS_ERR_REGSYNCATLOGONLOGOFF);
  364. }
  365. }
  366. return CWizardPage::OnWizardFinished();
  367. }
  368. //
  369. // CWizardPgOffline members ---------------------------------------------------
  370. //
  371. //
  372. // WM_INITDIALOG handler.
  373. //
  374. BOOL
  375. CWizardPgOffline::OnInitDialog(
  376. WPARAM wParam,
  377. LPARAM lParam
  378. )
  379. {
  380. //
  381. // If policy allows configuration of the reminders, check the "enable reminders"
  382. // checkbox.
  383. //
  384. CConfig& config = CConfig::GetSingleton();
  385. bool bNoConfigReminders;
  386. bool bNoCacheViewer = config.NoCacheViewer();
  387. config.NoReminders(&bNoConfigReminders);
  388. CheckDlgButton(m_hwndDlg, IDC_CBX_REMINDERS, !bNoConfigReminders);
  389. EnableWindow(GetDlgItem(m_hwndDlg, IDC_CBX_REMINDERS), !bNoConfigReminders);
  390. CheckDlgButton(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK, BST_UNCHECKED);
  391. EnableWindow(GetDlgItem(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK), !bNoCacheViewer);
  392. return CWizardPage::OnInitDialog(wParam, lParam);
  393. }
  394. //
  395. // PSN_WIZFINISH handler.
  396. //
  397. BOOL
  398. CWizardPgOffline::OnPSNWizFinish(
  399. void
  400. )
  401. {
  402. //
  403. // Send PSM_QUERYSIBLINGS to all of the pages with
  404. // wParam set to WM_WIZARDFINISHED. This will trigger
  405. // a call to the virtual function OnWizardFinished()
  406. // allowing each page to respond to the successful completion
  407. // of the wizard.
  408. //
  409. PropSheet_QuerySiblings(GetParent(m_hwndDlg),
  410. CWizardPage::WM_WIZARDFINISHED,
  411. 0);
  412. //
  413. // Now handle for this page.
  414. //
  415. OnWizardFinished();
  416. return CWizardPage::OnPSNWizFinish();
  417. }
  418. //
  419. // PSN_WIZFINISH handler.
  420. //
  421. BOOL
  422. CWizardPgOffline::OnWizardFinished(
  423. void
  424. )
  425. {
  426. bool bEnableReminders = (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_REMINDERS));
  427. DWORD dwValue;
  428. DWORD dwErr;
  429. dwValue = bEnableReminders ? 0 : 1;
  430. dwErr = SHSetValue(HKEY_CURRENT_USER,
  431. REGSTR_KEY_OFFLINEFILES,
  432. REGSTR_VAL_NOREMINDERS,
  433. REG_DWORD,
  434. &dwValue,
  435. sizeof(dwValue));
  436. if (bEnableReminders)
  437. {
  438. PostToSystray(PWM_RESET_REMINDERTIMER, 0, 0);
  439. }
  440. if (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK))
  441. {
  442. COfflineFilesFolder::CreateLinkOnDesktop(m_hwndDlg);
  443. }
  444. return CWizardPage::OnWizardFinished();
  445. }
  446. //
  447. // CFirstPinWizard members ----------------------------------------------------
  448. //
  449. CFirstPinWizard::CFirstPinWizard(
  450. HINSTANCE hInstance,
  451. HWND hwndParent
  452. ) : m_hInstance(hInstance),
  453. m_hwndParent(hwndParent),
  454. m_PgWelcome(hInstance,
  455. IDD_FIRSTPIN_WELCOME,
  456. 0,
  457. 0,
  458. PSP_DEFAULT,
  459. PSWIZB_NEXT),
  460. m_PgPin(hInstance,
  461. IDD_FIRSTPIN_PIN,
  462. 0,
  463. 0,
  464. PSP_DEFAULT,
  465. PSWIZB_NEXT | PSWIZB_BACK),
  466. m_PgOffline(hInstance,
  467. IDD_FIRSTPIN_OFFLINE,
  468. 0,
  469. 0,
  470. PSP_DEFAULT,
  471. PSWIZB_FINISH | PSWIZB_BACK)
  472. {
  473. //
  474. // Store pointers to each page in an array. Makes creating the
  475. // prop sheet easier in Run().
  476. //
  477. m_rgpWizPages[0] = &m_PgWelcome;
  478. m_rgpWizPages[1] = &m_PgPin;
  479. m_rgpWizPages[2] = &m_PgOffline;
  480. }
  481. //
  482. // Creates the wizard and runs it.
  483. // The wizard runs modally.
  484. //
  485. // Returns:
  486. //
  487. // S_OK = User completed wizard and pressed "Finish".
  488. // S_FALSE = User pressed "Cancel" in wizard.
  489. // Other = Error creating wizard.
  490. //
  491. HRESULT
  492. CFirstPinWizard::Run(
  493. void
  494. )
  495. {
  496. HRESULT hr = NOERROR;
  497. PROPSHEETHEADER psh;
  498. PROPSHEETPAGE psp;
  499. HPROPSHEETPAGE rghpage[ARRAYSIZE(m_rgpWizPages)];
  500. ZeroMemory(&psh, sizeof(psh));
  501. ZeroMemory(rghpage, sizeof(rghpage));
  502. psh.dwSize = sizeof(psh);
  503. psh.dwFlags = PSH_WIZARD_LITE;
  504. psh.hwndParent = m_hwndParent;
  505. psh.hInstance = m_hInstance;
  506. psh.nPages = ARRAYSIZE(rghpage);
  507. psh.phpage = rghpage;
  508. TCHAR szTitle[MAX_PATH];
  509. TCHAR szSubTitle[MAX_PATH];
  510. for (int i = 0; i < ARRAYSIZE(rghpage) && SUCCEEDED(hr); i++)
  511. {
  512. CWizardPage *pwp = m_rgpWizPages[i];
  513. ZeroMemory(&psp, sizeof(psp));
  514. psp.dwSize = sizeof(psp);
  515. psp.dwFlags |= pwp->GetPageFlags();
  516. psp.hInstance = m_hInstance;
  517. psp.pszTemplate = MAKEINTRESOURCE(pwp->GetDlgTemplate());
  518. psp.pfnDlgProc = pwp->GetDlgProc();
  519. psp.lParam = (LPARAM)pwp;
  520. rghpage[i] = CreatePropertySheetPage(&psp);
  521. if (NULL == rghpage[i])
  522. {
  523. while(0 <= --i)
  524. {
  525. DestroyPropertySheetPage(rghpage[i]);
  526. }
  527. hr = E_FAIL;
  528. }
  529. }
  530. if (SUCCEEDED(hr))
  531. {
  532. switch(PropertySheet(&psh))
  533. {
  534. case -1:
  535. hr = HRESULT_FROM_WIN32(GetLastError());
  536. break;
  537. case 0:
  538. hr = S_FALSE; // User pressed "Cancel".
  539. break;
  540. case 1:
  541. hr = S_OK; // User pressed "Finish".
  542. break;
  543. }
  544. }
  545. return hr;
  546. }
  547. //
  548. // This is the function you call when you want to run the wizard.
  549. // It merely creates a wizard object and tells it to run.
  550. // If the user finishes the wizard, it records this fact in the
  551. // registry. Calling FirstPinWizardCompleted() will tell
  552. // you later if the user has finished the wizard.
  553. //
  554. // Returns:
  555. //
  556. // S_OK = User completed wizard and pressed "Finish".
  557. // S_FALSE = User cancelled out of wizard.
  558. // Other = Error creating wizard.
  559. //
  560. HRESULT
  561. ShowFirstPinWizard(
  562. HWND hwndParent
  563. )
  564. {
  565. HRESULT hr = NOERROR;
  566. CFirstPinWizard Wizard(g_hInstance, hwndParent);
  567. hr = Wizard.Run();
  568. if (S_OK == hr)
  569. {
  570. //
  571. // Only record "finished" in registry if user
  572. // pressed "finish".
  573. //
  574. RegKey key(HKEY_CURRENT_USER, REGSTR_KEY_OFFLINEFILES);
  575. if (SUCCEEDED(key.Open(KEY_SET_VALUE, true)))
  576. {
  577. key.SetValue(REGSTR_VAL_FIRSTPINWIZARDSHOWN, 1);
  578. }
  579. }
  580. return hr;
  581. }
  582. //
  583. // Has user seen the wizard and pressed "finish"?
  584. //
  585. bool
  586. FirstPinWizardCompleted(
  587. void
  588. )
  589. {
  590. return CConfig::GetSingleton().FirstPinWizardShown();
  591. }