Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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