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.

5721 lines
160 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #ifndef ARRAYSIZE
  4. #define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
  5. #endif
  6. typedef struct
  7. {
  8. WORD wDlgVer;
  9. WORD wSignature;
  10. DWORD dwHelpID;
  11. DWORD dwExStyle;
  12. DWORD dwStyle;
  13. WORD cDlgItems;
  14. WORD x;
  15. WORD y;
  16. WORD cx;
  17. WORD cy;
  18. } DLGTEMPLATEEX, FAR *LPDLGTEMPLATEEX;
  19. //
  20. // We'll use this to disable passing through dialog boxes because we're
  21. // unattended.
  22. //
  23. BOOL CancelPending = FALSE;
  24. //
  25. // This indicates that well give the user some detailed data-throughput
  26. // info.
  27. //
  28. BOOL DetailedCopyProgress = FALSE;
  29. //
  30. // This indicates that one may only upgade (I.E. CCP media)
  31. //
  32. BOOL UpgradeOnly = FALSE;
  33. //
  34. // Points to thread that does the machine inspection.
  35. //
  36. HANDLE InspectionThreadHandle;
  37. #ifdef _X86_
  38. //
  39. // Win9x upgrade report status
  40. //
  41. UINT g_UpgradeReportMode;
  42. #endif
  43. //
  44. // Stuff used for watermarking
  45. //
  46. WNDPROC OldWizardProc;
  47. UINT WatermarkHeaderHeight;
  48. BITMAP_DATA Watermark;
  49. BITMAP_DATA Header;
  50. BITMAP_DATA Header2;
  51. HWND WizardHandle;
  52. HWND BackgroundWnd = NULL;
  53. HWND GetBBhwnd();
  54. BOOL StartStopBB(BOOL bStart);
  55. void BB_SetProgressText(LPTSTR szText);
  56. void BB_SetInfoText(LPTSTR szText);
  57. LRESULT BB_ProgressGaugeMsg(UINT msg, WPARAM wparam, LPARAM lparam);
  58. BOOL BB_ShowProgressGaugeWnd(UINT nCmdShow);
  59. void SetBBStep(int iStep);
  60. typedef enum {
  61. Phase_Unknown = -1,
  62. Phase_DynamicUpdate = 0,
  63. Phase_HwCompatDat,
  64. Phase_UpgradeReport,
  65. Phase_FileCopy,
  66. Phase_Reboot,
  67. Phase_RestOfSetup
  68. } SetupPhases;
  69. typedef struct _SETUPPHASE {
  70. DWORD Time;
  71. BOOL Clean;
  72. DWORD OS;
  73. } SETUPPHASE;
  74. #define ALLOS (VER_PLATFORM_WIN32_WINDOWS | VER_PLATFORM_WIN32_NT)
  75. #define TIME_DYNAMICUPDATE 300
  76. #define TIME_HWCOMPDAT 120
  77. #define TIME_UPGRADEREPORT 600
  78. #define TIME_REBOOT 15
  79. // 13 minnutes for text mode, 37 minutes for GUI mode.
  80. #define TIME_RESTOFSETUP (13+37)*60
  81. SETUPPHASE SetupPhase[] = {
  82. { 0, TRUE, ALLOS }, // DynamicUpdate
  83. { TIME_HWCOMPDAT, FALSE, VER_PLATFORM_WIN32_WINDOWS }, // HwCompatDat
  84. { TIME_UPGRADEREPORT, FALSE, VER_PLATFORM_WIN32_WINDOWS }, // UpgradeReport
  85. { 0, TRUE, ALLOS }, // FileCopy
  86. { TIME_REBOOT, TRUE, ALLOS }, // Reboot
  87. { TIME_RESTOFSETUP, TRUE, ALLOS } // RestOfSetup
  88. };
  89. void SetTimeEstimates();
  90. DWORD CalcTimeRemaining(UINT Phase);
  91. void UpdateTimeString(DWORD RemainungTimeMsecInThisPhase,
  92. DWORD *PreviousRemainingTime);
  93. void SetRemainingTime(DWORD TimeInSeconds);
  94. DWORD GetFileCopyEstimate();
  95. DWORD GetHwCompDatEstimate();
  96. DWORD GetUpgradeReportEstimate();
  97. DWORD GetDynamicUpdateEstimate();
  98. DWORD GetRestOfSetupEstimate();
  99. UINT CurrentPhase = Phase_Unknown;
  100. ULONG RemainingTime = 0;
  101. //
  102. // Enum for SetDialogFont().
  103. //
  104. typedef enum {
  105. DlgFontTitle,
  106. DlgFontSupertitle,
  107. DlgFontSubtitle,
  108. DlgFontStart
  109. } MyDlgFont;
  110. INT_PTR SetNextPhaseWizPage(
  111. IN HWND hdlg,
  112. IN UINT msg,
  113. IN WPARAM wParam,
  114. IN LPARAM lParam
  115. );
  116. INT_PTR
  117. TimeEstimateWizPage(
  118. IN HWND hdlg,
  119. IN UINT msg,
  120. IN WPARAM wParam,
  121. IN LPARAM lParam
  122. );
  123. BOOL
  124. WizardDlgProc(
  125. IN HWND hdlg,
  126. IN UINT msg,
  127. IN WPARAM wParam,
  128. IN LPARAM lParam
  129. );
  130. INT_PTR
  131. WelcomeWizPage(
  132. IN HWND hdlg,
  133. IN UINT msg,
  134. IN WPARAM wParam,
  135. IN LPARAM lParam
  136. );
  137. INT_PTR
  138. EulaWizPage(
  139. IN HWND hdlg,
  140. IN UINT msg,
  141. IN WPARAM wParam,
  142. IN LPARAM lParam
  143. );
  144. INT_PTR
  145. SelectPid30WizPage(
  146. IN HWND hdlg,
  147. IN UINT msg,
  148. IN WPARAM wParam,
  149. IN LPARAM lParam
  150. );
  151. INT_PTR
  152. OemPid30WizPage(
  153. IN HWND hdlg,
  154. IN UINT msg,
  155. IN WPARAM wParam,
  156. IN LPARAM lParam
  157. );
  158. INT_PTR
  159. CdPid30WizPage(
  160. IN HWND hdlg,
  161. IN UINT msg,
  162. IN WPARAM wParam,
  163. IN LPARAM lParam
  164. );
  165. #ifdef _X86_
  166. INT_PTR
  167. Win9xUpgradeReportPage(
  168. IN HWND hdlg,
  169. IN UINT msg,
  170. IN WPARAM wParam,
  171. IN LPARAM lParam
  172. );
  173. #endif
  174. INT_PTR
  175. DynSetupWizPage(
  176. IN HWND hdlg,
  177. IN UINT msg,
  178. IN WPARAM wParam,
  179. IN LPARAM lParam
  180. );
  181. INT_PTR
  182. DynSetup2WizPage(
  183. IN HWND hdlg,
  184. IN UINT msg,
  185. IN WPARAM wParam,
  186. IN LPARAM lParam
  187. );
  188. INT_PTR
  189. DynSetup3WizPage(
  190. IN HWND hdlg,
  191. IN UINT msg,
  192. IN WPARAM wParam,
  193. IN LPARAM lParam
  194. );
  195. INT_PTR
  196. DynSetup4WizPage(
  197. IN HWND hdlg,
  198. IN UINT msg,
  199. IN WPARAM wParam,
  200. IN LPARAM lParam
  201. );
  202. INT_PTR
  203. DynSetup5WizPage(
  204. IN HWND hdlg,
  205. IN UINT msg,
  206. IN WPARAM wParam,
  207. IN LPARAM lParam
  208. );
  209. INT_PTR
  210. RestartWizPage (
  211. IN HWND hdlg,
  212. IN UINT msg,
  213. IN WPARAM wParam,
  214. IN LPARAM lParam
  215. );
  216. INT_PTR
  217. ServerWizPage(
  218. IN HWND hdlg,
  219. IN UINT msg,
  220. IN WPARAM wParam,
  221. IN LPARAM lParam
  222. );
  223. INT_PTR
  224. CompatibilityWizPage(
  225. IN HWND hdlg,
  226. IN UINT msg,
  227. IN WPARAM wParam,
  228. IN LPARAM lParam
  229. );
  230. INT_PTR
  231. NTFSConvertWizPage(
  232. IN HWND hdlg,
  233. IN UINT msg,
  234. IN WPARAM wParam,
  235. IN LPARAM lParam
  236. );
  237. INT_PTR
  238. OptionsWizPage(
  239. IN HWND hdlg,
  240. IN UINT msg,
  241. IN WPARAM wParam,
  242. IN LPARAM lParam
  243. );
  244. INT_PTR
  245. Working1WizPage(
  246. IN HWND hdlg,
  247. IN UINT msg,
  248. IN WPARAM wParam,
  249. IN LPARAM lParam
  250. );
  251. #ifdef _X86_
  252. INT_PTR
  253. FloppyWizPage(
  254. IN HWND hdlg,
  255. IN UINT msg,
  256. IN WPARAM wParam,
  257. IN LPARAM lParam
  258. );
  259. #endif
  260. INT_PTR
  261. CopyingWizPage(
  262. IN HWND hdlg,
  263. IN UINT msg,
  264. IN WPARAM wParam,
  265. IN LPARAM lParam
  266. );
  267. INT_PTR
  268. DoneWizPage(
  269. IN HWND hdlg,
  270. IN UINT msg,
  271. IN WPARAM wParam,
  272. IN LPARAM lParam
  273. );
  274. INT_PTR
  275. CleaningWizPage(
  276. IN HWND hdlg,
  277. IN UINT msg,
  278. IN WPARAM wParam,
  279. IN LPARAM lParam
  280. );
  281. INT_PTR
  282. NotDoneWizPage(
  283. IN HWND hdlg,
  284. IN UINT msg,
  285. IN WPARAM wParam,
  286. IN LPARAM lParam
  287. );
  288. VOID
  289. AdjustWatermarkBitmap(
  290. IN HANDLE hdlg,
  291. IN HDC hdc,
  292. IN OUT PBITMAP_DATA BitmapData,
  293. IN BOOL FullPage
  294. );
  295. //
  296. // Page descriptors. Put this after function declarations so the initializers
  297. // work properly and the compiler doesn't complain.
  298. //
  299. PAGE_CREATE_DATA ProtoPages[] = {
  300. {
  301. NULL,NULL,
  302. IDD_WELCOME,
  303. {
  304. WelcomeWizPage,
  305. BBSTEP_COLLECTING_INFORMATION,
  306. PSWIZB_NEXT,
  307. WIZPAGE_FULL_PAGE_WATERMARK | WIZPAGE_SEPARATOR_CREATED
  308. }
  309. },
  310. {
  311. NULL,NULL,
  312. IDD_EULA,
  313. {
  314. EulaWizPage,
  315. BBSTEP_COLLECTING_INFORMATION,
  316. PSWIZB_BACK
  317. }
  318. },
  319. {
  320. NULL,NULL,
  321. IDD_PID_CD,
  322. {
  323. CdPid30WizPage,
  324. BBSTEP_COLLECTING_INFORMATION,
  325. PSWIZB_NEXT | PSWIZB_BACK
  326. }
  327. },
  328. {
  329. NULL,NULL,
  330. IDD_PID_OEM,
  331. {
  332. OemPid30WizPage,
  333. BBSTEP_COLLECTING_INFORMATION,
  334. PSWIZB_NEXT | PSWIZB_BACK
  335. }
  336. },
  337. {
  338. NULL,NULL,
  339. IDD_PID_SELECT,
  340. {
  341. SelectPid30WizPage,
  342. BBSTEP_COLLECTING_INFORMATION,
  343. PSWIZB_NEXT | PSWIZB_BACK
  344. }
  345. },
  346. {
  347. NULL,NULL,
  348. IDD_OPTIONS,
  349. {
  350. OptionsWizPage,
  351. BBSTEP_COLLECTING_INFORMATION,
  352. PSWIZB_NEXT | PSWIZB_BACK
  353. }
  354. },
  355. {
  356. NULL,NULL,
  357. IDD_NTFS_CONVERT,
  358. {
  359. NTFSConvertWizPage,
  360. BBSTEP_COLLECTING_INFORMATION,
  361. PSWIZB_NEXT | PSWIZB_BACK
  362. }
  363. },
  364. {
  365. NULL,NULL,
  366. IDD_SRVCOMP,
  367. {
  368. ServerWizPage,
  369. BBSTEP_COLLECTING_INFORMATION,
  370. PSWIZB_NEXT | PSWIZB_BACK
  371. }
  372. },
  373. #ifdef _X86_
  374. {
  375. NULL,NULL,
  376. IDD_REPORT_HELP,
  377. {
  378. Win9xUpgradeReportPage,
  379. BBSTEP_COLLECTING_INFORMATION,
  380. PSWIZB_NEXT | PSWIZB_BACK
  381. }
  382. },
  383. #endif
  384. {
  385. NULL,NULL,
  386. IDD_DYNAMICSETUP,
  387. {
  388. DynSetupWizPage,
  389. BBSTEP_DYNAMIC_UPDATE,
  390. PSWIZB_NEXT | PSWIZB_BACK
  391. }
  392. },
  393. {
  394. NULL,NULL,
  395. IDD_DYNAMICSETUP2,
  396. {
  397. DynSetup2WizPage,
  398. BBSTEP_DYNAMIC_UPDATE
  399. }
  400. },
  401. {
  402. NULL,NULL,
  403. IDD_RESTART,
  404. {
  405. RestartWizPage,
  406. BBSTEP_DYNAMIC_UPDATE,
  407. PSWIZB_NEXT
  408. }
  409. },
  410. {
  411. NULL,NULL,
  412. IDD_DYNAMICSETUP3,
  413. {
  414. DynSetup3WizPage,
  415. BBSTEP_DYNAMIC_UPDATE,
  416. PSWIZB_NEXT
  417. }
  418. },
  419. {
  420. NULL,NULL,
  421. IDD_DYNAMICSETUP4,
  422. {
  423. DynSetup4WizPage,
  424. BBSTEP_DYNAMIC_UPDATE,
  425. PSWIZB_NEXT
  426. }
  427. },
  428. {
  429. NULL,NULL,
  430. IDD_DYNAMICSETUP5,
  431. {
  432. DynSetup5WizPage,
  433. BBSTEP_DYNAMIC_UPDATE,
  434. PSWIZB_NEXT
  435. }
  436. },
  437. {
  438. NULL,NULL,
  439. IDD_EMPTY,
  440. {
  441. TimeEstimateWizPage,
  442. BBSTEP_PREPARING,
  443. 0
  444. }
  445. },
  446. {
  447. NULL,NULL,
  448. IDD_EMPTY,
  449. {
  450. SetNextPhaseWizPage,
  451. BBSTEP_PREPARING,
  452. 0
  453. }
  454. },
  455. {
  456. &UpgradeSupport.Pages1,
  457. &UpgradeSupport.AfterWelcomePageCount
  458. },
  459. {
  460. &UpgradeSupport.Pages2,
  461. &UpgradeSupport.AfterOptionsPageCount
  462. },
  463. {
  464. NULL,NULL,
  465. IDD_WORKING1,
  466. {
  467. Working1WizPage,
  468. BBSTEP_PREPARING
  469. }
  470. },
  471. {
  472. NULL,NULL,
  473. IDD_COMPATIBILITY,
  474. {
  475. CompatibilityWizPage,
  476. BBSTEP_PREPARING,
  477. PSWIZB_NEXT
  478. }
  479. },
  480. {
  481. &UpgradeSupport.Pages3,
  482. &UpgradeSupport.BeforeCopyPageCount
  483. },
  484. #ifdef _X86_
  485. {
  486. NULL,NULL,
  487. IDD_FLOPPY,
  488. {
  489. FloppyWizPage,
  490. BBSTEP_PREPARING
  491. }
  492. },
  493. #endif
  494. {
  495. NULL,NULL,
  496. IDD_COPYING,
  497. {
  498. CopyingWizPage,
  499. BBSTEP_PREPARING
  500. }
  501. },
  502. {
  503. NULL,NULL,
  504. IDD_DONE,
  505. {
  506. DoneWizPage,
  507. BBSTEP_PREPARING,
  508. PSWIZB_FINISH,
  509. WIZPAGE_FULL_PAGE_WATERMARK | WIZPAGE_SEPARATOR_CREATED
  510. }
  511. },
  512. {
  513. NULL,NULL,
  514. IDD_CLEANING,
  515. {
  516. CleaningWizPage,
  517. BBSTEP_NONE
  518. }
  519. },
  520. {
  521. NULL,NULL,
  522. IDD_NOTDONE,
  523. {
  524. NotDoneWizPage,
  525. BBSTEP_NONE,
  526. PSWIZB_FINISH,
  527. WIZPAGE_FULL_PAGE_WATERMARK | WIZPAGE_SEPARATOR_CREATED
  528. }
  529. }
  530. };
  531. //
  532. // LTR/RTL layout
  533. //
  534. typedef DWORD(WINAPI * PSETLAYOUT)(HDC, DWORD);
  535. #define _LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008
  536. PSETLAYOUT g_SetLayout;
  537. DWORD g_OldLayout;
  538. VOID
  539. SetDialogFont(
  540. IN HWND hdlg,
  541. IN UINT ControlId,
  542. IN MyDlgFont WhichFont
  543. )
  544. {
  545. static HFONT BigBoldFont = NULL;
  546. static HFONT BoldFont = NULL;
  547. static HFONT StartFont = NULL;
  548. HFONT Font;
  549. LOGFONT LogFont;
  550. TCHAR FontSizeString[24];
  551. int FontSize;
  552. HDC hdc;
  553. switch(WhichFont) {
  554. case DlgFontStart:
  555. if (!StartFont)
  556. {
  557. if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0))
  558. {
  559. if(GetObject(Font,sizeof(LOGFONT),&LogFont))
  560. {
  561. if(hdc = GetDC(hdlg))
  562. {
  563. LogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * 10 / 72);
  564. StartFont = CreateFontIndirect(&LogFont);
  565. ReleaseDC(hdlg,hdc);
  566. }
  567. }
  568. }
  569. }
  570. Font = StartFont;
  571. break;
  572. case DlgFontTitle:
  573. if(!BigBoldFont) {
  574. if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) {
  575. if(GetObject(Font,sizeof(LOGFONT),&LogFont)) {
  576. //
  577. // Now we're using the Arial Black font, so we don't need
  578. // to make it bold.
  579. //
  580. // LogFont.lfWeight = FW_BOLD;
  581. //
  582. // Load size and name from resources, since these may change
  583. // from locale to locale based on the size of the system font, etc.
  584. //
  585. if(!LoadString(hInst,IDS_LARGEFONTNAME,LogFont.lfFaceName,LF_FACESIZE)) {
  586. lstrcpy(LogFont.lfFaceName,TEXT("MS Serif"));
  587. }
  588. if(LoadString(hInst,IDS_LARGEFONTSIZE,FontSizeString,sizeof(FontSizeString)/sizeof(TCHAR))) {
  589. FontSize = _tcstoul(FontSizeString,NULL,10);
  590. } else {
  591. FontSize = 18;
  592. }
  593. if(hdc = GetDC(hdlg)) {
  594. LogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
  595. BigBoldFont = CreateFontIndirect(&LogFont);
  596. ReleaseDC(hdlg,hdc);
  597. }
  598. }
  599. }
  600. }
  601. Font = BigBoldFont;
  602. break;
  603. case DlgFontSupertitle:
  604. if(!BoldFont) {
  605. if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) {
  606. if(GetObject(Font,sizeof(LOGFONT),&LogFont)) {
  607. LogFont.lfWeight = FW_BOLD;
  608. if(hdc = GetDC(hdlg)) {
  609. BoldFont = CreateFontIndirect(&LogFont);
  610. ReleaseDC(hdlg,hdc);
  611. }
  612. }
  613. }
  614. }
  615. Font = BoldFont;
  616. break;
  617. case DlgFontSubtitle:
  618. default:
  619. //
  620. // Nothing to do here.
  621. //
  622. Font = NULL;
  623. break;
  624. }
  625. if(Font) {
  626. SendDlgItemMessage(hdlg,ControlId,WM_SETFONT,(WPARAM)Font,0);
  627. }
  628. }
  629. VOID
  630. pMoveButtons(
  631. HWND WizardHandle,
  632. UINT Id,
  633. LONG cx,
  634. LONG cy
  635. )
  636. /*++
  637. Routine Description:
  638. pMoveButtons moves a window by a delta, to reposition a control when the
  639. wizard changes size.
  640. Arguments:
  641. WizardHandle - Specifies the main wizard window
  642. Id - Specifies the child control ID that exists in the main
  643. wizard window
  644. cx - Specifies the horizontal delta
  645. cy - Specifies the vertical delta
  646. Return Value:
  647. None.
  648. --*/
  649. {
  650. HWND Button;
  651. RECT Rect;
  652. Button = GetDlgItem(WizardHandle,Id);
  653. if( !Button )
  654. return;
  655. GetClientRect( Button, &Rect );
  656. MapWindowPoints(Button, WizardHandle, (LPPOINT)&Rect,2);
  657. Rect.left += cx;
  658. Rect.top += cy;
  659. SetWindowPos( Button, NULL, Rect.left, Rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW );
  660. return;
  661. }
  662. BOOL
  663. CALLBACK
  664. pVerifyChildText (
  665. HWND WizardPage,
  666. HWND HiddenPage,
  667. INT Id
  668. )
  669. {
  670. TCHAR text1[512];
  671. TCHAR text2[512];
  672. HWND hwnd1;
  673. HWND hwnd2;
  674. hwnd1 = GetDlgItem (WizardPage, Id);
  675. hwnd2 = GetDlgItem (HiddenPage, Id);
  676. if (!hwnd1 && !hwnd2) {
  677. return TRUE;
  678. }
  679. if (!hwnd1 || !hwnd2) {
  680. return FALSE;
  681. }
  682. text1[0] = 0;
  683. GetWindowText (hwnd1, text1, ARRAYSIZE(text1));
  684. text2[0] = 0;
  685. GetWindowText (hwnd2, text2, ARRAYSIZE(text2));
  686. if (lstrcmp (text1, text2)) {
  687. return FALSE;
  688. }
  689. return TRUE;
  690. }
  691. INT_PTR
  692. CALLBACK
  693. HiddenDlgProc(
  694. HWND hwndDlg,
  695. UINT uMsg,
  696. WPARAM wParam,
  697. LPARAM lParam
  698. )
  699. {
  700. HWND wizardPage;
  701. HRSRC dlgResInfo;
  702. HGLOBAL dlgRes;
  703. PVOID dlgTemplate;
  704. INT_PTR result = 0;
  705. static BOOL recursiveCall;
  706. switch (uMsg) {
  707. case WM_INITDIALOG:
  708. //
  709. // Verify text in this dialog is the same as the parent. If it is not
  710. // the same, then the code pages differ because of an OS bug,
  711. // and we have to force the English page dimensions.
  712. //
  713. wizardPage = *((HWND *) lParam);
  714. if (!recursiveCall) {
  715. if (!pVerifyChildText (wizardPage, hwndDlg, IDT_SUPERTITLE) ||
  716. !pVerifyChildText (wizardPage, hwndDlg, IDT_SUBTITLE) ||
  717. !pVerifyChildText (wizardPage, hwndDlg, IDT_TITLE)
  718. ) {
  719. //
  720. // Load the English resource if possible, then recursively call
  721. // ourselves to get the correct rect
  722. //
  723. __try {
  724. //
  725. // Find the resource
  726. //
  727. dlgResInfo = FindResourceEx (
  728. hInst,
  729. RT_DIALOG,
  730. MAKEINTRESOURCE(IDD_WELCOME),
  731. MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
  732. );
  733. if (!dlgResInfo) {
  734. __leave;
  735. }
  736. dlgRes = LoadResource (hInst, dlgResInfo);
  737. if (!dlgRes) {
  738. __leave;
  739. }
  740. dlgTemplate = LockResource (dlgRes);
  741. if (!dlgTemplate) {
  742. __leave;
  743. }
  744. //
  745. // Create another hidden dialog (indirectly)
  746. //
  747. recursiveCall = TRUE;
  748. result = DialogBoxIndirectParam (
  749. hInst,
  750. (LPCDLGTEMPLATE) dlgTemplate,
  751. GetParent (hwndDlg),
  752. HiddenDlgProc,
  753. lParam
  754. );
  755. recursiveCall = FALSE;
  756. }
  757. __finally {
  758. MYASSERT (result);
  759. }
  760. EndDialog (hwndDlg, result);
  761. break;
  762. }
  763. }
  764. //
  765. // If we get here it is because we need to use this dialog's size
  766. //
  767. GetClientRect (hwndDlg, (RECT *) lParam);
  768. EndDialog (hwndDlg, 1);
  769. break;
  770. }
  771. return 0;
  772. }
  773. VOID
  774. pGetTrueClientRect(
  775. HWND hdlg,
  776. PRECT rc
  777. )
  778. /*++
  779. Routine Description:
  780. pGetTrueClientRect creates a hidden dialog box to retreive the proper
  781. dimensions of a dialog template. These dimensions are used to drive wizard
  782. resizing for when the system Wizard font does not match the property sheet
  783. font.
  784. Arguments:
  785. hdlg - Specifies the wizard page
  786. rc - Receives the wizard page rectangle coordinates (window coordinates)
  787. Return Value:
  788. None.
  789. --*/
  790. {
  791. HWND WizardHandle;
  792. static RECT pageRect;
  793. static BOOL initialized;
  794. if (initialized) {
  795. CopyMemory (rc, &pageRect, sizeof (RECT));
  796. return;
  797. }
  798. //
  799. // Initialize by creating a hidden window
  800. //
  801. WizardHandle = GetParent(hdlg);
  802. // send the wizard page handle to the HiddenDlgProc
  803. MYASSERT (sizeof (HWND *) <= sizeof (RECT));
  804. *((HWND *) rc) = hdlg;
  805. if (!DialogBoxParam (
  806. hInst,
  807. MAKEINTRESOURCE(IDD_WELCOME),
  808. WizardHandle,
  809. HiddenDlgProc,
  810. (LPARAM) rc
  811. )){
  812. //
  813. // On failure, do not alter the size of the page -- use current
  814. // rectangle for resizing
  815. //
  816. GetClientRect( hdlg, rc );
  817. }
  818. CopyMemory (&pageRect, rc, sizeof (RECT));
  819. initialized = TRUE;
  820. return;
  821. }
  822. VOID
  823. ResizeWindowForFont(
  824. HWND hdlg
  825. )
  826. /*++
  827. Routine Description:
  828. ResizeWindowForFont takes a wizard page and makes sure that the page and
  829. its parent is sized properly.
  830. Arguments:
  831. hdlg - Specifies the wizard page (a window within the main wizard)
  832. Return Value:
  833. None.
  834. --*/
  835. {
  836. RECT WizardRect;
  837. RECT PageRect;
  838. RECT NewWizardRect;
  839. RECT NewWizardClientRect;
  840. RECT WizardClientRect;
  841. RECT BorderRect;
  842. RECT NewPageRect;
  843. RECT Sep;
  844. HWND Seperator, WizardHandle;
  845. LONG MarginX, MarginY, ButtonSpace, LineThickness;
  846. LONG x, y, cx, cy;
  847. static BOOL ParentResized = FALSE;
  848. WizardHandle = GetParent (hdlg);
  849. Seperator = GetDlgItem(WizardHandle,0x3026);
  850. if(!Seperator) {
  851. return;
  852. }
  853. //
  854. // Save original page dimensions, compute new page width/height
  855. //
  856. GetWindowRect (hdlg, &PageRect);
  857. pGetTrueClientRect (hdlg, &NewPageRect);
  858. //
  859. // Move page
  860. //
  861. SetWindowPos (
  862. hdlg,
  863. NULL,
  864. 0,
  865. 0,
  866. NewPageRect.right,
  867. NewPageRect.bottom,
  868. SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW
  869. );
  870. //
  871. // Has the parent already been resized? If so, we're done.
  872. //
  873. if (ParentResized) {
  874. return;
  875. }
  876. //
  877. // Is this wizard hidden? It might be width or height of zero.
  878. // Delay parent resizing until the next page.
  879. //
  880. GetWindowRect (WizardHandle, &WizardRect);
  881. if (((WizardRect.right - WizardRect.left) < 1) ||
  882. ((WizardRect.bottom - WizardRect.top) < 1)
  883. ) {
  884. return;
  885. }
  886. ParentResized = TRUE;
  887. //
  888. // Adjust width/height into coordinates. Resize the main wizard if we haven't done so yet.
  889. //
  890. MapWindowPoints (hdlg, NULL, (LPPOINT)&NewPageRect, 2);
  891. //
  892. // Get window rects (in window coordinates) of:
  893. //
  894. // - the whole wizard
  895. // - the wizard's client area
  896. // - the page rectangle
  897. // - the separator bar rectangle
  898. GetWindowRect (WizardHandle, &WizardRect);
  899. GetClientRect (WizardHandle, &WizardClientRect);
  900. MapWindowPoints (WizardHandle, NULL, (LPPOINT)&WizardClientRect, 2);
  901. GetWindowRect (Seperator, &Sep);
  902. //
  903. // Calculate various margins, thickness and borders
  904. //
  905. MarginX = WizardClientRect.right - PageRect.right;
  906. MarginY = Sep.top - PageRect.bottom;
  907. ButtonSpace = WizardClientRect.bottom - Sep.bottom;
  908. LineThickness = Sep.bottom - Sep.top;
  909. BorderRect.right = (WizardRect.right - WizardClientRect.right);
  910. BorderRect.bottom = (WizardRect.bottom - WizardClientRect.bottom);
  911. BorderRect.left = (WizardClientRect.left - WizardRect.left);
  912. BorderRect.top = (WizardClientRect.top - WizardRect.top);
  913. //
  914. // Find the new bottom right corner
  915. //
  916. x = (NewPageRect.right + MarginX + BorderRect.right);
  917. y = (NewPageRect.bottom + MarginY + ButtonSpace + LineThickness + BorderRect.bottom);
  918. //
  919. // Compute the new window coordinates
  920. //
  921. NewWizardRect.top = WizardRect.top;
  922. NewWizardRect.left = WizardRect.left;
  923. NewWizardRect.right = x;
  924. NewWizardRect.bottom = y;
  925. //
  926. // Manually calculate client coordinates
  927. //
  928. NewWizardClientRect.left = NewWizardRect.left + BorderRect.left;
  929. NewWizardClientRect.right = NewWizardRect.right - BorderRect.right;
  930. NewWizardClientRect.top = NewWizardRect.top + BorderRect.top;
  931. NewWizardClientRect.bottom = NewWizardRect.bottom - BorderRect.bottom;
  932. //
  933. // Calculate new seperator position
  934. //
  935. x = Sep.left - WizardClientRect.left;
  936. y = NewWizardClientRect.bottom - NewWizardClientRect.top;
  937. y -= ButtonSpace - LineThickness;
  938. cx = (NewWizardClientRect.right - NewWizardClientRect.left);
  939. cx -= 2*(Sep.left - WizardClientRect.left);
  940. cy = Sep.bottom-Sep.top;
  941. //
  942. // Move/resize the seperator
  943. //
  944. SetWindowPos( Seperator, NULL, x, y, cx, cy, SWP_NOZORDER | SWP_NOREDRAW );
  945. //
  946. // Compute the new button coordinates
  947. //
  948. cx = NewWizardRect.right - WizardRect.right;
  949. cy = NewWizardRect.bottom - WizardRect.bottom;
  950. pMoveButtons( WizardHandle, 0x3023, cx, cy );
  951. pMoveButtons( WizardHandle, 0x3024, cx, cy );
  952. pMoveButtons( WizardHandle, 0x3025, cx, cy );
  953. pMoveButtons( WizardHandle, IDCANCEL, cx, cy );
  954. pMoveButtons( WizardHandle, IDHELP, cx, cy );
  955. //
  956. // Resize the wizard window
  957. //
  958. cx = (NewWizardRect.right - NewWizardRect.left);
  959. cy = (NewWizardRect.bottom-NewWizardRect.top);
  960. SetWindowPos( WizardHandle, NULL, 0, 0, cx, cy, SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
  961. return;
  962. }
  963. VOID
  964. CenterWindowRelativeToWindow(
  965. HWND hwndtocenter,
  966. HWND hwndcenteron
  967. )
  968. /*++
  969. Routine Description:
  970. Centers a dialog on the desktop.
  971. Arguments:
  972. hwnd - window handle of dialog to center
  973. Return Value:
  974. None.
  975. --*/
  976. {
  977. RECT rcFrame,
  978. rcWindow;
  979. LONG x,
  980. y,
  981. w,
  982. h;
  983. POINT point;
  984. HWND Parent;
  985. UINT uiHeight = 0;
  986. GetWindowRect(GetDesktopWindow(), &rcWindow);
  987. uiHeight = rcWindow.bottom - rcWindow.top;
  988. if (hwndcenteron == NULL)
  989. Parent = GetDesktopWindow();
  990. else
  991. Parent = hwndcenteron;
  992. point.x = point.y = 0;
  993. ClientToScreen(Parent,&point);
  994. GetWindowRect(hwndtocenter,&rcWindow);
  995. GetClientRect(Parent,&rcFrame);
  996. w = rcWindow.right - rcWindow.left + 1;
  997. h = rcWindow.bottom - rcWindow.top + 1;
  998. y = point.y + ((rcFrame.bottom - rcFrame.top + 1 - h) / 2);
  999. if (uiHeight > 480)
  1000. x = point.x + ((rcFrame.right - rcFrame.left + 1 - w) / 2);
  1001. else
  1002. {
  1003. RECT rcParentWindow;
  1004. GetWindowRect(Parent, &rcParentWindow);
  1005. x = point.x + rcParentWindow.right - rcParentWindow.left + 1 - w;
  1006. }
  1007. MoveWindow(hwndtocenter,x,y,w,h,FALSE);
  1008. }
  1009. int
  1010. CALLBACK
  1011. Winnt32SheetCallback(
  1012. IN HWND DialogHandle,
  1013. IN UINT Message,
  1014. IN LPARAM lParam
  1015. )
  1016. {
  1017. HMENU menu;
  1018. DLGTEMPLATE *DlgTemplate;
  1019. LPDLGTEMPLATEEX pDlgTemplateEx;
  1020. switch(Message) {
  1021. case PSCB_PRECREATE:
  1022. //
  1023. // Make sure we get into the foreground.
  1024. //
  1025. DlgTemplate = (DLGTEMPLATE *)lParam;
  1026. pDlgTemplateEx = (LPDLGTEMPLATEEX)DlgTemplate;
  1027. if (pDlgTemplateEx->wSignature == 0xFFFF) {
  1028. pDlgTemplateEx->dwStyle &= ~DS_CONTEXTHELP;
  1029. pDlgTemplateEx->dwStyle |= DS_SETFOREGROUND;
  1030. } else {
  1031. DlgTemplate->style &= ~DS_CONTEXTHELP;
  1032. DlgTemplate->style |= DS_SETFOREGROUND;
  1033. }
  1034. break;
  1035. case PSCB_INITIALIZED:
  1036. //
  1037. // Load the watermark bitmap and override the dialog procedure for the wizard.
  1038. //
  1039. GetBitmapDataAndPalette(
  1040. hInst,
  1041. MAKEINTRESOURCE(IDB_WELCOME),
  1042. &Watermark.Palette,
  1043. &Watermark.PaletteColorCount,
  1044. &Watermark.BitmapInfoHeader
  1045. );
  1046. Watermark.BitmapBits = (LPBYTE)Watermark.BitmapInfoHeader
  1047. + Watermark.BitmapInfoHeader->biSize + (Watermark.PaletteColorCount * sizeof(RGBQUAD));
  1048. Watermark.Adjusted = FALSE;
  1049. GetBitmapDataAndPalette(
  1050. hInst,
  1051. MAKEINTRESOURCE(IDB_HEADER),
  1052. &Header.Palette,
  1053. &Header.PaletteColorCount,
  1054. &Header.BitmapInfoHeader
  1055. );
  1056. Header.BitmapBits = (LPBYTE)Header.BitmapInfoHeader
  1057. + Header.BitmapInfoHeader->biSize + (Header.PaletteColorCount * sizeof(RGBQUAD));
  1058. Header.Adjusted = FALSE;
  1059. GetBitmapDataAndPalette(
  1060. hInst,
  1061. MAKEINTRESOURCE(IDB_HEADER2),
  1062. &Header2.Palette,
  1063. &Header2.PaletteColorCount,
  1064. &Header2.BitmapInfoHeader
  1065. );
  1066. Header2.BitmapBits = (LPBYTE)Header2.BitmapInfoHeader
  1067. + Header2.BitmapInfoHeader->biSize + (Header2.PaletteColorCount * sizeof(RGBQUAD));
  1068. Header2.Adjusted = FALSE;
  1069. // innitialize WHH so we know that it is invalid, and will not draw the separator
  1070. // until WHH is non-zero
  1071. WatermarkHeaderHeight = 0;
  1072. //
  1073. // Get rid of close item on system menu.
  1074. // Also need to process WM_SYSCOMMAND to eliminate use
  1075. // of Alt+F4.
  1076. //
  1077. if(menu = GetSystemMenu(DialogHandle,FALSE)) {
  1078. EnableMenuItem(menu,SC_CLOSE,MF_BYCOMMAND|MF_GRAYED);
  1079. }
  1080. OldWizardProc = (WNDPROC)SetWindowLongPtr(DialogHandle,DWLP_DLGPROC,(LONG_PTR)WizardDlgProc);
  1081. break;
  1082. }
  1083. return(0);
  1084. }
  1085. VOID
  1086. pSetDisplayOrientation (
  1087. IN HDC hdc
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. pSetDisplayOrientation sets the OS to treat BitBlts in left-to-right and
  1092. top-to-bottom and no bitmap flip orientation. We expect our bitmaps to be
  1093. localized to the proper orientation.
  1094. This function loads the SetLayout API dynamically, so that winnt32 can run
  1095. on very old OSes (such as Win95 gold). The resources are not cleaned up,
  1096. because the LoadLibrary is to gdi32.dll, which is held until the process
  1097. dies anyhow.
  1098. Arguments:
  1099. hdc - Specifies the device context that will be used for the BitBlt (or
  1100. equivalent) operation.
  1101. Return Value:
  1102. None.
  1103. Remarks:
  1104. The current orientation is saved to g_OldLayout, so don't call this function
  1105. again until pRestoreDisplayOrientation is called.
  1106. --*/
  1107. {
  1108. DWORD flags;
  1109. HINSTANCE lib;
  1110. static BOOL initialized;
  1111. if (!initialized) {
  1112. lib = LoadLibrary (TEXT("gdi32.dll"));
  1113. MYASSERT (lib);
  1114. if (lib) {
  1115. (FARPROC) g_SetLayout = GetProcAddress (lib, "SetLayout");
  1116. }
  1117. initialized = TRUE;
  1118. }
  1119. if (g_SetLayout) {
  1120. g_OldLayout = g_SetLayout (hdc, _LAYOUT_BITMAPORIENTATIONPRESERVED);
  1121. }
  1122. }
  1123. VOID
  1124. pRestoreDisplayOrientation (
  1125. IN HDC hdc
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. pRestoreDisplayOrientation returns the render layout to whatever the OS
  1130. wants it to be.
  1131. Arguments:
  1132. hdc - Specifies the device context that was passed to
  1133. pSetDisplayOrientation.
  1134. Return Value:
  1135. None.
  1136. --*/
  1137. {
  1138. if (g_SetLayout) {
  1139. g_SetLayout (hdc, g_OldLayout);
  1140. }
  1141. }
  1142. BOOL
  1143. PaintWatermark(
  1144. IN HWND hdlg,
  1145. IN HDC DialogDC,
  1146. IN UINT XOffset,
  1147. IN UINT YOffset,
  1148. IN UINT FullPage
  1149. )
  1150. {
  1151. PBITMAP_DATA BitmapData;
  1152. HPALETTE OldPalette;
  1153. RECT rect;
  1154. int Height,Width;
  1155. //
  1156. // Don't show watermark on NT3.51. It looks awful.
  1157. // Returning FALSE causes the system to do its standard
  1158. // background erasing.
  1159. //
  1160. #if 0
  1161. if(OsVersion.dwMajorVersion < 4) {
  1162. return(FALSE);
  1163. }
  1164. #endif
  1165. if (FullPage & WIZPAGE_FULL_PAGE_WATERMARK)
  1166. {
  1167. BitmapData = &Watermark;
  1168. }
  1169. else if (FullPage & WIZPAGE_NEW_HEADER)
  1170. {
  1171. BitmapData = &Header2;
  1172. }
  1173. else
  1174. {
  1175. BitmapData = &Header;
  1176. }
  1177. //
  1178. // The correct palette is already realized in foreground from
  1179. // WM_xxxPALETTExxx processing in dialog procs.
  1180. //
  1181. #if 0 // fix palette problem
  1182. OldPalette = SelectPalette(DialogDC,BitmapData->Palette,TRUE);
  1183. #endif
  1184. Width = BitmapData->BitmapInfoHeader->biWidth - (2*XOffset);
  1185. //
  1186. // For full-page watermarks, the height is the height of the bitmap.
  1187. // For header watermarks, the height is the header area's height.
  1188. // Also account for the y offset within the source bitmap.
  1189. //
  1190. Height = (FullPage ? BitmapData->BitmapInfoHeader->biHeight : WatermarkHeaderHeight) - YOffset;
  1191. //
  1192. // Set the display orientation to left-to-right
  1193. //
  1194. pSetDisplayOrientation (DialogDC);
  1195. //
  1196. // Display the bitmap
  1197. //
  1198. SetDIBitsToDevice(
  1199. DialogDC,
  1200. 0, // top
  1201. 0, // left
  1202. Width, // width
  1203. Height, // height
  1204. XOffset, // X origin (lower left)
  1205. 0, // Y origin (lower left)
  1206. 0, // start scan line
  1207. BitmapData->BitmapInfoHeader->biHeight, // # of scan lines
  1208. BitmapData->BitmapBits, // bitmap image
  1209. (BITMAPINFO *)BitmapData->BitmapInfoHeader, // bitmap header
  1210. DIB_RGB_COLORS // bitmap type
  1211. );
  1212. //
  1213. // Return to normal display orientation
  1214. //
  1215. pRestoreDisplayOrientation (DialogDC);
  1216. //
  1217. // Fill in area below the watermark if needed. We do this by removing the area
  1218. // we filled with watermark from the clipping area, and passing a return code
  1219. // back from WM_ERASEBKGND indicating that we didn't erase the background.
  1220. // The dialog manager will do its default thing, which is to fill the background
  1221. // in the correct color, but won't touch what we just painted.
  1222. //
  1223. GetClientRect (hdlg, &rect);
  1224. if((Height < rect.bottom) || (Width+(int)XOffset < rect.right)) {
  1225. ExcludeClipRect(DialogDC,0,0,Width+XOffset,Height);
  1226. return(FALSE);
  1227. }
  1228. return(TRUE);
  1229. }
  1230. VOID
  1231. AdjustWatermarkBitmap(
  1232. IN HANDLE hdlg,
  1233. IN HDC hdc,
  1234. IN OUT PBITMAP_DATA BitmapData,
  1235. IN BOOL FullPage
  1236. )
  1237. {
  1238. RECT rect;
  1239. RECT rect2;
  1240. HWND Separator;
  1241. PVOID Bits;
  1242. HBITMAP hDib;
  1243. HBITMAP hOldBitmap;
  1244. BITMAPINFO *BitmapInfo;
  1245. HDC MemDC;
  1246. int i;
  1247. BOOL b;
  1248. INT Scale;
  1249. if(BitmapData->Adjusted) {
  1250. return;
  1251. }
  1252. //
  1253. // Determine whether the bitmap needs to be stretched.
  1254. // If the width is within 10 pixels and the height is within 5
  1255. // then we don't worry about stretching.
  1256. //
  1257. // Note that 0x3026 is the identifier of the bottom divider in
  1258. // the template. This is kind of slimy but it works.
  1259. //
  1260. Separator = GetDlgItem(hdlg,0x3026);
  1261. if(!Separator) {
  1262. goto c0;
  1263. }
  1264. // NOTE: The bitmap resoures is about the size of the dialog.
  1265. // That is the only reason why the below GetClientRect makes sence.
  1266. // This should be changed to have only the relevant part of the bitmap.
  1267. // Or we have to find something in the case where a none DBCS setup runs
  1268. // on a DBCS system. Here the wizard page are sized incorrect. They are wider
  1269. // then needed and smaller (adjusted when adding the pages).
  1270. GetClientRect(Separator,&rect2);
  1271. MapWindowPoints(Separator,hdlg,(LPPOINT)&rect2,2);
  1272. GetClientRect(hdlg,&rect);
  1273. b = TRUE;
  1274. i = rect.right - BitmapData->BitmapInfoHeader->biWidth;
  1275. if((i < -5) || (i > 5)) {
  1276. b = FALSE;
  1277. }
  1278. i = rect2.top - BitmapData->BitmapInfoHeader->biHeight;
  1279. if((i < -3) || (i > 0)) {
  1280. b = FALSE;
  1281. }
  1282. if(b) {
  1283. goto c0;
  1284. }
  1285. //
  1286. // Create a copy of the existing bitmap's header structure.
  1287. // We then modify the width and height and leave everything else alone.
  1288. //
  1289. BitmapInfo = MALLOC(BitmapData->BitmapInfoHeader->biSize + (BitmapData->PaletteColorCount * sizeof(RGBQUAD)));
  1290. if(!BitmapInfo) {
  1291. goto c0;
  1292. }
  1293. CopyMemory(
  1294. BitmapInfo,
  1295. BitmapData->BitmapInfoHeader,
  1296. BitmapData->BitmapInfoHeader->biSize + (BitmapData->PaletteColorCount * sizeof(RGBQUAD))
  1297. );
  1298. if (!FullPage) {
  1299. Scale = (rect.right + 1) * 100 / BitmapInfo->bmiHeader.biWidth;
  1300. rect2.top = BitmapInfo->bmiHeader.biHeight * Scale / 100;
  1301. }
  1302. BitmapInfo->bmiHeader.biHeight = rect2.top;
  1303. BitmapInfo->bmiHeader.biWidth = rect.right + 1;
  1304. hDib = CreateDIBSection(NULL,BitmapInfo,DIB_RGB_COLORS,&Bits,NULL,0);
  1305. if(!hDib) {
  1306. goto c1;
  1307. }
  1308. //
  1309. // Create a "template" memory DC and select the DIB we created
  1310. // into it. Passing NULL to CreateCompatibleDC creates a DC into which
  1311. // any format bitmap can be selected. We don't want to use the dialog's
  1312. // DC because if the pixel depth of the watermark bitmap differs from
  1313. // the screen, we wouldn't be able to select the dib into the mem dc.
  1314. //
  1315. MemDC = CreateCompatibleDC(NULL);
  1316. if(!MemDC) {
  1317. goto c2;
  1318. }
  1319. hOldBitmap = SelectObject(MemDC,hDib);
  1320. if(!hOldBitmap) {
  1321. goto c3;
  1322. }
  1323. //
  1324. // Do the stretch operation from the source bitmap onto
  1325. // the dib.
  1326. //
  1327. SetStretchBltMode(MemDC,COLORONCOLOR);
  1328. i = StretchDIBits(
  1329. MemDC,
  1330. 0,0,
  1331. rect.right+1,
  1332. rect2.top,
  1333. 0,0,
  1334. BitmapData->BitmapInfoHeader->biWidth,
  1335. BitmapData->BitmapInfoHeader->biHeight,
  1336. BitmapData->BitmapBits,
  1337. (BITMAPINFO *)BitmapData->BitmapInfoHeader,
  1338. DIB_RGB_COLORS,
  1339. SRCCOPY
  1340. );
  1341. if(i == GDI_ERROR) {
  1342. goto c4;
  1343. }
  1344. //
  1345. // Got everything we need, set up pointers to use new bitmap data.
  1346. //
  1347. BitmapData->BitmapBits = Bits;
  1348. BitmapData->BitmapInfoHeader = (BITMAPINFOHEADER *)BitmapInfo;
  1349. b = TRUE;
  1350. c4:
  1351. SelectObject(MemDC,hOldBitmap);
  1352. c3:
  1353. DeleteDC(MemDC);
  1354. c2:
  1355. if(!b) {
  1356. DeleteObject(hDib);
  1357. }
  1358. c1:
  1359. if(!b) {
  1360. FREE(BitmapInfo);
  1361. }
  1362. c0:
  1363. BitmapData->Adjusted = TRUE;
  1364. if (!FullPage){
  1365. WatermarkHeaderHeight = BitmapData->BitmapInfoHeader->biHeight;
  1366. }
  1367. return;
  1368. }
  1369. // NOTE: Need to add this, since it is only defined for _WIN32_IE >= 0x0400
  1370. // And if we do that, the propertysheet structure changes, which we cannot do
  1371. // or the upgrade DLLs need to change too. And I don't know what other side
  1372. // effects that will have.
  1373. // So I copied this define from commctrl.h
  1374. #define PBM_SETBARCOLOR (WM_USER+9) // lParam = bar color
  1375. BOOL
  1376. WizardDlgProc(
  1377. IN HWND hdlg,
  1378. IN UINT msg,
  1379. IN WPARAM wParam,
  1380. IN LPARAM lParam
  1381. )
  1382. {
  1383. BOOL b;
  1384. HWND CurrentPage;
  1385. PPAGE_RUNTIME_DATA WizPage;
  1386. static RECT rect;
  1387. static BOOL Visible = TRUE;
  1388. static BOOL First = TRUE; // used to keep bitmap from being painted twice
  1389. static DWORD MsecPerProcessTick;
  1390. static DWORD PreviousRemainingTime = 0;
  1391. static DWORD RemainungTimeMsecInThisPhase = 0;
  1392. static UINT StepSize;
  1393. switch(msg) {
  1394. case WM_CHAR:
  1395. if (wParam == VK_ESCAPE)
  1396. {
  1397. // Make this a Cancel button message, so that the wizard can do its work.
  1398. b = (BOOL)CallWindowProc(OldWizardProc,hdlg,WM_COMMAND,IDCANCEL,0);
  1399. }
  1400. else {
  1401. b = FALSE;
  1402. }
  1403. break;
  1404. #if 0 // fix palette problem
  1405. case WM_PALETTECHANGED:
  1406. //
  1407. // If this is our window we need to avoid selecting and realizing
  1408. // because doing so would cause an infinite loop between WM_QUERYNEWPALETTE
  1409. // and WM_PALETTECHANGED.
  1410. //
  1411. if((HWND)wParam == hdlg) {
  1412. return(FALSE);
  1413. }
  1414. //
  1415. // FALL THROUGH
  1416. //
  1417. case WM_QUERYNEWPALETTE:
  1418. {
  1419. HDC hdc;
  1420. HPALETTE pal;
  1421. hdc = GetDC(hdlg);
  1422. if((CurrentPage = PropSheet_GetCurrentPageHwnd(hdlg))
  1423. && (WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(CurrentPage,DWLP_USER))
  1424. && WizPage->CommonData.Flags & WIZPAGE_FULL_PAGE_WATERMARK) {
  1425. pal = SelectPalette(hdc,Watermark.Palette,(msg == WM_PALETTECHANGED));
  1426. } else
  1427. {
  1428. if (WizPage->CommonData.Flags & WIZPAGE_NEW_HEADER)
  1429. pal = SelectPalette(hdc,Header2.Palette,(msg == WM_PALETTECHANGED));
  1430. else
  1431. pal = SelectPalette(hdc,Header.Palette,(msg == WM_PALETTECHANGED));
  1432. }
  1433. RealizePalette(hdc);
  1434. InvalidateRect(hdlg,NULL,TRUE);
  1435. if(pal) {
  1436. SelectPalette(hdc,pal,TRUE);
  1437. }
  1438. ReleaseDC(hdlg,hdc);
  1439. }
  1440. return(TRUE);
  1441. #endif
  1442. case WM_ERASEBKGND:
  1443. {
  1444. if((CurrentPage = PropSheet_GetCurrentPageHwnd(hdlg))
  1445. && (WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(CurrentPage,DWLP_USER))) {
  1446. if(WizPage->CommonData.Flags & WIZPAGE_FULL_PAGE_WATERMARK) {
  1447. AdjustWatermarkBitmap(hdlg,(HDC)wParam,&Watermark, TRUE);
  1448. }
  1449. else if (WizPage->CommonData.Flags & WIZPAGE_NEW_HEADER)
  1450. {
  1451. AdjustWatermarkBitmap(hdlg,(HDC)wParam,&Header2, FALSE);
  1452. }
  1453. else
  1454. {
  1455. AdjustWatermarkBitmap(hdlg,(HDC)wParam,&Header, FALSE);
  1456. }
  1457. b = PaintWatermark(
  1458. hdlg,
  1459. (HDC)wParam,
  1460. 0,0,
  1461. WizPage->CommonData.Flags
  1462. );
  1463. } else {
  1464. b = FALSE;
  1465. }
  1466. }
  1467. break;
  1468. // Set the progress text
  1469. // Indicates what setup is doing.
  1470. case WMX_SETPROGRESSTEXT:
  1471. BB_SetProgressText((PTSTR)lParam);
  1472. b = TRUE;
  1473. break;
  1474. case WMX_BB_SETINFOTEXT:
  1475. BB_SetInfoText((PTSTR)lParam);
  1476. b = TRUE;
  1477. break;
  1478. // The next messages are private progess messages, which get translated to the
  1479. // Windows progress messages, Could not use the windows messages direct, because
  1480. // for some reason this get send by the wizard too and would confuse the
  1481. // progress on the billboard.
  1482. case WMX_PBM_SETRANGE:
  1483. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_SETRANGE, wParam, lParam));
  1484. StepSize = 10; // default for StepIt if SetStep is not called.
  1485. RemainingTime = CalcTimeRemaining(CurrentPhase); // In seconds
  1486. SetRemainingTime(RemainingTime);
  1487. //
  1488. // Time per tick is in milli seconds
  1489. // make sure we do not divide by 0 (NTBUG9: 381151)
  1490. //
  1491. if (HIWORD(lParam) > LOWORD(lParam)) {
  1492. MsecPerProcessTick = ((SetupPhase[CurrentPhase].Time*1000)/(HIWORD(lParam)-LOWORD(lParam)) ) + 1;
  1493. }
  1494. RemainungTimeMsecInThisPhase = (SetupPhase[CurrentPhase].Time * 1000);
  1495. PreviousRemainingTime = RemainungTimeMsecInThisPhase;
  1496. b= TRUE;
  1497. break;
  1498. case WMX_PBM_SETPOS:
  1499. if (wParam != 0)
  1500. {
  1501. DWORD Delta = (MsecPerProcessTick * (DWORD)wParam);
  1502. DWORD TimeInPhase = (SetupPhase[CurrentPhase].Time * 1000);
  1503. // position on progress bar changes to wParam ticks.
  1504. if (Delta > TimeInPhase)
  1505. {
  1506. RemainungTimeMsecInThisPhase = 0;
  1507. }
  1508. else
  1509. {
  1510. RemainungTimeMsecInThisPhase = TimeInPhase - Delta;
  1511. }
  1512. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  1513. }
  1514. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_SETPOS, wParam, lParam));
  1515. b= TRUE;
  1516. break;
  1517. case WMX_PBM_DELTAPOS:
  1518. if (wParam != 0)
  1519. {
  1520. // position on progress bar changes by wParam ticks.
  1521. DWORD Delta = (MsecPerProcessTick * (DWORD)wParam);
  1522. if (RemainungTimeMsecInThisPhase > Delta)
  1523. {
  1524. RemainungTimeMsecInThisPhase -= Delta;
  1525. }
  1526. else
  1527. {
  1528. RemainungTimeMsecInThisPhase = 0;
  1529. }
  1530. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  1531. }
  1532. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_DELTAPOS, wParam, lParam));
  1533. b= TRUE;
  1534. break;
  1535. case WMX_PBM_SETSTEP:
  1536. StepSize = (UINT)wParam;
  1537. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_SETSTEP, wParam, lParam));
  1538. b= TRUE;
  1539. break;
  1540. case WMX_PBM_STEPIT:
  1541. // position on progress bar changes by StepSize ticks.
  1542. {
  1543. DWORD Delta = (MsecPerProcessTick * StepSize);
  1544. if (RemainungTimeMsecInThisPhase > Delta)
  1545. {
  1546. RemainungTimeMsecInThisPhase -= Delta;
  1547. }
  1548. else
  1549. {
  1550. RemainungTimeMsecInThisPhase = 0;
  1551. }
  1552. }
  1553. UpdateTimeString(RemainungTimeMsecInThisPhase, &PreviousRemainingTime);
  1554. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_STEPIT, wParam, lParam));
  1555. b= TRUE;
  1556. break;
  1557. case WMX_PBM_SETBARCOLOR:
  1558. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ProgressGaugeMsg(PBM_SETBARCOLOR, wParam, lParam));
  1559. b= TRUE;
  1560. break;
  1561. // Enabled, disable, show, hide the progress gauge on the billboard
  1562. // wParam should be SW_SHOW or SW_HIDE
  1563. case WMX_BBPROGRESSGAUGE:
  1564. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,BB_ShowProgressGaugeWnd((UINT)wParam));
  1565. b= TRUE;
  1566. break;
  1567. // Advance the setup phase.
  1568. case WMX_BB_ADVANCE_SETUPPHASE:
  1569. if (CurrentPhase < Phase_RestOfSetup)
  1570. {
  1571. CurrentPhase++;
  1572. }
  1573. SetRemainingTime(CalcTimeRemaining(CurrentPhase));
  1574. b = TRUE;
  1575. break;
  1576. // Start, stop the billboard text.
  1577. // This start, stops the billboard text and shows, hides the wizard pages
  1578. case WMX_BBTEXT:
  1579. if (hinstBB)
  1580. {
  1581. if (wParam != 0)
  1582. {
  1583. if (Visible)
  1584. {
  1585. // Get the current position of the wizard
  1586. // We restore this position when we need to show it.
  1587. GetWindowRect(hdlg, &rect);
  1588. if (!SetWindowPos(hdlg,
  1589. GetBBhwnd(),
  1590. 0,0,0,0,
  1591. SWP_NOZORDER))
  1592. {
  1593. DebugLog(Winnt32LogWarning,
  1594. TEXT("Warning: Wizard, SetWindowPos to 0,0,0,0 failed with GetLastError=%d"),
  1595. 0,
  1596. GetLastError());
  1597. }
  1598. SetActiveWindow(GetBBhwnd());
  1599. Visible = FALSE;
  1600. }
  1601. }
  1602. else
  1603. {
  1604. if (!Visible)
  1605. {
  1606. SetWindowPos(hdlg,
  1607. HWND_TOP,
  1608. rect.left,
  1609. rect.top,
  1610. rect.right-rect.left,
  1611. rect.bottom-rect.top,
  1612. SWP_SHOWWINDOW);
  1613. }
  1614. Visible = TRUE;
  1615. }
  1616. if (!StartStopBB((wParam != 0)))
  1617. {
  1618. if (!Visible)
  1619. {
  1620. DebugLog(Winnt32LogWarning,
  1621. TEXT("Warning: Could not start the billboard text, make Wizard visible"),
  1622. 0);
  1623. SetWindowPos(hdlg,
  1624. HWND_TOP,
  1625. rect.left,
  1626. rect.top,
  1627. rect.right-rect.left,
  1628. rect.bottom-rect.top,
  1629. SWP_SHOWWINDOW);
  1630. }
  1631. Visible = TRUE;
  1632. }
  1633. }
  1634. else
  1635. {
  1636. if (!Visible)
  1637. {
  1638. SetWindowPos(hdlg,
  1639. HWND_TOP,
  1640. rect.left,
  1641. rect.top,
  1642. rect.right-rect.left,
  1643. rect.bottom-rect.top,
  1644. SWP_SHOWWINDOW);
  1645. }
  1646. Visible = TRUE;
  1647. }
  1648. return TRUE;
  1649. case WM_SYSCOMMAND:
  1650. if (!ISNT()) {
  1651. switch (wParam & 0xFFF0) {
  1652. case SC_MINIMIZE:
  1653. ShowWindow (WizardHandle, SW_HIDE);
  1654. PostMessage (BackgroundWnd, msg, wParam, lParam);
  1655. return 0;
  1656. case SC_RESTORE:
  1657. ShowWindow (WizardHandle, SW_SHOW);
  1658. return 0;
  1659. }
  1660. }
  1661. b = (BOOL)CallWindowProc(OldWizardProc,hdlg,msg,wParam,lParam);
  1662. break;
  1663. case WMX_ACTIVATEPAGE:
  1664. if (!First) {
  1665. InvalidateRect(hdlg,NULL,TRUE);
  1666. } else {
  1667. First = FALSE;
  1668. }
  1669. b = TRUE;
  1670. break;
  1671. case WM_ACTIVATE:
  1672. // If someone wants to active (set the focus to our hiden window) don't
  1673. if ((LOWORD(wParam)== WA_ACTIVE) || (LOWORD(wParam)== WA_CLICKACTIVE))
  1674. {
  1675. if (!Visible)
  1676. {
  1677. InvalidateRect(GetBBhwnd(),NULL, TRUE);
  1678. return 0;
  1679. }
  1680. }
  1681. b = (BOOL)CallWindowProc(OldWizardProc,hdlg,msg,wParam,lParam);
  1682. break;
  1683. default:
  1684. b = (BOOL)CallWindowProc(OldWizardProc,hdlg,msg,wParam,lParam);
  1685. break;
  1686. }
  1687. return(b);
  1688. }
  1689. //
  1690. // This DlgProc gets called for all wizard pages. It may then call a DlgProc
  1691. // for the specific page we're on.
  1692. //
  1693. INT_PTR
  1694. WizardCommonDlgProc(
  1695. IN HWND hdlg,
  1696. IN UINT msg,
  1697. IN WPARAM wParam,
  1698. IN LPARAM lParam
  1699. )
  1700. {
  1701. LONG NextPageOverrideId=0;
  1702. static UINT AdvanceDirection = 0;
  1703. PPAGE_RUNTIME_DATA WizPage;
  1704. NMHDR *Notify;
  1705. BOOL b;
  1706. int i;
  1707. RECT rc1,rc2;
  1708. static BOOL PreviouslyCancelled = FALSE;
  1709. static BOOL center = TRUE;
  1710. WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  1711. b = FALSE;
  1712. switch(msg) {
  1713. case WM_INITDIALOG:
  1714. //
  1715. // lParam points at the PROPSHEETPAGE used for this page.
  1716. //
  1717. WizPage = (PPAGE_RUNTIME_DATA)((PROPSHEETPAGE *)lParam)->lParam;
  1718. SetWindowLongPtr(hdlg,DWLP_USER,(LPARAM)WizPage);
  1719. #if (IDT_TITLE != ID_TITLE_TEXT) || (IDT_SUBTITLE != ID_SUBTITLE_TEXT)
  1720. #error Title and Subtitle text control IDs are out of sync!
  1721. #endif
  1722. //
  1723. // Set large font for the title string in the dialog.
  1724. // Set bold font for subtitle in the dialog.
  1725. //
  1726. SetDialogFont(hdlg,IDT_TITLE,DlgFontTitle);
  1727. SetDialogFont(hdlg,IDT_SUBTITLE,DlgFontSubtitle);
  1728. SetDialogFont(hdlg,IDT_SUPERTITLE,DlgFontSupertitle);
  1729. break;
  1730. case WM_ERASEBKGND:
  1731. GetClientRect(GetParent(hdlg),&rc1);
  1732. MapWindowPoints(GetParent(hdlg),NULL,(POINT *)&rc1,2);
  1733. GetClientRect(hdlg,&rc2);
  1734. MapWindowPoints(hdlg,NULL,(POINT *)&rc2,2);
  1735. b = PaintWatermark(
  1736. hdlg,
  1737. (HDC)wParam,
  1738. rc2.left-rc1.left,
  1739. rc2.top-rc1.top,
  1740. WizPage->CommonData.Flags
  1741. );
  1742. return(b);
  1743. case WM_CTLCOLORSTATIC:
  1744. //
  1745. // We want to let text that is over the background bitmap paint
  1746. // transparently. Other text should not be painted transparently,
  1747. // because there are static text fields that we update to indicate
  1748. // progress, and if it's drawn transparently we end up with text
  1749. // piling up on top of other text, which is messy and unreadable.
  1750. //
  1751. if(WizPage->CommonData.Flags & WIZPAGE_FULL_PAGE_WATERMARK) {
  1752. b = TRUE;
  1753. } else {
  1754. GetWindowRect((HWND)lParam,&rc1);
  1755. ScreenToClient(hdlg,(POINT *)&rc1);
  1756. b = (rc1.top < (LONG)WatermarkHeaderHeight);
  1757. }
  1758. // B320610: In some languages the background on the icon on the EULA page is
  1759. // not drawn correct. If we exclude the icon from here, everythign is fine.
  1760. if(b && (GetDlgCtrlID((HWND) lParam) != (int)IDC_DIALOG_ICON)) {
  1761. SetBkMode((HDC)wParam,TRANSPARENT);
  1762. SetBkColor((HDC)wParam,GetSysColor(COLOR_3DFACE));
  1763. return((BOOL)PtrToUlong(GetStockObject(HOLLOW_BRUSH)));
  1764. }
  1765. else {
  1766. return(0);
  1767. }
  1768. case WM_NOTIFY:
  1769. Notify = (NMHDR *)lParam;
  1770. switch(Notify->code) {
  1771. case PSN_QUERYCANCEL:
  1772. //
  1773. // We want to ask the user whether he's sure he wants to cancel.
  1774. //
  1775. // If there's presently a file copy error being displayed, then
  1776. // in general the user can't get to the cancel button on the
  1777. // wizard, since the wizard is used as the parent/owner for the
  1778. // error dialog. So we should be guaranteed to be able to grab the
  1779. // UI mutex without contention.
  1780. //
  1781. // But, there could be a race condition. If the user hits
  1782. // the cancel button on the wizard just as a copy error occurrs,
  1783. // then the copy thread could get there first and grab the
  1784. // ui mutex. This would cause us to block here waiting for the user
  1785. // to dismiss the file error dialog -- but the file error dialog
  1786. // wants to use the wizard as its parent/owner, and blammo,
  1787. // we have a deadlock.
  1788. //
  1789. // To get around this, we use a 0 timeout on the wait for
  1790. // the ui mutex. We either get ownership of the mutex or
  1791. // we know that there's already an error dialog up already.
  1792. // In the latter case we just ignore the cancel request.
  1793. //
  1794. // If a file copy error occurs then the error path code simulates
  1795. // a press of the cancel button. In that case when we get here the
  1796. // Cancelled flag has already been set, no no need for additional
  1797. // confirmation now.
  1798. //
  1799. AdvanceDirection = 0;
  1800. if(Cancelled) {
  1801. i = IDYES;
  1802. } else {
  1803. i = WaitForSingleObject(UiMutex,0);
  1804. if((i == WAIT_OBJECT_0) && !Cancelled) {
  1805. BOOL bCancel = TRUE;
  1806. BOOL bHandled;
  1807. //
  1808. // Got the ui mutex, it's safe to diaplay ui. But first,
  1809. // signal not to pass through dialog boxes anymore just
  1810. // because we're unattended (e.g. the finish dialog).
  1811. //
  1812. // Ask the page first if it wants to treat this cancel message
  1813. //
  1814. bHandled = (BOOL) CallWindowProc (
  1815. (WNDPROC)WizPage->CommonData.DialogProcedure,
  1816. hdlg,
  1817. WMX_QUERYCANCEL,
  1818. 0,
  1819. (LPARAM)&bCancel
  1820. );
  1821. if (!bHandled || bCancel) {
  1822. CancelPending = TRUE;
  1823. if( CheckUpgradeOnly ) {
  1824. //
  1825. // If we're running the upgrade checker, just
  1826. // cancel.
  1827. //
  1828. i = IDYES;
  1829. } else {
  1830. i = MessageBoxFromMessage(
  1831. hdlg,
  1832. MSG_SURE_EXIT,
  1833. FALSE,
  1834. AppTitleStringId,
  1835. MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL | MB_DEFBUTTON2
  1836. );
  1837. }
  1838. if(i == IDYES) {
  1839. Cancelled = TRUE;
  1840. }
  1841. CancelPending = FALSE;
  1842. }
  1843. ReleaseMutex(UiMutex);
  1844. } else {
  1845. //
  1846. // Can't get ui mutex or user already cancelled,
  1847. // ignore the cancel request.
  1848. //
  1849. i = IDNO;
  1850. }
  1851. }
  1852. //
  1853. // Set DWLP_MSGRESULT to TRUE to prevent the cancel operation.
  1854. // If we're going to allow the cancel operation, don't actually
  1855. // do it here, but instead jump to our special clean-up/cancel
  1856. // page, which does some work before actually exiting.
  1857. //
  1858. // Note: we need to avoid jumping to the cleanup page more than
  1859. // once, which can happen if the user cancels on a page with a
  1860. // worker thread. When the user cancels, we run through this code,
  1861. // which sets the Cancelled flag and jumps to the cleanup page.
  1862. // Some time later the worker thread, which is still hanging around,
  1863. // posts a message to its page when it's done. The page sees the
  1864. // Cancelled flag set and turns around and posts a cancel message,
  1865. // which puts us here again. See WMX_INSPECTRESULT in the
  1866. // Working1WizPage dialog proc.
  1867. //
  1868. if((i == IDYES) && !PreviouslyCancelled) {
  1869. PreviouslyCancelled = TRUE;
  1870. PropSheet_SetCurSelByID(GetParent(hdlg),IDD_CLEANING);
  1871. }
  1872. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,TRUE);
  1873. return(TRUE);
  1874. case PSN_SETACTIVE:
  1875. /*
  1876. //
  1877. // Add separator at top of page if not there already.
  1878. // Can't do this at WM_INITDIALOG time because positions aren't
  1879. // set up properly yet and the mapping fails.
  1880. //
  1881. if(!(WizPage->CommonData.Flags & WIZPAGE_SEPARATOR_CREATED)) {
  1882. if (WatermarkHeaderHeight != 0){
  1883. GetClientRect(hdlg,&rc1);
  1884. MapWindowPoints(hdlg,GetParent(hdlg),(POINT *)&rc1,2);
  1885. CreateWindowEx(
  1886. WS_EX_STATICEDGE | WS_EX_NOPARENTNOTIFY,
  1887. TEXT("Static"),
  1888. TEXT("HeaderSeparator"),
  1889. WS_CHILD | WS_VISIBLE | ((OsVersion.dwMajorVersion < 4) ? SS_BLACKRECT : SS_SUNKEN),
  1890. 0,
  1891. WatermarkHeaderHeight - rc1.top,
  1892. rc1.right-rc1.left,2,
  1893. hdlg,
  1894. (HMENU)IDC_HEADER_BOTTOM,
  1895. hInst,
  1896. 0
  1897. );
  1898. WizPage->CommonData.Flags |= WIZPAGE_SEPARATOR_CREATED;
  1899. // } else {
  1900. // PostMessage(GetParent(hdlg),PSN_SETACTIVE,wParam,lParam);
  1901. }
  1902. }
  1903. */
  1904. //
  1905. // Scale windows to proper size, then set up buttons and ask real
  1906. // dialog whether it wants to be activated.
  1907. //
  1908. ResizeWindowForFont (hdlg);
  1909. if (center) {
  1910. CenterWindowRelativeToWindow (GetParent (hdlg), GetBBhwnd());
  1911. center = FALSE;
  1912. }
  1913. if(WizPage->CommonData.Buttons != (DWORD)(-1)) {
  1914. PropSheet_SetWizButtons(GetParent(hdlg),WizPage->CommonData.Buttons);
  1915. }
  1916. SetWindowLongPtr(
  1917. hdlg,
  1918. DWLP_MSGRESULT,
  1919. CallWindowProc((WNDPROC)WizPage->CommonData.DialogProcedure,hdlg,WMX_ACTIVATEPAGE,TRUE,AdvanceDirection) ? 0 : -1
  1920. );
  1921. //
  1922. // update billboard step
  1923. //
  1924. if (WizPage->CommonData.BillboardStep) {
  1925. SetBBStep (WizPage->CommonData.BillboardStep);
  1926. }
  1927. PostMessage(GetParent(hdlg),WMX_ACTIVATEPAGE,0,0);
  1928. PostMessage(GetParent(hdlg),WMX_I_AM_VISIBLE,0,0);
  1929. return(TRUE);
  1930. case PSN_KILLACTIVE:
  1931. //
  1932. // Page is being deactivated. Ask real dlg proc.
  1933. //
  1934. SetWindowLongPtr(
  1935. hdlg,
  1936. DWLP_MSGRESULT,
  1937. CallWindowProc((WNDPROC)WizPage->CommonData.DialogProcedure,hdlg,WMX_ACTIVATEPAGE,FALSE,AdvanceDirection) ? 0 : -1
  1938. );
  1939. return(TRUE);
  1940. case PSN_WIZFINISH:
  1941. case PSN_WIZBACK:
  1942. case PSN_WIZNEXT:
  1943. //
  1944. // set the button id
  1945. //
  1946. switch(Notify->code) {
  1947. case PSN_WIZFINISH:
  1948. i = WMX_FINISHBUTTON;
  1949. break;
  1950. case PSN_WIZBACK:
  1951. i = WMX_BACKBUTTON;
  1952. break;
  1953. case PSN_WIZNEXT:
  1954. i = WMX_NEXTBUTTON;
  1955. break;
  1956. }
  1957. //
  1958. // Tell the page-specific dialog proc about it.
  1959. //
  1960. CallWindowProc((WNDPROC)WizPage->CommonData.DialogProcedure,hdlg,i,0,(LPARAM)&NextPageOverrideId);
  1961. //
  1962. // Allow user to use these buttons. Remember which button was chosen.
  1963. //
  1964. AdvanceDirection = Notify->code;
  1965. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,NextPageOverrideId);
  1966. return(TRUE);
  1967. default:
  1968. //
  1969. // Unknown code, pass it on.
  1970. //
  1971. break;
  1972. }
  1973. break;
  1974. case WMX_UNATTENDED:
  1975. PropSheet_PressButton(GetParent(hdlg),wParam);
  1976. break;
  1977. case WM_NCPAINT:
  1978. //
  1979. // we delay drawing the separator until here in some cases, because
  1980. // we must make sure that the header bitmap has been adjusted correctly,
  1981. // and then we can place the separator relative to the header bitmap
  1982. //
  1983. /*
  1984. if(!(WizPage->CommonData.Flags & WIZPAGE_SEPARATOR_CREATED)) {
  1985. if (WatermarkHeaderHeight){
  1986. GetClientRect(hdlg,&rc1);
  1987. MapWindowPoints(hdlg,GetParent(hdlg),(POINT *)&rc1,2);
  1988. CreateWindowEx(
  1989. WS_EX_STATICEDGE | WS_EX_NOPARENTNOTIFY,
  1990. TEXT("Static"),
  1991. TEXT("HeaderSeparator"),
  1992. WS_CHILD | WS_VISIBLE | ((OsVersion.dwMajorVersion < 4) ? SS_BLACKRECT : SS_SUNKEN),
  1993. 0,
  1994. WatermarkHeaderHeight - rc1.top,
  1995. rc1.right-rc1.left,2,
  1996. hdlg,
  1997. (HMENU)IDC_HEADER_BOTTOM,
  1998. hInst,
  1999. 0
  2000. );
  2001. WizPage->CommonData.Flags |= WIZPAGE_SEPARATOR_CREATED;
  2002. }
  2003. }
  2004. */
  2005. default:
  2006. break;
  2007. }
  2008. if(WizPage) {
  2009. return((BOOL)CallWindowProc((WNDPROC)WizPage->CommonData.DialogProcedure,hdlg,msg,wParam,lParam));
  2010. } else {
  2011. return(b);
  2012. }
  2013. }
  2014. BOOL
  2015. GrowWizardArray(
  2016. IN OUT PUINT ArraySize,
  2017. IN UINT PageCount,
  2018. IN OUT LPPROPSHEETPAGE *PagesArray,
  2019. IN OUT PPAGE_RUNTIME_DATA *DataArray
  2020. )
  2021. {
  2022. PVOID p;
  2023. BOOL b;
  2024. #define _INCR 3
  2025. if(*ArraySize == PageCount) {
  2026. b = FALSE;
  2027. if(p = REALLOC(*PagesArray,(*ArraySize+_INCR) * sizeof(PROPSHEETPAGE))) {
  2028. *PagesArray = p;
  2029. if(p = REALLOC(*DataArray,(*ArraySize+_INCR) * sizeof(PAGE_RUNTIME_DATA))) {
  2030. *DataArray = p;
  2031. *ArraySize += _INCR;
  2032. b = TRUE;
  2033. }
  2034. }
  2035. #undef _INCR
  2036. if(!b) {
  2037. FREE(*PagesArray);
  2038. FREE(*DataArray);
  2039. MessageBoxFromMessage(
  2040. NULL,
  2041. MSG_OUT_OF_MEMORY,
  2042. FALSE,
  2043. AppTitleStringId,
  2044. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2045. );
  2046. }
  2047. } else {
  2048. b = TRUE;
  2049. }
  2050. return(b);
  2051. }
  2052. VOID
  2053. FixUpWizardTitle(
  2054. IN HWND Wizard
  2055. )
  2056. {
  2057. HWND TabControl;
  2058. int Count,i;
  2059. TCHAR Title[250];
  2060. TC_ITEM ItemData;
  2061. LoadString(hInst,AppTitleStringId,Title,sizeof(Title)/sizeof(Title[0]));
  2062. TabControl = PropSheet_GetTabControl(Wizard);
  2063. Count = TabCtrl_GetItemCount(TabControl);
  2064. ItemData.mask = TCIF_TEXT;
  2065. ItemData.pszText = Title;
  2066. for(i=0; i<Count; i++) {
  2067. TabCtrl_SetItem(TabControl,i,&ItemData);
  2068. }
  2069. }
  2070. #if ASSERTS_ON
  2071. VOID
  2072. EnsureCorrectPageSize(
  2073. PROPSHEETPAGE PropSheetPage
  2074. )
  2075. {
  2076. LPDLGTEMPLATE pDlgTemplate;
  2077. LPDLGTEMPLATEEX pDlgTemplateEx;
  2078. HRSRC hRes;
  2079. HGLOBAL hDlgTemplate;
  2080. pDlgTemplate = NULL;
  2081. if (PropSheetPage.dwFlags & PSP_DLGINDIRECT) {
  2082. pDlgTemplate = (LPDLGTEMPLATE) PropSheetPage.pResource;
  2083. goto UseTemplate;
  2084. } else {
  2085. hRes = FindResource(PropSheetPage.hInstance, PropSheetPage.pszTemplate, RT_DIALOG);
  2086. if (hRes) {
  2087. hDlgTemplate = LoadResource(PropSheetPage.hInstance, hRes);
  2088. if (hDlgTemplate) {
  2089. pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate);
  2090. if (pDlgTemplate) {
  2091. UseTemplate:
  2092. pDlgTemplateEx = (LPDLGTEMPLATEEX)pDlgTemplate;
  2093. if (pDlgTemplateEx->wSignature == 0xFFFF) {
  2094. MYASSERT(pDlgTemplateEx->cx == WIZ_PAGE_SIZE_X && pDlgTemplateEx->cy==WIZ_PAGE_SIZE_Y);
  2095. } else {
  2096. MYASSERT(pDlgTemplate->cx == WIZ_PAGE_SIZE_X && pDlgTemplate->cy == WIZ_PAGE_SIZE_Y);
  2097. }
  2098. if (PropSheetPage.dwFlags & PSP_DLGINDIRECT)
  2099. return;
  2100. UnlockResource(hDlgTemplate);
  2101. }
  2102. }
  2103. }
  2104. }
  2105. }
  2106. #endif
  2107. LRESULT
  2108. CALLBACK
  2109. BackgroundWndProc (
  2110. HWND hwnd,
  2111. UINT uMsg,
  2112. WPARAM wParam,
  2113. LPARAM lParam
  2114. )
  2115. {
  2116. HDC hdc;
  2117. PAINTSTRUCT ps;
  2118. RECT rect;
  2119. HBRUSH Brush, OldBrush;
  2120. INT i;
  2121. INT y1, y2;
  2122. INT Height;
  2123. switch (uMsg) {
  2124. case WM_ACTIVATE:
  2125. if (LOWORD (wParam) == WA_ACTIVE) {
  2126. InvalidateRect (hwnd, NULL, FALSE);
  2127. }
  2128. break;
  2129. case WM_SYSCOMMAND:
  2130. switch (wParam & 0xFFF0) {
  2131. case SC_MINIMIZE:
  2132. ShowWindow (hwnd, SW_MINIMIZE);
  2133. return 0;
  2134. case SC_RESTORE:
  2135. case SC_CLOSE:
  2136. ShowWindow (hwnd, SW_RESTORE);
  2137. PostMessage (WizardHandle, uMsg, wParam, lParam);
  2138. return 0;
  2139. default:
  2140. MYASSERT (FALSE);
  2141. }
  2142. break;
  2143. case WM_PAINT:
  2144. hdc = BeginPaint (hwnd, &ps);
  2145. //SelectObject (hdc, GetStockObject (BLACK_BRUSH));
  2146. SelectObject (hdc, GetStockObject (NULL_PEN));
  2147. GetClientRect (hwnd, &rect);
  2148. Height = rect.bottom - rect.top;
  2149. for (i = 0 ; i < 256 ; i++) {
  2150. Brush = CreateSolidBrush (RGB(0, 0, i));
  2151. if (Brush != NULL) {
  2152. OldBrush = (HBRUSH) SelectObject (hdc, Brush);
  2153. y1 = rect.top + Height * i / 256;
  2154. y2 = rect.top + Height * (i + 1) / 256;
  2155. Rectangle (hdc, rect.left, y1, rect.right + 1, y2 + 1);
  2156. SelectObject (hdc, OldBrush);
  2157. DeleteObject (Brush);
  2158. }
  2159. }
  2160. EndPaint (hwnd, &ps);
  2161. break;
  2162. }
  2163. return DefWindowProc (hwnd, uMsg, wParam, lParam);
  2164. }
  2165. typedef HWND (CALLBACK* GETBBHWND)(void);
  2166. typedef BOOL (CALLBACK* SETSTEP)(int);
  2167. typedef BOOL (CALLBACK *STOPBILLBOARD)();
  2168. typedef BOOL (CALLBACK *STARTBILLBOARD)();
  2169. typedef BOOL (WINAPI* SETPROGRESSTEXT)(LPCTSTR szText);
  2170. typedef BOOL (WINAPI* SETTIMEESTIMATE)(LPCTSTR szText);
  2171. typedef BOOL (WINAPI* SETINFOTEXT)(LPCTSTR szText);
  2172. typedef LRESULT (WINAPI* PROGRESSGAUGEMSG)(UINT msg, WPARAM wparam, LPARAM lparam);
  2173. typedef BOOL (WINAPI* SHOWPROGRESSGAUGEWINDOW)(UINT uiShow);
  2174. BOOL BB_ShowProgressGaugeWnd(UINT nCmdShow)
  2175. {
  2176. static SHOWPROGRESSGAUGEWINDOW fpShowGauge = NULL;
  2177. BOOL bRet = FALSE;;
  2178. if (fpShowGauge == NULL)
  2179. {
  2180. if (hinstBB)
  2181. {
  2182. fpShowGauge = (SHOWPROGRESSGAUGEWINDOW )GetProcAddress(hinstBB, "ShowProgressGaugeWindow");
  2183. }
  2184. }
  2185. if (fpShowGauge != NULL)
  2186. {
  2187. bRet = fpShowGauge(nCmdShow);
  2188. }
  2189. return bRet;
  2190. }
  2191. LRESULT BB_ProgressGaugeMsg(UINT msg, WPARAM wparam, LPARAM lparam)
  2192. {
  2193. static PROGRESSGAUGEMSG fpProgressGaugeMsg = NULL;
  2194. LRESULT lresult = 0;
  2195. if (fpProgressGaugeMsg == NULL)
  2196. {
  2197. if (hinstBB)
  2198. {
  2199. fpProgressGaugeMsg = (PROGRESSGAUGEMSG )GetProcAddress(hinstBB, "ProgressGaugeMsg");
  2200. }
  2201. }
  2202. if (fpProgressGaugeMsg != NULL)
  2203. {
  2204. lresult = fpProgressGaugeMsg(msg, wparam, lparam);
  2205. }
  2206. return lresult;
  2207. }
  2208. void BB_SetProgressText(LPTSTR szText)
  2209. {
  2210. static SETPROGRESSTEXT fpSetProgressText = NULL;
  2211. if (fpSetProgressText == NULL)
  2212. {
  2213. if (hinstBB)
  2214. {
  2215. fpSetProgressText = (SETPROGRESSTEXT )GetProcAddress(hinstBB, "SetProgressText");
  2216. }
  2217. }
  2218. if (fpSetProgressText != NULL)
  2219. {
  2220. fpSetProgressText(szText);
  2221. }
  2222. }
  2223. void BB_SetTimeEstimateText(LPTSTR szText)
  2224. {
  2225. static SETTIMEESTIMATE fpSetTimeEstimate = NULL;
  2226. if (fpSetTimeEstimate == NULL)
  2227. {
  2228. if (hinstBB)
  2229. {
  2230. fpSetTimeEstimate = (SETTIMEESTIMATE)GetProcAddress(hinstBB, "SetTimeEstimate");
  2231. }
  2232. }
  2233. if (fpSetTimeEstimate != NULL)
  2234. {
  2235. fpSetTimeEstimate(szText);
  2236. }
  2237. }
  2238. void BB_SetInfoText(LPTSTR szText)
  2239. {
  2240. static SETINFOTEXT fpSetInfoText = NULL;
  2241. if (fpSetInfoText == NULL)
  2242. {
  2243. if (hinstBB)
  2244. {
  2245. fpSetInfoText = (SETINFOTEXT )GetProcAddress(hinstBB, "SetInfoText");
  2246. }
  2247. }
  2248. if (fpSetInfoText != NULL)
  2249. {
  2250. fpSetInfoText(szText);
  2251. }
  2252. }
  2253. BOOL StartStopBB(BOOL bStart)
  2254. {
  2255. static STARTBILLBOARD fpStart = NULL;
  2256. static STOPBILLBOARD fpStop = NULL;
  2257. BOOL bRet = FALSE;
  2258. if ((fpStart == NULL) || (fpStop == NULL))
  2259. {
  2260. if (hinstBB)
  2261. {
  2262. fpStop = (STARTBILLBOARD )GetProcAddress(hinstBB, "StopBillBoard");
  2263. fpStart = (STOPBILLBOARD )GetProcAddress(hinstBB, "StartBillBoard");
  2264. }
  2265. }
  2266. if ((fpStart != NULL) && (fpStop != NULL))
  2267. {
  2268. if (bStart)
  2269. bRet = fpStart();
  2270. else
  2271. bRet = fpStop();
  2272. }
  2273. return bRet;
  2274. }
  2275. HWND GetBBhwnd()
  2276. {
  2277. GETBBHWND pgetbbhwnd;
  2278. static HWND retHWND = NULL;
  2279. if (retHWND == NULL)
  2280. {
  2281. if (hinstBB)
  2282. {
  2283. if (pgetbbhwnd = (GETBBHWND )GetProcAddress(hinstBB, "GetBBHwnd"))
  2284. retHWND = pgetbbhwnd();
  2285. }
  2286. }
  2287. return retHWND;
  2288. }
  2289. HWND GetBBMainHwnd()
  2290. {
  2291. GETBBHWND pgetbbhwnd;
  2292. static HWND retHWND = NULL;
  2293. if (retHWND == NULL)
  2294. {
  2295. if (hinstBB)
  2296. {
  2297. if (pgetbbhwnd = (GETBBHWND )GetProcAddress(hinstBB, "GetBBMainHwnd"))
  2298. retHWND = pgetbbhwnd();
  2299. }
  2300. }
  2301. return retHWND;
  2302. }
  2303. void SetBBStep(int iStep)
  2304. {
  2305. static SETSTEP psetstep = NULL;
  2306. if (psetstep == NULL)
  2307. {
  2308. if (hinstBB)
  2309. {
  2310. psetstep = (SETSTEP )GetProcAddress(hinstBB, "SetStep");
  2311. }
  2312. }
  2313. if (psetstep)
  2314. psetstep(iStep);
  2315. }
  2316. VOID
  2317. Wizard(
  2318. VOID
  2319. )
  2320. {
  2321. UINT ArraySize;
  2322. LPPROPSHEETPAGE PropSheetPages;
  2323. PPAGE_RUNTIME_DATA PageData;
  2324. UINT u;
  2325. UINT i;
  2326. UINT PageCount;
  2327. PROPSHEETHEADER Sheet;
  2328. WNDCLASSEX wcx;
  2329. RECT rect;
  2330. TCHAR Caption[512];
  2331. LONG l;
  2332. ArraySize = 5;
  2333. PropSheetPages = MALLOC(ArraySize * sizeof(PROPSHEETPAGE));
  2334. if(!PropSheetPages) {
  2335. MessageBoxFromMessage(
  2336. NULL,
  2337. MSG_OUT_OF_MEMORY,
  2338. FALSE,
  2339. AppTitleStringId,
  2340. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2341. );
  2342. return;
  2343. }
  2344. PageData = MALLOC(ArraySize * sizeof(PAGE_RUNTIME_DATA));
  2345. if(!PageData) {
  2346. FREE(PropSheetPages);
  2347. MessageBoxFromMessage(
  2348. NULL,
  2349. MSG_OUT_OF_MEMORY,
  2350. FALSE,
  2351. AppTitleStringId,
  2352. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2353. );
  2354. return;
  2355. }
  2356. PageCount = 0;
  2357. //
  2358. // Now loop through the array of protopages, adding ones we supply, and
  2359. // ranges of pages supplied externally.
  2360. //
  2361. for(u=0; u<(sizeof(ProtoPages)/sizeof(ProtoPages[0])); u++) {
  2362. if(ProtoPages[u].ExternalPages) {
  2363. //
  2364. // Supplied externally. If there are any pages, add them now.
  2365. //
  2366. for(i=0; i<*ProtoPages[u].ExternalPageCount; i++) {
  2367. if(!GrowWizardArray(&ArraySize,PageCount,&PropSheetPages,&PageData)) {
  2368. return;
  2369. }
  2370. PropSheetPages[PageCount] = (*ProtoPages[u].ExternalPages)[i];
  2371. ZeroMemory(&PageData[PageCount],sizeof(PAGE_RUNTIME_DATA));
  2372. PageData[PageCount].CommonData.DialogProcedure = PropSheetPages[PageCount].pfnDlgProc;
  2373. PropSheetPages[PageCount].pfnDlgProc = WizardCommonDlgProc;
  2374. PageData[PageCount].CommonData.Buttons = (DWORD)(-1);
  2375. PageCount++;
  2376. }
  2377. } else {
  2378. //
  2379. // Supplied internally. Add now.
  2380. //
  2381. if(!GrowWizardArray(&ArraySize,PageCount,&PropSheetPages,&PageData)) {
  2382. return;
  2383. }
  2384. ZeroMemory(&PropSheetPages[PageCount],sizeof(PROPSHEETPAGE));
  2385. ZeroMemory(&PageData[PageCount],sizeof(PAGE_RUNTIME_DATA));
  2386. PageData[PageCount].CommonData = ProtoPages[u].CommonData;
  2387. PropSheetPages[PageCount].dwSize = sizeof(PROPSHEETPAGE);
  2388. PropSheetPages[PageCount].dwFlags = PSP_USETITLE;
  2389. PropSheetPages[PageCount].hInstance = hInst;
  2390. PropSheetPages[PageCount].pszTemplate = MAKEINTRESOURCE(ProtoPages[u].Template);
  2391. PropSheetPages[PageCount].pszTitle = MAKEINTRESOURCE(AppTitleStringId);
  2392. PropSheetPages[PageCount].pfnDlgProc = WizardCommonDlgProc;
  2393. PageCount++;
  2394. }
  2395. }
  2396. for(u=0; u<PageCount; u++) {
  2397. #if ASSERTS_ON
  2398. //
  2399. // Make sure that the page size is correct
  2400. //
  2401. // PW: Why??? Localization should be able to resize this.
  2402. // This would also prevent us from resizing the pages
  2403. // in the case where we are running an none DBCS setup
  2404. // on a DBCS system.
  2405. // We need to resize the pages, because the fonts for the
  2406. // page and the frame are different. When comctrl calcs
  2407. // the size of the frame it comes up short for the font
  2408. // used in the page.
  2409. //
  2410. EnsureCorrectPageSize(PropSheetPages[u]);
  2411. #endif
  2412. //
  2413. // Set pointers to runtime page data.
  2414. //
  2415. PropSheetPages[u].lParam = (LPARAM)&PageData[u];
  2416. }
  2417. //
  2418. // Set up the property sheet header structure.
  2419. //
  2420. ZeroMemory(&Sheet,sizeof(PROPSHEETHEADER));
  2421. Sheet.dwSize = sizeof(PROPSHEETHEADER);
  2422. Sheet.dwFlags = PSH_WIZARD | PSH_PROPSHEETPAGE | PSH_USECALLBACK;
  2423. Sheet.hInstance = hInst;
  2424. Sheet.nPages = PageCount;
  2425. Sheet.ppsp = PropSheetPages;
  2426. Sheet.pfnCallback = Winnt32SheetCallback;
  2427. #if 0
  2428. //
  2429. // Create background (for Win9x only currently)
  2430. //
  2431. if (!ISNT()) {
  2432. GetWindowRect (GetDesktopWindow(), &rect);
  2433. ZeroMemory (&wcx, sizeof (wcx));
  2434. wcx.cbSize = sizeof (wcx);
  2435. wcx.style = CS_NOCLOSE;
  2436. wcx.lpfnWndProc = BackgroundWndProc;
  2437. wcx.hInstance = hInst;
  2438. wcx.lpszClassName = TEXT("Winnt32Background");
  2439. RegisterClassEx (&wcx);
  2440. if (!LoadString (
  2441. hInst,
  2442. AppTitleStringId,
  2443. Caption,
  2444. sizeof(Caption)/sizeof(TCHAR)
  2445. )) {
  2446. Caption[0] = 0;
  2447. }
  2448. BackgroundWnd = CreateWindowEx (
  2449. WS_EX_APPWINDOW,
  2450. TEXT("Winnt32Background"),
  2451. Caption,
  2452. WS_DISABLED|WS_CLIPCHILDREN|WS_POPUP|WS_VISIBLE,
  2453. rect.left,
  2454. rect.top,
  2455. rect.right,
  2456. rect.bottom,
  2457. NULL,
  2458. NULL,
  2459. hInst,
  2460. 0
  2461. );
  2462. Sheet.hwndParent = BackgroundWnd;
  2463. UpdateWindow (BackgroundWnd);
  2464. }
  2465. #else
  2466. Sheet.hwndParent = GetBBhwnd();
  2467. #endif
  2468. //
  2469. // Do it.
  2470. //
  2471. __try{
  2472. i = (UINT)PropertySheet(&Sheet);
  2473. }
  2474. __except(EXCEPTION_EXECUTE_HANDLER){
  2475. i = 0;
  2476. MessageBoxFromMessage(
  2477. NULL,
  2478. MSG_RESTART_TO_RUN_AGAIN,
  2479. FALSE,
  2480. AppTitleStringId,
  2481. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2482. );
  2483. }
  2484. if (BackgroundWnd) {
  2485. DestroyWindow (BackgroundWnd);
  2486. BackgroundWnd = NULL;
  2487. }
  2488. if(i == (UINT)(-1)) {
  2489. MessageBoxFromMessage(
  2490. NULL,
  2491. MSG_OUT_OF_MEMORY,
  2492. FALSE,
  2493. AppTitleStringId,
  2494. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2495. );
  2496. }
  2497. FREE(PageData);
  2498. FREE(PropSheetPages);
  2499. }
  2500. BOOL
  2501. GetComplianceIds(
  2502. DWORD SourceSku,
  2503. DWORD DestinationType,
  2504. DWORD DestinationVersion,
  2505. PDWORD pSourceId,
  2506. PDWORD pDestId
  2507. )
  2508. {
  2509. BOOL bError = FALSE;
  2510. switch (SourceSku) {
  2511. case COMPLIANCE_SKU_NTSDTC:
  2512. *pSourceId = MSG_TYPE_NTSDTC51;
  2513. break;
  2514. case COMPLIANCE_SKU_NTSFULL:
  2515. case COMPLIANCE_SKU_NTSU:
  2516. *pSourceId = MSG_TYPE_NTS51;
  2517. break;
  2518. case COMPLIANCE_SKU_NTSEFULL:
  2519. case COMPLIANCE_SKU_NTSEU:
  2520. *pSourceId = MSG_TYPE_NTAS51;
  2521. break;
  2522. case COMPLIANCE_SKU_NTWFULL:
  2523. case COMPLIANCE_SKU_NTW32U:
  2524. *pSourceId = MSG_TYPE_NTPRO51;
  2525. break;
  2526. case COMPLIANCE_SKU_NTWPFULL:
  2527. case COMPLIANCE_SKU_NTWPU:
  2528. *pSourceId = MSG_TYPE_NTPER51;
  2529. break;
  2530. case COMPLIANCE_SKU_NTSB:
  2531. case COMPLIANCE_SKU_NTSBU:
  2532. *pSourceId = MSG_TYPE_NTBLA51;
  2533. break;
  2534. default:
  2535. bError = TRUE;
  2536. };
  2537. switch (DestinationType) {
  2538. case COMPLIANCE_INSTALLTYPE_WIN31:
  2539. *pDestId = MSG_TYPE_WIN31;
  2540. break;
  2541. case COMPLIANCE_INSTALLTYPE_WIN9X:
  2542. switch (OsVersionNumber) {
  2543. case 410:
  2544. *pDestId = MSG_TYPE_WIN98;
  2545. break;
  2546. case 490:
  2547. *pDestId = MSG_TYPE_WINME;
  2548. break;
  2549. default:
  2550. *pDestId = MSG_TYPE_WIN95;
  2551. break;
  2552. }
  2553. break;
  2554. case COMPLIANCE_INSTALLTYPE_NTW:
  2555. if (DestinationVersion > 1381) {
  2556. if (DestinationVersion < 2031) {
  2557. *pDestId = MSG_TYPE_NTPROPRE;
  2558. } else if (DestinationVersion <= 2195) {
  2559. *pDestId = MSG_TYPE_NTPRO;
  2560. } else {
  2561. *pDestId = MSG_TYPE_NTPRO51;
  2562. }
  2563. } else {
  2564. *pDestId = MSG_TYPE_NTW;
  2565. }
  2566. break;
  2567. case COMPLIANCE_INSTALLTYPE_NTS:
  2568. if (DestinationVersion > 1381) {
  2569. if (DestinationVersion < 2031) {
  2570. *pDestId = MSG_TYPE_NTSPRE;
  2571. } else if (DestinationVersion <= 2195) {
  2572. *pDestId = MSG_TYPE_NTS2;
  2573. } else {
  2574. *pDestId = MSG_TYPE_NTS51;
  2575. }
  2576. } else {
  2577. *pDestId = MSG_TYPE_NTS;
  2578. }
  2579. break;
  2580. case COMPLIANCE_INSTALLTYPE_NTSE:
  2581. if (DestinationVersion > 1381) {
  2582. if (DestinationVersion < 2031) {
  2583. *pDestId = MSG_TYPE_NTASPRE;
  2584. } else if (DestinationVersion <= 2195) {
  2585. *pDestId = MSG_TYPE_NTAS;
  2586. } else {
  2587. *pDestId = MSG_TYPE_NTAS51;
  2588. }
  2589. } else {
  2590. *pDestId = MSG_TYPE_NTSE;
  2591. }
  2592. break;
  2593. case COMPLIANCE_INSTALLTYPE_NTSTSE:
  2594. if (DestinationVersion < 1381) {
  2595. *pDestId = MSG_TYPE_NTSCITRIX;
  2596. } else {
  2597. *pDestId = MSG_TYPE_NTSTSE;
  2598. }
  2599. break;
  2600. case COMPLIANCE_INSTALLTYPE_NTSDTC:
  2601. if (DestinationVersion <= 2195) {
  2602. *pDestId = MSG_TYPE_NTSDTC;
  2603. } else {
  2604. *pDestId = MSG_TYPE_NTSDTC51;
  2605. }
  2606. break;
  2607. case COMPLIANCE_INSTALLTYPE_NTWP:
  2608. if (DestinationVersion <= 2195) {
  2609. bError = TRUE;
  2610. } else {
  2611. *pDestId = MSG_TYPE_NTPER51;
  2612. }
  2613. break;
  2614. case COMPLIANCE_INSTALLTYPE_NTSB:
  2615. if (DestinationVersion <= 2195) {
  2616. bError = TRUE;
  2617. } else {
  2618. *pDestId = MSG_TYPE_NTBLA51;
  2619. }
  2620. break;
  2621. default:
  2622. bError = TRUE;
  2623. };
  2624. return (!bError);
  2625. }
  2626. INT_PTR
  2627. WelcomeWizPage(
  2628. IN HWND hdlg,
  2629. IN UINT msg,
  2630. IN WPARAM wParam,
  2631. IN LPARAM lParam
  2632. )
  2633. {
  2634. BOOL b;
  2635. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  2636. LONG l;
  2637. static BOOL WantToUpgrade; // need to remember if "Upgrade" is in the listbox
  2638. BOOL noupgradeallowed = FALSE;
  2639. UINT srcsku,reason,desttype,destversion;
  2640. TCHAR reasontxt[200];
  2641. PTSTR p;
  2642. TCHAR buffer[MAX_PATH];
  2643. TCHAR win9xInf[MAX_PATH];
  2644. BOOL CompliantInstallation = FALSE;
  2645. BOOLEAN CleanInstall = FALSE;
  2646. UINT skuerr[] = {
  2647. 0, // COMPLIANCE_SKU_NONE
  2648. MSG_SKU_FULL, // COMPLIANCE_SKU_NTWFULL
  2649. MSG_SKU_UPGRADE, // COMPLIANCE_SKU_NTW32U
  2650. 0, // COMPLIANCE_SKU_NTWU
  2651. MSG_SKU_FULL, // COMPLIANCE_SKU_NTSEFULL
  2652. MSG_SKU_FULL, // COMPLIANCE_SKU_NTSFULL
  2653. MSG_SKU_UPGRADE, // COMPLIANCE_SKU_NTSEU
  2654. 0, // COMPLIANCE_SKU_NTSSEU
  2655. MSG_SKU_UPGRADE, // COMPLIANCE_SKU_NTSU
  2656. MSG_SKU_FULL, // COMPLIANCE_SKU_NTSDTC
  2657. 0, // COMPLIANCE_SKU_NTSDTCU
  2658. MSG_SKU_FULL, // COMPLIANCE_SKU_NTWPFULL
  2659. MSG_SKU_UPGRADE, // COMPLIANCE_SKU_NTWPU
  2660. MSG_SKU_FULL, // COMPLIANCE_SKU_NTSB
  2661. MSG_SKU_UPGRADE, // COMPLIANCE_SKU_NTSBU
  2662. MSG_SKU_FULL, // COMPLIANCE_SKU_NTSBS
  2663. MSG_SKU_UPGRADE // COMPLIANCE_SKU_NTSBSU
  2664. } ;
  2665. UINT skureason[] = {
  2666. 0, //MSG_SKU_REASON_NONE;
  2667. MSG_SKU_VERSION, //COMPLIANCEERR_VERSION;
  2668. MSG_SKU_SUITE, //COMPLIANCEERR_SUITE;
  2669. MSG_SKU_TYPE, // COMPLIANCEERR_TYPE;
  2670. MSG_SKU_VARIATION, //COMPLIANCEERR_VARIATION;
  2671. MSG_SKU_UNKNOWNTARGET, //COMPLIANCEERR_UNKNOWNTARGET
  2672. MSG_SKU_UNKNOWNSOURCE, //COMPLIANCEERR_UNKNOWNSOURCE
  2673. MSG_CANT_UPGRADE_FROM_BUILD_NUMBER //COMPLIANCEERR_VERSION (Old on New Builds)
  2674. } ;
  2675. switch(msg) {
  2676. case WM_COMMAND:
  2677. b = FALSE;
  2678. //
  2679. // Check for buttons.
  2680. //
  2681. if(HIWORD(wParam) == CBN_SELCHANGE)
  2682. {
  2683. TCHAR szLoadText[MAX_STRING];
  2684. if (0 == SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_GETCURSEL, 0, 0) && WantToUpgrade)
  2685. {
  2686. dwSetupFlags |= UPG_FLAG_TYPICAL;
  2687. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_CLEAN), SW_HIDE);
  2688. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_CLEAN), SW_HIDE);
  2689. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_UPG), SW_SHOW);
  2690. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_UPG), SW_SHOW);
  2691. if(LoadString(hInst,IDS_INSTALLTYPE_EXPRESS,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  2692. {
  2693. SendMessage(GetDlgItem(hdlg, IDT_INSTALLTYPE), WM_SETTEXT, 0, (LPARAM)szLoadText);
  2694. }
  2695. InvalidateRect(hdlg,NULL,TRUE);
  2696. }
  2697. else
  2698. {
  2699. dwSetupFlags &= (~UPG_FLAG_TYPICAL);
  2700. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_CLEAN), SW_SHOW);
  2701. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_CLEAN), SW_SHOW);
  2702. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_UPG), SW_HIDE);
  2703. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_UPG), SW_HIDE);
  2704. if(LoadString(hInst,IDS_INSTALLTYPE_CUSTOM,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  2705. {
  2706. SendMessage(GetDlgItem(hdlg, IDT_INSTALLTYPE), WM_SETTEXT, 0, (LPARAM)szLoadText);
  2707. }
  2708. InvalidateRect(hdlg,NULL,TRUE);
  2709. }
  2710. b = TRUE;
  2711. }
  2712. break;
  2713. case WM_INITDIALOG:
  2714. //
  2715. // Center the wizard
  2716. //
  2717. WizardHandle = GetParent (hdlg);
  2718. #ifdef _X86_
  2719. if (!ISNT()) {
  2720. //
  2721. // NOTE: Win98, Win98 SE and WinME don't work properly with a wizard
  2722. // that can minimize. So while the minimize functionality is
  2723. // useful, we can't allow it on anything other than Win95,
  2724. // OSR1 or OSR2.
  2725. //
  2726. if (BUILDNUM() <= 1080) {
  2727. l = GetWindowLong (WizardHandle, GWL_STYLE);
  2728. l |= WS_MINIMIZEBOX|WS_SYSMENU;
  2729. SetWindowLong (WizardHandle, GWL_STYLE, l);
  2730. }
  2731. ProtectAllModules(); // protects modules from 0xC0000006
  2732. }
  2733. #endif
  2734. //
  2735. // We're about to check if upgrades are allowed.
  2736. // Remember if the user wants an upgrade (this would be via an unattend
  2737. // mechanism).
  2738. //
  2739. WantToUpgrade = Upgrade;
  2740. if (ISNT()) AdjustPrivilege((PWSTR)SE_RESTORE_NAME);
  2741. if (!NoCompliance) {
  2742. TCHAR SourceName[200];
  2743. UINT srcid, destid;
  2744. TCHAR DestName[200];
  2745. CompliantInstallation = IsCompliant(
  2746. &UpgradeOnly,
  2747. &noupgradeallowed,
  2748. &srcsku,
  2749. &desttype,
  2750. &destversion,
  2751. &reason);
  2752. DebugLog(Winnt32LogInformation, TEXT("Upgrade only = %1"), 0, UpgradeOnly?TEXT("Yes"):TEXT("No"));
  2753. DebugLog(Winnt32LogInformation, TEXT("Upgrade allowed = %1"), 0, noupgradeallowed?TEXT("No"):TEXT("Yes"));
  2754. if (GetComplianceIds(
  2755. srcsku,
  2756. desttype,
  2757. destversion,
  2758. &srcid,
  2759. &destid))
  2760. {
  2761. FormatMessage(
  2762. FORMAT_MESSAGE_FROM_HMODULE,
  2763. hInst,
  2764. srcid,
  2765. 0,
  2766. SourceName,
  2767. sizeof(SourceName) / sizeof(TCHAR),
  2768. NULL
  2769. );
  2770. DebugLog(Winnt32LogInformation, TEXT("Source SKU = %1!ld!"), 0, srcsku);
  2771. DebugLog(Winnt32LogInformation, TEXT("Source SKU = %1"), 0, SourceName);
  2772. FormatMessage(
  2773. FORMAT_MESSAGE_FROM_HMODULE,
  2774. hInst,
  2775. destid,
  2776. 0,
  2777. DestName,
  2778. sizeof(DestName) / sizeof(TCHAR),
  2779. NULL
  2780. );
  2781. DebugLog(Winnt32LogInformation, TEXT("Current installed SKU = %1!ld!"), 0, desttype);
  2782. DebugLog(Winnt32LogInformation, TEXT("Current installed SKU = %1"), 0, DestName);
  2783. }
  2784. else
  2785. {
  2786. DebugLog(Winnt32LogInformation, TEXT("Source SKU = %1!ld!"), 0, srcsku);
  2787. DebugLog(Winnt32LogInformation, TEXT("Current installed SKU = %1!ld!"), 0, desttype);
  2788. }
  2789. DebugLog(Winnt32LogInformation, TEXT("Current Version = %1!ld!"), 0, destversion);
  2790. if (!CompliantInstallation)
  2791. {
  2792. DebugLog(Winnt32LogInformation, TEXT("Reason = %1!ld!"), 0, reason);
  2793. }
  2794. //
  2795. // Do only clean installs in WinPE mode & don't
  2796. // shut down automatically once Winnt32.exe completes
  2797. //
  2798. if (IsWinPEMode()) {
  2799. noupgradeallowed = TRUE;
  2800. AutomaticallyShutDown = FALSE;
  2801. }
  2802. CleanInstall = CompliantInstallation ? TRUE : FALSE;
  2803. if (!CompliantInstallation) {
  2804. //
  2805. // if they aren't compliant, we won't let them upgrade.
  2806. // we also won't let them do a clean install from winnt32
  2807. //
  2808. switch(reason) {
  2809. case COMPLIANCEERR_UNKNOWNTARGET:
  2810. MessageBoxFromMessage(
  2811. GetBBhwnd(),
  2812. MSG_SKU_UNKNOWNTARGET,
  2813. FALSE,
  2814. AppTitleStringId,
  2815. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2816. );
  2817. Cancelled = TRUE;
  2818. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  2819. return(FALSE);
  2820. break;
  2821. case COMPLIANCEERR_UNKNOWNSOURCE:
  2822. MessageBoxFromMessage(
  2823. GetBBhwnd(),
  2824. MSG_SKU_UNKNOWNSOURCE,
  2825. FALSE,
  2826. AppTitleStringId,
  2827. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2828. );
  2829. Cancelled = TRUE;
  2830. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  2831. return(FALSE);
  2832. break;
  2833. case COMPLIANCEERR_SERVICEPACK5:
  2834. MessageBoxFromMessage(
  2835. GetBBhwnd(),
  2836. MSG_SKU_SERVICEPACK,
  2837. FALSE,
  2838. AppTitleStringId,
  2839. MB_OK | MB_ICONWARNING | MB_TASKMODAL
  2840. );
  2841. Cancelled = TRUE;
  2842. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  2843. return(FALSE);
  2844. break;
  2845. default:
  2846. break;
  2847. };
  2848. // If we add this part to the message, it sound bad and is not needed.
  2849. if (reason == COMPLIANCEERR_VERSION)
  2850. {
  2851. reasontxt[0] = TEXT('\0');
  2852. }
  2853. else
  2854. {
  2855. FormatMessage(
  2856. FORMAT_MESSAGE_FROM_HMODULE,
  2857. hInst,
  2858. skureason[reason],
  2859. 0,
  2860. reasontxt,
  2861. sizeof(reasontxt) / sizeof(TCHAR),
  2862. NULL
  2863. );
  2864. }
  2865. //
  2866. // don't warn again if winnt32 just restarted
  2867. //
  2868. if (!Winnt32Restarted ()) {
  2869. MessageBoxFromMessage(
  2870. GetBBhwnd(),
  2871. skuerr[srcsku],
  2872. FALSE,
  2873. AppTitleStringId,
  2874. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  2875. reasontxt
  2876. );
  2877. }
  2878. if (UpgradeOnly) {
  2879. Cancelled = TRUE;
  2880. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  2881. return(FALSE);
  2882. }
  2883. Upgrade = FALSE;
  2884. } else if (Upgrade && noupgradeallowed) {
  2885. Upgrade = FALSE;
  2886. if (!UnattendedOperation && !BuildCmdcons && !IsWinPEMode() &&
  2887. //
  2888. // don't warn again if winnt32 just restarted
  2889. //
  2890. !Winnt32Restarted ()) {
  2891. //
  2892. // put up an error message for the user.
  2893. //
  2894. if (GetComplianceIds(
  2895. srcsku,
  2896. desttype,
  2897. destversion,
  2898. &srcid,
  2899. &destid)) {
  2900. if (srcid != destid) {
  2901. #ifdef UNICODE
  2902. //
  2903. // for Win9x upgrades, the message is already displayed
  2904. // by the upgrade module; no need to repeat it here
  2905. //
  2906. FormatMessage(
  2907. FORMAT_MESSAGE_FROM_HMODULE,
  2908. hInst,
  2909. srcid,
  2910. 0,
  2911. SourceName,
  2912. sizeof(SourceName) / sizeof(TCHAR),
  2913. NULL
  2914. );
  2915. FormatMessage(
  2916. FORMAT_MESSAGE_FROM_HMODULE,
  2917. hInst,
  2918. destid,
  2919. 0,
  2920. DestName,
  2921. sizeof(DestName) / sizeof(TCHAR),
  2922. NULL
  2923. );
  2924. MessageBoxFromMessage(
  2925. GetBBhwnd(),
  2926. MSG_NO_UPGRADE_ALLOWED,
  2927. FALSE,
  2928. AppTitleStringId,
  2929. MB_OK | MB_ICONWARNING | MB_TASKMODAL,
  2930. DestName,
  2931. SourceName
  2932. );
  2933. #endif
  2934. } else {
  2935. MessageBoxFromMessage(
  2936. GetBBhwnd(),
  2937. MSG_CANT_UPGRADE_FROM_BUILD_NUMBER,
  2938. FALSE,
  2939. AppTitleStringId,
  2940. MB_OK | MB_ICONWARNING | MB_TASKMODAL
  2941. );
  2942. }
  2943. } else {
  2944. MessageBoxFromMessage(
  2945. GetBBhwnd(),
  2946. MSG_NO_UPGRADE_ALLOWED_GENERIC,
  2947. FALSE,
  2948. AppTitleStringId,
  2949. MB_OKCANCEL | MB_ICONWARNING | MB_TASKMODAL
  2950. );
  2951. }
  2952. }
  2953. }
  2954. } else {
  2955. CleanInstall = !UpgradeOnly;
  2956. }
  2957. //
  2958. // Set install type combo box.
  2959. //
  2960. if (!UpgradeSupport.DllModuleHandle) {
  2961. MYASSERT(!Upgrade);
  2962. }
  2963. //
  2964. // Upgrade defaults to TRUE. If it's set to FALSE, then assume
  2965. // something has gone wrong, so disable the user's ability to
  2966. // upgrade.
  2967. //
  2968. if (UpgradeOnly && !Upgrade) {
  2969. //
  2970. // in this case upgrade isn't possible, but neither is clean install
  2971. // post an error message and bail.
  2972. //
  2973. MessageBoxFromMessage(
  2974. GetBBhwnd(),
  2975. MSG_NO_UPGRADE_OR_CLEAN,
  2976. FALSE,
  2977. AppTitleStringId,
  2978. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2979. );
  2980. Cancelled = TRUE;
  2981. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  2982. break;
  2983. } else if (!Upgrade && WantToUpgrade && UnattendedOperation && !BuildCmdcons) {
  2984. //
  2985. // we can't do an upgrade and they wanted unattended upgrade.
  2986. // let the user know and then bail out
  2987. //
  2988. //
  2989. // don't warn again if winnt32 just restarted
  2990. //
  2991. if (!Winnt32Restarted ()) {
  2992. TCHAR SourceName[200];
  2993. UINT srcid, destid;
  2994. TCHAR DestName[200];
  2995. if (GetComplianceIds(
  2996. srcsku,
  2997. desttype,
  2998. destversion,
  2999. &srcid,
  3000. &destid) && (srcid != destid)) {
  3001. FormatMessage(
  3002. FORMAT_MESSAGE_FROM_HMODULE,
  3003. hInst,
  3004. srcid,
  3005. 0,
  3006. SourceName,
  3007. sizeof(SourceName) / sizeof(TCHAR),
  3008. NULL
  3009. );
  3010. FormatMessage(
  3011. FORMAT_MESSAGE_FROM_HMODULE,
  3012. hInst,
  3013. destid,
  3014. 0,
  3015. DestName,
  3016. sizeof(DestName) / sizeof(TCHAR),
  3017. NULL
  3018. );
  3019. MessageBoxFromMessage(
  3020. GetBBhwnd(),
  3021. MSG_NO_UNATTENDED_UPGRADE_SPECIFIC,
  3022. FALSE,
  3023. AppTitleStringId,
  3024. MB_OK | MB_ICONWARNING | MB_TASKMODAL,
  3025. DestName,
  3026. SourceName
  3027. );
  3028. } else {
  3029. MessageBoxFromMessage(
  3030. GetBBhwnd(),
  3031. MSG_NO_UNATTENDED_UPGRADE,
  3032. FALSE,
  3033. AppTitleStringId,
  3034. MB_OK | MB_ICONERROR | MB_TASKMODAL
  3035. );
  3036. }
  3037. }
  3038. //
  3039. // let setup go if they did /CheckUpgradeOnly
  3040. // so they can see the message in the report
  3041. //
  3042. if (!CheckUpgradeOnly) {
  3043. Cancelled = TRUE;
  3044. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3045. break;
  3046. }
  3047. }
  3048. MYASSERT(Upgrade || CleanInstall);
  3049. {
  3050. TCHAR szLoadText[MAX_STRING]; // need enclosing braces for this b/c of switch statement
  3051. if (Upgrade)
  3052. {
  3053. if(LoadString(hInst,IDS_INSTALL_EXPRESS,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  3054. {
  3055. SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_INSERTSTRING, -1, (LPARAM)szLoadText);
  3056. }
  3057. else
  3058. {
  3059. SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_INSERTSTRING, -1, (LPARAM)TEXT("Express Upgrade"));
  3060. }
  3061. } else {
  3062. WantToUpgrade = FALSE;
  3063. }
  3064. if (CleanInstall)
  3065. {
  3066. if(LoadString(hInst,IDS_INSTALL_CUSTOM,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  3067. {
  3068. SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_INSERTSTRING, -1, (LPARAM)szLoadText);
  3069. }
  3070. else
  3071. {
  3072. SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_INSERTSTRING, -1, (LPARAM)TEXT("Custom"));
  3073. }
  3074. }
  3075. SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_SETCURSEL, 0, 0);
  3076. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_CLEAN), Upgrade?SW_HIDE:SW_SHOW);
  3077. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_CLEAN), Upgrade?SW_HIDE:SW_SHOW);
  3078. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_TEXT_UPG), Upgrade?SW_SHOW:SW_HIDE);
  3079. ShowWindow(GetDlgItem(hdlg, IDC_NOTE_UPG), Upgrade?SW_SHOW:SW_HIDE);
  3080. if (Upgrade)
  3081. {
  3082. dwSetupFlags |= UPG_FLAG_TYPICAL;
  3083. if(LoadString(hInst,IDS_INSTALLTYPE_EXPRESS,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  3084. {
  3085. SendMessage(GetDlgItem(hdlg, IDT_INSTALLTYPE), WM_SETTEXT, 0, (LPARAM)szLoadText);
  3086. }
  3087. }
  3088. else
  3089. {
  3090. dwSetupFlags &= (~UPG_FLAG_TYPICAL);
  3091. if(LoadString(hInst,IDS_INSTALLTYPE_CUSTOM,szLoadText,sizeof(szLoadText) / sizeof(TCHAR)))
  3092. {
  3093. SendMessage(GetDlgItem(hdlg, IDT_INSTALLTYPE), WM_SETTEXT, 0, (LPARAM)szLoadText);
  3094. }
  3095. }
  3096. }
  3097. b = FALSE;
  3098. break;
  3099. case WMX_ACTIVATEPAGE:
  3100. CHECKUPGRADEONLY();
  3101. if(wParam) {
  3102. //
  3103. // don't activate the page in restart mode
  3104. //
  3105. if (Winnt32RestartedWithAF ()) {
  3106. if (GetPrivateProfileString(
  3107. WINNT_UNATTENDED,
  3108. ISNT() ? WINNT_D_NTUPGRADE : WINNT_D_WIN95UPGRADE,
  3109. TEXT(""),
  3110. buffer,
  3111. sizeof(buffer) / sizeof(TCHAR),
  3112. g_DynUpdtStatus->RestartAnswerFile
  3113. )) {
  3114. Upgrade = !lstrcmpi (buffer, WINNT_A_YES);
  3115. if (!Upgrade) {
  3116. dwSetupFlags &= (~UPG_FLAG_TYPICAL);
  3117. }
  3118. return FALSE;
  3119. }
  3120. }
  3121. //
  3122. // Nothing to do. Advance page in unattended case.
  3123. //
  3124. if(UnattendedOperation && !CancelPending) {
  3125. PostMessage (hdlg, WMX_UNATTENDED, PSBTN_NEXT, 0);
  3126. }
  3127. else
  3128. {
  3129. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  3130. }
  3131. } else {
  3132. //
  3133. // Deactivation. Set state of upgrade based on radio buttons.
  3134. //
  3135. Upgrade = (0 == SendMessage(GetDlgItem(hdlg, IDC_INSTALLCOMBO), CB_GETCURSEL, 0, 0)) && WantToUpgrade;
  3136. //
  3137. // On upgrade, delete the setup log files.
  3138. //
  3139. if (Upgrade) {
  3140. TCHAR FilePath[MAX_PATH];
  3141. MyGetWindowsDirectory( FilePath, MAX_PATH );
  3142. ConcatenatePaths( FilePath, TEXT("setupact.log"), MAX_PATH);
  3143. DeleteFile( FilePath );
  3144. MyGetWindowsDirectory( FilePath, MAX_PATH );
  3145. ConcatenatePaths( FilePath, TEXT("setuperr.log"), MAX_PATH);
  3146. DeleteFile( FilePath );
  3147. }
  3148. }
  3149. b = TRUE;
  3150. break;
  3151. case WMX_I_AM_VISIBLE:
  3152. // Force repainting first to make sure the page is visible.
  3153. //
  3154. // Set the focus on the NEXT button, people were unintentionally
  3155. // changing the install type from upgrade to clean with wheel mouse
  3156. SetFocus (GetDlgItem (GetParent(hdlg), 0x3024));
  3157. InvalidateRect(hdlg,NULL,FALSE);
  3158. UpdateWindow(hdlg);
  3159. b = TRUE;
  3160. break;
  3161. default:
  3162. b = FALSE;
  3163. break;
  3164. }
  3165. return(b);
  3166. }
  3167. typedef BOOL (WINAPI *EnumProcessesFn)(DWORD * lpidProcess,
  3168. DWORD cb,
  3169. DWORD * cbNeeded);
  3170. typedef BOOL (WINAPI *EnumProcessModulesFn)(HANDLE hProcess,
  3171. HMODULE *lphModule,
  3172. DWORD cb,
  3173. LPDWORD lpcbNeeded);
  3174. #ifdef UNICODE
  3175. typedef DWORD (WINAPI *GetModuleBaseNameFn)(HANDLE hProcess,
  3176. HMODULE hModule,
  3177. LPWSTR lpBaseName,
  3178. DWORD nSize);
  3179. #else
  3180. typedef DWORD (WINAPI *GetModuleBaseNameFn)(HANDLE hProcess,
  3181. HMODULE hModule,
  3182. LPSTR lpBaseName,
  3183. DWORD nSize);
  3184. #endif // !UNICODE
  3185. #define DEF_PROCESSES_SIZE 1000
  3186. BOOL
  3187. pDoesProcessExist(
  3188. IN LPCTSTR pProcessName
  3189. )
  3190. {
  3191. HMODULE hPSLib = NULL;
  3192. EnumProcessesFn EnumProcesses;
  3193. EnumProcessModulesFn EnumProcessModules;
  3194. GetModuleBaseNameFn GetModuleBaseName;
  3195. HANDLE hProcess;
  3196. HMODULE hModule;
  3197. TCHAR ProcessName[MAX_PATH];
  3198. DWORD * pdwProcessesID = NULL;
  3199. DWORD dwBytesExist = 0;
  3200. DWORD dwBytesNeeded = 0;
  3201. BOOL bResult = FALSE;
  3202. UINT i;
  3203. UINT iLen;
  3204. __try{
  3205. hPSLib = LoadLibrary(TEXT("psapi.dll"));
  3206. if(!hPSLib){
  3207. __leave;
  3208. }
  3209. EnumProcesses = (EnumProcessesFn)GetProcAddress(hPSLib, "EnumProcesses");
  3210. EnumProcessModules = (EnumProcessModulesFn)GetProcAddress(hPSLib, "EnumProcessModules");
  3211. GetModuleBaseName = (GetModuleBaseNameFn)GetProcAddress(hPSLib,
  3212. "GetModuleBaseName"
  3213. #ifdef UNICODE
  3214. "W"
  3215. #else
  3216. "A"
  3217. #endif
  3218. );
  3219. if(!EnumProcesses || !EnumProcessModules || !GetModuleBaseName){
  3220. __leave;
  3221. }
  3222. do{
  3223. if(pdwProcessesID){
  3224. FREE(pdwProcessesID);
  3225. }
  3226. dwBytesExist += DEF_PROCESSES_SIZE;
  3227. pdwProcessesID = (DWORD*)MALLOC(dwBytesExist);
  3228. if(!pdwProcessesID){
  3229. __leave;
  3230. }
  3231. if(!EnumProcesses(pdwProcessesID, dwBytesExist, &dwBytesNeeded)){
  3232. __leave;
  3233. }
  3234. }while(dwBytesNeeded >= dwBytesExist);
  3235. for(i = 0, iLen = dwBytesNeeded / sizeof(DWORD); i < iLen; i++){
  3236. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pdwProcessesID[i]);
  3237. if(hProcess &&
  3238. EnumProcessModules(hProcess, &hModule, sizeof(hModule), &dwBytesNeeded) &&
  3239. GetModuleBaseName(hProcess, hModule, ProcessName, ARRAYSIZE(ProcessName)) &&
  3240. !_tcsicmp(pProcessName, ProcessName)){
  3241. CloseHandle(hProcess);
  3242. bResult = TRUE;
  3243. break;
  3244. }
  3245. CloseHandle(hProcess);
  3246. }
  3247. }
  3248. __finally{
  3249. if(pdwProcessesID){
  3250. FREE(pdwProcessesID);
  3251. }
  3252. FreeLibrary(hPSLib);
  3253. }
  3254. return bResult;
  3255. }
  3256. INT_PTR
  3257. OptionsWizPage(
  3258. IN HWND hdlg,
  3259. IN UINT msg,
  3260. IN WPARAM wParam,
  3261. IN LPARAM lParam
  3262. )
  3263. {
  3264. static BOOL bCopyFarEast = FALSE;
  3265. static BOOL bUserSelectedCopyFarEast = FALSE;
  3266. BOOL b;
  3267. BOOL MultipleSource;
  3268. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  3269. TCHAR Buffer[4];
  3270. #ifdef RUN_SYSPARSE
  3271. static BOOL FirstTime = TRUE;
  3272. #endif
  3273. int status;
  3274. switch(msg) {
  3275. case WM_INITDIALOG:
  3276. //
  3277. // Enable autopartition picking feature only on personal and professional
  3278. // when the user has not specified a /tempdrive and its not unattened mode
  3279. //
  3280. if (!Server && !UserSpecifiedLocalSourceDrive && !Upgrade && !UnattendedOperation) {
  3281. ChoosePartition = FALSE;
  3282. }
  3283. b = FALSE;
  3284. AccessibleMagnifier = pDoesProcessExist(TEXT("magnify.exe"));
  3285. break;
  3286. case WM_COMMAND:
  3287. b = FALSE;
  3288. //
  3289. // Check for buttons.
  3290. //
  3291. if(HIWORD(wParam) == BN_CLICKED) {
  3292. switch(LOWORD(wParam)) {
  3293. case IDB_ACCESSIBILITY:
  3294. DoAccessibility(hdlg);
  3295. b = TRUE;
  3296. break;
  3297. case IDB_ADVANCED:
  3298. DoOptions(hdlg);
  3299. b = TRUE;
  3300. break;
  3301. case IDC_FAREAST_LANG:
  3302. // Remember if the user put the check mark in it
  3303. // If the control gets checked because a FE langauge was selected
  3304. // windows does not send a BN_CLICKED message, so this does not get executed.
  3305. bUserSelectedCopyFarEast = (IsDlgButtonChecked(hdlg,IDC_FAREAST_LANG) == BST_CHECKED);
  3306. break;
  3307. }
  3308. }
  3309. if(HIWORD(wParam) == CBN_SELCHANGE)
  3310. {
  3311. PrimaryLocale = (DWORD)SendDlgItemMessage( hdlg, IDC_COMBO1, CB_GETCURSEL, 0, 0 );
  3312. // Only if we did not hide the window.
  3313. // The window would be hidden if the current OS or the to be install language is
  3314. // a FarEast Language.
  3315. if (IsWindowVisible(GetDlgItem(hdlg,IDC_FAREAST_LANG)))
  3316. {
  3317. if (IsFarEastLanguage(PrimaryLocale))
  3318. {
  3319. // User seleted a FarEast Language,
  3320. // Select the check box and diable it.
  3321. CheckDlgButton(hdlg,IDC_FAREAST_LANG,BST_CHECKED);
  3322. EnableWindow(GetDlgItem(hdlg,IDC_FAREAST_LANG), FALSE);
  3323. }
  3324. else
  3325. {
  3326. // Don't change the check mark, if the user checked it.
  3327. if (!bUserSelectedCopyFarEast)
  3328. {
  3329. // User seleted a non FarEast Language,
  3330. // Unselect the check box and enable it.
  3331. CheckDlgButton(hdlg,IDC_FAREAST_LANG,BST_UNCHECKED);
  3332. }
  3333. EnableWindow(GetDlgItem(hdlg,IDC_FAREAST_LANG), TRUE);
  3334. }
  3335. }
  3336. }
  3337. break;
  3338. case WMX_ACTIVATEPAGE:
  3339. CHECKUPGRADEONLY();
  3340. #if defined PRERELEASE || defined PRERELEASE_IDWLOG
  3341. if (wParam ){ // START IDWLOG. remove before ship
  3342. TCHAR szDllPath[MAX_PATH];
  3343. TCHAR szCommandString[MAX_PATH + 120];
  3344. LPTSTR lpDllPath;
  3345. LPTSTR lp;
  3346. STARTUPINFO si;
  3347. PROCESS_INFORMATION pi;
  3348. #ifdef PRERELEASE_IDWLOG
  3349. BOOL RunFromSP = TRUE;
  3350. #else
  3351. BOOL RunFromSP = FALSE;
  3352. #endif
  3353. //Initialize for Prefix
  3354. szDllPath[0]=0;
  3355. //
  3356. // Launch idwlog.exe from the same directory as winnt32.exe.
  3357. // INTERNAL: Tool to track the health of the build.
  3358. // Ignore errors, NOT INCLUDED IN THE RETAIL release.
  3359. // Remove this code before shipping
  3360. //
  3361. if ( FALSE == BuildCmdcons ) {
  3362. if ( GetModuleFileName (NULL, szDllPath, MAX_PATH)) {
  3363. for (lp=NULL,lpDllPath=szDllPath; *lpDllPath; lpDllPath=CharNext(lpDllPath)) {
  3364. // the char '\' is never a lead byte
  3365. if (*lpDllPath == TEXT('\\')) {
  3366. lp = lpDllPath;
  3367. }
  3368. }
  3369. _tcscpy(lp ? lp+1 : szDllPath , TEXT("IDWLOG.EXE -1"));
  3370. _tcscpy(szCommandString, szDllPath);
  3371. // If this is an Upgrade.
  3372. _tcscat(szCommandString, Upgrade ? TEXT(" upgrade") : TEXT(""));
  3373. // If this is from a CD
  3374. _tcscat(szCommandString, RunFromCD ? TEXT(" cdrom") : TEXT(""));
  3375. // If this is a MSI install
  3376. _tcscat(szCommandString, RunFromMSI? TEXT(" MSI") : TEXT(""));
  3377. // If this is a SP install
  3378. _tcscat(szCommandString, RunFromSP? TEXT(" sp_full") : TEXT(""));
  3379. // Start new JoeHol code.
  3380. _tcscat(szCommandString, TEXT(" Path="));
  3381. _tcscat(szCommandString, NativeSourcePaths[0] );
  3382. ZeroMemory(&si,sizeof(si));
  3383. si.cb = sizeof(si);
  3384. if (CreateProcess( NULL,
  3385. szCommandString,
  3386. NULL,
  3387. NULL,
  3388. FALSE,
  3389. 0,
  3390. NULL,
  3391. NULL,
  3392. &si,
  3393. &pi)
  3394. ) {
  3395. CloseHandle(pi.hProcess);
  3396. CloseHandle(pi.hThread);
  3397. }
  3398. }
  3399. }
  3400. } // END IDWLOG
  3401. #endif // PRERELEASE
  3402. #ifdef RUN_SYSPARSE
  3403. if (FirstTime && wParam && !NoSysparse && (FALSE == BuildCmdcons) && !IsWinPEMode()) { // START sysparse. remove before RTM
  3404. TCHAR szCommandString[MAX_PATH + 125];
  3405. LPTSTR lpDllPath;
  3406. LPTSTR lp;
  3407. STARTUPINFO si;
  3408. //
  3409. // Launch sysparse.exe from the same directory as winnt32.exe.
  3410. //
  3411. FirstTime = FALSE;
  3412. if ( GetModuleFileName (NULL, szCommandString, MAX_PATH+125)) {
  3413. for (lp=NULL,lpDllPath=szCommandString; *lpDllPath; lpDllPath=CharNext(lpDllPath)) {
  3414. // the char '\' is never a lead byte
  3415. if (*lpDllPath == TEXT('\\')) {
  3416. lp = lpDllPath;
  3417. }
  3418. }
  3419. _tcscpy(lp ? lp+1 : szCommandString , TEXT("SYSPARSE.EXE /donotrun1 /donotrun2 /n sysparse /w c:\\ /x /l /o /1 NA /2 NA /3 NA /4 NA /5 NA /6 NA /7 NA /8 NA /9 1 /m /a"));
  3420. ZeroMemory(&si,sizeof(si));
  3421. si.cb = sizeof(si);
  3422. if (CreateProcess( NULL,
  3423. szCommandString,
  3424. NULL,
  3425. NULL,
  3426. FALSE,
  3427. 0,
  3428. NULL,
  3429. NULL,
  3430. &si,
  3431. &piSysparse)
  3432. ) {
  3433. } else {
  3434. piSysparse.hProcess = NULL;
  3435. DebugLog(Winnt32LogInformation, TEXT("Warning: Could not start sysparse.exe"), 0 );
  3436. }
  3437. } else {
  3438. DebugLog(Winnt32LogInformation, TEXT("Warning: Could not find sysparse.exe - make sure it exists along with winnt32.exe"), 0 );
  3439. }
  3440. }
  3441. #endif
  3442. //
  3443. // Read intl.inf for the language options dialog. We only do this if
  3444. // it's the first activation and there's not a regional settings section
  3445. // in the answer file.
  3446. //
  3447. if (wParam && !IntlInfProcessed &&
  3448. !GetPrivateProfileString(
  3449. WINNT_REGIONALSETTINGS,
  3450. NULL,
  3451. TEXT(""),
  3452. Buffer,
  3453. sizeof(Buffer)/sizeof(TCHAR),
  3454. UnattendedScriptFile)) {
  3455. if (ReadIntlInf( hdlg ))
  3456. {
  3457. InitLangControl(hdlg, bCopyFarEast);
  3458. }
  3459. }
  3460. if( Upgrade || TYPICAL()) {
  3461. return( FALSE );
  3462. }
  3463. b = TRUE;
  3464. if(wParam) {
  3465. if (Winnt32RestartedWithAF ()) {
  3466. if (LoadAdvancedOptions (g_DynUpdtStatus->RestartAnswerFile) &&
  3467. LoadLanguageOptions (g_DynUpdtStatus->RestartAnswerFile) &&
  3468. LoadAccessibilityOptions (g_DynUpdtStatus->RestartAnswerFile)
  3469. ) {
  3470. return FALSE;
  3471. }
  3472. }
  3473. //
  3474. // Activation.
  3475. //
  3476. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  3477. ShowWindow( GetDlgItem(hdlg,IDC_ACCESS_ICON), Upgrade ? SW_HIDE : SW_SHOW );
  3478. ShowWindow( GetDlgItem(hdlg,IDT_LABEL1), Upgrade ? SW_HIDE : SW_SHOW );
  3479. ShowWindow( GetDlgItem(hdlg,IDB_ACCESSIBILITY), Upgrade ? SW_HIDE : SW_SHOW );
  3480. } else {
  3481. //
  3482. // Deactivation.
  3483. // Verify source if not canceling or backing up. Stay here if the source
  3484. // dir does not exist.
  3485. //
  3486. // Save so that we can init the checkbox to whatever this is.
  3487. if (IsWindowVisible(GetDlgItem(hdlg,IDC_FAREAST_LANG)))
  3488. {
  3489. bCopyFarEast = (IsDlgButtonChecked(hdlg,IDC_FAREAST_LANG) == BST_CHECKED);
  3490. SelectFarEastLangGroup(bCopyFarEast );
  3491. }
  3492. if (!Cancelled && lParam != PSN_WIZBACK) {
  3493. //
  3494. // Determine if source edit control is disabled. If it is disabled
  3495. // and the multiple source dirs are invalid, reset the wizard page.
  3496. //
  3497. MultipleSource = !(SourceCount == 1);
  3498. b = InspectSources (hdlg);
  3499. if (!b && MultipleSource) {
  3500. // Reset the wizard page
  3501. CallWindowProc ((WNDPROC)OptionsWizPage, hdlg, WM_INITDIALOG, 0, 0);
  3502. }
  3503. }
  3504. }
  3505. break;
  3506. case WMX_I_AM_VISIBLE:
  3507. //
  3508. // In the unattended case, this page might get reactivated because of an error,
  3509. // in which case we don't want to automatically continue because we could
  3510. // get into an infinite loop.
  3511. //
  3512. if(!WizPage->PerPageData) {
  3513. WizPage->PerPageData = 1;
  3514. UNATTENDED(PSBTN_NEXT);
  3515. }
  3516. b = TRUE;
  3517. break;
  3518. default:
  3519. b = FALSE;
  3520. break;
  3521. }
  3522. return(b);
  3523. }
  3524. INT_PTR
  3525. Working1WizPage(
  3526. IN HWND hdlg,
  3527. IN UINT msg,
  3528. IN WPARAM wParam,
  3529. IN LPARAM lParam
  3530. )
  3531. {
  3532. BOOL b;
  3533. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  3534. HWND Animation = GetDlgItem(hdlg,IDA_COMP_MAGNIFY);
  3535. int status;
  3536. switch(msg) {
  3537. case WM_INITDIALOG:
  3538. //
  3539. // Load the avi resource for the animation.
  3540. //
  3541. Animate_Open(Animation,MAKEINTRESOURCE(IDA_COMP_MAGNIFY));
  3542. //
  3543. // Set the subtitle correctly if we're only inspecting.
  3544. //
  3545. if( CheckUpgradeOnly ) {
  3546. SetDlgItemText(hdlg,IDT_SUBTITLE,(PTSTR)TEXT("") );
  3547. }
  3548. b = FALSE;
  3549. break;
  3550. case WMX_ACTIVATEPAGE:
  3551. //
  3552. // Start/stop the animation. In the activate case, also
  3553. // start doing some meaningful work.
  3554. //
  3555. if(wParam) {
  3556. DWORD ThreadId;
  3557. Animate_Play(Animation,0,-1,-1);
  3558. InspectionThreadHandle = CreateThread( NULL,
  3559. 0,
  3560. InspectAndLoadThread,
  3561. hdlg,
  3562. 0,
  3563. &ThreadId );
  3564. if(InspectionThreadHandle) {
  3565. b = TRUE;
  3566. //
  3567. // enable the billboard text if we can.
  3568. // This will hide the wizard if the billboard text was enabled
  3569. //
  3570. SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  3571. } else {
  3572. MessageBoxFromMessage(
  3573. hdlg,
  3574. MSG_OUT_OF_MEMORY,
  3575. FALSE,
  3576. AppTitleStringId,
  3577. MB_OK | MB_ICONERROR | MB_TASKMODAL
  3578. );
  3579. b = FALSE;
  3580. }
  3581. } else {
  3582. Animate_Stop(Animation);
  3583. b = TRUE;
  3584. // Do schema version check for NT5 DCs
  3585. // Do only if not already cancelled
  3586. if (!Cancelled) {
  3587. // For NT5 DC upgrades, check for schema version match
  3588. if (Upgrade && ISNT() && IsNT5DC()) {
  3589. status = CheckSchemaVersionForNT5DCs(hdlg);
  3590. if (status != DSCHECK_ERR_SUCCESS) {
  3591. // error in checking schema version for NT5 DCs.
  3592. // Setup cannot proceed, go to unsuccessful
  3593. // completion. all necessary message has already
  3594. // been raised
  3595. Cancelled = TRUE;
  3596. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3597. return( FALSE );
  3598. }
  3599. }
  3600. }
  3601. }
  3602. break;
  3603. case WMX_ERRORMESSAGEUP:
  3604. //
  3605. // Start/stop the animation control.
  3606. //
  3607. if(wParam) {
  3608. Animate_Stop(Animation);
  3609. } else {
  3610. Animate_Play(Animation,0,-1,-1);
  3611. }
  3612. b = TRUE;
  3613. break;
  3614. case WMX_SETPROGRESSTEXT:
  3615. //
  3616. // lParam is the progress text.
  3617. //
  3618. SetDlgItemText(hdlg,IDT_WORKING,(PTSTR)lParam);
  3619. b = TRUE;
  3620. break;
  3621. case WMX_INSPECTRESULT:
  3622. //
  3623. // We get here when the InspectionThread
  3624. // sends us this message, so it's done.
  3625. //
  3626. if(InspectionThreadHandle) {
  3627. CloseHandle(InspectionThreadHandle);
  3628. InspectionThreadHandle = NULL;
  3629. }
  3630. if(Cancelled) {
  3631. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3632. } else {
  3633. if( !wParam ) {
  3634. Cancelled = TRUE;
  3635. }
  3636. //
  3637. // Advance or retreat.
  3638. //
  3639. PropSheet_SetWizButtons(
  3640. GetParent(hdlg),
  3641. wParam ? PSWIZB_NEXT : PSBTN_CANCEL
  3642. );
  3643. PropSheet_PressButton(
  3644. GetParent(hdlg),
  3645. wParam ? PSBTN_NEXT : PSBTN_CANCEL
  3646. );
  3647. }
  3648. b = TRUE;
  3649. break;
  3650. default:
  3651. b = FALSE;
  3652. break;
  3653. }
  3654. return(b);
  3655. }
  3656. #ifdef _X86_
  3657. INT_PTR
  3658. FloppyWizPage(
  3659. IN HWND hdlg,
  3660. IN UINT msg,
  3661. IN WPARAM wParam,
  3662. IN LPARAM lParam
  3663. )
  3664. {
  3665. BOOL b;
  3666. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  3667. HWND Gauge = GetDlgItem(hdlg,IDC_PROGRESS);
  3668. HANDLE ThreadHandle;
  3669. DWORD ThreadId;
  3670. b = FALSE;
  3671. switch(msg) {
  3672. case WM_INITDIALOG:
  3673. //
  3674. // Make sure the gas gauge is cleared out.
  3675. //
  3676. SendMessage(Gauge,PBM_SETPOS,0,0);
  3677. //
  3678. // Add border on NT3.51
  3679. //
  3680. if(OsVersion.dwMajorVersion < 4) {
  3681. SetWindowLong(
  3682. Gauge,
  3683. GWL_STYLE,
  3684. GetWindowLong(Gauge,GWL_STYLE) | WS_BORDER
  3685. );
  3686. }
  3687. break;
  3688. case WMX_ACTIVATEPAGE:
  3689. if(wParam)
  3690. {
  3691. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  3692. //
  3693. // Activating. Only activate if we are supposed to create
  3694. // boot floppies. Ask the floppy creation stuff how many total files
  3695. // are to be copied and initialize the progress indicator.
  3696. //
  3697. if(!Floppyless) {
  3698. if(!AddExternalParams(hdlg)) {
  3699. Cancelled = TRUE;
  3700. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3701. b = FALSE;
  3702. break;
  3703. }
  3704. SendMessage(hdlg,WMX_COPYPROGRESS,FloppyGetTotalFileCount(),0);
  3705. ThreadHandle = CreateThread(
  3706. NULL,
  3707. 0,
  3708. FloppyWorkerThread,
  3709. (PVOID)hdlg,
  3710. 0,
  3711. &ThreadId
  3712. );
  3713. if(ThreadHandle) {
  3714. b = TRUE;
  3715. } else {
  3716. //
  3717. // Can't get the copy thread going.
  3718. //
  3719. MessageBoxFromMessageAndSystemError(
  3720. hdlg,
  3721. MSG_CANT_START_COPYING,
  3722. GetLastError(),
  3723. AppTitleStringId,
  3724. MB_OK | MB_ICONWARNING
  3725. );
  3726. Cancelled = TRUE;
  3727. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3728. }
  3729. }
  3730. } else {
  3731. //
  3732. // Deactivating.
  3733. //
  3734. // No progress bar not progress text on the billboard
  3735. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  3736. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  3737. b = TRUE;
  3738. }
  3739. break;
  3740. case WMX_COPYPROGRESS:
  3741. if(lParam) {
  3742. //
  3743. // Done copying. Advance to next page.
  3744. //
  3745. PropSheet_SetWizButtons(GetParent(hdlg),PSWIZB_NEXT);
  3746. PropSheet_PressButton(GetParent(hdlg),PSBTN_NEXT);
  3747. // No progress bar not progress text on the billboard
  3748. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  3749. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  3750. } else {
  3751. if(wParam) {
  3752. TCHAR buffer[MAX_PATH];
  3753. //
  3754. // This tells us how many files are to be copied.
  3755. // Use it as an initialization message.
  3756. //
  3757. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,wParam));
  3758. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETPOS,0,0);
  3759. // Show progress text on the billboard
  3760. if (!LoadString (
  3761. hInst,
  3762. IDS_BB_COPYING,
  3763. buffer,
  3764. sizeof(buffer)/sizeof(TCHAR)
  3765. )) {
  3766. buffer[0] = 0;
  3767. }
  3768. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)buffer);
  3769. // Show the progress gauge on the billboard
  3770. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_SHOW, 0);
  3771. // forward the progress messages to the billboard progress bar
  3772. SendMessage(GetParent(hdlg),WMX_PBM_SETRANGE,0,MAKELPARAM(0,wParam));
  3773. SendMessage(GetParent(hdlg),WMX_PBM_SETPOS,0,0);
  3774. } else {
  3775. //
  3776. // This is a simple tick.
  3777. //
  3778. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_DELTAPOS,1,0);
  3779. // Do the same to the billoard progress
  3780. SendMessage(GetParent(hdlg),WMX_PBM_DELTAPOS,1,0);
  3781. }
  3782. }
  3783. b = TRUE;
  3784. break;
  3785. }
  3786. return(b);
  3787. }
  3788. #endif
  3789. // Then nummber below are actually a little different for each SKU.
  3790. #if DBG
  3791. #define ALWAYS_COPY (13419*1024)
  3792. #define LOCALSOURCE_COPY (655322 *1024)
  3793. #else
  3794. #define ALWAYS_COPY (5020*1024)
  3795. #define LOCALSOURCE_COPY (209507 *1024)
  3796. #endif
  3797. INT_PTR
  3798. CopyingWizPage(
  3799. IN HWND hdlg,
  3800. IN UINT msg,
  3801. IN WPARAM wParam,
  3802. IN LPARAM lParam
  3803. )
  3804. {
  3805. BOOL b;
  3806. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  3807. HWND Gauge = GetDlgItem(hdlg,IDC_PROGRESS);
  3808. HANDLE ThreadHandle;
  3809. DWORD ThreadId;
  3810. static DWORD StartCopyTime;
  3811. static DWORD NumFile = 0;
  3812. switch(msg) {
  3813. case WM_INITDIALOG:
  3814. //
  3815. // Make sure the gas gauge is cleared out.
  3816. //
  3817. SendMessage(Gauge,PBM_SETPOS,0,0);
  3818. //
  3819. // Add border on NT3.51
  3820. //
  3821. if(OsVersion.dwMajorVersion < 4) {
  3822. SetWindowLong(
  3823. Gauge,
  3824. GWL_STYLE,
  3825. GetWindowLong(Gauge,GWL_STYLE) | WS_BORDER
  3826. );
  3827. }
  3828. b = FALSE;
  3829. break;
  3830. case WMX_ACTIVATEPAGE:
  3831. CHECKUPGRADEONLY();
  3832. if(wParam) {
  3833. //
  3834. // Activating -- initialize the source progress indicators and
  3835. // start the copy thread. We do the source progress indicators here
  3836. // to guarantee that the source count is right (it may fluctuate).
  3837. //
  3838. UINT i;
  3839. #ifdef _X86_
  3840. //
  3841. // Make sure we actually have something to copy.
  3842. // Note that we'll always be copying for RISC.
  3843. //
  3844. if( (!MakeLocalSource) && // don't copy ~LS
  3845. (!Floppyless) ) { // don't copy ~BT
  3846. DoPostCopyingStuff(hdlg);
  3847. b = TRUE;
  3848. break;
  3849. }
  3850. #endif
  3851. //#ifdef _X86_
  3852. //
  3853. // Before copying, allow extensions to write changes to the
  3854. // textmode params file.
  3855. //
  3856. // It's legal for them to set a cancelled flag during
  3857. // this call, so we'll need to check for that too. This
  3858. // looks a little odd, but info.CancelledFlag points to
  3859. // Cancelled. So we need to execute this block if his
  3860. // function returns FALSE, or if he's set the Cancelled
  3861. // flag. In either case, we behave the same, we set
  3862. // the Cancelled flag and proceed with a cancel.
  3863. //
  3864. //
  3865. if ( (!AddExternalParams(hdlg)) ||
  3866. (Cancelled == TRUE) ) {
  3867. //
  3868. // Failed... cancel!
  3869. //
  3870. Cancelled = TRUE;
  3871. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3872. b = FALSE;
  3873. break;
  3874. }
  3875. //#endif
  3876. if(SourceCount == 1) {
  3877. //
  3878. // Single-source case gets no details or anything.
  3879. //
  3880. for(i=0; i<MAX_SOURCE_COUNT; i++) {
  3881. ShowWindow(GetDlgItem(hdlg,IDT_LABEL1+i),SW_HIDE);
  3882. ShowWindow(GetDlgItem(hdlg,IDT_SOURCE1+i),SW_HIDE);
  3883. }
  3884. ShowWindow(GetDlgItem(hdlg,IDS_DETAILS),SW_HIDE);
  3885. } else {
  3886. //
  3887. // Show label and file for each source we're using.
  3888. // Disable the others.
  3889. //
  3890. for(i=0; i<MAX_SOURCE_COUNT; i++) {
  3891. ShowWindow(GetDlgItem(hdlg,IDT_LABEL1+i),SW_SHOW);
  3892. EnableWindow(GetDlgItem(hdlg,IDT_LABEL1+i),(i < SourceCount));
  3893. ShowWindow(GetDlgItem(hdlg,IDT_SOURCE1+i),SW_SHOW);
  3894. SetDlgItemText(hdlg,IDT_SOURCE1+i,TEXT(""));
  3895. }
  3896. ShowWindow(GetDlgItem(hdlg,IDS_DETAILS),SW_SHOW);
  3897. }
  3898. //
  3899. // Show more detailed copy progress gauge.
  3900. //
  3901. StartCopyTime = GetTickCount();
  3902. if( DetailedCopyProgress ) {
  3903. //
  3904. // How much have we copied?
  3905. //
  3906. ShowWindow( GetDlgItem(hdlg,IDT_SIZE),SW_SHOW );
  3907. EnableWindow( GetDlgItem(hdlg,IDT_SIZE), TRUE );
  3908. ShowWindow( GetDlgItem(hdlg,IDT_SIZE2),SW_SHOW );
  3909. SetDlgItemText(hdlg,IDT_SIZE2,TEXT("0"));
  3910. //
  3911. // How long have we been at this?
  3912. //
  3913. ShowWindow( GetDlgItem(hdlg,IDT_ELAPSED_TIME),SW_SHOW );
  3914. EnableWindow( GetDlgItem(hdlg,IDT_ELAPSED_TIME), TRUE );
  3915. ShowWindow( GetDlgItem(hdlg,IDT_ELAPSED_TIME2),SW_SHOW );
  3916. SetDlgItemText(hdlg,IDT_ELAPSED_TIME2,TEXT("00:00:00") );
  3917. } else {
  3918. //
  3919. // Hide the details.
  3920. //
  3921. ShowWindow( GetDlgItem(hdlg,IDT_SIZE),SW_HIDE);
  3922. ShowWindow( GetDlgItem(hdlg,IDT_SIZE2),SW_HIDE);
  3923. ShowWindow( GetDlgItem(hdlg,IDT_ELAPSED_TIME),SW_HIDE);
  3924. ShowWindow( GetDlgItem(hdlg,IDT_ELAPSED_TIME2),SW_HIDE);
  3925. }
  3926. SendMessage(hdlg,WMX_COPYPROGRESS,GetTotalFileCount(),0);
  3927. ThreadHandle = CreateThread(
  3928. NULL,
  3929. 0,
  3930. StartCopyingThread,
  3931. (PVOID)hdlg,
  3932. 0,
  3933. &ThreadId
  3934. );
  3935. if(ThreadHandle) {
  3936. b = TRUE;
  3937. } else {
  3938. //
  3939. // Can't get the copy thread going.
  3940. //
  3941. MessageBoxFromMessageAndSystemError(
  3942. hdlg,
  3943. MSG_CANT_START_COPYING,
  3944. GetLastError(),
  3945. AppTitleStringId,
  3946. MB_OK | MB_ICONWARNING
  3947. );
  3948. Cancelled = TRUE;
  3949. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  3950. b = FALSE;
  3951. }
  3952. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  3953. } else {
  3954. //
  3955. // Deactivating.
  3956. //
  3957. // No progress bar not progress text on the billboard
  3958. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  3959. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  3960. b = TRUE;
  3961. }
  3962. break;
  3963. case WMX_COPYPROGRESS:
  3964. if(lParam) {
  3965. //
  3966. // Done copying. On x86, set up boot.ini (etc).
  3967. // Also save NTFT stuff.
  3968. // Advance to next page.
  3969. //
  3970. ThreadHandle = CreateThread(NULL,0,DoPostCopyingStuff,hdlg,0,&ThreadId);
  3971. if(ThreadHandle) {
  3972. CloseHandle(ThreadHandle);
  3973. } else {
  3974. //
  3975. // Just do it synchronously. Might look a little ugly but at least
  3976. // it will get done.
  3977. //
  3978. DoPostCopyingStuff(hdlg);
  3979. }
  3980. } else {
  3981. if(wParam) {
  3982. TCHAR buffer[MAX_PATH];
  3983. //
  3984. // This tells us how many files are to be copied.
  3985. // Use it as an initialization message.
  3986. //
  3987. CurrentPhase = Phase_FileCopy;
  3988. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,wParam));
  3989. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_SETPOS,0,0);
  3990. // Show progress text on the billboard
  3991. if (!LoadString (
  3992. hInst,
  3993. IDS_BB_COPYING,
  3994. buffer,
  3995. sizeof(buffer)/sizeof(TCHAR)
  3996. )) {
  3997. buffer[0] = 0;
  3998. }
  3999. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)buffer);
  4000. // Show the progress gauge on the billboard
  4001. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_SHOW, 0);
  4002. // forward the progress messages to the billboard progress bar
  4003. SendMessage(GetParent(hdlg),WMX_PBM_SETRANGE,0,MAKELPARAM(0,wParam));
  4004. SendMessage(GetParent(hdlg),WMX_PBM_SETPOS,0,0);
  4005. } else {
  4006. //
  4007. // This is a simple tick.
  4008. //
  4009. SendDlgItemMessage(hdlg,IDC_PROGRESS,PBM_DELTAPOS,1,0);
  4010. // forward the progress messages to the billboard progress bar
  4011. SendMessage(GetParent(hdlg),WMX_PBM_DELTAPOS,1,0);
  4012. //
  4013. NumFile++;
  4014. // Are giving the user detailed timings?
  4015. //
  4016. if( DetailedCopyProgress ) {
  4017. TCHAR MyString[256];
  4018. DWORD ElapsedTime = ((GetTickCount() - StartCopyTime) / 1000);
  4019. //
  4020. // Figure out elapsed time.
  4021. //
  4022. wsprintf( MyString, TEXT( "%02d:%02d:%02d" ),
  4023. (ElapsedTime / 3600), // hours
  4024. ((ElapsedTime % 3600) / 60), // minutes
  4025. (ElapsedTime % 60) ); // seconds
  4026. SetDlgItemText( hdlg, IDT_ELAPSED_TIME2, MyString );
  4027. //
  4028. // Figure out data throughput.
  4029. //
  4030. if (GetUserPrintableFileSizeString(
  4031. TotalDataCopied,
  4032. MyString,
  4033. sizeof(MyString)/sizeof(TCHAR))) {
  4034. SetDlgItemText( hdlg, IDT_SIZE2, MyString );
  4035. }
  4036. }
  4037. }
  4038. }
  4039. b = TRUE;
  4040. break;
  4041. case WMX_I_AM_DONE:
  4042. //
  4043. // Advance to next page or bail.
  4044. //
  4045. if(wParam) {
  4046. TCHAR MyString[256];
  4047. TCHAR Size[256];
  4048. DWORD ElapsedTime = ((GetTickCount() - StartCopyTime) / 1000);
  4049. //
  4050. // Figure out elapsed time.
  4051. //
  4052. if (GetUserPrintableFileSizeString(
  4053. TotalDataCopied,
  4054. Size,
  4055. sizeof(Size)/sizeof(TCHAR))) {
  4056. wsprintf( MyString, TEXT( "%s copied. Elapsed time: %02d:%02d:%02d\r\n" ),
  4057. Size, // How much data did we copy?
  4058. (ElapsedTime / 3600), // hours
  4059. ((ElapsedTime % 3600) / 60), // minutes
  4060. (ElapsedTime % 60) ); // seconds
  4061. //
  4062. // Log our data throughput along with the time it took.
  4063. //
  4064. DebugLog( Winnt32LogInformation,
  4065. MyString,
  4066. 0 );
  4067. }
  4068. PropSheet_SetWizButtons(GetParent(hdlg),PSWIZB_NEXT);
  4069. PropSheet_PressButton(GetParent(hdlg),PSBTN_NEXT);
  4070. } else {
  4071. Cancelled = TRUE;
  4072. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  4073. }
  4074. // Set the remaining time to what ever is left for the other parts of setup.
  4075. SetRemainingTime(CalcTimeRemaining(Phase_RestOfSetup));
  4076. // Hide the billboard progress gauge.
  4077. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  4078. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  4079. b = TRUE;
  4080. break;
  4081. default:
  4082. b = FALSE;
  4083. break;
  4084. }
  4085. return(b);
  4086. }
  4087. INT_PTR
  4088. DoneWizPage(
  4089. IN HWND hdlg,
  4090. IN UINT msg,
  4091. IN WPARAM wParam,
  4092. IN LPARAM lParam
  4093. )
  4094. {
  4095. #define ID_REBOOT_TIMER (10)
  4096. BOOL b = FALSE;
  4097. PWSTR p;
  4098. static UINT Countdown;
  4099. TCHAR Text[MAX_PATH];
  4100. switch(msg) {
  4101. case WM_INITDIALOG:
  4102. Countdown = TIME_REBOOT * 10;
  4103. SendDlgItemMessage( hdlg,
  4104. IDC_PROGRESS1,
  4105. PBM_SETRANGE,
  4106. 0,
  4107. MAKELONG(0,Countdown) );
  4108. SendDlgItemMessage( hdlg,
  4109. IDC_PROGRESS1,
  4110. PBM_SETSTEP,
  4111. 1,
  4112. 0 );
  4113. SendDlgItemMessage( hdlg,
  4114. IDC_PROGRESS1,
  4115. PBM_SETPOS,
  4116. 0,
  4117. 0 );
  4118. SetTimer( hdlg,
  4119. ID_REBOOT_TIMER,
  4120. 100,
  4121. NULL );
  4122. SetFocus(GetDlgItem(hdlg,IDNORESTART));
  4123. return( FALSE );
  4124. case WM_TIMER:
  4125. if( Countdown )
  4126. Countdown--;
  4127. if( Cancelled == TRUE ) {
  4128. //
  4129. // Put a note in the debug log so that we know this was cancelled.
  4130. //
  4131. DebugLog (Winnt32LogInformation, NULL, MSG_WINNT32_CANCELLED);
  4132. //
  4133. // Clean up the timer.
  4134. //
  4135. KillTimer( hdlg, ID_REBOOT_TIMER );
  4136. DeleteObject((HGDIOBJ)SendDlgItemMessage(hdlg,IDOK,BM_GETIMAGE,0,0));
  4137. } else {
  4138. if( Countdown ) {
  4139. SendDlgItemMessage( hdlg,
  4140. IDC_PROGRESS1,
  4141. PBM_STEPIT,
  4142. 0,
  4143. 0 );
  4144. SendMessage(GetParent(hdlg),WMX_PBM_STEPIT,0,0);
  4145. } else {
  4146. if( !CancelPending )
  4147. PropSheet_PressButton(GetParent(hdlg),PSBTN_FINISH);
  4148. }
  4149. }
  4150. b = TRUE;
  4151. break;
  4152. case WMX_ACTIVATEPAGE:
  4153. if( BuildCmdcons ) {
  4154. PropSheet_PressButton(GetParent(hdlg),PSBTN_FINISH);
  4155. }
  4156. if( CheckUpgradeOnly ) {
  4157. AutomaticallyShutDown = FALSE;
  4158. return( FALSE );
  4159. }
  4160. DebugLog (Winnt32LogInformation,
  4161. TEXT("AutomaticallyShutDown: <%1!u!>"), 0, AutomaticallyShutDown);
  4162. if ( AutomaticallyShutDown ) {
  4163. if(LoadString(hInst,IDS_BB_REBOOT_TXT,Text,sizeof(Text) / sizeof(TCHAR)))
  4164. {
  4165. COLORREF colGauge;
  4166. HDC hdc = GetDC(hdlg);
  4167. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  4168. // See what color the grow bar should be for the reboot count down
  4169. if ((UINT) GetDeviceCaps(hdc, BITSPIXEL) > 8)
  4170. {
  4171. // High color
  4172. colGauge = RGB(255, 64, 0); // Orange
  4173. }
  4174. else
  4175. {
  4176. // Low color
  4177. colGauge = RGB(255, 0, 0); // Red
  4178. }
  4179. ReleaseDC(hdlg, hdc);
  4180. CurrentPhase = Phase_Reboot;
  4181. if(!LoadString(hInst,IDS_ESC_TOCANCEL_REBOOT,Text,sizeof(Text) / sizeof(TCHAR)))
  4182. {
  4183. *Text = TEXT('\0');
  4184. }
  4185. BB_SetInfoText(Text ); // Replace the ESC text
  4186. StartStopBB(FALSE); // Only stop the billoard text, don't make the wizard visibl
  4187. // Show the grow bar on the billboard for the reboot count donw
  4188. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_SHOW, 0);
  4189. // Set the color to some red
  4190. SendMessage(GetParent(hdlg), WMX_PBM_SETBARCOLOR, 0, (LPARAM)colGauge);
  4191. // Setup the growbar ont eh billboard for the reboot count down.
  4192. SendMessage(GetParent(hdlg),WMX_PBM_SETRANGE,0,MAKELPARAM(0,Countdown));
  4193. SendMessage(GetParent(hdlg),WMX_PBM_SETPOS,0,0);
  4194. SendMessage(GetParent(hdlg),WMX_PBM_SETSTEP,1,0);
  4195. }
  4196. }
  4197. //
  4198. // Accept activation/deactivation.
  4199. //
  4200. b = TRUE;
  4201. break;
  4202. case WM_COMMAND:
  4203. if((HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDNORESTART)) {
  4204. AutomaticallyShutDown = FALSE;
  4205. PropSheet_PressButton(GetParent(hdlg),PSBTN_FINISH);
  4206. } else {
  4207. return(FALSE);
  4208. }
  4209. break;
  4210. case WMX_QUERYCANCEL:
  4211. AutomaticallyShutDown = FALSE;
  4212. *(BOOL*)lParam = FALSE; // Don't cancel setup, just don't reboot.
  4213. b = TRUE;
  4214. PropSheet_PressButton(GetParent(hdlg),PSBTN_FINISH);
  4215. break;
  4216. case WMX_FINISHBUTTON:
  4217. //
  4218. // If we get here then we have been successful.
  4219. // No other case indicates overall success.
  4220. //
  4221. //
  4222. // Clean up the timer.
  4223. //
  4224. KillTimer( hdlg, ID_REBOOT_TIMER );
  4225. DeleteObject((HGDIOBJ)SendDlgItemMessage(hdlg,IDOK,BM_GETIMAGE,0,0));
  4226. //
  4227. // Let upgrade code do its cleanup.
  4228. //
  4229. if(UpgradeSupport.CleanupRoutine) {
  4230. UpgradeSupport.CleanupRoutine();
  4231. }
  4232. GlobalResult = TRUE;
  4233. b = TRUE;
  4234. break;
  4235. default:
  4236. b = FALSE;
  4237. break;
  4238. }
  4239. return(b);
  4240. }
  4241. INT_PTR
  4242. CleaningWizPage(
  4243. IN HWND hdlg,
  4244. IN UINT msg,
  4245. IN WPARAM wParam,
  4246. IN LPARAM lParam
  4247. )
  4248. {
  4249. BOOL b;
  4250. HANDLE ThreadHandle;
  4251. DWORD ThreadId;
  4252. HWND Animation = GetDlgItem(hdlg,IDA_COMP_MAGNIFY);
  4253. b = FALSE;
  4254. switch(msg) {
  4255. case WM_INITDIALOG:
  4256. //
  4257. // Load the avi resource for the animation.
  4258. //
  4259. Animate_Open(Animation,MAKEINTRESOURCE(IDA_COMP_MAGNIFY));
  4260. break;
  4261. case WMX_ACTIVATEPAGE:
  4262. if(wParam) {
  4263. //
  4264. // Disable the wizard cancel button.
  4265. //
  4266. EnableWindow(GetDlgItem(GetParent(hdlg),IDCANCEL),FALSE);
  4267. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  4268. } else {
  4269. //
  4270. // Kill the animation.
  4271. //
  4272. Animate_Stop(Animation);
  4273. }
  4274. b = TRUE;
  4275. break;
  4276. case WMX_I_AM_VISIBLE:
  4277. Animate_Play(Animation,0,-1,-1);
  4278. SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  4279. //
  4280. // Our inspection thread hasn't finished. He'll be
  4281. // looking for the 'Cancelled' flag and he'll stop processing
  4282. // the infs (i.e. building the copylist) when he sees it.
  4283. //
  4284. // If we proceed before he exits though, winnt32.exe will unload
  4285. // winnt32u.dll while our thread is running, causing an AV. Let's
  4286. // give him a reasonable amount of time to finish before we
  4287. // proceed.
  4288. //
  4289. // On Alpha, we can also hit a race condition where we think we
  4290. // need to clean up NVRAM but are still in the middle of writing
  4291. // it (because it takes a really long time to write). This
  4292. // fixes that too.
  4293. //
  4294. if( InspectionThreadHandle ) {
  4295. WaitForSingleObject( InspectionThreadHandle, 20 * (1000) );
  4296. CloseHandle(InspectionThreadHandle);
  4297. InspectionThreadHandle = NULL;
  4298. }
  4299. //
  4300. // Start the restoration process.
  4301. //
  4302. ThreadHandle = CreateThread(
  4303. NULL,
  4304. 0,
  4305. StartCleanup,
  4306. hdlg,
  4307. 0,
  4308. &ThreadId
  4309. );
  4310. if(ThreadHandle) {
  4311. CloseHandle(ThreadHandle);
  4312. } else {
  4313. //
  4314. // Just do it synchronously. It won't look pretty
  4315. // but it will at least get done.
  4316. //
  4317. StartCleanup(hdlg);
  4318. }
  4319. b = TRUE;
  4320. break;
  4321. case WMX_I_AM_DONE:
  4322. //
  4323. // Cleanup is done. Press the next button to advance to
  4324. // the next page.
  4325. //
  4326. PropSheet_SetWizButtons(GetParent(hdlg),PSWIZB_NEXT);
  4327. PropSheet_PressButton(GetParent(hdlg),PSBTN_NEXT);
  4328. break;
  4329. }
  4330. return(b);
  4331. }
  4332. INT_PTR
  4333. NotDoneWizPage(
  4334. IN HWND hdlg,
  4335. IN UINT msg,
  4336. IN WPARAM wParam,
  4337. IN LPARAM lParam
  4338. )
  4339. {
  4340. BOOL b;
  4341. b = FALSE;
  4342. switch(msg) {
  4343. case WMX_ACTIVATEPAGE:
  4344. //
  4345. // Accept activation/deactivation.
  4346. //
  4347. b = TRUE;
  4348. #if defined PRERELEASE || defined PRERELEASE_IDWLOG
  4349. {
  4350. TCHAR DllPath[MAX_PATH];
  4351. TCHAR *p, *q;
  4352. STARTUPINFO StartupInfo;
  4353. PROCESS_INFORMATION ProcessInfo;
  4354. TCHAR szCommand [MAX_PATH + 120];
  4355. //
  4356. // Cancel IDWLOG
  4357. // Remove this code before shipping
  4358. //
  4359. if ( GetModuleFileName (NULL, DllPath, MAX_PATH)) {
  4360. for (q=NULL,p=DllPath; *p; p=CharNext(p)) {
  4361. // the char '\' is never a lead byte
  4362. if (*p == TEXT('\\')) {
  4363. q = p;
  4364. }
  4365. }
  4366. lstrcpy(q ? q+1 : DllPath,TEXT("IDWLOG.EXE -0"));
  4367. lstrcpy(szCommand,DllPath);
  4368. ZeroMemory(&StartupInfo,sizeof(StartupInfo));
  4369. StartupInfo.cb = sizeof(StartupInfo);
  4370. if(CreateProcess(NULL, szCommand,NULL,NULL,FALSE,0,NULL,NULL,&StartupInfo,&ProcessInfo)) {
  4371. CloseHandle(ProcessInfo.hProcess);
  4372. CloseHandle(ProcessInfo.hThread);
  4373. }
  4374. }
  4375. }
  4376. #endif // PRERELEASE
  4377. #ifdef RUN_SYSPARSE
  4378. if (!NoSysparse && (FALSE == BuildCmdcons) && piSysparse.hProcess && !IsWinPEMode()) {
  4379. DWORD ret;
  4380. ret = WaitForSingleObject( piSysparse.hProcess, 0);
  4381. if( ret != WAIT_OBJECT_0) {
  4382. TerminateProcess( piSysparse.hProcess, ERROR_TIMEOUT);
  4383. CloseHandle(piSysparse.hProcess);
  4384. CloseHandle(piSysparse.hThread);
  4385. piSysparse.hProcess = NULL;
  4386. DebugLog(Winnt32LogInformation, TEXT("Warning: Sysparse.exe did not finish, killing process."), 0 );
  4387. }
  4388. }
  4389. #endif
  4390. if (Aborted || CheckUpgradeOnly || BatchMode) {
  4391. PropSheet_PressButton(GetParent(hdlg),PSBTN_FINISH);
  4392. }
  4393. break;
  4394. }
  4395. return(b);
  4396. }
  4397. void SetRemainingTime(DWORD TimeInSeconds)
  4398. {
  4399. DWORD Minutes;
  4400. TCHAR MinuteString[MAX_PATH];
  4401. TCHAR TimeLeft[MAX_PATH];
  4402. Minutes = ((TimeInSeconds)/60) +1;
  4403. if (Minutes > 1)
  4404. {
  4405. if(!LoadString(hInst,IDS_TIMEESTIMATE_MINUTES,MinuteString, MAX_PATH))
  4406. {
  4407. lstrcpy(MinuteString,TEXT("Installation will complete in %d minutes or less."));
  4408. }
  4409. wsprintf(TimeLeft, MinuteString, Minutes);
  4410. }
  4411. else
  4412. {
  4413. if(!LoadString(hInst,IDS_TIMEESTIMATE_LESSTHENONEMINUTE,TimeLeft, MAX_PATH))
  4414. {
  4415. lstrcpy(TimeLeft,TEXT("Installation will complete in less then 1 minute."));
  4416. }
  4417. }
  4418. BB_SetTimeEstimateText(TimeLeft);
  4419. }
  4420. void SetTimeEstimates()
  4421. {
  4422. SetupPhase[Phase_DynamicUpdate].Time = GetDynamicUpdateEstimate();
  4423. if (CheckUpgradeOnly)
  4424. {
  4425. // In CheckUpgradeOnly, we don't copy files and do continue setup.
  4426. // and it can only be set from the command line, so the user can not change.
  4427. SetupPhase[Phase_FileCopy].Time = 0;
  4428. SetupPhase[Phase_RestOfSetup].Time = 0;
  4429. }
  4430. else
  4431. {
  4432. SetupPhase[Phase_FileCopy].Time = GetFileCopyEstimate();
  4433. if (!Upgrade)
  4434. {
  4435. SetupPhase[Phase_HwCompatDat].Time = 0;
  4436. SetupPhase[Phase_UpgradeReport].Time = 0;
  4437. }
  4438. else
  4439. {
  4440. if (!ISNT())
  4441. {
  4442. // Is there a way to find out if we need to update the hwcomp.dat file?
  4443. SetupPhase[Phase_HwCompatDat].Time = GetHwCompDatEstimate();
  4444. SetupPhase[Phase_UpgradeReport].Time = GetUpgradeReportEstimate();
  4445. }
  4446. }
  4447. // Calc the time for the rest of setup.
  4448. // The Win9x migration varies depending on the registery size.
  4449. // The GetRestOfSetupEstimate takes care of that.
  4450. SetupPhase[Phase_RestOfSetup].Time = GetRestOfSetupEstimate();
  4451. }
  4452. }
  4453. // Returns the time remaining starting with the current "Phase"
  4454. DWORD CalcTimeRemaining(UINT Phase)
  4455. {
  4456. UINT i;
  4457. DWORD Time = 0;
  4458. for (i = Phase; i<= Phase_RestOfSetup; i++)
  4459. {
  4460. if (SetupPhase[i].OS & OsVersion.dwPlatformId)
  4461. {
  4462. Time += SetupPhase[i].Time;
  4463. }
  4464. }
  4465. return Time;
  4466. }
  4467. INT_PTR TimeEstimateWizPage(
  4468. IN HWND hdlg,
  4469. IN UINT msg,
  4470. IN WPARAM wParam,
  4471. IN LPARAM lParam
  4472. )
  4473. {
  4474. BOOL b = FALSE;
  4475. switch(msg)
  4476. {
  4477. case WMX_ACTIVATEPAGE:
  4478. if(wParam)
  4479. {
  4480. SetTimeEstimates();
  4481. CurrentPhase = Phase_DynamicUpdate;
  4482. RemainingTime = CalcTimeRemaining(CurrentPhase);
  4483. SetRemainingTime(RemainingTime);
  4484. }
  4485. break;
  4486. default:
  4487. b = FALSE;
  4488. break;
  4489. }
  4490. return(b);
  4491. }
  4492. INT_PTR SetNextPhaseWizPage(
  4493. IN HWND hdlg,
  4494. IN UINT msg,
  4495. IN WPARAM wParam,
  4496. IN LPARAM lParam
  4497. )
  4498. {
  4499. BOOL b = FALSE;
  4500. switch(msg)
  4501. {
  4502. case WMX_ACTIVATEPAGE:
  4503. if(wParam)
  4504. {
  4505. CurrentPhase++;
  4506. while ((!SetupPhase[CurrentPhase].Clean & !Upgrade) ||
  4507. !(SetupPhase[CurrentPhase].OS & OsVersion.dwPlatformId))
  4508. {
  4509. CurrentPhase++;
  4510. }
  4511. RemainingTime = CalcTimeRemaining(CurrentPhase);
  4512. SetRemainingTime(RemainingTime);
  4513. }
  4514. break;
  4515. default:
  4516. b = FALSE;
  4517. break;
  4518. }
  4519. return(b);
  4520. }
  4521. void UpdateTimeString(DWORD RemainungTimeMsecInThisPhase,
  4522. DWORD *PreviousRemainingTime)
  4523. {
  4524. // If the previous displayed time is 1 minute old, update the time remaining.
  4525. if ((*PreviousRemainingTime >= 60000) && ((*PreviousRemainingTime - 60000) > RemainungTimeMsecInThisPhase))
  4526. {
  4527. // Substract one minute.
  4528. RemainingTime -= 60;
  4529. *PreviousRemainingTime = RemainungTimeMsecInThisPhase;
  4530. SetRemainingTime(RemainingTime);
  4531. }
  4532. }
  4533. DWORD GetHwCompDatEstimate()
  4534. {
  4535. return TIME_HWCOMPDAT;
  4536. }
  4537. DWORD GetUpgradeReportEstimate()
  4538. {
  4539. return TIME_UPGRADEREPORT ;
  4540. }
  4541. DWORD GetDynamicUpdateEstimate()
  4542. {
  4543. return 0;
  4544. }
  4545. DWORD GetFileCopyEstimate()
  4546. {
  4547. // dosnet.inf and the TempDirSpace512 numbers look ok.
  4548. //
  4549. DWORD TimeEstimate = 1;
  4550. UINT u;
  4551. TCHAR infPath[MAX_PATH];
  4552. TCHAR CopyEstimate[100];
  4553. TCHAR *p;
  4554. BOOL bFound = FALSE;
  4555. DWORD AlwaysCopy = 0;
  4556. DWORD LocalCopy = 0;
  4557. DWORD Time;
  4558. //
  4559. // Get the numbers from dosnet.inf
  4560. //
  4561. if (AlternateSourcePath[0])
  4562. {
  4563. lstrcpy(infPath,AlternateSourcePath);
  4564. ConcatenatePaths(infPath,InfName,MAX_PATH);
  4565. bFound = FileExists(infPath, NULL);
  4566. }
  4567. if (!bFound)
  4568. {
  4569. u = 0;
  4570. do
  4571. {
  4572. lstrcpy(infPath,NativeSourcePaths[u]);
  4573. ConcatenatePaths(infPath,InfName,MAX_PATH);
  4574. bFound = FileExists(infPath, NULL);
  4575. u++;
  4576. } while ((u<=SourceCount) && !bFound);
  4577. }
  4578. if (bFound)
  4579. {
  4580. // Get the diskspace numbers. We use them to determine the copy size and
  4581. // with that determine the time estimate.
  4582. // We don't need to worry about the cluster size, we only want the byte
  4583. // amount copied. Therefore the 512byte cluster is good enough.
  4584. //
  4585. GetPrivateProfileString(TEXT("DiskSpaceRequirements"), TEXT("TempDirSpace512"),
  4586. TEXT("0"),
  4587. CopyEstimate, sizeof(CopyEstimate)/sizeof(TCHAR),
  4588. infPath);
  4589. //
  4590. // Now get the separate diskspace numbers.
  4591. // If we have a comma, then there are 2 values.
  4592. p = _tcschr(CopyEstimate,TEXT(','));
  4593. if (p)
  4594. {
  4595. // Get the second value
  4596. p++;
  4597. AlwaysCopy = _tcstoul(p,NULL,10);
  4598. }
  4599. LocalCopy = _tcstoul(CopyEstimate,NULL,10);
  4600. }
  4601. else
  4602. {
  4603. // If we could not find the file, use some value.
  4604. // Setup should fail later when we need the file.
  4605. //
  4606. AlwaysCopy = ALWAYS_COPY;
  4607. LocalCopy = LOCALSOURCE_COPY;
  4608. }
  4609. //
  4610. // To avoid divide by zero exception, if we could not
  4611. // calculate throughput, assume it to be the default.
  4612. //
  4613. if (!dwThroughPutSrcToDest) {
  4614. dwThroughPutSrcToDest = DEFAULT_IO_THROUGHPUT;
  4615. }
  4616. if (AlwaysCopy >= dwThroughPutSrcToDest)
  4617. {
  4618. TimeEstimate = AlwaysCopy / dwThroughPutSrcToDest;
  4619. if (TimeEstimate >= 1000)
  4620. {
  4621. TimeEstimate = (TimeEstimate / 1000) + 1;
  4622. }
  4623. else
  4624. {
  4625. TimeEstimate = 1;
  4626. }
  4627. }
  4628. if (MakeLocalSource && (LocalCopy >= dwThroughPutSrcToDest))
  4629. {
  4630. Time = LocalCopy / dwThroughPutSrcToDest;
  4631. if (Time >= 1000)
  4632. {
  4633. Time = (Time / 1000) + 1;
  4634. }
  4635. else
  4636. {
  4637. Time = 1;
  4638. }
  4639. TimeEstimate += Time;
  4640. }
  4641. TimeEstimate = TimeEstimate * 125/100; // Add 25% for other overhead
  4642. wsprintf(infPath, TEXT("Throughput src - dest is %d bytes per msec\r\n"), dwThroughPutSrcToDest);
  4643. DebugLog(Winnt32LogInformation,infPath,0 );
  4644. wsprintf(infPath, TEXT("Throughput HD - HD is %d bytes per msec\r\n"), dwThroughPutHDToHD);
  4645. DebugLog(Winnt32LogInformation,infPath,0 );
  4646. wsprintf(infPath, TEXT("%d bytes copied, should take %d Sec\r\n"), AlwaysCopy+LocalCopy, TimeEstimate);
  4647. DebugLog(Winnt32LogInformation,infPath,0 );
  4648. return TimeEstimate;
  4649. }
  4650. LPTSTR WinRegisteries[] = { TEXT("system.dat"),
  4651. TEXT("User.dat"),
  4652. TEXT("classes.dat"),
  4653. TEXT("")};
  4654. DWORD GetRestOfSetupEstimate()
  4655. {
  4656. DWORD dwTime = TIME_RESTOFSETUP;
  4657. DWORD dwSize = 0;
  4658. TCHAR szRegPath[MAX_PATH];
  4659. TCHAR szRegName[MAX_PATH];
  4660. LPTSTR pRegName = NULL;
  4661. UINT index = 0;
  4662. HANDLE hFind;
  4663. WIN32_FIND_DATA FindData;
  4664. if (!ISNT() && Upgrade)
  4665. {
  4666. DebugLog(Winnt32LogInformation, TEXT("Calculating registery size"), 0 );
  4667. if (GetWindowsDirectory(szRegPath, MAX_PATH))
  4668. {
  4669. dwTime = 0; // We calculate the time from the registery size.
  4670. while (*WinRegisteries[index])
  4671. {
  4672. lstrcpy(szRegName, szRegPath);
  4673. ConcatenatePaths( szRegName, WinRegisteries[index], MAX_PATH);
  4674. hFind = FindFirstFile(szRegName, &FindData);
  4675. if (hFind != INVALID_HANDLE_VALUE)
  4676. {
  4677. DebugLog (Winnt32LogInformation,
  4678. TEXT("%1 size is: %2!ld!"),
  4679. 0,
  4680. szRegName,
  4681. FindData.nFileSizeLow
  4682. );
  4683. // Don't worry about the nFileSizeHigh,
  4684. // if that is used the registery is over 4GB
  4685. dwSize += FindData.nFileSizeLow;
  4686. FindClose(hFind);
  4687. }
  4688. index++;
  4689. }
  4690. if (dwSize > 3000000)
  4691. {
  4692. dwSize -= 3000000;
  4693. dwTime += (dwSize/9000);
  4694. }
  4695. DebugLog (Winnt32LogInformation,
  4696. TEXT("Calculated time for Win9x migration = %1!ld! seconds"),
  4697. 0,
  4698. dwTime + 120); // 120 = base time for Win9x migration
  4699. // Now add the rest of time needed for setup.
  4700. // This includes the base time we estimate for the Win9x migration (120 seconds)
  4701. dwTime+= TIME_RESTOFSETUP;
  4702. }
  4703. }
  4704. return dwTime;
  4705. }
  4706. #ifdef _X86_
  4707. ULONGLONG
  4708. pSystemTimeToFileTime64 (
  4709. IN PSYSTEMTIME SystemTime
  4710. )
  4711. {
  4712. FILETIME ft;
  4713. ULARGE_INTEGER result;
  4714. SystemTimeToFileTime (SystemTime, &ft);
  4715. result.LowPart = ft.dwLowDateTime;
  4716. result.HighPart = ft.dwHighDateTime;
  4717. return result.QuadPart;
  4718. }
  4719. INT_PTR
  4720. Win9xUpgradeReportPage (
  4721. IN HWND hdlg,
  4722. IN UINT msg,
  4723. IN WPARAM wParam,
  4724. IN LPARAM lParam
  4725. )
  4726. {
  4727. BOOL b = FALSE;
  4728. INT mode;
  4729. static BOOL getFromUi = FALSE;
  4730. HKEY key;
  4731. LONG rc;
  4732. SYSTEMTIME lastReport;
  4733. SYSTEMTIME currentTime;
  4734. ULONGLONG lastReportIn100Ns;
  4735. ULONGLONG currentTimeIn100Ns;
  4736. ULONGLONG difference;
  4737. DWORD size;
  4738. switch(msg) {
  4739. case WM_INITDIALOG:
  4740. break;
  4741. case WMX_ACTIVATEPAGE:
  4742. if(wParam) {
  4743. //
  4744. // Activation case
  4745. //
  4746. if (ISNT() || !Upgrade) {
  4747. return FALSE;
  4748. }
  4749. if (CheckUpgradeOnly || UnattendedOperation) {
  4750. g_UpgradeReportMode = IDC_ALL_ISSUES;
  4751. return FALSE;
  4752. }
  4753. //
  4754. // Dynamic update -- fetch caller's selection from answer file
  4755. //
  4756. if (Winnt32RestartedWithAF ()) {
  4757. g_UpgradeReportMode = GetPrivateProfileInt (
  4758. WINNT_UNATTENDED,
  4759. WINNT_D_REPORTMODE,
  4760. 0,
  4761. g_DynUpdtStatus->RestartAnswerFile
  4762. );
  4763. if (g_UpgradeReportMode == IDC_CRITICAL_ISSUES ||
  4764. g_UpgradeReportMode == IDC_ALL_ISSUES ||
  4765. g_UpgradeReportMode == IDC_NO_REPORT
  4766. ) {
  4767. //
  4768. // We got our answer -- skip page
  4769. //
  4770. return FALSE;
  4771. }
  4772. }
  4773. //
  4774. // Check the registry to see if the report has been
  4775. // generated recently.
  4776. //
  4777. rc = RegOpenKeyEx (
  4778. HKEY_LOCAL_MACHINE,
  4779. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Setup"),
  4780. 0,
  4781. KEY_READ,
  4782. &key
  4783. );
  4784. if (rc == ERROR_SUCCESS) {
  4785. size = sizeof (lastReport);
  4786. rc = RegQueryValueEx (
  4787. key,
  4788. TEXT("LastReportTime"),
  4789. NULL,
  4790. NULL,
  4791. (PBYTE) (&lastReport),
  4792. &size
  4793. );
  4794. RegCloseKey (key);
  4795. if (rc == ERROR_SUCCESS) {
  4796. //
  4797. // Compare current time to report time
  4798. //
  4799. GetSystemTime (&currentTime);
  4800. lastReportIn100Ns = pSystemTimeToFileTime64 (&lastReport);
  4801. currentTimeIn100Ns = pSystemTimeToFileTime64 (&currentTime);
  4802. if (currentTimeIn100Ns > lastReportIn100Ns) {
  4803. //
  4804. // Compute difference in seconds
  4805. //
  4806. difference = currentTimeIn100Ns - lastReportIn100Ns;
  4807. difference /= (10 * 1000 * 1000);
  4808. if (difference < (30 * 60)) {
  4809. //
  4810. // Report was saved less than 30 minutes ago
  4811. // from compatibility checker; don't show it again.
  4812. //
  4813. DebugLog (
  4814. Winnt32LogInformation,
  4815. TEXT("Not showing report because /checkupgradeonly ran %1!i! seconds ago"),
  4816. 0,
  4817. (INT) difference
  4818. );
  4819. g_UpgradeReportMode = IDC_NO_REPORT;
  4820. return FALSE;
  4821. }
  4822. }
  4823. }
  4824. }
  4825. //
  4826. // Validate the selection
  4827. //
  4828. if (g_UpgradeReportMode != IDC_CRITICAL_ISSUES &&
  4829. g_UpgradeReportMode != IDC_ALL_ISSUES &&
  4830. g_UpgradeReportMode != IDC_NO_REPORT
  4831. ) {
  4832. g_UpgradeReportMode = IDC_CRITICAL_ISSUES;
  4833. }
  4834. //
  4835. // Update the UI
  4836. //
  4837. CheckDlgButton (
  4838. hdlg,
  4839. IDC_CRITICAL_ISSUES,
  4840. g_UpgradeReportMode == IDC_CRITICAL_ISSUES ? BST_CHECKED : BST_UNCHECKED
  4841. );
  4842. CheckDlgButton (
  4843. hdlg,
  4844. IDC_ALL_ISSUES,
  4845. g_UpgradeReportMode == IDC_ALL_ISSUES ? BST_CHECKED : BST_UNCHECKED
  4846. );
  4847. CheckDlgButton (
  4848. hdlg,
  4849. IDC_NO_REPORT,
  4850. g_UpgradeReportMode == IDC_NO_REPORT ? BST_CHECKED : BST_UNCHECKED
  4851. );
  4852. SetFocus (GetDlgItem (hdlg, g_UpgradeReportMode));
  4853. getFromUi = TRUE;
  4854. } else {
  4855. //
  4856. // Deactivation case
  4857. //
  4858. if (!getFromUi) {
  4859. return TRUE;
  4860. }
  4861. //
  4862. // Get selection from UI
  4863. //
  4864. if (IsDlgButtonChecked (hdlg, IDC_CRITICAL_ISSUES) == BST_CHECKED) {
  4865. g_UpgradeReportMode = IDC_CRITICAL_ISSUES;
  4866. } else if (IsDlgButtonChecked (hdlg, IDC_ALL_ISSUES) == BST_CHECKED) {
  4867. g_UpgradeReportMode = IDC_ALL_ISSUES;
  4868. } else if (IsDlgButtonChecked (hdlg, IDC_NO_REPORT) == BST_CHECKED) {
  4869. g_UpgradeReportMode = IDC_NO_REPORT;
  4870. }
  4871. getFromUi = FALSE;
  4872. }
  4873. b = TRUE;
  4874. break;
  4875. }
  4876. return(b);
  4877. }
  4878. #endif