Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5215 lines
160 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. wizproc.c
  5. Abstract:
  6. This module implements the wizard page procedures needed for the Win9x side
  7. of the upgrade.
  8. Author:
  9. Jim Schmidt (jimschm) 17-Mar-1997
  10. Revision History:
  11. jimschm 24-Jun-1999 Added UI_PreDomainPageProc
  12. jimschm 15-Sep-1998 Resource dump
  13. marcw 15-Sep-1998 Anti-virus checker changes
  14. marcw 18-Aug-1998 Changed BadTimeZone to list box.
  15. marcw 08-Jul-1998 Added UI_BadTimeZonePageProc
  16. jimschm 21-Jan-1998 Added UI_DomainPageProc
  17. jimschm 08-Jan-1998 Moved deferred init to init9x.lib
  18. jimschm 24-Dec-1997 Added UI_NameCollisionPageProc functionality
  19. --*/
  20. #include "pch.h"
  21. #include "uip.h"
  22. #include "memdb.h"
  23. #include "encrypt.h"
  24. //
  25. // Enums
  26. //
  27. typedef enum {
  28. BIP_DONOT,
  29. BIP_NOT_ENOUGH_SPACE,
  30. BIP_SIZE_EXCEED_LIMIT
  31. } BACKUP_IMPOSSIBLE_PAGE;
  32. //
  33. // Defines
  34. //
  35. #define WMX_PAGE_VISIBLE (WMX_PLUGIN_FIRST+0)
  36. #define MAX_NUMBER_OF_DRIVES ('Z' - 'B')
  37. #define NESSESSARY_DISK_SPACE_TO_BACKUP_UNCOMPRESSED (512<<20) //512MB
  38. #define MAX_BACKUP_IMAGE_SIZE_FOR_BACKUP (((LONGLONG)2048)<<20) //2048GB
  39. #define MAX_AMOUNT_OF_TIME_TO_TRY_CONSTRUCT_UNDO_DIR 1000
  40. #define PROPSHEET_NEXT_BUTTON_ID 0x3024
  41. #define MAX_LISTVIEW_TEXT 1024
  42. #define IMAGE_INDENT 2
  43. #define TEXT_INDENT 2
  44. #define TEXT_EXTRA_TAIL_SPACE 2
  45. #define LINEATTR_BOLD 0x0001
  46. #define LINEATTR_INDENTED 0x0002
  47. #define LINEATTR_ALTCOLOR 0x0004
  48. //
  49. // Globals
  50. //
  51. extern HANDLE g_WorkerThreadHandle;
  52. extern ULARGE_INTEGER g_SpaceNeededForSlowBackup;
  53. extern ULARGE_INTEGER g_SpaceNeededForFastBackup;
  54. extern ULARGE_INTEGER g_SpaceNeededForUpgrade;
  55. extern DWORD g_MasterSequencer;
  56. HWND g_ParentWndAlwaysValid = NULL;
  57. HWND g_Winnt32Wnd = NULL;
  58. HWND g_TextViewInDialog = NULL;
  59. BOOL g_DomainSkipped = FALSE;
  60. BOOL g_Offline = FALSE;
  61. BOOL g_SilentBackupMode = FALSE;
  62. BOOL g_UIQuitSetup = FALSE;
  63. BOOL g_IncompatibleDevicesWarning = FALSE;
  64. BACKUP_IMPOSSIBLE_PAGE g_ShowBackupImpossiblePage = BIP_DONOT;
  65. WNDPROC OldProgressProc;
  66. BOOL
  67. NewProgessProc(
  68. IN HWND hdlg,
  69. IN UINT msg,
  70. IN WPARAM wParam,
  71. IN LPARAM lParam
  72. );
  73. #ifdef PRERELEASE
  74. HANDLE g_AutoStressHandle;
  75. #endif
  76. //
  77. // Prototypes
  78. //
  79. VOID
  80. SaveConfigurationForBeta (
  81. VOID
  82. );
  83. //
  84. // Implementation
  85. //
  86. void SetupBBProgressText(HWND hdlg, UINT id)
  87. {
  88. PCTSTR string = NULL;
  89. string = GetStringResource (id);
  90. if (string)
  91. {
  92. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)string);
  93. FreeStringResource (string);
  94. }
  95. }
  96. BOOL
  97. pAbortSetup (
  98. HWND hdlg
  99. )
  100. {
  101. SETCANCEL();
  102. PropSheet_PressButton (GetParent (hdlg), PSBTN_CANCEL);
  103. return TRUE;
  104. }
  105. // BackupPageProc does not allow the user to actually perform a backup
  106. BOOL
  107. UI_BackupPageProc (
  108. HWND hdlg,
  109. UINT uMsg,
  110. WPARAM wParam,
  111. LPARAM lParam
  112. )
  113. {
  114. static BOOL InitSent = FALSE;
  115. HKEY UrlKey;
  116. HWND TextView;
  117. __try {
  118. switch (uMsg) {
  119. case WMX_INIT_DIALOG:
  120. UrlKey = OpenRegKeyStr (TEXT("HKCR\\.URL"));
  121. TextView = GetDlgItem (hdlg, IDC_HOTLINK);
  122. if (UrlKey) {
  123. CloseRegKey (UrlKey);
  124. } else {
  125. ShowWindow (TextView, SW_HIDE);
  126. }
  127. return FALSE;
  128. case WMX_ACTIVATEPAGE:
  129. if (wParam) {
  130. if (!UPGRADE() || CANCELLED()) {
  131. return FALSE;
  132. }
  133. if (!InitSent) {
  134. SendMessage (hdlg, WMX_INIT_DIALOG, 0, 0);
  135. InitSent = TRUE;
  136. }
  137. g_ParentWndAlwaysValid = GetParent (hdlg);
  138. SetOutOfMemoryParent (g_ParentWndAlwaysValid);
  139. //
  140. // Skip this page in unattended mode.
  141. //
  142. if (UNATTENDED() || TYPICAL()) {
  143. return FALSE;
  144. }
  145. //
  146. // Fill in text of the IDC_TEXT1 control
  147. //
  148. //ArgArray[0] = g_Win95Name;
  149. //ParseMessageInWnd (GetDlgItem (hdlg, IDC_TEXT1), ArgArray);
  150. // On activate, turn on next and back
  151. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT|PSWIZB_BACK);
  152. } else {
  153. DEBUGLOGTIME(("Backup Wizard Page done."));
  154. }
  155. return TRUE;
  156. }
  157. } __except (1) {
  158. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Backup Page."));
  159. SafeModeExceptionOccured ();
  160. }
  161. return FALSE;
  162. }
  163. BOOL
  164. UI_HwCompDatPageProc (
  165. HWND hdlg,
  166. UINT uMsg,
  167. WPARAM wParam,
  168. LPARAM lParam
  169. )
  170. {
  171. DWORD threadId;
  172. static BOOL HwReportGenerated = FALSE;
  173. static BOOL DeferredInitExecuted = FALSE;
  174. PCTSTR ArgArray[1];
  175. __try {
  176. switch (uMsg) {
  177. case WMX_ACTIVATEPAGE:
  178. if (wParam) {
  179. if (!UPGRADE() || CANCELLED()) {
  180. return FALSE;
  181. }
  182. //
  183. // Block upgrades of Server
  184. //
  185. // This case usually does not detect server. If WINNT32 ever updates the
  186. // Server variable earlier, this will work.
  187. //
  188. if (*g_ProductType == NT_SERVER) {
  189. ArgArray[0] = g_Win95Name;
  190. ResourceMessageBox (
  191. g_ParentWnd,
  192. MSG_SERVER_UPGRADE_UNSUPPORTED_INIT,
  193. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  194. ArgArray
  195. );
  196. return pAbortSetup (hdlg);
  197. }
  198. TurnOnWaitCursor();
  199. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  200. __try {
  201. if (!DeferredInitExecuted) {
  202. DeferredInitExecuted = TRUE;
  203. DEBUGLOGTIME(("Deferred init..."));
  204. //
  205. // This page is the first page that gets control from WINNT32 after
  206. // the INIT routine. We _must_ use this opportunity to do any delayed
  207. // initialization that may be necessary.
  208. //
  209. if (!DeferredInit (hdlg)) {
  210. return pAbortSetup (hdlg);
  211. }
  212. BuildPunctTable();
  213. }
  214. DEBUGLOGTIME(("HWCOMP.DAT Wizard Page..."));
  215. if (HwReportGenerated) {
  216. //
  217. // The code below was already processed
  218. //
  219. return FALSE;
  220. }
  221. HwReportGenerated = TRUE;
  222. //
  223. // Determine if hwcomp.dat needs to be rebuilt, and if it does, determine the progress bar
  224. // ticks. If it does not need to be rebuilt, b will be FALSE.
  225. //
  226. // hwcomp.dat is rebuilt whenever there is an INF file that is changed from the ones shipped
  227. // with NT. Internally, this includes the INFs that are compressed, so consequently anyone
  228. // who installs off the corpnet automatically gets their hwcomp.dat rebuilt.
  229. //
  230. if (!HwComp_DoesDatFileNeedRebuilding()) {
  231. HwComp_ScanForCriticalDevices();
  232. DEBUGMSG((DBG_NAUSEA,"UI_HwCompDatPageProc: Skipping page since INF files do not nead to be read."));
  233. return FALSE;
  234. }
  235. //
  236. // On activate, disable next and back
  237. //
  238. PropSheet_SetWizButtons (GetParent(hdlg), 0);
  239. PostMessage (hdlg, WMX_PAGE_VISIBLE, 0, 0);
  240. }
  241. __finally {
  242. TurnOffWaitCursor();
  243. }
  244. }
  245. return TRUE;
  246. case WMX_PAGE_VISIBLE:
  247. //
  248. // Create thread that does the work
  249. //
  250. UpdateWindow (hdlg);
  251. OldProgressProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hdlg, IDC_PROGRESS),GWLP_WNDPROC,(LONG_PTR)NewProgessProc);
  252. SetupBBProgressText(hdlg, MSG_HWCOMP_TEXT);
  253. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_SHOW, 0);
  254. g_WorkerThreadHandle = CreateThread (
  255. NULL,
  256. 0,
  257. UI_CreateNewHwCompDat,
  258. (PVOID) hdlg,
  259. 0,
  260. &threadId
  261. );
  262. break;
  263. case WMX_REPORT_COMPLETE:
  264. SetWindowLongPtr(GetDlgItem(hdlg, IDC_PROGRESS),GWLP_WNDPROC,(LONG_PTR)OldProgressProc );
  265. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  266. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  267. if (g_WorkerThreadHandle != NULL) {
  268. CloseHandle (g_WorkerThreadHandle);
  269. g_WorkerThreadHandle = NULL;
  270. }
  271. if (lParam != ERROR_SUCCESS) {
  272. // For errors, cancel WINNT32
  273. LOG ((LOG_ERROR, "Report code failed!"));
  274. return pAbortSetup (hdlg);
  275. }
  276. else {
  277. HwComp_ScanForCriticalDevices();
  278. // Automatically move to the next wizard page when done
  279. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  280. }
  281. break;
  282. }
  283. } __except (1) {
  284. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Hardware Scanning Page."));
  285. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  286. SafeModeExceptionOccured ();
  287. return pAbortSetup (hdlg);
  288. }
  289. return FALSE;
  290. }
  291. BOOL
  292. UI_BadTimeZonePageProc (
  293. HWND hdlg,
  294. UINT uMsg,
  295. WPARAM wParam,
  296. LPARAM lParam
  297. )
  298. {
  299. HWND timeZoneList;
  300. TCHAR timeZone[MAX_TIMEZONE];
  301. TIMEZONE_ENUM e;
  302. INT index;
  303. static BOOL firstTime = TRUE;
  304. PCTSTR unknown = NULL;
  305. __try {
  306. switch (uMsg) {
  307. case WMX_ACTIVATEPAGE:
  308. if (wParam) {
  309. if (!UPGRADE() || CANCELLED()) {
  310. return FALSE;
  311. }
  312. DEBUGLOGTIME(("Bad Time Zone Wizard Page..."));
  313. //
  314. // Skip this page if in Unattended ReportOnly mode.
  315. //
  316. if (UNATTENDED() && REPORTONLY()) {
  317. return FALSE;
  318. }
  319. if (UNATTENDED()) {
  320. return FALSE;
  321. }
  322. if (EnumFirstTimeZone (&e, 0) || EnumFirstTimeZone(&e, TZFLAG_ENUM_ALL)) {
  323. if (e.MapCount == 1 && *e.CurTimeZone) {
  324. //
  325. // Timezone is not ambiguous. Skip page.
  326. //
  327. return FALSE;
  328. }
  329. if (firstTime) {
  330. //
  331. // Disable the next button until something is selected.
  332. //
  333. PropSheet_SetWizButtons (GetParent(hdlg), 0);
  334. firstTime = FALSE;
  335. timeZoneList = GetDlgItem (hdlg, IDC_TIMEZONE_LIST);
  336. if (!*e.CurTimeZone) {
  337. unknown = GetStringResource (MSG_TIMEZONE_UNKNOWN);
  338. }
  339. SetWindowText (GetDlgItem (hdlg, IDC_CURTIMEZONE), *e.CurTimeZone ? e.CurTimeZone : unknown);
  340. if (unknown) {
  341. FreeStringResource (unknown);
  342. }
  343. do {
  344. SendMessage (timeZoneList, LB_ADDSTRING, 0, (LPARAM) e.NtTimeZone);
  345. } while (EnumNextTimeZone (&e));
  346. }
  347. // Stop the bill board and make sure the wizard shows again.
  348. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  349. }
  350. else {
  351. return FALSE;
  352. }
  353. }
  354. else {
  355. //
  356. // Get users selection and map it in.
  357. //
  358. timeZoneList = GetDlgItem (hdlg, IDC_TIMEZONE_LIST);
  359. index = (INT) SendMessage (timeZoneList, LB_GETCURSEL, 0, 0);
  360. SendMessage (timeZoneList, LB_GETTEXT, index, (LPARAM) timeZone);
  361. DEBUGMSG ((DBG_NAUSEA,"User selected %s timezone.", timeZone));
  362. ForceTimeZoneMap(timeZone);
  363. return TRUE;
  364. }
  365. return TRUE;
  366. break;
  367. case WM_COMMAND:
  368. switch (HIWORD(wParam)) {
  369. case CBN_SELCHANGE:
  370. //
  371. // Something has been selected. We will let them pass this page now.
  372. //
  373. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  374. break;
  375. }
  376. return TRUE;
  377. break;
  378. }
  379. } __except (1) {
  380. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Timezone Page."));
  381. SafeModeExceptionOccured ();
  382. }
  383. return FALSE;
  384. }
  385. BOOL
  386. UI_BadHardDrivePageProc (
  387. HWND hdlg,
  388. UINT uMsg,
  389. WPARAM wParam,
  390. LPARAM lParam
  391. )
  392. {
  393. __try {
  394. switch (uMsg) {
  395. case WMX_ACTIVATEPAGE:
  396. if (wParam) {
  397. if (!UPGRADE() || CANCELLED()) {
  398. return FALSE;
  399. }
  400. DEBUGLOGTIME(("Bad Hdd Wizard Page..."));
  401. //
  402. // Scan for critical hardware (i.e. compatible hard disk) after we are sure the hwcomp.dat
  403. // file matches the INFs.
  404. //
  405. if (!HwComp_ScanForCriticalDevices()) {
  406. LOG ((LOG_ERROR,"Aborting since Setup was unable to find critical devices."));
  407. return pAbortSetup (hdlg);
  408. }
  409. //
  410. // Skip this page if there is a usable HardDrive.
  411. //
  412. if (g_ConfigOptions.GoodDrive || HwComp_NtUsableHardDriveExists()) {
  413. DEBUGMSG((DBG_NAUSEA,"UI_BadHardDrivePageProc: Skipping page since a usable Hard Drive exists."));
  414. return FALSE;
  415. }
  416. //
  417. // Skip this page if in Unattended ReportOnly mode.
  418. //
  419. if (UNATTENDED() && REPORTONLY()) {
  420. return FALSE;
  421. }
  422. //
  423. // On activate, disable back and set the cancel flag pointer to true.
  424. //
  425. SETCANCEL(); // Non-standard, normal cases use pAbortSetup
  426. DEBUGMSG ((DBG_ERROR, "Bad hard drive caused setup to exit!"));
  427. PropSheet_SetWizButtons (GetParent(hdlg),0);
  428. }
  429. return TRUE;
  430. break;
  431. }
  432. } __except (1) {
  433. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Incompatible Harddrive Page."));
  434. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  435. SafeModeExceptionOccured ();
  436. pAbortSetup (hdlg);
  437. }
  438. return FALSE;
  439. }
  440. BOOL
  441. UI_BadCdRomPageProc (
  442. HWND hdlg,
  443. UINT uMsg,
  444. WPARAM wParam,
  445. LPARAM lParam
  446. )
  447. {
  448. __try {
  449. switch (uMsg) {
  450. case WMX_ACTIVATEPAGE:
  451. if (wParam) {
  452. if (!UPGRADE() || CANCELLED()) {
  453. return FALSE;
  454. }
  455. DEBUGLOGTIME(("Bad CdRom Wizard Page..."));
  456. //
  457. // Skip this page if invalid CdRom will not stop upgrade.
  458. //
  459. if (!HwComp_NtUsableCdRomDriveExists() && *g_CdRomInstallPtr) {
  460. *g_CdRomInstallPtr = FALSE;
  461. *g_MakeLocalSourcePtr = TRUE;
  462. if (UNATTENDED()) {
  463. return FALSE;
  464. }
  465. }
  466. else if (HwComp_MakeLocalSourceDeviceExists () && *g_CdRomInstallPtr) {
  467. *g_CdRomInstallPtr = FALSE;
  468. *g_MakeLocalSourcePtr = TRUE;
  469. return FALSE;
  470. }
  471. else {
  472. DEBUGMSG((DBG_NAUSEA,"UI_BadCdRomDrivePageProc: Skipping page since a usable CdRom exists or is not needed."));
  473. return FALSE;
  474. }
  475. //
  476. // On activate, disable next and back
  477. //
  478. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  479. PostMessage (hdlg, WMX_PAGE_VISIBLE, 0, 0);
  480. }
  481. else {
  482. //
  483. // Switch to LocalSource mode.
  484. //
  485. *g_CdRomInstallPtr = FALSE;
  486. *g_MakeLocalSourcePtr = TRUE;
  487. }
  488. return TRUE;
  489. break;
  490. }
  491. } __except (1) {
  492. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Incompatible CDRom Drive Page."));
  493. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  494. SafeModeExceptionOccured ();
  495. pAbortSetup (hdlg);
  496. }
  497. return FALSE;
  498. }
  499. VOID
  500. EnableDlgItem (
  501. HWND hdlg,
  502. UINT Id,
  503. BOOL Enable,
  504. UINT FocusId
  505. )
  506. {
  507. HWND Control;
  508. Control = GetDlgItem (hdlg, Id);
  509. if (!Control) {
  510. DEBUGMSG ((DBG_WHOOPS, "Control ID %u missing!", Id));
  511. return;
  512. }
  513. if (!Enable && GetFocus() == Control) {
  514. SetFocus (GetDlgItem (hdlg, FocusId));
  515. }
  516. if ((Enable && IsWindowVisible (Control)) ||
  517. !Enable
  518. ) {
  519. EnableWindow (Control, Enable);
  520. }
  521. }
  522. VOID
  523. ShowDlgItem (
  524. HWND hdlg,
  525. UINT Id,
  526. INT Show,
  527. UINT FocusId
  528. )
  529. {
  530. if (Show == SW_HIDE) {
  531. EnableDlgItem (hdlg, Id, FALSE, FocusId);
  532. }
  533. ShowWindow (GetDlgItem (hdlg, Id), Show);
  534. if (Show == SW_SHOW) {
  535. EnableDlgItem (hdlg, Id, TRUE, FocusId);
  536. }
  537. }
  538. BOOL
  539. UI_HardwareDriverPageProc (
  540. HWND hdlg,
  541. UINT uMsg,
  542. WPARAM wParam,
  543. LPARAM lParam
  544. )
  545. {
  546. BROWSEINFO bi;
  547. HARDWARE_ENUM e;
  548. LPITEMIDLIST ItemIdList;
  549. HWND List;
  550. PCTSTR ModifiedDescription;
  551. PCTSTR ArgArray[2];
  552. PCTSTR ListText;
  553. TCHAR SearchPathStr[MAX_TCHAR_PATH];
  554. UINT Index;
  555. DWORD rc;
  556. BOOL DriverFound;
  557. BOOL b;
  558. static BOOL InitSent = FALSE;
  559. DEVNODESTRING_ENUM DevNodeStr;
  560. GROWBUFFER ResBuf = GROWBUF_INIT;
  561. PCTSTR ResText;
  562. __try {
  563. switch (uMsg) {
  564. case WMX_INIT_DIALOG:
  565. #if 0
  566. GetWindowRect (GetDlgItem (hdlg, IDC_LIST), &ShortSize);
  567. LongSize = ShortSize;
  568. ScreenToClient (hdlg, (PPOINT) &ShortSize);
  569. ScreenToClient (hdlg, ((PPOINT) &ShortSize) + 1);
  570. GetWindowRect (GetDlgItem (hdlg, IDC_OFFLINE_HELP), &HelpPos);
  571. LongSize.bottom = HelpPos.bottom;
  572. ScreenToClient (hdlg, (PPOINT) &LongSize);
  573. ScreenToClient (hdlg, ((PPOINT) &LongSize) + 1);
  574. #endif
  575. SendMessage (hdlg, WMX_UPDATE_LIST, 0, 0);
  576. return FALSE;
  577. case WMX_UPDATE_LIST:
  578. List = GetDlgItem (hdlg, IDC_LIST);
  579. SendMessage (List, LB_RESETCONTENT, 0, 0);
  580. if (EnumFirstHardware (&e, ENUM_INCOMPATIBLE_DEVICES, ENUM_WANT_ONLINE_FLAG)) {
  581. do {
  582. //
  583. // See if the registry key for this device was handled by a
  584. // migration DLL
  585. //
  586. if (IsReportObjectHandled (e.FullKey)) {
  587. continue;
  588. }
  589. //
  590. // See if the user has supplied a driver that will
  591. // support this device
  592. //
  593. if (FindUserSuppliedDriver (
  594. e.HardwareID,
  595. e.CompatibleIDs
  596. )) {
  597. continue;
  598. }
  599. //
  600. // Not supported -- add to report
  601. //
  602. if (e.DeviceDesc) {
  603. ArgArray[0] = e.DeviceDesc;
  604. ModifiedDescription = ParseMessageID (MSG_OFFLINE_DEVICE_PLAIN, ArgArray);
  605. if (!e.Online) {
  606. ListText = ModifiedDescription;
  607. } else {
  608. ListText = e.DeviceDesc;
  609. }
  610. //
  611. // Has this text already been listed? We don't need to list
  612. // the device type more than once, even if the user has multiple
  613. // instances of the hardware installed. Also, if we happened to
  614. // add text that says the device is off line, and then we come
  615. // across one that is online, we delete the offline message and
  616. // put in the unaltered device description.
  617. //
  618. //
  619. Index = SendMessage (List, LB_FINDSTRINGEXACT, 0, (LPARAM) e.DeviceDesc);
  620. if (Index == LB_ERR) {
  621. Index = SendMessage (List, LB_FINDSTRINGEXACT, 0, (LPARAM) ModifiedDescription);
  622. if (ListText != ModifiedDescription && Index != LB_ERR) {
  623. SendMessage (List, LB_DELETESTRING, Index, 0);
  624. Index = LB_ERR;
  625. }
  626. }
  627. if (Index == LB_ERR) {
  628. Index = SendMessage (List, LB_ADDSTRING, 0, (LPARAM) ListText);
  629. SendMessage (List, LB_SETITEMDATA, Index, (LPARAM) e.Online);
  630. }
  631. FreeStringResource (ModifiedDescription);
  632. //
  633. // Dump resources to setupact.log
  634. //
  635. if (EnumFirstDevNodeString (&DevNodeStr, e.FullKey)) {
  636. do {
  637. ArgArray[0] = DevNodeStr.ResourceName;
  638. ArgArray[1] = DevNodeStr.Value;
  639. ResText = ParseMessageID (
  640. MSG_RESOURCE_ITEM_LOG,
  641. ArgArray
  642. );
  643. GrowBufAppendString (&ResBuf, ResText);
  644. FreeStringResource (ResText);
  645. } while (EnumNextDevNodeString (&DevNodeStr));
  646. LOG ((
  647. LOG_INFORMATION,
  648. (PCSTR)MSG_RESOURCE_HEADER_LOG,
  649. ListText,
  650. e.Mfg,
  651. e.Class,
  652. ResBuf.Buf
  653. ));
  654. FreeGrowBuffer (&ResBuf);
  655. }
  656. }
  657. } while (EnumNextHardware (&e));
  658. }
  659. #if 0
  660. //
  661. // Scan list for one line that has item data of TRUE
  662. //
  663. Count = SendMessage (List, LB_GETCOUNT, 0, 0);
  664. for (Index = 0 ; Index < Count ; Index++) {
  665. if (!SendMessage (List, LB_GETITEMDATA, Index, 0)) {
  666. break;
  667. }
  668. }
  669. if (Index < Count) {
  670. //
  671. // Show "not currently present" info
  672. //
  673. ShowDlgItem (hdlg, IDC_NOTE, SW_SHOW, IDC_HAVE_DISK);
  674. ShowDlgItem (hdlg, IDC_OFFLINE_HELP, SW_SHOW, IDC_HAVE_DISK);
  675. SetWindowPos (
  676. List,
  677. NULL,
  678. 0,
  679. 0,
  680. ShortSize.right - ShortSize.left,
  681. ShortSize.bottom - ShortSize.top,
  682. SWP_NOZORDER|SWP_NOMOVE
  683. );
  684. } else {
  685. //
  686. // Hide "not currently present" info
  687. //
  688. ShowDlgItem (hdlg, IDC_NOTE, SW_HIDE, IDC_HAVE_DISK);
  689. ShowDlgItem (hdlg, IDC_OFFLINE_HELP, SW_HIDE, IDC_HAVE_DISK);
  690. SetWindowPos (
  691. List,
  692. NULL,
  693. 0,
  694. 0,
  695. LongSize.right - LongSize.left,
  696. LongSize.bottom - LongSize.top,
  697. SWP_NOZORDER|SWP_NOMOVE
  698. );
  699. }
  700. #endif
  701. return TRUE;
  702. case WM_COMMAND:
  703. switch (LOWORD (wParam)) {
  704. case IDOK:
  705. case IDCANCEL:
  706. EndDialog (hdlg, IDOK);
  707. return TRUE;
  708. case IDC_HAVE_DISK:
  709. ZeroMemory (&bi, sizeof (bi));
  710. bi.hwndOwner = hdlg;
  711. bi.pszDisplayName = SearchPathStr;
  712. bi.lpszTitle = GetStringResource (MSG_DRIVER_DLG_TITLE);
  713. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  714. do {
  715. ItemIdList = SHBrowseForFolder (&bi);
  716. if (!ItemIdList) {
  717. break;
  718. }
  719. TurnOnWaitCursor();
  720. __try {
  721. if (!SHGetPathFromIDList (ItemIdList, SearchPathStr) ||
  722. *SearchPathStr == 0
  723. ) {
  724. //
  725. // Message box -- please reselect
  726. //
  727. OkBox (hdlg, MSG_BAD_SEARCH_PATH);
  728. ItemIdList = NULL;
  729. }
  730. }
  731. __finally {
  732. TurnOffWaitCursor();
  733. }
  734. } while (!ItemIdList);
  735. if (ItemIdList) {
  736. rc = SearchForDrivers (hdlg, SearchPathStr, &DriverFound);
  737. if (DriverFound) {
  738. SendMessage (hdlg, WMX_UPDATE_LIST, 0, 0);
  739. } else {
  740. //
  741. // Message box -- no driver found
  742. //
  743. if (rc == ERROR_DISK_FULL) {
  744. OkBox (hdlg, MSG_DISK_FULL);
  745. } else if (rc != ERROR_CANCELLED) {
  746. OkBox (hdlg, MSG_NO_DRIVERS_FOUND);
  747. }
  748. }
  749. }
  750. return TRUE;
  751. }
  752. break;
  753. case WMX_ACTIVATEPAGE:
  754. b = FALSE;
  755. if (wParam) {
  756. if (!UPGRADE() || CANCELLED()) {
  757. return FALSE;
  758. }
  759. DEBUGLOGTIME(("Hardware Wizard Page..."));
  760. //
  761. // check if any missing drivers are available from the Dynamic Update
  762. //
  763. if (g_DynamicUpdateDrivers) {
  764. if (!AppendDynamicSuppliedDrivers (g_DynamicUpdateDrivers)) {
  765. LOG ((
  766. LOG_ERROR,
  767. "AppendDynamicSuppliedDrivers failed; some downloaded drivers might be reported as missing"
  768. ));
  769. }
  770. }
  771. //
  772. // prepare Hardware compat report
  773. //
  774. HwComp_PrepareReport ();
  775. // On activate, turn on next
  776. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  777. #if 0
  778. if (!InitSent) {
  779. SendMessage (hdlg, WMX_INIT_DIALOG, 0, 0);
  780. InitSent = TRUE;
  781. }
  782. __try {
  783. //
  784. // If in unattended mode, skip this page.
  785. //
  786. if (UNATTENDED() || REPORTONLY()) {
  787. __leave;
  788. }
  789. //
  790. // Unless an incompatibile device is found, skip this page.
  791. //
  792. if (EnumFirstHardware (&e, ENUM_INCOMPATIBLE_DEVICES, ENUM_DONT_WANT_DEV_FIELDS)) {
  793. do {
  794. if (!IsReportObjectHandled (e.FullKey)) {
  795. //
  796. // Incompatible device found
  797. //
  798. AbortHardwareEnum (&e);
  799. b = TRUE;
  800. __leave;
  801. }
  802. } while (EnumNextHardware (&e));
  803. }
  804. }
  805. __finally {
  806. if (!b) {
  807. //
  808. // Because this page will be skipped, generate the hardware report now
  809. //
  810. HwComp_PrepareReport();
  811. }
  812. }
  813. } else {
  814. //
  815. // If a floppy disk was inserted, require user to eject it.
  816. //
  817. EjectDriverMedia (NULL); // NULL == "on any removable media path"
  818. HwComp_PrepareReport();
  819. b = TRUE;
  820. #endif
  821. }
  822. return b;
  823. }
  824. } __except (1) {
  825. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Provide Driver Page."));
  826. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  827. SafeModeExceptionOccured ();
  828. pAbortSetup (hdlg);
  829. }
  830. return FALSE;
  831. }
  832. BOOL
  833. UI_UpgradeModulePageProc (
  834. HWND hdlg,
  835. UINT uMsg,
  836. WPARAM wParam,
  837. LPARAM lParam
  838. )
  839. {
  840. BOOL Enable;
  841. BROWSEINFO bi;
  842. PRELOADED_DLL_ENUM PreLoadedEnum;
  843. MIGDLL_ENUM e;
  844. RECT ListRect;
  845. LPITEMIDLIST ItemIdList;
  846. HWND List;
  847. PCTSTR Data;
  848. TCHAR SearchPathStr[MAX_TCHAR_PATH];
  849. LONG Index;
  850. LONG TopIndex;
  851. LONG ItemData;
  852. UINT ActiveModulesFound;
  853. UINT Length;
  854. LONG rc;
  855. INT Show;
  856. BOOL OneModuleFound;
  857. static BOOL InitSent = FALSE;
  858. __try {
  859. switch (uMsg) {
  860. case WMX_INIT_DIALOG:
  861. CheckDlgButton (hdlg, IDC_HAVE_MIGDLLS, BST_CHECKED);
  862. CheckDlgButton (hdlg, IDC_NO_MIGDLLS, BST_UNCHECKED);
  863. SendMessage (hdlg, WMX_UPDATE_LIST, 0, 0);
  864. SendMessage (hdlg, WMX_ENABLE_CONTROLS, 0, 0);
  865. break;
  866. case WMX_ENABLE_CONTROLS:
  867. //
  868. // Enable/disable the controls
  869. //
  870. Enable = IsDlgButtonChecked (hdlg, IDC_HAVE_MIGDLLS) == BST_CHECKED;
  871. if (Enable) {
  872. Show = SW_SHOW;
  873. } else {
  874. Show = SW_HIDE;
  875. }
  876. ShowDlgItem (hdlg, IDC_TITLE, Show, IDC_HAVE_DISK);
  877. ShowDlgItem (hdlg, IDC_PACK_LIST, Show, IDC_HAVE_DISK);
  878. ShowDlgItem (hdlg, IDC_HAVE_DISK, Show, IDC_HAVE_DISK);
  879. //
  880. // Special case -- show, then determine disable state
  881. //
  882. if (Enable) {
  883. Enable = SendMessage (GetDlgItem (hdlg, IDC_PACK_LIST), LB_GETCURSEL, 0, 0) != LB_ERR;
  884. }
  885. ShowWindow (GetDlgItem (hdlg, IDC_REMOVE), Show);
  886. EnableDlgItem (hdlg, IDC_REMOVE, Enable, IDC_HAVE_DISK);
  887. break;
  888. case WM_COMMAND:
  889. switch (LOWORD (wParam)) {
  890. case IDC_HAVE_MIGDLLS:
  891. case IDC_NO_MIGDLLS:
  892. if (HIWORD (wParam) == BN_CLICKED) {
  893. SendMessage (hdlg, WMX_ENABLE_CONTROLS, 0, 0);
  894. }
  895. break;
  896. case IDC_PACK_LIST:
  897. if (HIWORD (wParam) == LBN_SELCHANGE) {
  898. EnableDlgItem (hdlg, IDC_REMOVE, TRUE, IDC_HAVE_DISK);
  899. }
  900. break;
  901. case IDC_REMOVE:
  902. //
  903. // Delete item from internal memory structure
  904. // or keep registry-loaded DLL from running
  905. //
  906. List = GetDlgItem (hdlg, IDC_PACK_LIST);
  907. SendMessage (List, WM_SETREDRAW, FALSE, 0);
  908. Index = SendMessage (List, LB_GETCURSEL, 0, 0);
  909. MYASSERT (Index != LB_ERR);
  910. ItemData = (LONG) SendMessage (List, LB_GETITEMDATA, Index, 0);
  911. //
  912. // If ItemData is REGISTRY_DLL, then suppress the DLL.
  913. // Otherwise, delete loaded migration DLL
  914. //
  915. if (ItemData == REGISTRY_DLL) {
  916. Length = SendMessage (List, LB_GETTEXTLEN, Index, 0) + 1;
  917. Data = AllocText (Length);
  918. if (Data) {
  919. SendMessage (List, LB_GETTEXT, Index, (LPARAM) Data);
  920. MemDbSetValueEx (MEMDB_CATEGORY_DISABLED_MIGDLLS, NULL, NULL, Data, 0, NULL);
  921. FreeText (Data);
  922. }
  923. } else {
  924. RemoveDllFromList (ItemData);
  925. }
  926. //
  927. // Update the list box
  928. //
  929. TopIndex = SendMessage (List, LB_GETTOPINDEX, 0, 0);
  930. SendMessage (hdlg, WMX_UPDATE_LIST, 0, 0);
  931. SendMessage (List, LB_SETTOPINDEX, (WPARAM) TopIndex, 0);
  932. //
  933. // Disable remove button
  934. //
  935. SetFocus (GetDlgItem (hdlg, IDC_HAVE_DISK));
  936. EnableDlgItem (hdlg, IDC_REMOVE, FALSE, IDC_HAVE_DISK);
  937. //
  938. // Go back to no if all items were removed
  939. //
  940. if (!SendMessage (List, LB_GETCOUNT, 0, 0)) {
  941. CheckDlgButton (hdlg, IDC_HAVE_MIGDLLS, BST_UNCHECKED);
  942. CheckDlgButton (hdlg, IDC_NO_MIGDLLS, BST_CHECKED);
  943. }
  944. //
  945. // Redraw list box
  946. //
  947. SendMessage (List, WM_SETREDRAW, TRUE, 0);
  948. GetWindowRect (List, &ListRect);
  949. ScreenToClient (hdlg, (LPPOINT) &ListRect);
  950. ScreenToClient (hdlg, ((LPPOINT) &ListRect) + 1);
  951. InvalidateRect (hdlg, &ListRect, FALSE);
  952. break;
  953. case IDC_HAVE_DISK:
  954. ZeroMemory (&bi, sizeof (bi));
  955. bi.hwndOwner = hdlg;
  956. bi.pszDisplayName = SearchPathStr;
  957. bi.lpszTitle = GetStringResource (MSG_UPGRADE_MODULE_DLG_TITLE);
  958. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  959. do {
  960. ItemIdList = SHBrowseForFolder (&bi);
  961. if (!ItemIdList) {
  962. break;
  963. }
  964. TurnOnWaitCursor();
  965. __try {
  966. if (!SHGetPathFromIDList (ItemIdList, SearchPathStr) ||
  967. *SearchPathStr == 0
  968. ) {
  969. //
  970. // Message box -- please reselect
  971. //
  972. OkBox (hdlg, MSG_BAD_SEARCH_PATH);
  973. continue;
  974. }
  975. rc = SearchForMigrationDlls (
  976. hdlg,
  977. SearchPathStr,
  978. &ActiveModulesFound,
  979. &OneModuleFound
  980. );
  981. //
  982. // If the search was successful, update the list, or
  983. // tell the user why the list is not changing.
  984. //
  985. // If the search was not successful, the search UI
  986. // already gave the error message, so we just continue
  987. // silently.
  988. //
  989. if (!OneModuleFound) {
  990. if (rc == ERROR_SUCCESS) {
  991. OkBox (hdlg, MSG_NO_MODULES_FOUND);
  992. }
  993. } else if (!ActiveModulesFound) {
  994. if (rc == ERROR_SUCCESS) {
  995. OkBox (hdlg, MSG_NO_NECESSARY_MODULES_FOUND);
  996. }
  997. } else {
  998. SendMessage (hdlg, WMX_UPDATE_LIST, 0, 0);
  999. }
  1000. break;
  1001. }
  1002. __finally {
  1003. TurnOffWaitCursor();
  1004. }
  1005. } while (TRUE);
  1006. return TRUE;
  1007. }
  1008. break;
  1009. case WMX_ACTIVATEPAGE:
  1010. if (wParam) {
  1011. if (!UPGRADE() || CANCELLED() || REPORTONLY() || !g_ConfigOptions.TestDlls) {
  1012. return FALSE;
  1013. }
  1014. DEBUGLOGTIME(("Upgrade Module Wizard Page..."));
  1015. if (!InitSent) {
  1016. SendMessage (hdlg, WMX_INIT_DIALOG, 0, 0);
  1017. InitSent = TRUE;
  1018. }
  1019. // On activate, turn on next and back
  1020. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT|PSWIZB_BACK);
  1021. // Verify copy thread is running
  1022. StartCopyThread();
  1023. // Require that background copy thread to complete
  1024. EndCopyThread();
  1025. // Fail if error
  1026. if (DidCopyThreadFail()) {
  1027. OkBox (hdlg, MSG_FILE_COPY_ERROR);
  1028. //
  1029. // Abort setup (disabled for internal builds)
  1030. //
  1031. return pAbortSetup (hdlg);
  1032. }
  1033. //
  1034. // If in unattended mode, skip this page.
  1035. //
  1036. if (UNATTENDED()) {
  1037. return FALSE;
  1038. }
  1039. }
  1040. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)!wParam, 0);
  1041. return TRUE;
  1042. case WMX_UPDATE_LIST:
  1043. //
  1044. // Enumerate all migration DLLs and shove the program ID in list box
  1045. //
  1046. List = GetDlgItem (hdlg, IDC_PACK_LIST);
  1047. SendMessage (List, LB_RESETCONTENT, 0, 0);
  1048. EnableDlgItem (hdlg, IDC_REMOVE, FALSE, IDC_HAVE_DISK);
  1049. if (EnumFirstMigrationDll (&e)) {
  1050. EnableDlgItem (hdlg, IDC_PACK_LIST, TRUE, IDC_HAVE_DISK);
  1051. CheckDlgButton (hdlg, IDC_HAVE_MIGDLLS, BST_CHECKED);
  1052. CheckDlgButton (hdlg, IDC_NO_MIGDLLS, BST_UNCHECKED);
  1053. EnableDlgItem (hdlg, IDC_HAVE_MIGDLLS, FALSE, IDC_HAVE_DISK);
  1054. EnableDlgItem (hdlg, IDC_NO_MIGDLLS, FALSE, IDC_HAVE_DISK);
  1055. do {
  1056. Index = SendMessage (List, LB_ADDSTRING, 0, (LPARAM) e.ProductId);
  1057. SendMessage (List, LB_SETITEMDATA, Index, (LPARAM) e.Id);
  1058. } while (EnumNextMigrationDll (&e));
  1059. } else {
  1060. EnableDlgItem (hdlg, IDC_HAVE_MIGDLLS, TRUE, IDC_HAVE_DISK);
  1061. EnableDlgItem (hdlg, IDC_NO_MIGDLLS, TRUE, IDC_HAVE_DISK);
  1062. }
  1063. //
  1064. // Enumerate all migration DLLs pre-loaded in the registry, and add them
  1065. // to the list box if they haven't been "removed" by the user
  1066. //
  1067. if (EnumFirstPreLoadedDll (&PreLoadedEnum)) {
  1068. do {
  1069. Index = SendMessage (List, LB_ADDSTRING, 0, (LPARAM) PreLoadedEnum.eValue.ValueName);
  1070. SendMessage (List, LB_SETITEMDATA, Index, (LPARAM) REGISTRY_DLL);
  1071. } while (EnumNextPreLoadedDll (&PreLoadedEnum));
  1072. }
  1073. if (SendMessage (List, LB_GETCOUNT, 0, 0) == 0) {
  1074. EnableDlgItem (hdlg, IDC_PACK_LIST, FALSE, IDC_HAVE_DISK);
  1075. }
  1076. return TRUE;
  1077. }
  1078. } __except (1) {
  1079. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Provide Upgrade Packs Page."));
  1080. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  1081. SafeModeExceptionOccured ();
  1082. pAbortSetup (hdlg);
  1083. }
  1084. return FALSE;
  1085. }
  1086. typedef struct {
  1087. INT TotalWidth;
  1088. INT CategoryWidth;
  1089. INT CurrentNameWidth;
  1090. INT NewNameWidth;
  1091. } LISTMETRICS, *PLISTMETRICS;
  1092. VOID
  1093. pUpdateNameCollisionListBox (
  1094. IN HWND List,
  1095. OUT PLISTMETRICS ListMetrics OPTIONAL
  1096. )
  1097. /*++
  1098. Routine Description:
  1099. pUpdateNameCollisionListBox fills the specified list box with the all names
  1100. that are going to change during the upgrade.
  1101. Arguments:
  1102. List - Specifies the handle to the list box to fill. This list box must
  1103. have tabs enabled.
  1104. ListMetrics - Receives the max width of the text in each column, plus the
  1105. total list width
  1106. Return Value:
  1107. none
  1108. --*/
  1109. {
  1110. INT TopIndex;
  1111. INT SelIndex;
  1112. INT NewIndex;
  1113. INVALID_NAME_ENUM e;
  1114. TCHAR ListLine[MEMDB_MAX];
  1115. HDC hdc;
  1116. RECT rect;
  1117. SIZE size;
  1118. TCHAR OriginalNameTrimmed[24 * 2];
  1119. UINT OriginalNameLen;
  1120. //
  1121. // Obtain current positions if list is being refreshed
  1122. //
  1123. if (SendMessage (List, LB_GETCOUNT, 0, 0)) {
  1124. TopIndex = (INT) SendMessage (List, LB_GETTOPINDEX, 0, 0);
  1125. SelIndex = (INT) SendMessage (List, LB_GETCURSEL, 0, 0);
  1126. } else {
  1127. TopIndex = 0;
  1128. SelIndex = -1;
  1129. }
  1130. //
  1131. // If necessary, compute the tab positions
  1132. //
  1133. if (ListMetrics) {
  1134. hdc = GetDC (List);
  1135. if (hdc) {
  1136. SelectObject (hdc, (HFONT) SendMessage (List, WM_GETFONT, 0, 0));
  1137. }
  1138. ListMetrics->CategoryWidth = 0;
  1139. ListMetrics->CurrentNameWidth = 0;
  1140. ListMetrics->NewNameWidth = 0;
  1141. GetClientRect (List, &rect);
  1142. ListMetrics->TotalWidth = rect.right - rect.left;
  1143. } else {
  1144. hdc = NULL;
  1145. }
  1146. //
  1147. // Reset the content and refill the list
  1148. //
  1149. SendMessage (List, WM_SETREDRAW, FALSE, 0);
  1150. SendMessage (List, LB_RESETCONTENT, 0, 0);
  1151. if (EnumFirstInvalidName (&e)) {
  1152. do {
  1153. //
  1154. // Trim the original name to 20 characters
  1155. //
  1156. _tcssafecpy (OriginalNameTrimmed, e.OriginalName, 20);
  1157. OriginalNameLen = CharCount (OriginalNameTrimmed);
  1158. if (OriginalNameLen < CharCount (e.OriginalName)) {
  1159. StringCat (OriginalNameTrimmed, TEXT("..."));
  1160. OriginalNameLen += 3;
  1161. }
  1162. //
  1163. // If necessary, compute size of text
  1164. //
  1165. if (hdc) {
  1166. GetTextExtentPoint32 (hdc, e.DisplayGroupName, CharCount (e.DisplayGroupName), &size);
  1167. ListMetrics->CategoryWidth = max (ListMetrics->CategoryWidth, size.cx);
  1168. GetTextExtentPoint32 (hdc, OriginalNameTrimmed, OriginalNameLen, &size);
  1169. ListMetrics->CurrentNameWidth = max (ListMetrics->CurrentNameWidth, size.cx);
  1170. GetTextExtentPoint32 (hdc, e.NewName, CharCount (e.NewName), &size);
  1171. ListMetrics->NewNameWidth = max (ListMetrics->NewNameWidth, size.cx);
  1172. }
  1173. //
  1174. // Fill the list box
  1175. //
  1176. wsprintf (ListLine, TEXT("%s\t%s\t%s"), e.DisplayGroupName, OriginalNameTrimmed, e.NewName);
  1177. NewIndex = SendMessage (List, LB_ADDSTRING, 0, (LPARAM) ListLine);
  1178. SendMessage (List, LB_SETITEMDATA, NewIndex, e.Identifier);
  1179. } while (EnumNextInvalidName (&e));
  1180. }
  1181. //
  1182. // Restore current positions
  1183. //
  1184. SendMessage (List, LB_SETTOPINDEX, (WPARAM) TopIndex, 0);
  1185. SendMessage (List, LB_SETCURSEL, (WPARAM) SelIndex, 0);
  1186. SendMessage (List, WM_SETREDRAW, TRUE, 0);
  1187. //
  1188. // Clean up device context
  1189. //
  1190. if (hdc) {
  1191. ReleaseDC (List, hdc);
  1192. }
  1193. }
  1194. INT
  1195. pGetDialogBaseUnitsX (
  1196. HWND hdlg
  1197. )
  1198. {
  1199. HDC hdc;
  1200. static BOOL AlreadyComputed;
  1201. static INT LastBaseUnits;
  1202. SIZE size;
  1203. if (AlreadyComputed) {
  1204. return LastBaseUnits;
  1205. }
  1206. hdc = GetDC (hdlg);
  1207. if (!hdc) {
  1208. DEBUGMSG ((DBG_WHOOPS, "pGetDialogBaseUnitsX: Cannot get hdc from dialog handle"));
  1209. return GetDialogBaseUnits();
  1210. }
  1211. SelectObject (hdc, (HFONT) SendMessage (hdlg, WM_GETFONT, 0, 0));
  1212. GetTextExtentPoint32 (hdc, TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &size);
  1213. LastBaseUnits = (size.cx / 26 + 1) / 2;
  1214. AlreadyComputed = TRUE;
  1215. return LastBaseUnits;
  1216. }
  1217. INT
  1218. pPixelToDialogHorz (
  1219. HWND hdlg,
  1220. INT Pixels
  1221. )
  1222. {
  1223. return (Pixels * 4) / pGetDialogBaseUnitsX (hdlg);
  1224. }
  1225. INT
  1226. pDialogToPixelHorz (
  1227. HWND hdlg,
  1228. INT DlgUnits
  1229. )
  1230. {
  1231. return (DlgUnits * pGetDialogBaseUnitsX (hdlg)) / 4;
  1232. }
  1233. VOID
  1234. pGetChildWindowRect (
  1235. IN HWND hwnd,
  1236. OUT PRECT rect
  1237. )
  1238. {
  1239. RECT ParentRect, ChildRect;
  1240. HWND hdlg;
  1241. hdlg = GetParent(hwnd);
  1242. GetWindowRect (hwnd, &ChildRect);
  1243. GetClientRect (hdlg, &ParentRect);
  1244. ClientToScreen (hdlg, (PPOINT) &ParentRect);
  1245. ClientToScreen (hdlg, ((PPOINT) &ParentRect) + 1);
  1246. rect->left = ChildRect.left - ParentRect.left;
  1247. rect->top = ChildRect.top - ParentRect.top;
  1248. rect->right = ChildRect.right - ParentRect.right;
  1249. rect->bottom = ChildRect.bottom - ParentRect.bottom;
  1250. }
  1251. BOOL
  1252. pIsMsRedirectorInstalled (
  1253. VOID
  1254. )
  1255. {
  1256. HKEY Key;
  1257. BOOL b = FALSE;
  1258. Key = OpenRegKeyStr (TEXT("HKLM\\System\\CurrentControlSet\\Services\\MSNP32\\NetworkProvider"));
  1259. if (Key) {
  1260. b = TRUE;
  1261. CloseRegKey (Key);
  1262. }
  1263. return b;
  1264. }
  1265. VOID
  1266. pSanitizeHelpText (
  1267. HWND TextViewCtrl,
  1268. PCTSTR Text
  1269. )
  1270. {
  1271. PTSTR FixedText;
  1272. PCTSTR p;
  1273. PCTSTR p2;
  1274. PCTSTR End;
  1275. PTSTR q;
  1276. BOOL FindClose = FALSE;
  1277. BOOL RequireEnd;
  1278. FixedText = AllocText (SizeOfString (Text));
  1279. p = Text;
  1280. q = FixedText;
  1281. End = GetEndOfString (p);
  1282. while (p < End) {
  1283. if (FindClose) {
  1284. if (_tcsnextc (p) == TEXT('>')) {
  1285. FindClose = FALSE;
  1286. }
  1287. } else {
  1288. //
  1289. // Allow only <A ...>, <B> and <P> tags, or any </xxx> tag
  1290. //
  1291. if (_tcsnextc (p) == TEXT('<')) {
  1292. p2 = SkipSpace (_tcsinc (p));
  1293. RequireEnd = FALSE;
  1294. switch (_totlower (_tcsnextc (p2))) {
  1295. case TEXT('b'):
  1296. case TEXT('p'):
  1297. //
  1298. // Require close bracket
  1299. //
  1300. p2 = SkipSpace (_tcsinc (p2));
  1301. if (_tcsnextc (p2) != TEXT('>')) {
  1302. FindClose = TRUE;
  1303. }
  1304. break;
  1305. case TEXT('a'):
  1306. //
  1307. // Require space after A. Control will figure out
  1308. // if the anchor is valid or not.
  1309. //
  1310. p2 = _tcsinc (p2);
  1311. if (!_istspace (_tcsnextc (p2))) {
  1312. FindClose = TRUE;
  1313. }
  1314. RequireEnd = TRUE;
  1315. break;
  1316. case TEXT('/'):
  1317. //
  1318. // Don't care about this
  1319. //
  1320. RequireEnd = TRUE;
  1321. break;
  1322. default:
  1323. //
  1324. // Unsupported tag, or at least one we don't want
  1325. // used.
  1326. //
  1327. FindClose = TRUE;
  1328. break;
  1329. }
  1330. if (RequireEnd) {
  1331. while (p2 < End) {
  1332. if (_tcsnextc (p2) == TEXT('>')) {
  1333. break;
  1334. }
  1335. p2 = _tcsinc (p2);
  1336. }
  1337. if (p2 >= End) {
  1338. FindClose = TRUE;
  1339. }
  1340. }
  1341. if (FindClose) {
  1342. //
  1343. // We just went into the mode where we have to
  1344. // skip the tag. So continue without incrementing.
  1345. //
  1346. continue;
  1347. }
  1348. }
  1349. //
  1350. // Good character -- copy it
  1351. //
  1352. _copytchar (q, p);
  1353. q = _tcsinc (q);
  1354. }
  1355. p = _tcsinc (p);
  1356. }
  1357. *q = 0;
  1358. SetWindowText (TextViewCtrl, FixedText);
  1359. FreeText (FixedText);
  1360. }
  1361. VOID
  1362. pFillDomainHelpText (
  1363. HWND TextViewCtrl
  1364. )
  1365. {
  1366. HINF Inf;
  1367. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  1368. PCTSTR Str;
  1369. BOOL Filled = FALSE;
  1370. __try {
  1371. //
  1372. // If unattend or command line switch specified, use it
  1373. //
  1374. if (g_ConfigOptions.DomainJoinText) {
  1375. if (*g_ConfigOptions.DomainJoinText) {
  1376. pSanitizeHelpText (TextViewCtrl, g_ConfigOptions.DomainJoinText);
  1377. Filled = TRUE;
  1378. __leave;
  1379. }
  1380. }
  1381. //
  1382. // Try opening INF in source directory. If it does not exist,
  1383. // try %windir%\INF dir.
  1384. //
  1385. Inf = InfOpenInfInAllSources (S_OPTIONS_INF);
  1386. if (Inf == INVALID_HANDLE_VALUE) {
  1387. Inf = InfOpenInfFile (S_OPTIONS_INF);
  1388. }
  1389. if (Inf != INVALID_HANDLE_VALUE) {
  1390. //
  1391. // Get the alternate text
  1392. //
  1393. if (InfFindFirstLine (Inf, TEXT("Wizard"), TEXT("DomainJoinText"), &is)) {
  1394. Str = InfGetLineText (&is);
  1395. if (Str && *Str) {
  1396. pSanitizeHelpText (TextViewCtrl, Str);
  1397. Filled = TRUE;
  1398. }
  1399. }
  1400. InfCleanUpInfStruct (&is);
  1401. InfCloseInfFile (Inf);
  1402. }
  1403. }
  1404. __finally {
  1405. if (!Filled) {
  1406. Str = GetStringResource (MSG_DOMAIN_HELP);
  1407. MYASSERT (Str);
  1408. if (Str) {
  1409. pSanitizeHelpText (TextViewCtrl, Str);
  1410. }
  1411. }
  1412. }
  1413. }
  1414. BOOL
  1415. UI_PreDomainPageProc (
  1416. IN HWND hdlg,
  1417. IN UINT uMsg,
  1418. IN WPARAM wParam,
  1419. IN LPARAM lParam
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. UI_PreDomainPageProc implements a wizard page that:
  1424. (A) Alerts the user that they need a computer account to participate on
  1425. a domain with Windows NT
  1426. (B) Offers them an ability to skip joining a domain, and go into
  1427. workgroup mode.
  1428. Before showing this page, we check to see if the Workgroup setting
  1429. already has the correct domain name in it.
  1430. Arguments:
  1431. hdlg - Handle to the wizard page; its parent is the wizard frame
  1432. uMsg - Message to process
  1433. wParam - Message data
  1434. lParam - Message data
  1435. Return Value:
  1436. TRUE if the message was handled, or FALSE if not.
  1437. Exception:
  1438. WMX_ACTIVATEPAGE - If called for activation, return of FALSE causes the
  1439. page to be skipped; TRUE causes page to be processed.
  1440. If called for deactivation, return of FALSE causes the
  1441. page not to be deactivated; TRUE causes page to be
  1442. deactivated.
  1443. --*/
  1444. {
  1445. TCHAR ComputerName[MAX_COMPUTER_NAME + 1];
  1446. static BOOL Initialized = FALSE;
  1447. LONG rc;
  1448. static CREDENTIALS Credentials;
  1449. PCTSTR ArgArray[1];
  1450. __try {
  1451. switch (uMsg) {
  1452. case WMX_ACTIVATEPAGE:
  1453. if (wParam) {
  1454. if (!UPGRADE() || CANCELLED() || g_DomainSkipped) {
  1455. return FALSE;
  1456. }
  1457. //
  1458. // Personal upgrades go to workgroup.
  1459. // (regardless if unattended or not...)
  1460. //
  1461. if (*g_ProductFlavor == PERSONAL_PRODUCTTYPE)
  1462. {
  1463. g_ConfigOptions.ForceWorkgroup = TRUE;
  1464. }
  1465. //
  1466. // If unattended mode, the user must generate a computer account themselves,
  1467. // or already have it generated by an administrator. We cannot provide UI
  1468. // to resolve this issue.
  1469. //
  1470. if (UNATTENDED() || REPORTONLY()) {
  1471. g_DomainSkipped = TRUE;
  1472. return FALSE;
  1473. }
  1474. //
  1475. // If force workgroup mode specified via answer file, skip this page
  1476. //
  1477. if (g_ConfigOptions.ForceWorkgroup && !Initialized) {
  1478. g_DomainSkipped = TRUE;
  1479. return FALSE;
  1480. }
  1481. //
  1482. // let this page be visible even on typical upgrade cases
  1483. //
  1484. #if 0
  1485. if(TYPICAL())
  1486. {
  1487. g_DomainSkipped = TRUE;
  1488. return FALSE;
  1489. }
  1490. #endif
  1491. //
  1492. // Validate the domain name in Workgroup
  1493. //
  1494. DEBUGLOGTIME(("Pre-domain resolution page..."));
  1495. if (!GetUpgradeComputerName (ComputerName)) {
  1496. g_DomainSkipped = TRUE;
  1497. return FALSE;
  1498. }
  1499. if (!Initialized) {
  1500. //
  1501. // Put all the in-use names (user names, comptuer name, etc)
  1502. // in memdb
  1503. //
  1504. CreateNameTables();
  1505. //
  1506. // Check for a computer that is offline
  1507. //
  1508. g_Offline |= IsComputerOffline();
  1509. }
  1510. if (!GetUpgradeDomainName (Credentials.DomainName) ||
  1511. #if 0
  1512. IsOriginalDomainNameValid() ||
  1513. #endif
  1514. !pIsMsRedirectorInstalled()
  1515. ) {
  1516. //
  1517. // Domain logon is not enabled or is valid
  1518. //
  1519. Initialized = TRUE;
  1520. g_DomainSkipped = TRUE;
  1521. return FALSE;
  1522. }
  1523. if (!Initialized) {
  1524. Initialized = TRUE;
  1525. if (g_Offline) {
  1526. g_ConfigOptions.ForceWorkgroup = TRUE;
  1527. g_DomainSkipped = TRUE;
  1528. return FALSE;
  1529. }
  1530. #if 0
  1531. rc = DoesComputerAccountExistOnDomain (Credentials.DomainName, ComputerName, TRUE);
  1532. if (rc == 1) {
  1533. //
  1534. // There is already an account for this computer on the user domain.
  1535. //
  1536. ChangeName (GetDomainIdentifier(), Credentials.DomainName);
  1537. g_DomainSkipped = TRUE;
  1538. return FALSE;
  1539. }
  1540. #endif
  1541. //
  1542. // We have now determined that there is no account for the computer.
  1543. // Initialize the wizard page controls.
  1544. //
  1545. ArgArray[0] = Credentials.DomainName;
  1546. //ParseMessageInWnd (GetDlgItem (hdlg, IDC_TEXT2), ArgArray);
  1547. //ParseMessageInWnd (GetDlgItem (hdlg, IDC_TEXT3), ArgArray);
  1548. CheckDlgButton (hdlg, IsComputerOffline() ? IDC_JOIN_WORKGROUP : IDC_JOIN_DOMAIN, BST_CHECKED);
  1549. }
  1550. // Stop the bill board and make sure the wizard shows again.
  1551. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  1552. //
  1553. // On activate, turn on next and back
  1554. //
  1555. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  1556. } else {
  1557. if (!UPGRADE() || CANCELLED() || UNATTENDED() || lParam == PSN_WIZBACK) {
  1558. return TRUE;
  1559. }
  1560. //
  1561. // Force workgroup?
  1562. //
  1563. if (IsDlgButtonChecked (hdlg, IDC_JOIN_DOMAIN) == BST_CHECKED) {
  1564. g_ConfigOptions.ForceWorkgroup = FALSE;
  1565. g_Offline = FALSE;
  1566. } else {
  1567. g_ConfigOptions.ForceWorkgroup = TRUE;
  1568. g_Offline = TRUE;
  1569. }
  1570. DEBUGLOGTIME(("Pre-domain resolution page done."));
  1571. }
  1572. return TRUE;
  1573. }
  1574. } __except (1) {
  1575. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Pre-Domain Page."));
  1576. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  1577. SafeModeExceptionOccured ();
  1578. pAbortSetup (hdlg);
  1579. }
  1580. return FALSE;
  1581. }
  1582. BOOL
  1583. UI_DomainPageProc (
  1584. IN HWND hdlg,
  1585. IN UINT uMsg,
  1586. IN WPARAM wParam,
  1587. IN LPARAM lParam
  1588. )
  1589. /*++
  1590. Routine Description:
  1591. UI_DomainPageProc implements a wizard page that:
  1592. (A) Asks to select find an existing computer account, or to provide
  1593. information to create a computer account.
  1594. (B) Offers them an ability to enter the credentials to create an account,
  1595. or provide the name of a domain that has an account.
  1596. Before showing this page, we verify it is supposed to show up by
  1597. checking several special conditions where the page is not necessary.
  1598. Arguments:
  1599. hdlg - Handle to the wizard page; its parent is the wizard frame
  1600. uMsg - Message to process
  1601. wParam - Message data
  1602. lParam - Message data
  1603. Return Value:
  1604. TRUE if the message was handled, or FALSE if not.
  1605. Exception:
  1606. WMX_ACTIVATEPAGE - If called for activation, return of FALSE causes the
  1607. page to be skipped; TRUE causes page to be processed.
  1608. If called for deactivation, return of FALSE causes the
  1609. page not to be deactivated; TRUE causes page to be
  1610. deactivated.
  1611. --*/
  1612. {
  1613. TCHAR ComputerName[MAX_COMPUTER_NAME + 1];
  1614. static BOOL Initialized = FALSE;
  1615. static BOOL Skipped = FALSE;
  1616. LONG rc;
  1617. static CREDENTIALS Credentials;
  1618. BOOL createAccount;
  1619. PCTSTR ArgArray[1];
  1620. __try {
  1621. switch (uMsg) {
  1622. case WMX_ACTIVATEPAGE:
  1623. if (wParam) {
  1624. if (!UPGRADE() || CANCELLED() || Skipped || g_DomainSkipped) {
  1625. return FALSE;
  1626. }
  1627. //
  1628. // If unattended mode, the user must generate a computer account themselves,
  1629. // or already have it generated by an administrator. We cannot provide UI
  1630. // to resolve this issue.
  1631. //
  1632. if (UNATTENDED() || REPORTONLY()) {
  1633. Skipped = TRUE;
  1634. return FALSE;
  1635. }
  1636. //
  1637. // If computer is offline, skip this page
  1638. //
  1639. if (g_Offline) {
  1640. //
  1641. // The offline state can change depending on the
  1642. // use of back/next.
  1643. //
  1644. return FALSE;
  1645. }
  1646. //
  1647. // Validate the domain name in Workgroup
  1648. //
  1649. DEBUGLOGTIME(("Domain resolution page..."));
  1650. if (!GetUpgradeComputerName (ComputerName)) {
  1651. Skipped = TRUE;
  1652. return FALSE;
  1653. }
  1654. SetDlgItemText (hdlg, IDC_COMPUTER_NAME, ComputerName);
  1655. if (!GetUpgradeDomainName (Credentials.DomainName)) {
  1656. //
  1657. // Domain logon is not enabled or is valid
  1658. //
  1659. Initialized = TRUE;
  1660. Skipped = TRUE;
  1661. return FALSE;
  1662. }
  1663. if (!Initialized) {
  1664. Initialized = TRUE;
  1665. //
  1666. // We have now determined that there is no account for the computer.
  1667. // Initialize the wizard page controls.
  1668. //
  1669. SendMessage (GetDlgItem (hdlg, IDC_DOMAIN), EM_LIMITTEXT, MAX_COMPUTER_NAME, 0);
  1670. //SetDlgItemText (hdlg, IDC_DOMAIN, Credentials.DomainName);
  1671. ArgArray[0] = ComputerName;
  1672. //ParseMessageInWnd (GetDlgItem (hdlg, IDC_SPECIFY_DOMAIN), ArgArray);
  1673. CheckDlgButton (hdlg, IDC_SPECIFY_DOMAIN, BST_CHECKED);
  1674. SetDlgItemText (hdlg, IDC_DOMAIN, Credentials.DomainName);
  1675. //CheckDlgButton (hdlg, IDC_IGNORE, BST_UNCHECKED);
  1676. CheckDlgButton (hdlg, IDC_SKIP, BST_UNCHECKED);
  1677. pFillDomainHelpText (GetDlgItem (hdlg, IDC_DOMAIN_HELP));
  1678. }
  1679. //
  1680. // On activate, turn on next and back
  1681. //
  1682. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT|PSWIZB_BACK);
  1683. } else {
  1684. if (!UPGRADE() || CANCELLED() || UNATTENDED() || lParam == PSN_WIZBACK) {
  1685. return TRUE;
  1686. }
  1687. EnableDomainChecks();
  1688. g_ConfigOptions.ForceWorkgroup = FALSE;
  1689. if (IsDlgButtonChecked (hdlg, IDC_SKIP) == BST_CHECKED) {
  1690. DisableDomainChecks();
  1691. g_ConfigOptions.ForceWorkgroup = TRUE;
  1692. }
  1693. GetDlgItemText (hdlg, IDC_COMPUTER_NAME, ComputerName, sizeof (ComputerName) / sizeof (ComputerName[0]));
  1694. GetDlgItemText (hdlg, IDC_DOMAIN, Credentials.DomainName, sizeof (Credentials.DomainName) / sizeof (Credentials.DomainName[0]));
  1695. //
  1696. // Use hardcoded domain?
  1697. //
  1698. createAccount = FALSE;
  1699. if (IsDlgButtonChecked (hdlg, IDC_SPECIFY_DOMAIN) == BST_CHECKED) {
  1700. if (*Credentials.DomainName) {
  1701. rc = DoesComputerAccountExistOnDomain (Credentials.DomainName, ComputerName, TRUE);
  1702. } else {
  1703. OkBox (hdlg, MSG_PLEASE_SPECIFY_A_DOMAIN);
  1704. SetFocus (GetDlgItem (hdlg, IDC_DOMAIN));
  1705. return FALSE;
  1706. }
  1707. if (rc == -1) {
  1708. //
  1709. // The user specified a bogus domain
  1710. //
  1711. OkBox (hdlg, MSG_DOMAIN_NOT_RESPONDING_POPUP);
  1712. SetFocus (GetDlgItem (hdlg, IDC_DOMAIN));
  1713. return FALSE;
  1714. } else if (rc == 0) {
  1715. //
  1716. // Account does not exist on specified domain
  1717. //
  1718. if (IDYES == YesNoBox (hdlg, MSG_ACCOUNT_NOT_FOUND_POPUP)) {
  1719. createAccount = TRUE;
  1720. } else {
  1721. SetFocus (GetDlgItem (hdlg, IDC_DOMAIN));
  1722. return FALSE;
  1723. }
  1724. } else {
  1725. //
  1726. // Domain is valid and account exists, use it.
  1727. //
  1728. ChangeName (GetDomainIdentifier(), Credentials.DomainName);
  1729. }
  1730. }
  1731. //
  1732. // Display credentials dialog
  1733. //
  1734. //if (IsDlgButtonChecked (hdlg, IDC_IGNORE) == BST_CHECKED) {
  1735. if (createAccount) {
  1736. TCHAR owfPwd[STRING_ENCODED_PASSWORD_SIZE];
  1737. PCTSTR encrypted;
  1738. EnableDomainChecks();
  1739. if (!CredentialsDlg (hdlg, &Credentials)) {
  1740. return FALSE;
  1741. }
  1742. DisableDomainChecks();
  1743. MYASSERT (*Credentials.DomainName);
  1744. if (GetDomainIdentifier()) {
  1745. ChangeName (GetDomainIdentifier(), Credentials.DomainName);
  1746. }
  1747. if (*Credentials.AdminName) {
  1748. if (g_ConfigOptions.EnableEncryption) {
  1749. StringEncodeOwfPassword (Credentials.Password, owfPwd, NULL);
  1750. encrypted = WINNT_A_YES;
  1751. } else {
  1752. StringCopy (owfPwd, Credentials.Password);
  1753. encrypted = WINNT_A_NO;
  1754. }
  1755. WriteInfKey (S_PAGE_IDENTIFICATION, S_DOMAIN_ACCT_CREATE, WINNT_A_YES);
  1756. WriteInfKey (S_PAGE_IDENTIFICATION, S_DOMAIN_ADMIN, Credentials.AdminName);
  1757. WriteInfKey (S_PAGE_IDENTIFICATION, S_DOMAIN_ADMIN_PW, owfPwd);
  1758. WriteInfKey (S_PAGE_IDENTIFICATION, S_ENCRYPTED_DOMAIN_ADMIN_PW, encrypted);
  1759. }
  1760. }
  1761. DEBUGLOGTIME(("Domain resolution page done."));
  1762. }
  1763. return TRUE;
  1764. case WM_COMMAND:
  1765. switch (LOWORD (wParam)) {
  1766. case IDC_DOMAIN:
  1767. if (HIWORD (wParam) == EN_CHANGE) {
  1768. CheckDlgButton (hdlg, IDC_SPECIFY_DOMAIN, BST_CHECKED);
  1769. CheckDlgButton (hdlg, IDC_SKIP, BST_UNCHECKED);
  1770. }
  1771. break;
  1772. case IDC_CHANGE:
  1773. CredentialsDlg (hdlg, &Credentials);
  1774. break;
  1775. }
  1776. break;
  1777. }
  1778. } __except (1) {
  1779. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Domain Page."));
  1780. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  1781. SafeModeExceptionOccured ();
  1782. pAbortSetup (hdlg);
  1783. }
  1784. return FALSE;
  1785. }
  1786. BOOL
  1787. UI_NameCollisionPageProc (
  1788. IN HWND hdlg,
  1789. IN UINT uMsg,
  1790. IN WPARAM wParam,
  1791. IN LPARAM lParam
  1792. )
  1793. /*++
  1794. Routine Description:
  1795. NameCollisionPageProc presents a wizard page when one or more incompatible
  1796. names are found on the Win9x machine. Setup automatically generates
  1797. replacement names, so this page is used to adjust what Setup comes up with.
  1798. If there are no incompatible names found on the Win9x machine, or if
  1799. Setup is in unattended mode, this page is skipped.
  1800. The following names are tested:
  1801. Computer Name - Must be alpha-numeric, or with dash or underscore.
  1802. Spaces are not permitted.
  1803. Computer Domain - If machine is set to participate in an NT domain, then
  1804. Setup must guess at what the correct computer domain
  1805. is, since Win9x does not enforce this name.
  1806. User Names - Setup checks each user name to make sure it is valid. Most
  1807. of the problems are conflicts with NT group names, such as
  1808. Guests.
  1809. Arguments:
  1810. hdlg - Handle to the wizard page; its parent is the wizard frame
  1811. uMsg - Message to process
  1812. wParam - Message data
  1813. lParam - Message data
  1814. Return Value:
  1815. TRUE if the message was handled, or FALSE if not.
  1816. Exception:
  1817. WMX_ACTIVATEPAGE - If called for activation, return of FALSE causes the
  1818. page to be skipped; TRUE causes page to be processed.
  1819. If called for deactivation, return of FALSE causes the
  1820. page not to be deactivated; TRUE causes page to be
  1821. deactivated.
  1822. --*/
  1823. {
  1824. static BOOL Initialized = FALSE;
  1825. static BOOL Skipped = FALSE;
  1826. static HWND List;
  1827. INT Index;
  1828. DWORD Identifier;
  1829. TCHAR NameGroup[MEMDB_MAX];
  1830. TCHAR OrgName[MEMDB_MAX];
  1831. TCHAR NewName[MEMDB_MAX];
  1832. LISTMETRICS ListMetrics;
  1833. INT Tabs[2];
  1834. RECT CategoryRect, CurrentNameRect, NewNameRect;
  1835. INT PixelSpace;
  1836. INT MaxWidth;
  1837. INT MaxColWidth;
  1838. __try {
  1839. switch (uMsg) {
  1840. case WMX_ACTIVATEPAGE:
  1841. if (wParam) {
  1842. if (!UPGRADE() || CANCELLED() || Skipped) {
  1843. return FALSE;
  1844. }
  1845. DEBUGLOGTIME(("Name collision page..."));
  1846. //
  1847. // Determine if there are any incompatible names on the machine
  1848. //
  1849. List = GetDlgItem (hdlg, IDC_NAME_LIST);
  1850. if (!Initialized) {
  1851. CreateNameTables();
  1852. }
  1853. //
  1854. // Skip this page in unattended mode. Also skip this page if there are
  1855. // no incompatible names.
  1856. //
  1857. if (UNATTENDED() || IsIncompatibleNamesTableEmpty() || REPORTONLY()) {
  1858. DEBUGMSG_IF ((IsIncompatibleNamesTableEmpty(), DBG_VERBOSE, "No incompatible names"));
  1859. Initialized = TRUE;
  1860. Skipped = TRUE;
  1861. //
  1862. // This is a workaround for a Win95 Gold bug
  1863. //
  1864. if (ISWIN95_GOLDEN()) {
  1865. PostMessage (hdlg, WMX_WIN95_WORKAROUND, 0, 0);
  1866. return TRUE;
  1867. } else {
  1868. return FALSE;
  1869. }
  1870. }
  1871. if (!Initialized) {
  1872. //
  1873. // Initialize list box
  1874. //
  1875. pUpdateNameCollisionListBox (List, &ListMetrics);
  1876. //
  1877. // Set tab stops
  1878. //
  1879. PixelSpace = pDialogToPixelHorz (hdlg, 8);
  1880. ListMetrics.CategoryWidth += PixelSpace;
  1881. ListMetrics.CurrentNameWidth += PixelSpace;
  1882. MaxWidth = ListMetrics.CategoryWidth +
  1883. ListMetrics.CurrentNameWidth +
  1884. ListMetrics.NewNameWidth;
  1885. MaxColWidth = max (ListMetrics.CategoryWidth, ListMetrics.CurrentNameWidth);
  1886. MaxColWidth = max (MaxColWidth, ListMetrics.NewNameWidth);
  1887. DEBUGMSG_IF ((
  1888. MaxWidth > ListMetrics.TotalWidth,
  1889. DBG_WHOOPS,
  1890. "NameCollisionPage: Text got truncated"
  1891. ));
  1892. Tabs[0] = ListMetrics.TotalWidth / 3;
  1893. if (Tabs[0] < MaxColWidth) {
  1894. Tabs[0] = pPixelToDialogHorz (hdlg, ListMetrics.CategoryWidth);
  1895. Tabs[1] = pPixelToDialogHorz (hdlg, ListMetrics.CurrentNameWidth) + Tabs[0];
  1896. } else {
  1897. Tabs[0] = pPixelToDialogHorz (hdlg, Tabs[0]);
  1898. Tabs[1] = Tabs[0] * 2;
  1899. }
  1900. SendMessage (List, LB_SETTABSTOPS, 2, (LPARAM) Tabs);
  1901. //
  1902. // Adjust titles
  1903. //
  1904. pGetChildWindowRect (GetDlgItem (hdlg, IDC_CATEGORY), &CategoryRect);
  1905. pGetChildWindowRect (GetDlgItem (hdlg, IDC_CURRENTNAME), &CurrentNameRect);
  1906. pGetChildWindowRect (GetDlgItem (hdlg, IDC_NEWNAME), &NewNameRect);
  1907. CurrentNameRect.left = CategoryRect.left + pDialogToPixelHorz (hdlg, Tabs[0]);
  1908. NewNameRect.left = CategoryRect.left + pDialogToPixelHorz (hdlg, Tabs[1]);
  1909. SetWindowPos (
  1910. GetDlgItem (hdlg, IDC_CURRENTNAME),
  1911. NULL,
  1912. CurrentNameRect.left,
  1913. CurrentNameRect.top,
  1914. 0,
  1915. 0,
  1916. SWP_NOSIZE|SWP_NOZORDER
  1917. );
  1918. SetWindowPos (
  1919. GetDlgItem (hdlg, IDC_NEWNAME),
  1920. NULL,
  1921. NewNameRect.left,
  1922. NewNameRect.top,
  1923. 0,
  1924. 0,
  1925. SWP_NOSIZE|SWP_NOZORDER
  1926. );
  1927. EnableDlgItem (hdlg, IDC_CHANGE, FALSE, IDC_NAME_LIST);
  1928. } else {
  1929. pUpdateNameCollisionListBox (List, &ListMetrics);
  1930. }
  1931. //
  1932. // On activate, turn on next and back
  1933. //
  1934. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  1935. Initialized = TRUE;
  1936. // Stop the bill board and make sure the wizard shows again.
  1937. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  1938. } else {
  1939. if (!CANCELLED() && (lParam != PSN_WIZBACK && !WarnAboutBadNames (hdlg))) {
  1940. return FALSE;
  1941. }
  1942. DEBUGLOGTIME(("Name collision page done."));
  1943. }
  1944. return TRUE;
  1945. case WMX_WIN95_WORKAROUND:
  1946. PostMessage (GetParent (hdlg), PSM_PRESSBUTTON, PSBTN_NEXT, 0);
  1947. return TRUE;
  1948. case WM_COMMAND:
  1949. switch (LOWORD (wParam)) {
  1950. case IDC_NAME_LIST:
  1951. switch (HIWORD (wParam)) {
  1952. case LBN_SELCHANGE:
  1953. EnableDlgItem (hdlg, IDC_CHANGE, TRUE, IDC_NAME_LIST);
  1954. return TRUE;
  1955. case LBN_DBLCLK:
  1956. PostMessage (
  1957. hdlg,
  1958. WM_COMMAND,
  1959. MAKELPARAM (IDC_CHANGE, BN_CLICKED),
  1960. (LPARAM) GetDlgItem (hdlg, IDC_CHANGE)
  1961. );
  1962. return TRUE;
  1963. }
  1964. break;
  1965. case IDC_CHANGE:
  1966. if (HIWORD (wParam) == BN_CLICKED) {
  1967. //
  1968. // Get memdb offset stored with list item.
  1969. //
  1970. Index = (INT) SendMessage (List, LB_GETCURSEL, 0, 0);
  1971. MYASSERT (Index != LB_ERR);
  1972. Identifier = (DWORD) SendMessage (List, LB_GETITEMDATA, (WPARAM) Index, 0);
  1973. MYASSERT (Identifier != LB_ERR);
  1974. //
  1975. // Generate names. The original name's value points to the new name.
  1976. //
  1977. GetNamesFromIdentifier (Identifier, NameGroup, OrgName, NewName);
  1978. //
  1979. // Now call dialog to allow the name change
  1980. //
  1981. if (ChangeNameDlg (hdlg, NameGroup, OrgName, NewName)) {
  1982. //
  1983. // The user has chosen to change the name.
  1984. //
  1985. ChangeName (Identifier, NewName);
  1986. pUpdateNameCollisionListBox (List, NULL);
  1987. }
  1988. }
  1989. return TRUE;
  1990. }
  1991. break;
  1992. }
  1993. } __except (1) {
  1994. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Name Collision Page."));
  1995. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  1996. SafeModeExceptionOccured ();
  1997. pAbortSetup (hdlg);
  1998. }
  1999. return FALSE;
  2000. }
  2001. BOOL
  2002. UI_ScanningPageProc (
  2003. IN HWND hdlg,
  2004. IN UINT uMsg,
  2005. IN WPARAM wParam,
  2006. IN LPARAM lParam
  2007. )
  2008. /*++
  2009. Routine Description:
  2010. ScanningPageProc initialiizes the progress bar, starts the report building
  2011. thread, and automatically advances to the next page when the thread completes.
  2012. Arguments:
  2013. hdlg - Handle to the wizard page; its parent is the wizard frame
  2014. uMsg - Message to process
  2015. wParam - Message data
  2016. lParam - Message data
  2017. Return Value:
  2018. TRUE if the message was handled, or FALSE if not.
  2019. Exception:
  2020. WMX_ACTIVATEPAGE - If called for activation, return of FALSE causes the
  2021. page to be skipped; TRUE causes page to be processed.
  2022. If called for deactivation, return of FALSE causes the
  2023. page not to be deactivated; TRUE causes page to be
  2024. deactivated.
  2025. --*/
  2026. {
  2027. DWORD dwThreadId;
  2028. PCTSTR ArgArray[1];
  2029. static BOOL InitSent = FALSE;
  2030. __try {
  2031. switch (uMsg) {
  2032. case WMX_INIT_DIALOG:
  2033. g_WorkerThreadHandle = NULL;
  2034. return TRUE;
  2035. case WMX_ACTIVATEPAGE:
  2036. if (wParam) {
  2037. if (!UPGRADE() || CANCELLED()) {
  2038. return FALSE;
  2039. }
  2040. if (!InitSent) {
  2041. SendMessage (hdlg, WMX_INIT_DIALOG, 0, 0);
  2042. InitSent = TRUE;
  2043. }
  2044. g_Winnt32Wnd = GetParent (hdlg);
  2045. //
  2046. // Block upgrades of Server
  2047. //
  2048. // enable the billboard text if we can.
  2049. // If we could, hide the wizard.
  2050. //
  2051. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)TRUE, 0);
  2052. if (*g_ProductType == NT_SERVER) {
  2053. ArgArray[0] = g_Win95Name;
  2054. ResourceMessageBox (
  2055. g_ParentWnd,
  2056. MSG_SERVER_UPGRADE_UNSUPPORTED_INIT,
  2057. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  2058. ArgArray
  2059. );
  2060. return pAbortSetup (hdlg);
  2061. }
  2062. DEBUGLOGTIME(("File System Scan Wizard Page..."));
  2063. // Make sure background thread is done
  2064. EndCopyThread();
  2065. // On activate, disable next and back
  2066. PropSheet_SetWizButtons (GetParent(hdlg), 0);
  2067. PostMessage (hdlg, WMX_PAGE_VISIBLE, 0, 0);
  2068. //
  2069. // If ReportOnly mode, set a friendly message on this page.
  2070. //
  2071. if (g_ConfigOptions.ReportOnly) {
  2072. PCTSTR reportFileName;
  2073. PCTSTR Args[1];
  2074. PCTSTR string;
  2075. reportFileName = JoinPaths(g_WinDir,S_UPGRADETXT);
  2076. if (reportFileName) {
  2077. Args[0] = (g_ConfigOptions.SaveReportTo && *g_ConfigOptions.SaveReportTo) ? g_ConfigOptions.SaveReportTo : reportFileName;
  2078. string = ParseMessageID(MSG_BUILDING_REPORT_MESSAGE,Args);
  2079. if (string) {
  2080. SetWindowText(GetDlgItem(hdlg,IDC_REPORTNOTE),string);
  2081. }
  2082. FreePathString(reportFileName);
  2083. }
  2084. ELSE_DEBUGMSG((DBG_ERROR,"Not even enough memory for a simple join paths..not good."));
  2085. }
  2086. } else {
  2087. // On terminate, save state
  2088. if (!CANCELLED() && !REPORTONLY()) {
  2089. MemDbSetValue (
  2090. MEMDB_CATEGORY_STATE TEXT("\\") MEMDB_ITEM_MASTER_SEQUENCER,
  2091. g_MasterSequencer
  2092. );
  2093. if (!MemDbSave (UI_GetMemDbDat())) {
  2094. pAbortSetup (hdlg);
  2095. }
  2096. }
  2097. }
  2098. return TRUE;
  2099. case WMX_PAGE_VISIBLE:
  2100. #ifdef PRERELEASE
  2101. //
  2102. // If autostress option enabled, provide dialog
  2103. //
  2104. if (g_ConfigOptions.AutoStress) {
  2105. g_AutoStressHandle = CreateThread (
  2106. NULL,
  2107. 0,
  2108. DoAutoStressDlg,
  2109. NULL,
  2110. 0,
  2111. &dwThreadId
  2112. );
  2113. }
  2114. #endif
  2115. SendMessage(GetParent (hdlg), WMX_BB_ADVANCE_SETUPPHASE, 0, 0);
  2116. // Estimate time required
  2117. UpdateWindow (GetParent (hdlg)); // make sure page is fully painted
  2118. OldProgressProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hdlg, IDC_PROGRESS),GWLP_WNDPROC,(LONG_PTR)NewProgessProc);
  2119. SetupBBProgressText(hdlg, MSG_UPGRADEREPORT_TEXT);
  2120. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_SHOW, 0);
  2121. // Create thread that does the work
  2122. g_WorkerThreadHandle = CreateThread (NULL,
  2123. 0,
  2124. UI_ReportThread,
  2125. (PVOID) hdlg,
  2126. 0,
  2127. &dwThreadId
  2128. );
  2129. break;
  2130. case WMX_REPORT_COMPLETE:
  2131. #ifdef PRERELEASE
  2132. if (g_AutoStressHandle) {
  2133. if (WaitForSingleObject (g_AutoStressHandle, 10) != WAIT_OBJECT_0) {
  2134. PostMessage (hdlg, uMsg, wParam, lParam);
  2135. break;
  2136. }
  2137. CloseHandle (g_AutoStressHandle);
  2138. }
  2139. #endif
  2140. SendMessage(GetParent(hdlg),WMX_SETPROGRESSTEXT,0,0);
  2141. SendMessage(GetParent(hdlg), WMX_BBPROGRESSGAUGE, SW_HIDE, 0);
  2142. SetWindowLongPtr(GetDlgItem(hdlg, IDC_PROGRESS),GWLP_WNDPROC,(LONG_PTR)OldProgressProc );
  2143. if (g_WorkerThreadHandle != NULL) {
  2144. CloseHandle (g_WorkerThreadHandle);
  2145. g_WorkerThreadHandle = NULL;
  2146. }
  2147. if (lParam != ERROR_SUCCESS) {
  2148. // For errors, cancel WINNT32
  2149. if (lParam != ERROR_CANCELLED) {
  2150. LOG ((LOG_ERROR, "Thread running Winnt32 report failed."));
  2151. }
  2152. return pAbortSetup (hdlg);
  2153. }
  2154. else {
  2155. // Automatically move to the next wizard page when done
  2156. PropSheet_PressButton (GetParent (hdlg), PSBTN_NEXT);
  2157. }
  2158. break;
  2159. }
  2160. } __except (1) {
  2161. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Scanning Page."));
  2162. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  2163. SafeModeExceptionOccured ();
  2164. pAbortSetup (hdlg);
  2165. }
  2166. return FALSE;
  2167. }
  2168. BOOL
  2169. pFillListControl (
  2170. IN HWND ListHandle,
  2171. OUT PDWORD SeverityLevel OPTIONAL
  2172. )
  2173. /*++
  2174. Routine Description:
  2175. pFillListControl enumerates all the incompatibility messages and
  2176. fills the message group list box with the root-level components.
  2177. Arguments:
  2178. List - Specifies the list to receive the message group list
  2179. SeverityLevel - Receives an array of REPORTLEVEL_* bits reflecting listview content
  2180. Return Value:
  2181. Returns TRUE if at least one item was added, or FALSE if no items were added.
  2182. --*/
  2183. {
  2184. LISTREPORTENTRY_ENUM e;
  2185. UINT iBullet, iBlocking, iIncompHw, iWarning, iReinstall;
  2186. UINT count = 0;
  2187. PCTSTR listEntries;
  2188. DWORD lowestLevel;
  2189. PCTSTR text;
  2190. SendMessage (ListHandle, LB_RESETCONTENT, 0, 0);
  2191. lowestLevel = (g_ConfigOptions.ShowReport == TRISTATE_PARTIAL) ? REPORTLEVEL_ERROR : REPORTLEVEL_INFORMATION;
  2192. listEntries = CreateReportText (
  2193. FALSE,
  2194. 0,
  2195. lowestLevel,
  2196. TRUE
  2197. );
  2198. if (SeverityLevel) {
  2199. *SeverityLevel = REPORTLEVEL_NONE;
  2200. }
  2201. if (EnumFirstListEntry (&e, listEntries)) {
  2202. HIMAGELIST hIml;
  2203. LV_COLUMN lvc = {0};
  2204. LV_ITEM lvi = {0};
  2205. RECT rect;
  2206. SIZE size;
  2207. DWORD max = 0;
  2208. DWORD cxIcon = GetSystemMetrics (SM_CXSMICON);
  2209. DWORD dwExtra = IMAGE_INDENT + cxIcon + TEXT_INDENT;
  2210. HDC hdc = GetDC (ListHandle);
  2211. HFONT font = GetStockObject (DEFAULT_GUI_FONT);
  2212. HFONT prevFont = NULL;
  2213. HFONT boldFont = NULL;
  2214. LOGFONT lf;
  2215. if (font) {
  2216. GetObject (font, sizeof (lf), &lf);
  2217. lf.lfWeight += FW_BOLD - FW_NORMAL;
  2218. boldFont = CreateFontIndirect (&lf);
  2219. }
  2220. #ifdef LIST_BKGND_BTNFACE_COLOR
  2221. ListView_SetBkColor (ListHandle, GetSysColor (COLOR_BTNFACE));
  2222. #endif
  2223. GetClientRect (ListHandle, &rect);
  2224. lvc.mask = LVCF_WIDTH;
  2225. lvc.cx = rect.right - rect.left - dwExtra;
  2226. ListView_InsertColumn (ListHandle, 0, &lvc);
  2227. hIml = ImageList_Create (
  2228. GetSystemMetrics (SM_CXSMICON),
  2229. GetSystemMetrics (SM_CYSMICON),
  2230. ILC_COLOR | ILC_MASK,
  2231. 4,
  2232. 1
  2233. );
  2234. ListView_SetImageList (ListHandle, hIml, LVSIL_SMALL);
  2235. iBullet = ImageList_AddIcon (hIml, LoadIcon (g_hInst, MAKEINTRESOURCE (IDI_BULLET)));
  2236. iBlocking = ImageList_AddIcon (hIml, LoadIcon (NULL, IDI_ERROR));
  2237. iIncompHw = ImageList_AddIcon (hIml, LoadIcon (g_hInst, MAKEINTRESOURCE (IDI_INCOMPHW)));
  2238. iWarning = ImageList_AddIcon (hIml, LoadIcon (NULL, IDI_WARNING));
  2239. iReinstall = ImageList_AddIcon (hIml, LoadIcon (g_hInst, MAKEINTRESOURCE(IDI_FLOPPY_INSTALL)));
  2240. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_INDENT;
  2241. lvi.stateMask = 0;
  2242. do {
  2243. if (!e.Entry[0]) {
  2244. continue;
  2245. }
  2246. lvi.pszText = (PTSTR)e.Entry;
  2247. lvi.iItem = count;
  2248. lvi.lParam = 0;
  2249. if (e.Header) {
  2250. lvi.iIndent = 0;
  2251. switch (e.Level) {
  2252. case REPORTLEVEL_INFORMATION:
  2253. lvi.iImage = iReinstall;
  2254. break;
  2255. case REPORTLEVEL_WARNING:
  2256. lvi.iImage = iWarning;
  2257. break;
  2258. case REPORTLEVEL_ERROR:
  2259. lvi.iImage = iIncompHw;
  2260. break;
  2261. case REPORTLEVEL_BLOCKING:
  2262. lvi.iImage = iBlocking;
  2263. break;
  2264. default:
  2265. MYASSERT (FALSE);
  2266. lvi.iImage = -1;
  2267. e.Level = REPORTLEVEL_NONE;
  2268. }
  2269. if (SeverityLevel) {
  2270. *SeverityLevel |= e.Level;
  2271. }
  2272. lvi.lParam |= LINEATTR_BOLD;
  2273. } else {
  2274. lvi.iIndent = 1;
  2275. lvi.iImage = iBullet;
  2276. lvi.lParam |= LINEATTR_INDENTED;
  2277. }
  2278. if (ListView_InsertItem (ListHandle, &lvi) != -1) {
  2279. count++;
  2280. if (font) {
  2281. if (lvi.lParam & LINEATTR_BOLD) {
  2282. //
  2283. // draw the text in bold
  2284. //
  2285. if (boldFont) {
  2286. prevFont = SelectObject (hdc, boldFont);
  2287. } else {
  2288. prevFont = SelectObject (hdc, font);
  2289. }
  2290. } else {
  2291. prevFont = SelectObject (hdc, font);
  2292. }
  2293. }
  2294. if (GetTextExtentPoint32 (hdc, e.Entry, lstrlen (e.Entry), &size)) {
  2295. DWORD width = lvi.iIndent * cxIcon + dwExtra + size.cx + TEXT_EXTRA_TAIL_SPACE;
  2296. if (max < width) {
  2297. max = width;
  2298. }
  2299. }
  2300. if (prevFont) {
  2301. SelectObject (hdc, prevFont);
  2302. prevFont = NULL;
  2303. }
  2304. }
  2305. } while (EnumNextListEntry (&e));
  2306. ReleaseDC (ListHandle, hdc);
  2307. if (max > (DWORD)lvc.cx) {
  2308. ListView_SetColumnWidth (ListHandle, 0, max);
  2309. }
  2310. }
  2311. FreeReportText ();
  2312. return count > 0;
  2313. }
  2314. DWORD
  2315. pReviewOrQuitMsgBox(
  2316. IN HWND hDlg,
  2317. IN DWORD dwMsgID
  2318. )
  2319. {
  2320. DWORD rc;
  2321. PCTSTR button1;
  2322. PCTSTR button2;
  2323. PCTSTR message;
  2324. button1 = GetStringResource (MSG_REVIEW_BUTTON);
  2325. button2 = GetStringResource (MSG_QUIT_BUTTON);
  2326. message = GetStringResource (dwMsgID);
  2327. MYASSERT(message && button2 && button1);
  2328. rc = TwoButtonBox (hDlg, message, button1, button2);
  2329. FreeStringResource (button1);
  2330. FreeStringResource (button2);
  2331. FreeStringResource (message);
  2332. return rc;
  2333. }
  2334. BOOL
  2335. pIsBlockingIssue(
  2336. VOID
  2337. )
  2338. {
  2339. return (g_NotEnoughDiskSpace ||
  2340. g_BlockingFileFound ||
  2341. g_BlockingHardwareFound ||
  2342. g_UnknownOs ||
  2343. g_OtherOsExists);
  2344. }
  2345. BOOL
  2346. pShowNotEnoughSpaceMessage(
  2347. IN HWND hDlg
  2348. )
  2349. {
  2350. static bDetermineSpaceUsageReported = FALSE;
  2351. if(REPORTONLY()){
  2352. return TRUE;
  2353. }
  2354. if(!bDetermineSpaceUsageReported){
  2355. bDetermineSpaceUsageReported = TRUE;
  2356. DetermineSpaceUsagePostReport ();
  2357. if(g_NotEnoughDiskSpace){
  2358. if(!UNATTENDED()){
  2359. if(GetNotEnoughSpaceMessage()){
  2360. DiskSpaceDlg(hDlg);
  2361. }
  2362. else{
  2363. MYASSERT (FALSE);
  2364. }
  2365. }
  2366. LOG ((LOG_WARNING, "User cannot continue because there is not enough disk space."));
  2367. return FALSE;
  2368. }
  2369. }
  2370. return TRUE;
  2371. }
  2372. BOOL
  2373. pDoPostReportProcessing (
  2374. HWND hdlg,
  2375. HWND UiTextViewCtrl,
  2376. BOOL WarningGiven,
  2377. PBOOL TurnOffUnattend OPTIONAL
  2378. )
  2379. /*++
  2380. Routine Description:
  2381. pDoPostReportProcessing contains all of the code that needs to be run after
  2382. the report has been generated for the user but before continuing on with
  2383. the upgrade. This includes tasks like checking to make sure there is enough
  2384. disk space, that there aren't files installed that we can't continue with,
  2385. that the user actually looked at the report, etc. This code is run in both
  2386. the attended and unattended case. Make sure your additions are properly
  2387. protected by the unattended flag if needed.
  2388. Arguments:
  2389. hdlg - the dialog window.
  2390. UiTextViewCtrl - The window to the report text.
  2391. WarningGiven - Wether the user has looked at the report or saved it.
  2392. TurnOffUnattend - Wether we should return to attended mode.
  2393. Return Value:
  2394. TRUE if it is ok to proceed with the upgrade, FALSE otherwise.
  2395. --*/
  2396. {
  2397. DWORD rc;
  2398. static BOOL firstTime = TRUE;
  2399. //
  2400. // Make sure we only do these checks once.
  2401. //
  2402. if (!firstTime) {
  2403. return TRUE;
  2404. }
  2405. firstTime = FALSE;
  2406. //
  2407. // If cancelled, no reason to continue.
  2408. //
  2409. if (CANCELLED()) {
  2410. return FALSE;
  2411. }
  2412. //
  2413. // If ReportOnly mode, prepare to get out of setup.
  2414. //
  2415. if (REPORTONLY()) {
  2416. pAbortSetup (hdlg);
  2417. DEBUGMSG ((DBG_NAUSEA, "Report Only mode caused setup to exit!"));
  2418. return FALSE;
  2419. }
  2420. //
  2421. // Make sure there was enough space to continue setup. They have
  2422. // to free it up now, or setup will not continue.
  2423. //
  2424. if(!pShowNotEnoughSpaceMessage(hdlg)){
  2425. pAbortSetup (hdlg);
  2426. return FALSE;
  2427. }
  2428. //
  2429. // Make sure we don't let them continue if they had blocking files on there computer.
  2430. // (Applications that must be uninstalled before we can continue..)
  2431. //
  2432. if (g_BlockingFileFound) {
  2433. if (UNATTENDED()) {
  2434. rc = pReviewOrQuitMsgBox(hdlg, MSG_BLOCKING_FILE_BLOCK_UNATTENDED);
  2435. if (rc == IDBUTTON1) {
  2436. //
  2437. // User wants to review the report.
  2438. //
  2439. g_BlockingFileFound = FALSE;
  2440. if (TurnOffUnattend) {
  2441. *TurnOffUnattend = TRUE;
  2442. }
  2443. return FALSE;
  2444. }
  2445. else {
  2446. //
  2447. // User just wants to cancel.
  2448. //
  2449. pAbortSetup (hdlg);
  2450. DEBUGMSG ((DBG_WARNING, "User cannot continue because of blocking files. Setup is exiting."));
  2451. return FALSE;
  2452. }
  2453. }
  2454. else {
  2455. rc = pReviewOrQuitMsgBox(hdlg, MSG_BLOCKING_FILE_BLOCK);
  2456. if(rc != IDBUTTON1){
  2457. pAbortSetup (hdlg);
  2458. }
  2459. else{
  2460. firstTime = TRUE;
  2461. }
  2462. DEBUGMSG ((DBG_WARNING, "User cannot continue because of blocking files. Setup is exiting."));
  2463. return FALSE;
  2464. }
  2465. }
  2466. //
  2467. // Make sure we don't let them continue if they had blocking files on there computer.
  2468. // (Applications that must be uninstalled before we can continue..)
  2469. //
  2470. if (g_BlockingHardwareFound) {
  2471. if (UNATTENDED()) {
  2472. rc = pReviewOrQuitMsgBox(hdlg, MSG_BLOCKING_HARDWARE_BLOCK_UNATTENDED);
  2473. if (rc == IDBUTTON1) {
  2474. //
  2475. // User wants to review the report.
  2476. //
  2477. g_BlockingHardwareFound = FALSE;
  2478. if (TurnOffUnattend) {
  2479. *TurnOffUnattend = TRUE;
  2480. }
  2481. return FALSE;
  2482. }
  2483. else {
  2484. //
  2485. // User just wants to cancel.
  2486. //
  2487. pAbortSetup (hdlg);
  2488. DEBUGMSG ((DBG_WARNING, "User cannot continue because of blocking files. Setup is exiting."));
  2489. return FALSE;
  2490. }
  2491. }
  2492. else {
  2493. rc = pReviewOrQuitMsgBox(hdlg, MSG_BLOCKING_HARDWARE_BLOCK);
  2494. if(rc != IDBUTTON1){
  2495. pAbortSetup (hdlg);
  2496. }
  2497. else{
  2498. firstTime = TRUE;
  2499. }
  2500. DEBUGMSG ((DBG_WARNING, "User cannot continue because of blocking files. Setup is exiting."));
  2501. return FALSE;
  2502. }
  2503. }
  2504. //
  2505. // Make sure we don't let them continue if they had an unknown OS version. Block setup.
  2506. //
  2507. if (g_UnknownOs) {
  2508. if(UNATTENDED()){
  2509. rc = OkBox (hdlg, MSG_UNKNOWN_OS);
  2510. pAbortSetup (hdlg);
  2511. }
  2512. else{
  2513. rc = pReviewOrQuitMsgBox(hdlg, MSG_UNKNOWN_OS);
  2514. if(rc != IDBUTTON1){
  2515. pAbortSetup (hdlg);
  2516. }
  2517. else{
  2518. firstTime = TRUE;
  2519. }
  2520. }
  2521. DEBUGMSG ((DBG_WARNING, "User cannot continue because his OS version is unsupported. Setup is exiting."));
  2522. return FALSE;
  2523. }
  2524. if (g_OtherOsExists) {
  2525. //
  2526. // If this is non-empty, we need to block them from upgrading.
  2527. //
  2528. if(UNATTENDED()){
  2529. OkBox (hdlg, MSG_OTHER_OS_FOUND_POPUP);
  2530. pAbortSetup (hdlg);
  2531. }
  2532. else{
  2533. rc = pReviewOrQuitMsgBox(hdlg, MSG_OTHER_OS_FOUND_POPUP);
  2534. if(rc != IDBUTTON1){
  2535. pAbortSetup (hdlg);
  2536. }
  2537. else{
  2538. firstTime = TRUE;
  2539. }
  2540. }
  2541. DEBUGMSG ((DBG_WARNING, "User cannot continue because he has another OS installed. Setup is exiting."));
  2542. return FALSE;
  2543. }
  2544. //
  2545. // Make sure you put code that needs to run only in the ATTENDED case in the block below.
  2546. //
  2547. if (!UNATTENDED()) {
  2548. //
  2549. // If the user has some app that must be uninstalled before upgrading, make
  2550. // sure that we warn them about the problem.
  2551. //
  2552. if (g_BlockingAppFound) {
  2553. WarningGiven = TRUE;
  2554. rc = SoftBlockDlg (hdlg);
  2555. if (rc == IDNO) {
  2556. DEBUGMSG ((DBG_WARNING, "User wants to uninstall the apps!"));
  2557. return pAbortSetup (hdlg);
  2558. }
  2559. if (rc == IDCANCEL) {
  2560. return FALSE;
  2561. }
  2562. MYASSERT (rc == IDOK);
  2563. }
  2564. if (!WarningGiven) {
  2565. //
  2566. // No popup if (A) the user scrolled all the way through, or
  2567. // (B) the user saved/printed the report
  2568. //
  2569. if (SendMessage (UiTextViewCtrl, WMX_ALL_LINES_PAINTED, 0, 0)) {
  2570. WarningGiven = TRUE;
  2571. }
  2572. }
  2573. if (!WarningGiven) {
  2574. WarningGiven = TRUE;
  2575. rc = WarningDlg (hdlg);
  2576. if (rc == IDNO) {
  2577. DEBUGMSG ((DBG_WARNING, "User doesn't like incompatibilities!"));
  2578. return pAbortSetup (hdlg);
  2579. }
  2580. if (rc == IDCANCEL) {
  2581. return FALSE;
  2582. }
  2583. MYASSERT (rc == IDOK);
  2584. }
  2585. //
  2586. // last thing: warn them if there are any incompatible devices
  2587. //
  2588. if (g_IncompatibleDevicesWarning) {
  2589. g_IncompatibleDevicesWarning = FALSE;
  2590. rc = IncompatibleDevicesDlg (hdlg);
  2591. if (rc == IDOK) {
  2592. //
  2593. // switch to Detailed report view
  2594. //
  2595. if (IsWindowVisible (GetDlgItem (hdlg, IDC_DETAILS))) {
  2596. PostMessage (hdlg, WM_COMMAND, MAKELONG (IDC_DETAILS, BN_CLICKED), 0);
  2597. }
  2598. return FALSE;
  2599. }
  2600. if (rc == IDNO) {
  2601. DEBUGMSG ((DBG_WARNING, "User doesn't like hardware incompatibilities!"));
  2602. return pAbortSetup (hdlg);
  2603. }
  2604. MYASSERT (rc == IDYES);
  2605. }
  2606. }
  2607. //
  2608. // Don't continue if there are blocking issues
  2609. //
  2610. if (AreThereAnyBlockingIssues()) {
  2611. return pAbortSetup (hdlg);
  2612. }
  2613. return TRUE;
  2614. }
  2615. BOOL
  2616. pMeasureItemHeight (
  2617. INT* ItemHeight
  2618. )
  2619. {
  2620. static INT g_ItemHeight = 0;
  2621. TEXTMETRIC tm;
  2622. HFONT font;
  2623. HDC hdc;
  2624. BOOL b = FALSE;
  2625. if (!g_ItemHeight) {
  2626. font = GetStockObject (DEFAULT_GUI_FONT);
  2627. if (font) {
  2628. hdc = GetDC (NULL);
  2629. if (hdc) {
  2630. HFONT hFontPrev = SelectObject (hdc, font);
  2631. GetTextMetrics (hdc, &tm);
  2632. g_ItemHeight = max (tm.tmHeight, GetSystemMetrics (SM_CYSMICON));
  2633. SelectObject (hdc, hFontPrev);
  2634. ReleaseDC (NULL, hdc);
  2635. }
  2636. }
  2637. }
  2638. if (g_ItemHeight) {
  2639. *ItemHeight = g_ItemHeight;
  2640. b = TRUE;
  2641. }
  2642. return b;
  2643. }
  2644. BOOL
  2645. UI_ResultsPageProc (
  2646. IN HWND hdlg,
  2647. IN UINT uMsg,
  2648. IN WPARAM wParam,
  2649. IN LPARAM lParam
  2650. )
  2651. /*++
  2652. Routine Description:
  2653. UI_ResultsPageProc is the wizard window procedure that is called to
  2654. present the incompatibility report. This procedure fills in a
  2655. list control with all root incompatibility components. When the user
  2656. clicks Full Report, a dialog appears displaying the complete report
  2657. text.
  2658. Arguments:
  2659. hdlg - Specifies the dialog handle
  2660. uMsg - Specifies the message to process
  2661. wParam - Specifies the wParam data associated with the message
  2662. lParam - Specifies the lParam data associated with the message
  2663. Return Value:
  2664. WMX_ACTIVATEPAGE: On activation (wParam is TRUE), returns FALSE if
  2665. page is to be skipped; returns TRUE if page is
  2666. to be processed.
  2667. On deactivation (wParam is FALSE), returns FALSE
  2668. if the page is not to be deactivated; returns
  2669. TRUE if the page is to be deactivated.
  2670. WM_NOTIFY: Returns FALSE
  2671. WM_COMMAND: Returns TRUE if command is processed; FALSE if
  2672. command is not processed.
  2673. Others: Returns FALSE.
  2674. --*/
  2675. {
  2676. static BOOL Initialized;
  2677. PCTSTR Msg;
  2678. static BOOL WarningGiven = TRUE;
  2679. static HWND UiTextViewCtrl;
  2680. static BOOL TurnOffUnattend = FALSE;
  2681. static HWND g_RestoreParent = NULL;
  2682. PCTSTR FinishText;
  2683. BOOL bUiReportEmpty;
  2684. DWORD severityLevel;
  2685. HWND listHandle, listHeaderText;
  2686. HWND thisBtn, otherBtn;
  2687. RECT rect;
  2688. HFONT font, boldFont, prevFont;
  2689. LOGFONT lf;
  2690. DWORD lowestLevel;
  2691. TCHAR textBuf[96];
  2692. SYSTEMTIME currentTime;
  2693. HKEY key;
  2694. PCTSTR ArgArray[1];
  2695. __try {
  2696. switch (uMsg) {
  2697. case WMX_ACTIVATEPAGE:
  2698. if (wParam) {
  2699. if (!UPGRADE() || CANCELLED()) {
  2700. return FALSE;
  2701. }
  2702. DEBUGLOGTIME(("Results Wizard Page..."));
  2703. if (!Initialized) {
  2704. Initialized = TRUE;
  2705. TurnOnWaitCursor ();
  2706. //
  2707. // Convert message manager struct into report items
  2708. //
  2709. MsgMgr_Resolve ();
  2710. if(TRISTATE_NO == g_ConfigOptions.ShowReport && AreThereAnyBlockingIssues()){
  2711. g_ConfigOptions.ShowReport = TRISTATE_PARTIAL;
  2712. }
  2713. //
  2714. // switch button text if necessary, update static text
  2715. //
  2716. if (g_ConfigOptions.ShowReport == TRISTATE_PARTIAL) {
  2717. Msg = GetStringResource (MSG_FULL_REPORT_BUTTON);
  2718. SetDlgItemText (hdlg, IDC_DETAILS, Msg);
  2719. FreeStringResource (Msg);
  2720. Msg = GetStringResource (MSG_FULL_REPORT_TEXT);
  2721. SetDlgItemText (hdlg, IDC_REPORT_HEADER, Msg);
  2722. FreeStringResource (Msg);
  2723. }
  2724. //
  2725. // save the report in config.dmp now
  2726. //
  2727. SaveConfigurationForBeta ();
  2728. //
  2729. // If SaveReportTo was specified in our unattend parameters, then
  2730. // save the reports there now.
  2731. //
  2732. if (g_ConfigOptions.SaveReportTo && *g_ConfigOptions.SaveReportTo) {
  2733. //
  2734. // Save reports.
  2735. //
  2736. if (!SaveReport (NULL, g_ConfigOptions.SaveReportTo)) {
  2737. DEBUGMSG((DBG_WARNING,"SaveReport failed."));
  2738. }
  2739. }
  2740. //
  2741. // In all cases, we save it to the windows directory unconditionally.
  2742. //
  2743. if (!SaveReport (NULL, g_WinDir)) {
  2744. DEBUGMSG((DBG_WARNING,"SaveReport failed."));
  2745. } else {
  2746. DEBUGMSG ((DBG_VERBOSE, "Report saved to %s", g_WinDir));
  2747. //
  2748. // In report only mode, output the current time, so
  2749. // the report is skipped in normal setup
  2750. //
  2751. if (REPORTONLY()) {
  2752. GetSystemTime (&currentTime);
  2753. key = CreateRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"));
  2754. if (key) {
  2755. RegSetValueEx (
  2756. key,
  2757. TEXT("LastReportTime"),
  2758. 0,
  2759. REG_BINARY,
  2760. (PBYTE) (&currentTime),
  2761. sizeof (currentTime)
  2762. );
  2763. CloseRegKey (key);
  2764. }
  2765. }
  2766. }
  2767. TurnOffWaitCursor ();
  2768. if (g_ConfigOptions.ShowReport == TRISTATE_NO) {
  2769. return FALSE;
  2770. }
  2771. //
  2772. // Prepare page for display
  2773. //
  2774. SendMessage (hdlg, DM_SETDEFID, IDOK, 0);
  2775. UiTextViewCtrl = GetDlgItem (hdlg, IDC_PLACEHOLDER);
  2776. MYASSERT (UiTextViewCtrl);
  2777. g_TextViewInDialog = UiTextViewCtrl;
  2778. SetFocus (UiTextViewCtrl);
  2779. //
  2780. // Prepare output text
  2781. //
  2782. Msg = CreateReportText (
  2783. TRUE,
  2784. 0,
  2785. REPORTLEVEL_VERBOSE,
  2786. FALSE
  2787. );
  2788. if (Msg) {
  2789. AddStringToTextView (UiTextViewCtrl, Msg);
  2790. }
  2791. FreeReportText ();
  2792. }
  2793. // Enable next
  2794. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  2795. // Fill in list view control
  2796. bUiReportEmpty = TRUE;
  2797. severityLevel = REPORTLEVEL_NONE;
  2798. listHandle = GetDlgItem (hdlg, IDC_ROOT_LIST);
  2799. if (listHandle) {
  2800. bUiReportEmpty = !pFillListControl (listHandle, &severityLevel);
  2801. }
  2802. //
  2803. // If unattended mode, skip page.
  2804. // Also skip it if the report is empty
  2805. //
  2806. if (*g_UnattendSwitchSpecified && !g_ConfigOptions.PauseAtReport ||
  2807. !REPORTONLY() && bUiReportEmpty
  2808. ) {
  2809. if (g_ConfigOptions.ReportOnly) {
  2810. *g_AbortFlagPtr = TRUE;
  2811. PostMessage (GetParent (hdlg), PSM_PRESSBUTTON, PSBTN_NEXT, 0);
  2812. }
  2813. else {
  2814. //
  2815. // ***DO NOT*** put code here, put it in pDoPostReportProcessing instead.
  2816. //
  2817. pDoPostReportProcessing (hdlg, UiTextViewCtrl, WarningGiven, &TurnOffUnattend);
  2818. //
  2819. // if TurnOffUnattend was set, this means we want to cancel the upgrade, but give the
  2820. // user a chance to check out the report.
  2821. //
  2822. if (TurnOffUnattend) {
  2823. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  2824. return TRUE;
  2825. }
  2826. else {
  2827. return FALSE;
  2828. }
  2829. }
  2830. }
  2831. //
  2832. // If ReportOnly mode, turn on Finish button
  2833. //
  2834. if (REPORTONLY()) {
  2835. FinishText = GetStringResource (MSG_FINISH);
  2836. if (FinishText) {
  2837. EnableWindow (GetDlgItem(GetParent(hdlg),IDCANCEL), FALSE);
  2838. SetWindowText (GetDlgItem(GetParent(hdlg), PROPSHEET_NEXT_BUTTON_ID), FinishText);
  2839. FreeStringResource (FinishText);
  2840. }
  2841. if (*g_UnattendSwitchSpecified) {
  2842. PostMessage (GetParent (hdlg), PSM_PRESSBUTTON, PSBTN_NEXT, 0);
  2843. } //
  2844. } else {
  2845. //
  2846. // check if any incompatible hardware is displayed in the report
  2847. //
  2848. g_IncompatibleDevicesWarning = IsIncompatibleHardwarePresent();
  2849. }
  2850. // Stop the bill board and make sure the wizard shows again.
  2851. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  2852. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  2853. if(pIsBlockingIssue()){
  2854. FinishText = GetStringResource (MSG_FINISH);
  2855. if(FinishText){
  2856. SetWindowText(GetDlgItem(GetParent(hdlg), PROPSHEET_NEXT_BUTTON_ID), FinishText);
  2857. FreeStringResource (FinishText);
  2858. }
  2859. }
  2860. if (bUiReportEmpty) {
  2861. //
  2862. // if the list report is empty, only show the detailed report
  2863. // switch view first
  2864. //
  2865. SendMessage (hdlg, WM_COMMAND, MAKELONG (IDC_DETAILS, BN_CLICKED), 0);
  2866. //
  2867. // then disable and hide both buttons
  2868. //
  2869. EnableWindow (GetDlgItem (hdlg, IDC_DETAILS), FALSE);
  2870. EnableWindow (GetDlgItem (hdlg, IDC_HIDEDETAILS), FALSE);
  2871. ShowWindow (GetDlgItem (hdlg, IDC_DETAILS), SW_HIDE);
  2872. ShowWindow (GetDlgItem (hdlg, IDC_HIDEDETAILS), SW_HIDE);
  2873. } else {
  2874. //
  2875. // set the proper List header based on severity of content
  2876. //
  2877. MYASSERT (severityLevel != REPORTLEVEL_NONE);
  2878. if (severityLevel & REPORTLEVEL_BLOCKING) {
  2879. //
  2880. // need to update the default header (which is set for "Warnings")
  2881. //
  2882. if (g_ConfigOptions.ShowReport == TRISTATE_PARTIAL) {
  2883. Msg = GetStringResource (MSG_REPORT_HEADER_BLOCKING_ISSUES_SHORT);
  2884. } else {
  2885. Msg = GetStringResource (MSG_REPORT_HEADER_BLOCKING_ISSUES);
  2886. }
  2887. listHeaderText = GetDlgItem (hdlg, IDC_REPORT_HEADER);
  2888. SetDlgItemText (hdlg, IDC_REPORT_HEADER, Msg);
  2889. FreeStringResource (Msg);
  2890. }
  2891. //
  2892. // now set text attributes (bold, color etc)
  2893. //
  2894. font = (HFONT)SendDlgItemMessage (
  2895. hdlg,
  2896. IDC_REPORT_HEADER,
  2897. WM_GETFONT,
  2898. 0,
  2899. 0
  2900. );
  2901. if (!font) {
  2902. font = GetStockObject (SYSTEM_FONT);
  2903. }
  2904. if (font) {
  2905. //
  2906. // draw the text in bold
  2907. //
  2908. GetObject (font, sizeof (lf), &lf);
  2909. lf.lfWeight += FW_BOLD - FW_NORMAL;
  2910. boldFont = CreateFontIndirect (&lf);
  2911. if (boldFont) {
  2912. font = (HFONT)SendDlgItemMessage (
  2913. hdlg,
  2914. IDC_REPORT_HEADER,
  2915. WM_SETFONT,
  2916. (WPARAM)boldFont,
  2917. MAKELONG (FALSE, 0)
  2918. );
  2919. }
  2920. }
  2921. }
  2922. }
  2923. else {
  2924. //
  2925. // In all cases, we save it to the windows directory unconditionally.
  2926. //
  2927. if (!SaveReport (NULL, g_WinDir)) {
  2928. DEBUGMSG((DBG_WARNING,"SaveReport failed."));
  2929. }
  2930. if (g_UIQuitSetup) {
  2931. //
  2932. // quit setup for a specific reason
  2933. //
  2934. pAbortSetup (hdlg);
  2935. return TRUE;
  2936. }
  2937. if (TurnOffUnattend) {
  2938. //
  2939. // We turned off unattend earlier so that the user could view the report. Now exit setup.
  2940. //
  2941. pAbortSetup (hdlg);
  2942. return TRUE;
  2943. }
  2944. //
  2945. // ***DO NOT*** put code here, put it in pDoPostReportProcessing instead.
  2946. //
  2947. if (!CANCELLED()) {
  2948. return pDoPostReportProcessing (hdlg, UiTextViewCtrl, WarningGiven, NULL);
  2949. }
  2950. else {
  2951. return TRUE;
  2952. }
  2953. }
  2954. return TRUE;
  2955. case WM_MEASUREITEM:
  2956. {
  2957. LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT)lParam;
  2958. return pMeasureItemHeight (&mis->itemHeight);
  2959. }
  2960. case WM_DRAWITEM:
  2961. {
  2962. LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
  2963. if (dis->itemAction == ODA_DRAWENTIRE) {
  2964. if (dis->itemID != -1) {
  2965. TCHAR text[MAX_LISTVIEW_TEXT];
  2966. LVITEM lvi;
  2967. boldFont = NULL;
  2968. prevFont = NULL;
  2969. ZeroMemory (&lvi, sizeof (lvi));
  2970. lvi.iItem = dis->itemID;
  2971. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_INDENT;
  2972. lvi.pszText = text;
  2973. lvi.cchTextMax = MAX_LISTVIEW_TEXT;
  2974. if (ListView_GetItem (dis->hwndItem, &lvi)) {
  2975. INT xStart, yStart;
  2976. HIMAGELIST hImgList;
  2977. INT itemHeight;
  2978. SIZE size;
  2979. xStart = dis->rcItem.left + IMAGE_INDENT;
  2980. yStart = dis->rcItem.top;
  2981. if (pMeasureItemHeight (&itemHeight)) {
  2982. font = GetStockObject (DEFAULT_GUI_FONT);
  2983. if (font) {
  2984. if (lvi.lParam & LINEATTR_BOLD) {
  2985. //
  2986. // draw the text in bold
  2987. //
  2988. GetObject (font, sizeof (lf), &lf);
  2989. lf.lfWeight += FW_BOLD - FW_NORMAL;
  2990. boldFont = CreateFontIndirect (&lf);
  2991. if (boldFont) {
  2992. prevFont = SelectObject (dis->hDC, boldFont);
  2993. } else {
  2994. prevFont = SelectObject (dis->hDC, font);
  2995. }
  2996. } else {
  2997. prevFont = SelectObject (dis->hDC, font);
  2998. }
  2999. }
  3000. SetTextColor (
  3001. dis->hDC,
  3002. lvi.lParam & LINEATTR_ALTCOLOR ? RGB (255, 0, 0) : GetSysColor (COLOR_WINDOWTEXT)
  3003. );
  3004. if (lvi.lParam & LINEATTR_INDENTED) {
  3005. xStart += GetSystemMetrics (SM_CXSMICON);
  3006. }
  3007. hImgList = ListView_GetImageList (dis->hwndItem, LVSIL_SMALL);
  3008. ImageList_Draw (hImgList, lvi.iImage, dis->hDC, xStart, yStart, ILD_TRANSPARENT);
  3009. xStart += GetSystemMetrics (SM_CXSMICON) + TEXT_INDENT;
  3010. GetTextExtentPoint32 (dis->hDC, text, lstrlen (text), &size);
  3011. if (itemHeight > size.cy) {
  3012. yStart += (itemHeight - size.cy + 1) / 2;
  3013. }
  3014. TextOut (dis->hDC, xStart, yStart, text, lstrlen (text));
  3015. if (prevFont) {
  3016. SelectObject (dis->hDC, prevFont);
  3017. }
  3018. if (boldFont) {
  3019. DeleteObject (boldFont);
  3020. }
  3021. }
  3022. }
  3023. } else {
  3024. return FALSE;
  3025. }
  3026. }
  3027. return TRUE;
  3028. }
  3029. case WM_NOTIFY:
  3030. if (wParam == IDC_ROOT_LIST) {
  3031. LPNMHDR hdr = (LPNMHDR)lParam;
  3032. if (hdr->code == NM_DBLCLK) {
  3033. //
  3034. // act just like IDC_DETAILS
  3035. //
  3036. SendMessage (hdlg, WM_COMMAND, MAKELONG (IDC_DETAILS, BN_CLICKED), 0);
  3037. }
  3038. }
  3039. break;
  3040. case WM_COMMAND:
  3041. switch (LOWORD (wParam)) {
  3042. case IDC_SAVE_AS:
  3043. if (HIWORD (wParam) == BN_CLICKED) {
  3044. SaveReport (hdlg, NULL);
  3045. WarningGiven = TRUE;
  3046. g_IncompatibleDevicesWarning = FALSE;
  3047. }
  3048. return TRUE;
  3049. case IDC_PRINT:
  3050. if (HIWORD (wParam) == BN_CLICKED) {
  3051. PrintReport (hdlg, REPORTLEVEL_VERBOSE);
  3052. WarningGiven = TRUE;
  3053. g_IncompatibleDevicesWarning = FALSE;
  3054. }
  3055. return TRUE;
  3056. case IDC_DETAILS:
  3057. case IDC_HIDEDETAILS:
  3058. if (HIWORD (wParam) == BN_CLICKED) {
  3059. BOOL bShowDetails = LOWORD (wParam) == IDC_DETAILS;
  3060. BOOL bSetFocus;
  3061. listHandle = GetDlgItem (hdlg, IDC_ROOT_LIST);
  3062. listHeaderText = GetDlgItem (hdlg, IDC_REPORT_HEADER);
  3063. UiTextViewCtrl = GetDlgItem (hdlg, IDC_PLACEHOLDER);
  3064. thisBtn = GetDlgItem (hdlg, LOWORD (wParam));
  3065. otherBtn = GetDlgItem (hdlg, bShowDetails ? IDC_HIDEDETAILS : IDC_DETAILS);
  3066. MYASSERT (listHandle && listHeaderText && UiTextViewCtrl && thisBtn && otherBtn);
  3067. if (listHandle && listHeaderText && UiTextViewCtrl && thisBtn && otherBtn) {
  3068. MYASSERT (!IsWindowVisible (bShowDetails ? UiTextViewCtrl : listHandle));
  3069. MYASSERT (!IsWindowVisible (otherBtn));
  3070. bSetFocus = GetFocus () == thisBtn;
  3071. ShowWindow (UiTextViewCtrl, bShowDetails ? SW_SHOW : SW_HIDE);
  3072. ShowWindow (listHandle, bShowDetails ? SW_HIDE : SW_SHOW);
  3073. ShowWindow (listHeaderText, bShowDetails ? SW_HIDE : SW_SHOW);
  3074. if (GetWindowRect (thisBtn, &rect)) {
  3075. ScreenToClient (hdlg, (LPPOINT)&rect.left);
  3076. ScreenToClient (hdlg, (LPPOINT)&rect.right);
  3077. MoveWindow (otherBtn, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, FALSE);
  3078. }
  3079. ShowWindow (otherBtn, SW_SHOW);
  3080. ShowWindow (thisBtn, SW_HIDE);
  3081. if (bSetFocus) {
  3082. SetFocus (otherBtn);
  3083. }
  3084. g_IncompatibleDevicesWarning = FALSE;
  3085. }
  3086. }
  3087. return TRUE;
  3088. }
  3089. break;
  3090. case WMX_RESTART_SETUP:
  3091. //
  3092. // some control determined that the user took some action
  3093. // that requires setup to terminate at this point
  3094. // wParam indicates if setup should terminate right away (if TRUE)
  3095. // or if it will terminate when user presses Next (if FALSE)
  3096. //
  3097. if (wParam) {
  3098. pAbortSetup (hdlg);
  3099. } else {
  3100. g_UIQuitSetup = TRUE;
  3101. if (lParam) {
  3102. //
  3103. // the billboard window should be made invisible,
  3104. // so the user can see the whole screen
  3105. //
  3106. HWND hwndWizard = GetParent(hdlg);
  3107. HWND hwndBillboard = GetParent(hwndWizard);
  3108. if (hwndBillboard && IsWindowVisible (hwndBillboard)) {
  3109. SetParent (hwndWizard, NULL);
  3110. ShowWindow (hwndBillboard, SW_HIDE);
  3111. g_RestoreParent = hwndBillboard;
  3112. }
  3113. }
  3114. }
  3115. break;
  3116. case WMX_NEXTBUTTON:
  3117. if (g_RestoreParent) {
  3118. //
  3119. // restore the old parent relationship, so things work as expected
  3120. //
  3121. HWND hwndWizard = GetParent(hdlg);
  3122. if (hwndWizard) {
  3123. DWORD style;
  3124. ShowWindow (g_RestoreParent, SW_SHOW);
  3125. g_RestoreParent = NULL;
  3126. SetForegroundWindow (hwndWizard);
  3127. }
  3128. }
  3129. break;
  3130. default:
  3131. break;
  3132. }
  3133. } __except (1) {
  3134. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Results Page."));
  3135. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  3136. SafeModeExceptionOccured ();
  3137. pAbortSetup (hdlg);
  3138. }
  3139. return FALSE;
  3140. }
  3141. //
  3142. //Backup Local Functions
  3143. //
  3144. BOOL
  3145. GetListOfNonRemovableDrivesWithAvailableSpace(
  3146. OUT PCHAR DriveLetterArray,
  3147. OUT PUINT NumberOfDrives,
  3148. IN UINT SizeOfArrays
  3149. )
  3150. {
  3151. UINT LogicalDrives;
  3152. CHAR DriveName[] = "?:\\";
  3153. ULARGE_INTEGER FreeBytesAvailable;
  3154. ULARGE_INTEGER TotalNumberOfBytes;
  3155. ULARGE_INTEGER TotalNumberOfFreeBytes;
  3156. UINT i;
  3157. if(!DriveLetterArray || !NumberOfDrives) {
  3158. return FALSE;
  3159. }
  3160. if(!(LogicalDrives = GetLogicalDrives())) {
  3161. return FALSE;
  3162. }
  3163. *NumberOfDrives = 0;
  3164. for(i = 0; LogicalDrives && ((*NumberOfDrives) < SizeOfArrays); LogicalDrives >>= 1, i++){
  3165. if(LogicalDrives&1) {
  3166. DriveName[0] = 'A' + (char)i;
  3167. if(DRIVE_FIXED != GetDriveType(DriveName)) {
  3168. continue;
  3169. }
  3170. *DriveLetterArray++ = DriveName[0];
  3171. (*NumberOfDrives)++;
  3172. }
  3173. }
  3174. return TRUE;
  3175. }
  3176. BOOL
  3177. IsBackUpPossible(
  3178. OUT PCHAR DriveLetterArray, OPTIONAL
  3179. OUT PULARGE_INTEGER AvailableSpaceOut, OPTIONAL
  3180. OUT PUINT NumberOfDrivesOut, OPTIONAL
  3181. OUT PBOOL IsPossibleBackupWithoutCompression, OPTIONAL
  3182. IN UINT SizeOfArrays OPTIONAL
  3183. )
  3184. {
  3185. CHAR Drives[MAX_NUMBER_OF_DRIVES];
  3186. UINT NumberOfDrives = 0;
  3187. UINT NumberAvailableDrives;
  3188. UINT i;
  3189. ULARGE_INTEGER finalFreeSpace;
  3190. BOOL Result;
  3191. TCHAR rootPath[] = TEXT("?:\\");
  3192. INT BackupDiskPadding;
  3193. ULARGE_INTEGER BackupDiskSpacePaddingInBytes;
  3194. BOOL IsExceedMaxSize = FALSE;
  3195. if(g_SpaceNeededForSlowBackup.QuadPart >= MAX_BACKUP_IMAGE_SIZE_FOR_BACKUP){
  3196. return FALSE;
  3197. }
  3198. //
  3199. // Now find a place for the backup
  3200. //
  3201. if(!GetListOfNonRemovableDrivesWithAvailableSpace(
  3202. Drives,
  3203. &NumberOfDrives,
  3204. ARRAYSIZE(Drives))) {
  3205. return FALSE;
  3206. }
  3207. if(IsPossibleBackupWithoutCompression){
  3208. if(g_ConfigOptions.DisableCompression == TRISTATE_REQUIRED) {
  3209. BackupDiskSpacePaddingInBytes.QuadPart = 0;
  3210. }
  3211. else{
  3212. if(GetUninstallMetrics(NULL, NULL, &BackupDiskPadding)) {
  3213. BackupDiskSpacePaddingInBytes.QuadPart = BackupDiskPadding;
  3214. BackupDiskSpacePaddingInBytes.QuadPart <<= 20;
  3215. }
  3216. else {
  3217. BackupDiskSpacePaddingInBytes.QuadPart = NESSESSARY_DISK_SPACE_TO_BACKUP_UNCOMPRESSED;
  3218. }
  3219. }
  3220. }
  3221. DEBUGMSG((DBG_VERBOSE, "Available %d NonRemovable Drives/Space:", NumberOfDrives));
  3222. if(g_SpaceNeededForFastBackup.QuadPart >= MAX_BACKUP_IMAGE_SIZE_FOR_BACKUP){
  3223. IsExceedMaxSize = TRUE;
  3224. }
  3225. else{
  3226. IsExceedMaxSize = FALSE;
  3227. }
  3228. for (NumberAvailableDrives = 0, Result = FALSE, i = 0; i < NumberOfDrives; i++) {
  3229. rootPath[0] = Drives[i];
  3230. DEBUGMSG ((DBG_VERBOSE, "QuerySpace:%I64i vs SpaceForSlowBackup:%I64i", QuerySpace (rootPath), (LONGLONG) g_SpaceNeededForSlowBackup.QuadPart));
  3231. if (QuerySpace (rootPath) > (LONGLONG) g_SpaceNeededForSlowBackup.QuadPart) {
  3232. Result = TRUE;
  3233. NumberAvailableDrives++;
  3234. if (IsPossibleBackupWithoutCompression != NULL) {
  3235. if (QuerySpace (rootPath) > (LONGLONG) (g_SpaceNeededForFastBackup.QuadPart +
  3236. BackupDiskSpacePaddingInBytes.QuadPart) &&
  3237. !IsExceedMaxSize) {
  3238. *IsPossibleBackupWithoutCompression++ = TRUE;
  3239. DEBUGMSG ((DBG_VERBOSE, "Backup is possible without compression on drive %c", Drives[i]));
  3240. } else {
  3241. *IsPossibleBackupWithoutCompression++ = FALSE;
  3242. DEBUGMSG ((DBG_VERBOSE, "Uncompresed backup is NOT possible on drive %c", Drives[i]));
  3243. }
  3244. }
  3245. if (SizeOfArrays > NumberAvailableDrives) {
  3246. if (DriveLetterArray) {
  3247. *DriveLetterArray++ = Drives[i];
  3248. }
  3249. if(AvailableSpaceOut) {
  3250. AvailableSpaceOut->QuadPart = QuerySpace (rootPath);
  3251. AvailableSpaceOut++;
  3252. }
  3253. }
  3254. }
  3255. }
  3256. if (NumberOfDrivesOut) {
  3257. *NumberOfDrivesOut = NumberAvailableDrives;
  3258. }
  3259. return Result;
  3260. }
  3261. PTSTR
  3262. pConstructPathForBackup(
  3263. IN TCHAR DriveLetter
  3264. )
  3265. {
  3266. static TCHAR pathForBackup[MAX_PATH];
  3267. WIN32_FIND_DATA win32FindData;
  3268. HANDLE handleOfDir;
  3269. INT i;
  3270. for(i = 0; i < MAX_AMOUNT_OF_TIME_TO_TRY_CONSTRUCT_UNDO_DIR; i++){
  3271. wsprintf(pathForBackup, i? TEXT("%c:\\undo%d"): TEXT("%c:\\undo"), DriveLetter, i);
  3272. handleOfDir = FindFirstFile(pathForBackup, &win32FindData);
  3273. if(INVALID_HANDLE_VALUE == handleOfDir){
  3274. break;
  3275. }
  3276. else{
  3277. FindClose(handleOfDir);
  3278. }
  3279. }
  3280. if(i == MAX_AMOUNT_OF_TIME_TO_TRY_CONSTRUCT_UNDO_DIR){
  3281. MYASSERT(FALSE);
  3282. DEBUGMSG((DBG_ERROR, "Can't construct directory for backup"));
  3283. return NULL;
  3284. }
  3285. return pathForBackup;
  3286. }
  3287. BOOL
  3288. UI_BackupYesNoPageProc (
  3289. IN HWND hdlg,
  3290. IN UINT uMsg,
  3291. IN WPARAM wParam,
  3292. IN LPARAM lParam
  3293. )
  3294. /*++
  3295. Routine Description:
  3296. UI_BackupYesNoPageProc is the wizard window procedure that is called to
  3297. backup asking page. User can choose to do backup or not. In the unattended
  3298. case, this page will not appear, but we do some validation for the backup
  3299. impossible page.
  3300. Arguments:
  3301. hdlg - Specifies the dialog handle
  3302. uMsg - Specifies the message to process
  3303. wParam - Specifies the wParam data associated with the message
  3304. lParam - Specifies the lParam data associated with the message
  3305. Return Value:
  3306. WMX_ACTIVATEPAGE: On activation (wParam is TRUE), returns FALSE if
  3307. page is to be skipped; returns TRUE if page is
  3308. to be processed.
  3309. On deactivation (wParam is FALSE), returns FALSE
  3310. if the page is not to be deactivated; returns
  3311. TRUE if the page is to be deactivated.
  3312. WM_NOTIFY: Returns FALSE
  3313. WM_COMMAND: Returns TRUE if command is processed; FALSE if
  3314. command is not processed.
  3315. Others: Returns FALSE.
  3316. --*/
  3317. {
  3318. TCHAR DiskSpaceString[10];
  3319. HWND hButtonWnd;
  3320. PCTSTR ArgArray[1];
  3321. PCTSTR Msg;
  3322. TCHAR DiskSpace[32];
  3323. static BOOL initialized;
  3324. CHAR Drives[MAX_NUMBER_OF_DRIVES];
  3325. ULARGE_INTEGER AvailableSpace[ARRAYSIZE(Drives)];
  3326. static UINT NumberAvailableDrives;
  3327. static TCHAR winDrivePath[16];
  3328. UINT i;
  3329. PSTR pathForBackupTemp;
  3330. BOOL IsExceedMaxBackupImageSize;
  3331. __try {
  3332. switch (uMsg) {
  3333. case WMX_ACTIVATEPAGE:
  3334. if (wParam) {
  3335. if (!UPGRADE() || CANCELLED()) {
  3336. return FALSE;
  3337. }
  3338. //
  3339. // If answer file specifies backup choice, then skip page.
  3340. // TRISTATE_YES is the "automatic" setting for the answer
  3341. // file.
  3342. //
  3343. if (g_SilentBackupMode) {
  3344. //
  3345. // We do not expect to enter this condition, because we
  3346. // are the ones who set silent mode. There should never be
  3347. // a condition where silent mode is on and the user can
  3348. // click Back on the wizard.
  3349. //
  3350. MYASSERT (FALSE);
  3351. return FALSE;
  3352. }
  3353. DEBUGLOGTIME(("Backup Yes/No Wizard Page..."));
  3354. if (!initialized) {
  3355. NumberAvailableDrives = 0;
  3356. if (IsBackUpPossible (
  3357. Drives,
  3358. AvailableSpace,
  3359. &NumberAvailableDrives,
  3360. NULL,
  3361. ARRAYSIZE(Drives)
  3362. )) {
  3363. //
  3364. // Backup is possible, but we have not yet taken into
  3365. // consideration the backup path setting from the
  3366. // answer file. Preserve the REQUIRED state.
  3367. //
  3368. if (g_ConfigOptions.EnableBackup == TRISTATE_REQUIRED) {
  3369. g_ConfigOptions.EnableBackup = TRISTATE_YES;
  3370. }
  3371. if (!g_ConfigOptions.PathForBackup || !g_ConfigOptions.PathForBackup[0]) {
  3372. //
  3373. // If backup is possible on the system drive, then
  3374. // continue silently.
  3375. //
  3376. for (i = 0; i < NumberAvailableDrives; i++) {
  3377. //
  3378. // Setup does not bother user, if we find possibility
  3379. // to have %undo% dir on %windir% drive.
  3380. //
  3381. if (_totlower (Drives[i]) == _totlower (g_WinDir[0])) {
  3382. g_SilentBackupMode = TRUE;
  3383. pathForBackupTemp = pConstructPathForBackup(g_WinDir[0]);
  3384. if(pathForBackupTemp){
  3385. StringCopy(winDrivePath, pathForBackupTemp);
  3386. g_ConfigOptions.PathForBackup = winDrivePath;
  3387. }ELSE_DEBUGMSG((DBG_ERROR, "Can't construct directory for backup."));
  3388. return FALSE;
  3389. }
  3390. }
  3391. }
  3392. } else {
  3393. //
  3394. // If we are running unattended, and backup is
  3395. // required, then stop right now.
  3396. //
  3397. // If we are running with UI, and backup is required,
  3398. // skip this page and head directly to the Backup
  3399. // Impossible page.
  3400. //
  3401. // Set the answer to NO because backup is not
  3402. // possible. In unattend mode, we'll just continue
  3403. // with setup, without a backup.
  3404. g_ConfigOptions.EnableBackup = TRISTATE_NO;
  3405. if(g_SpaceNeededForSlowBackup.QuadPart >= MAX_BACKUP_IMAGE_SIZE_FOR_BACKUP){
  3406. g_ShowBackupImpossiblePage = BIP_SIZE_EXCEED_LIMIT;
  3407. }
  3408. else{
  3409. g_ShowBackupImpossiblePage = BIP_NOT_ENOUGH_SPACE;
  3410. }
  3411. if (g_ConfigOptions.EnableBackup == TRISTATE_REQUIRED && UNATTENDED()) {
  3412. LOG ((LOG_ERROR, (PCSTR) MSG_STOP_BECAUSE_CANT_BACK_UP));
  3413. pAbortSetup (hdlg);
  3414. }
  3415. //
  3416. // If setup does not finds enough disk space to install system,
  3417. // it shows NotEnoughSpaceMessage dialog, with only QuitSetup button,
  3418. // only in non-unattended case.
  3419. //
  3420. if(!pShowNotEnoughSpaceMessage(hdlg)){
  3421. pAbortSetup (hdlg);
  3422. return FALSE;
  3423. }
  3424. return FALSE;
  3425. }
  3426. //
  3427. // If unattended, skip this page
  3428. //
  3429. if (UNATTENDED()) {
  3430. return FALSE;
  3431. }
  3432. //
  3433. // Fill the wizard page with disk space info
  3434. //
  3435. wsprintf (DiskSpace, TEXT("%d"), (UINT)(g_SpaceNeededForSlowBackup.QuadPart / (1<<20)));
  3436. ArgArray[0] = DiskSpace;
  3437. Msg = ParseMessageID (MSG_DISK_SPACE, ArgArray);
  3438. if (Msg) {
  3439. SetWindowText(GetDlgItem(hdlg, IDC_DISKSPACE), Msg);
  3440. FreeStringResource (Msg);
  3441. }
  3442. ELSE_DEBUGMSG ((DBG_ERROR, "Unable to load string resource on BackupYesNoPage wizard page. Check localization."));
  3443. hButtonWnd = GetDlgItem (hdlg, g_ConfigOptions.EnableBackup != TRISTATE_NO ?
  3444. IDC_BACKUP_YES: IDC_BACKUP_NO);
  3445. SetFocus (hButtonWnd);
  3446. SendMessage (hButtonWnd, BM_SETCHECK, BST_CHECKED, 0);
  3447. initialized = TRUE;
  3448. }
  3449. MYASSERT (!UNATTENDED());
  3450. //
  3451. // Enable next, disable back
  3452. //
  3453. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  3454. //
  3455. // Stop the billboard and make sure the wizard shows again.
  3456. //
  3457. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  3458. } else {
  3459. //
  3460. // Collect the user's choice (if it was presented to them)
  3461. //
  3462. if (initialized) {
  3463. if (IsDlgButtonChecked (hdlg, IDC_BACKUP_YES) == BST_CHECKED) {
  3464. g_ConfigOptions.EnableBackup = TRISTATE_YES;
  3465. } else {
  3466. g_ConfigOptions.EnableBackup = TRISTATE_NO;
  3467. }
  3468. }
  3469. }
  3470. return TRUE;
  3471. default:
  3472. break;
  3473. }
  3474. } __except (1) {
  3475. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Backup Yes/No Page."));
  3476. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  3477. SafeModeExceptionOccured ();
  3478. pAbortSetup (hdlg);
  3479. }
  3480. return FALSE;
  3481. }
  3482. BOOL
  3483. UI_BackupDriveSelectionProc (
  3484. IN HWND hdlg,
  3485. IN UINT uMsg,
  3486. IN WPARAM wParam,
  3487. IN LPARAM lParam
  3488. )
  3489. /*++
  3490. Routine Description:
  3491. UI_BackupDriveSelectionProc is the wizard window procedure that is called to
  3492. choose backup drive.
  3493. Arguments:
  3494. hdlg - Specifies the dialog handle
  3495. uMsg - Specifies the message to process
  3496. wParam - Specifies the wParam data associated with the message
  3497. lParam - Specifies the lParam data associated with the message
  3498. Return Value:
  3499. WMX_ACTIVATEPAGE: On activation (wParam is TRUE), returns FALSE if
  3500. page is to be skipped; returns TRUE if page is
  3501. to be processed.
  3502. On deactivation (wParam is FALSE), returns FALSE
  3503. if the page is not to be deactivated; returns
  3504. TRUE if the page is to be deactivated.
  3505. WM_NOTIFY: Returns FALSE
  3506. WM_COMMAND: Returns TRUE if command is processed; FALSE if
  3507. command is not processed.
  3508. Others: Returns FALSE.
  3509. --*/
  3510. {
  3511. TCHAR DiskSpaceString[32];
  3512. HWND hButtonWnd;
  3513. HWND hFirstRadioButton;
  3514. HWND hRadioButton;
  3515. HWND hDefaultRadioButton;
  3516. DWORD TemplateStyle;
  3517. DWORD TemplateStyleEx;
  3518. HFONT hFontOfFirstRadioButton;
  3519. static CHAR Drives[MAX_NUMBER_OF_DRIVES];
  3520. static BOOL IsPossibleBackupWithoutCompression[MAX_NUMBER_OF_DRIVES];
  3521. ULARGE_INTEGER AvailableSpace[ARRAYSIZE(Drives)];
  3522. static UINT NumberAvailableDrives;
  3523. RECT EtalonRadioButtonRect;
  3524. RECT PageRect;
  3525. POINT pointForTransform;
  3526. UINT NumberOfPossibleRadioButtonsByVertical;
  3527. UINT widthRadio;
  3528. UINT heightRadio;
  3529. UINT xOffset;
  3530. UINT yOffset;
  3531. UINT i;
  3532. PCTSTR PathForBackupImage;
  3533. PCTSTR ArgArray[2];
  3534. PCTSTR Msg;
  3535. TCHAR DiskSpace[32];
  3536. TCHAR DriveText[32];
  3537. static BOOL backupPathSet = FALSE;
  3538. static TCHAR PathForBackup[MAX_PATH];
  3539. BOOL b;
  3540. BOOL disableCompression;
  3541. static BOOL initialized;
  3542. TCHAR selectedDrive;
  3543. PSTR pathForBackupTemp;
  3544. __try {
  3545. switch (uMsg) {
  3546. case WMX_ACTIVATEPAGE:
  3547. if (wParam) {
  3548. if (!UPGRADE() || CANCELLED()) {
  3549. return FALSE;
  3550. }
  3551. DEBUGLOGTIME(("Backup Drive Selection Wizard Page..."));
  3552. b = TRUE;
  3553. if(g_ShowBackupImpossiblePage != BIP_DONOT){
  3554. b = FALSE;
  3555. }
  3556. //
  3557. // Validate length of PathForBackup
  3558. //
  3559. if (b && !initialized) {
  3560. //
  3561. // Obtain the available drive list
  3562. //
  3563. NumberAvailableDrives = 0;
  3564. if (!IsBackUpPossible (
  3565. Drives,
  3566. AvailableSpace,
  3567. &NumberAvailableDrives,
  3568. IsPossibleBackupWithoutCompression,
  3569. ARRAYSIZE(Drives)
  3570. )) {
  3571. //
  3572. // This is unexpected, because the Yes/No page did
  3573. // the work of validating if backup is possible.
  3574. //
  3575. MYASSERT (FALSE);
  3576. g_ConfigOptions.EnableBackup = TRISTATE_NO;
  3577. g_ShowBackupImpossiblePage = BIP_NOT_ENOUGH_SPACE;
  3578. b = FALSE;
  3579. }
  3580. }
  3581. if (b && g_SilentBackupMode || g_ConfigOptions.EnableBackup == TRISTATE_NO) {
  3582. //
  3583. // Skip drive selection page -- we already have the
  3584. // proper backup settings. Proceed to the deactivate
  3585. // routine so that backup is written to the SIF.
  3586. //
  3587. b = FALSE;
  3588. backupPathSet = TRUE;
  3589. MYASSERT (g_ConfigOptions.PathForBackup);
  3590. }
  3591. if (b && !initialized) {
  3592. //
  3593. // Validate the PathForBackup setting. If it is not
  3594. // specified, then allow the user to choose the backup
  3595. // drive (or continue with first valid choice if
  3596. // unattended).
  3597. //
  3598. if (g_ConfigOptions.PathForBackup && *g_ConfigOptions.PathForBackup == 0) {
  3599. g_ConfigOptions.PathForBackup = NULL;
  3600. }
  3601. if (g_ConfigOptions.PathForBackup) {
  3602. //
  3603. // Check path length restriction
  3604. //
  3605. if (TcharCount (g_ConfigOptions.PathForBackup) >= (MAX_PATH - 26)) {
  3606. g_ConfigOptions.PathForBackup = NULL;
  3607. LOG ((
  3608. LOG_ERROR,
  3609. (PCSTR) MSG_LONG_BACKUP_PATH,
  3610. g_ConfigOptions.PathForBackup
  3611. ));
  3612. pAbortSetup (hdlg);
  3613. return FALSE;
  3614. }
  3615. backupPathSet = TRUE;
  3616. for (i = 0; i < NumberAvailableDrives; i++) {
  3617. if(_totlower(g_ConfigOptions.PathForBackup[0]) == _totlower(Drives[i])) {
  3618. break;
  3619. }
  3620. }
  3621. if (i == NumberAvailableDrives) {
  3622. //
  3623. // Backup impossible on g_ConfigOptions.PathForBackup drive.
  3624. // If backup is required, fail setup now.
  3625. //
  3626. if (TRISTATE_REQUIRED == g_ConfigOptions.EnableBackup){
  3627. LOG ((
  3628. LOG_ERROR,
  3629. (PCSTR) MSG_STOP_BECAUSE_CANT_BACK_UP_2,
  3630. g_ConfigOptions.PathForBackup
  3631. ));
  3632. pAbortSetup (hdlg);
  3633. return FALSE;
  3634. }
  3635. //
  3636. // otherwise continue without a backup and skip this page too
  3637. //
  3638. g_ConfigOptions.EnableBackup = TRISTATE_NO;
  3639. b = FALSE;
  3640. }
  3641. if(UNATTENDED()){
  3642. b = FALSE;
  3643. }
  3644. } else {
  3645. //
  3646. // No backup path was specified. If unattended
  3647. // mode, pick first choice and skip this page.
  3648. //
  3649. if (UNATTENDED()) {
  3650. //wsprintf (PathForBackup, TEXT("%c:\\undo"), Drives[0]);
  3651. pathForBackupTemp = pConstructPathForBackup(Drives[0]);
  3652. if(pathForBackupTemp){
  3653. StringCopy(PathForBackup, pathForBackupTemp);
  3654. DEBUGMSG ((DBG_VERBOSE, "Selecting drive %c and path %s for backup, ", Drives[0], PathForBackup));
  3655. g_ConfigOptions.PathForBackup = PathForBackup;
  3656. backupPathSet = TRUE;
  3657. }ELSE_DEBUGMSG((DBG_ERROR, "Can't construct directory for backup."));
  3658. b = FALSE;
  3659. }
  3660. }
  3661. }
  3662. if (!b) { // page not needed
  3663. //
  3664. // Send private deactivate msg to ourselves and return FALSE
  3665. //
  3666. SendMessage (hdlg, uMsg, FALSE, 0);
  3667. return FALSE;
  3668. }
  3669. if (!initialized) {
  3670. //
  3671. // At this point we know we must present this page to the user.
  3672. //
  3673. // The code below dynamically generates controls based on how many
  3674. // drives we have to present. This code can only run once.
  3675. //
  3676. GetClientRect (hdlg, &PageRect);
  3677. hFirstRadioButton = GetDlgItem(hdlg, IDC_BACKUP_FIRST);
  3678. GetWindowRect (hFirstRadioButton, &EtalonRadioButtonRect);
  3679. widthRadio = EtalonRadioButtonRect.right - EtalonRadioButtonRect.left;
  3680. heightRadio = EtalonRadioButtonRect.bottom - EtalonRadioButtonRect.top;
  3681. pointForTransform.x = EtalonRadioButtonRect.left;
  3682. pointForTransform.y = EtalonRadioButtonRect.top;
  3683. MapWindowPoints (NULL, hdlg, &pointForTransform, 1);
  3684. NumberOfPossibleRadioButtonsByVertical = (PageRect.bottom - pointForTransform.y) /
  3685. (EtalonRadioButtonRect.bottom - EtalonRadioButtonRect.top);
  3686. hFontOfFirstRadioButton = (HFONT) SendMessage(hFirstRadioButton, WM_GETFONT, 0, 0);
  3687. hDefaultRadioButton = 0;
  3688. TemplateStyle = GetWindowLong(hFirstRadioButton, GWL_STYLE);
  3689. TemplateStyleEx = GetWindowLong(hFirstRadioButton, GWL_EXSTYLE);
  3690. for(i = 0; i < NumberAvailableDrives; i++) {
  3691. wsprintf(DriveText, TEXT("%c:\\"), Drives[i]);
  3692. wsprintf(DiskSpace, TEXT("%d"), (UINT)(AvailableSpace[i].QuadPart / (1 << 20)));
  3693. ArgArray[0] = DriveText;
  3694. ArgArray[1] = DiskSpace;
  3695. Msg = ParseMessageID (MSG_DISK_AND_FREE_DISK_SPACE, ArgArray);
  3696. if (Msg) {
  3697. if(!i){
  3698. SetWindowText(hFirstRadioButton, Msg);
  3699. hRadioButton = hFirstRadioButton;
  3700. }
  3701. else {
  3702. xOffset = i / NumberOfPossibleRadioButtonsByVertical;
  3703. yOffset = i % NumberOfPossibleRadioButtonsByVertical;
  3704. hRadioButton = CreateWindowEx(
  3705. TemplateStyleEx,
  3706. TEXT("Button"),
  3707. Msg,
  3708. TemplateStyle,
  3709. xOffset * widthRadio + pointForTransform.x,
  3710. yOffset * heightRadio + pointForTransform.y,
  3711. widthRadio,
  3712. heightRadio,
  3713. hdlg,
  3714. (HMENU) (IDC_BACKUP_FIRST + i),
  3715. g_hInst,
  3716. NULL
  3717. );
  3718. SendMessage(
  3719. hRadioButton,
  3720. WM_SETFONT,
  3721. (WPARAM) hFontOfFirstRadioButton,
  3722. TRUE
  3723. );
  3724. }
  3725. SetWindowLong (hRadioButton, GWL_USERDATA, (LONG) Drives[i]);
  3726. FreeStringResource (Msg);
  3727. }
  3728. ELSE_DEBUGMSG ((DBG_ERROR, "Unable to load string resource on BackupDriveSelection wizard page. Check localization."));
  3729. if(Drives[i] == g_WinDir[0]) {
  3730. hDefaultRadioButton = hRadioButton;
  3731. }
  3732. }
  3733. if(!hDefaultRadioButton) {
  3734. hDefaultRadioButton = hFirstRadioButton;
  3735. }
  3736. SendMessage (hdlg, WM_NEXTDLGCTL, (WPARAM) hDefaultRadioButton, 1L);
  3737. SendMessage (hDefaultRadioButton, BM_SETCHECK, BST_CHECKED, 0);
  3738. wsprintf(DiskSpace, TEXT("%d"), (UINT)(g_SpaceNeededForSlowBackup.QuadPart / (1<<20)));
  3739. ArgArray[0] = DiskSpace;
  3740. Msg = ParseMessageID (MSG_DISK_SPACE, ArgArray);
  3741. if (Msg) {
  3742. SetWindowText(GetDlgItem(hdlg, IDC_DISKSPACE), Msg);
  3743. FreeStringResource (Msg);
  3744. }
  3745. ELSE_DEBUGMSG ((DBG_ERROR, "Unable to load string resource on BackupDriveSelection wizard page. Check localization."));
  3746. initialized = TRUE;
  3747. }
  3748. //
  3749. // Enable next, disable back
  3750. //
  3751. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_BACK | PSWIZB_NEXT);
  3752. //
  3753. // Stop the billboard and make sure the wizard shows again.
  3754. //
  3755. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  3756. } else {
  3757. //
  3758. // Deactivating... this is were we output the backup options
  3759. // to winnt.sif.
  3760. //
  3761. if (g_ConfigOptions.EnableBackup && !backupPathSet) {
  3762. MYASSERT (!g_SilentBackupMode);
  3763. MYASSERT (!UNATTENDED());
  3764. //
  3765. // Compute the new path for backup by getting the UI choice
  3766. //
  3767. g_ConfigOptions.PathForBackup = PathForBackup;
  3768. selectedDrive = g_WinDir[0];
  3769. for (i = 0 ; i < NumberAvailableDrives ; i++) {
  3770. if (IsDlgButtonChecked (hdlg, IDC_BACKUP_FIRST + i)) {
  3771. selectedDrive = (TCHAR) GetWindowLong (
  3772. GetDlgItem (hdlg, IDC_BACKUP_FIRST + i),
  3773. GWL_USERDATA
  3774. );
  3775. break;
  3776. }
  3777. }
  3778. //wsprintf (PathForBackup, TEXT("%c:\\undo"), selectedDrive);
  3779. pathForBackupTemp = pConstructPathForBackup(selectedDrive);
  3780. if(pathForBackupTemp){
  3781. StringCopy(PathForBackup, pathForBackupTemp);
  3782. }ELSE_DEBUGMSG((DBG_ERROR, "Can't construct directory for backup."));
  3783. }
  3784. //
  3785. // Write the proper setting to winnt.sif
  3786. //
  3787. if (g_ConfigOptions.PathForBackup && g_ConfigOptions.EnableBackup) {
  3788. WriteInfKey (S_WIN9XUPGUSEROPTIONS, S_ENABLE_BACKUP, S_YES);
  3789. PathForBackupImage = JoinPaths (g_ConfigOptions.PathForBackup, TEXT("backup.cab"));
  3790. WriteInfKey (WINNT_DATA, WINNT_D_BACKUP_IMAGE, PathForBackupImage);
  3791. WriteInfKey (S_WIN9XUPGUSEROPTIONS, S_PATH_FOR_BACKUP, g_ConfigOptions.PathForBackup);
  3792. disableCompression = FALSE;
  3793. if (g_ConfigOptions.DisableCompression != TRISTATE_NO){
  3794. for(i = 0; i < NumberAvailableDrives; i++){
  3795. if (_totlower (Drives[i]) == _totlower (g_ConfigOptions.PathForBackup[0])){
  3796. disableCompression = IsPossibleBackupWithoutCompression[i];
  3797. DEBUGMSG ((DBG_VERBOSE, "Info for PathForBackup found; disableCompression=%u", (UINT) disableCompression));
  3798. break;
  3799. }
  3800. }
  3801. }
  3802. WriteInfKey (
  3803. S_WIN9XUPGUSEROPTIONS,
  3804. WINNT_D_DISABLE_BACKUP_COMPRESSION,
  3805. disableCompression? S_YES: S_NO
  3806. );
  3807. if (disableCompression) {
  3808. if (!UseSpace (PathForBackupImage, g_SpaceNeededForFastBackup.QuadPart)) {
  3809. FreeSpace (PathForBackupImage, g_SpaceNeededForFastBackup.QuadPart);
  3810. MYASSERT (FALSE);
  3811. }
  3812. } else {
  3813. if (!UseSpace (PathForBackupImage, g_SpaceNeededForSlowBackup.QuadPart)) {
  3814. FreeSpace (PathForBackupImage, g_SpaceNeededForSlowBackup.QuadPart);
  3815. MYASSERT (FALSE);
  3816. }
  3817. }
  3818. FreePathString (PathForBackupImage);
  3819. } else {
  3820. WriteInfKey (S_WIN9XUPGUSEROPTIONS, S_ENABLE_BACKUP, S_NO);
  3821. WriteInfKey (S_WIN9XUPGUSEROPTIONS, WINNT_D_DISABLE_BACKUP_COMPRESSION, S_NO);
  3822. WriteInfKey (WINNT_DATA, WINNT_D_BACKUP_LIST, NULL);
  3823. WriteInfKey (WINNT_DATA, WINNT_D_BACKUP_IMAGE, NULL);
  3824. WriteInfKey (S_WIN9XUPGUSEROPTIONS, S_PATH_FOR_BACKUP, NULL);
  3825. }
  3826. }
  3827. return TRUE;
  3828. default:
  3829. break;
  3830. }
  3831. } __except (1) {
  3832. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the BackupDriveSelection Page."));
  3833. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  3834. SafeModeExceptionOccured ();
  3835. pAbortSetup (hdlg);
  3836. }
  3837. return FALSE;
  3838. }
  3839. // LastPageProc is used for the last page special case
  3840. BOOL
  3841. UI_BackupImpossibleInfoProc (
  3842. IN HWND hdlg,
  3843. IN UINT uMsg,
  3844. IN WPARAM wParam,
  3845. IN LPARAM lParam
  3846. )
  3847. /*++
  3848. Routine Description:
  3849. UI_BackupImpossibleInfo is the wizard window procedure that is called to
  3850. show message that backup impossible
  3851. Arguments:
  3852. hdlg - Specifies the dialog handle
  3853. uMsg - Specifies the message to process
  3854. wParam - Specifies the wParam data associated with the message
  3855. lParam - Specifies the lParam data associated with the message
  3856. Return Value:
  3857. WMX_ACTIVATEPAGE: On activation (wParam is TRUE), returns FALSE if
  3858. page is to be skipped; returns TRUE if page is
  3859. to be processed.
  3860. On deactivation (wParam is FALSE), returns FALSE
  3861. if the page is not to be deactivated; returns
  3862. TRUE if the page is to be deactivated.
  3863. WM_NOTIFY: Returns FALSE
  3864. WM_COMMAND: Returns TRUE if command is processed; FALSE if
  3865. command is not processed.
  3866. Others: Returns FALSE.
  3867. --*/
  3868. {
  3869. PCTSTR ArgArray[1];
  3870. PCTSTR Msg;
  3871. TCHAR DiskSpace[32];
  3872. INT i;
  3873. __try {
  3874. switch (uMsg) {
  3875. case WMX_ACTIVATEPAGE:
  3876. if (wParam) {
  3877. if (!UPGRADE() || CANCELLED()) {
  3878. return FALSE;
  3879. }
  3880. //
  3881. // If unattended mode, skip page.
  3882. //
  3883. if (UNATTENDED()) {
  3884. return FALSE;
  3885. }
  3886. if(g_ShowBackupImpossiblePage != BIP_NOT_ENOUGH_SPACE) {
  3887. return FALSE;
  3888. }
  3889. DEBUGLOGTIME(("BackupImpossibleInfo Wizard Page..."));
  3890. wsprintf(DiskSpace, TEXT("%d"), (UINT)(g_SpaceNeededForSlowBackup.QuadPart / (1<<20)));
  3891. ArgArray[0] = DiskSpace;
  3892. ParseMessageInWnd (GetDlgItem(hdlg, IDC_DISKSPACE), ArgArray);
  3893. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  3894. //
  3895. // Stop the billboard and make sure the wizard shows again.
  3896. //
  3897. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  3898. }
  3899. return TRUE;
  3900. default:
  3901. break;
  3902. }
  3903. } __except (1) {
  3904. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the BackupImpossibleInfo Page."));
  3905. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  3906. SafeModeExceptionOccured ();
  3907. pAbortSetup (hdlg);
  3908. }
  3909. return FALSE;
  3910. }
  3911. BOOL
  3912. UI_BackupImpExceedLimitProc (
  3913. IN HWND hdlg,
  3914. IN UINT uMsg,
  3915. IN WPARAM wParam,
  3916. IN LPARAM lParam
  3917. )
  3918. /*++
  3919. Routine Description:
  3920. UI_BackupImpExceedLimitProc is the wizard window procedure that is called to
  3921. show message that backup impossible
  3922. Arguments:
  3923. hdlg - Specifies the dialog handle
  3924. uMsg - Specifies the message to process
  3925. wParam - Specifies the wParam data associated with the message
  3926. lParam - Specifies the lParam data associated with the message
  3927. Return Value:
  3928. WMX_ACTIVATEPAGE: On activation (wParam is TRUE), returns FALSE if
  3929. page is to be skipped; returns TRUE if page is
  3930. to be processed.
  3931. On deactivation (wParam is FALSE), returns FALSE
  3932. if the page is not to be deactivated; returns
  3933. TRUE if the page is to be deactivated.
  3934. WM_NOTIFY: Returns FALSE
  3935. WM_COMMAND: Returns TRUE if command is processed; FALSE if
  3936. command is not processed.
  3937. Others: Returns FALSE.
  3938. --*/
  3939. {
  3940. PCTSTR ArgArray[1];
  3941. PCTSTR Msg;
  3942. TCHAR DiskSpace[32];
  3943. INT i;
  3944. __try {
  3945. switch (uMsg) {
  3946. case WMX_ACTIVATEPAGE:
  3947. if (wParam) {
  3948. if (!UPGRADE() || CANCELLED()) {
  3949. return FALSE;
  3950. }
  3951. //
  3952. // If unattended mode, skip page.
  3953. //
  3954. if (UNATTENDED()) {
  3955. return FALSE;
  3956. }
  3957. if(g_ShowBackupImpossiblePage != BIP_SIZE_EXCEED_LIMIT) {
  3958. return FALSE;
  3959. }
  3960. DEBUGLOGTIME(("BackupImpExceedLimit Wizard Page..."));
  3961. wsprintf(DiskSpace, TEXT("%d"), (UINT)(g_SpaceNeededForSlowBackup.QuadPart / (1<<20)));
  3962. ArgArray[0] = DiskSpace;
  3963. ParseMessageInWnd (GetDlgItem(hdlg, IDC_DISKSPACE), ArgArray);
  3964. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT);
  3965. //
  3966. // Stop the billboard and make sure the wizard shows again.
  3967. //
  3968. SendMessage(GetParent (hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
  3969. }
  3970. return TRUE;
  3971. default:
  3972. break;
  3973. }
  3974. } __except (1) {
  3975. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the BackupImpExceedLimit Page."));
  3976. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNEXPECTED_ERROR_ENCOUNTERED_NORC));
  3977. SafeModeExceptionOccured ();
  3978. pAbortSetup (hdlg);
  3979. }
  3980. return FALSE;
  3981. }
  3982. BOOL
  3983. UI_LastPageProc (
  3984. HWND hdlg,
  3985. UINT uMsg,
  3986. WPARAM wParam,
  3987. LPARAM lParam
  3988. )
  3989. {
  3990. PCTSTR ArgArray[3];
  3991. PCTSTR Msg;
  3992. TCHAR Num1[32];
  3993. TCHAR Num2[32];
  3994. UINT LowEstimate;
  3995. UINT HighEstimate;
  3996. UINT MsgId;
  3997. __try {
  3998. switch (uMsg) {
  3999. case WMX_ACTIVATEPAGE:
  4000. if (wParam) {
  4001. if (!UPGRADE()) {
  4002. return FALSE;
  4003. }
  4004. if (CANCELLED()) {
  4005. PostMessage (GetParent (hdlg), PSM_PRESSBUTTON, PSBTN_CANCEL, 0);
  4006. }
  4007. MYASSERT (!REPORTONLY());
  4008. if (UNATTENDED() || TYPICAL()) {
  4009. //
  4010. // Make sure we clean up the data in the report.
  4011. //
  4012. if (g_TextViewInDialog) {
  4013. SendMessage (g_TextViewInDialog, WMX_CLEANUP, 0, 0);
  4014. g_TextViewInDialog = NULL;
  4015. }
  4016. return FALSE;
  4017. }
  4018. DEBUGLOGTIME(("Last Wizard Page..."));
  4019. //
  4020. // Compute the time estimate
  4021. //
  4022. DEBUGMSG ((DBG_VERBOSE, "g_ProgressBarTime: %u", g_ProgressBarTime));
  4023. LowEstimate = (g_ProgressBarTime - 70000) / 12000;
  4024. LowEstimate = (LowEstimate / 5) * 5;
  4025. LowEstimate = min (LowEstimate, 45);
  4026. LowEstimate += 30;
  4027. HighEstimate = LowEstimate + 15;
  4028. DEBUGMSG ((DBG_VERBOSE, "GUI mode time estimate: %u to %u mins", LowEstimate, HighEstimate));
  4029. //
  4030. // Fill in text of the IDC_TEXT1 control
  4031. //
  4032. wsprintf (Num1, TEXT("%u"), LowEstimate);
  4033. wsprintf (Num2, TEXT("%u"), HighEstimate);
  4034. ArgArray[0] = Num1;
  4035. ArgArray[1] = Num2;
  4036. ArgArray[2] = g_Win95Name;
  4037. if (g_ForceNTFSConversion && *g_ForceNTFSConversion) {
  4038. MsgId = MSG_LAST_PAGE_WITH_NTFS_CONVERSION;
  4039. }
  4040. else {
  4041. MsgId = MSG_LAST_PAGE;
  4042. }
  4043. Msg = ParseMessageID (MsgId, ArgArray);
  4044. if (Msg) {
  4045. SetDlgItemText (hdlg, IDC_TEXT1, Msg);
  4046. FreeStringResource (Msg);
  4047. }
  4048. ELSE_DEBUGMSG ((DBG_ERROR, "Unable to load string resource on last wizard page. Check localization."));
  4049. PropSheet_SetWizButtons (GetParent(hdlg), PSWIZB_NEXT|PSWIZB_BACK);
  4050. } else {
  4051. if (lParam != PSN_WIZBACK && g_TextViewInDialog) {
  4052. SendMessage (g_TextViewInDialog, WMX_CLEANUP, 0, 0);
  4053. g_TextViewInDialog = NULL;
  4054. }
  4055. }
  4056. return TRUE;
  4057. }
  4058. } __except (1) {
  4059. LOG ((LOG_WARNING, "An unhandled exception occurred during the processing of the Last Page."));
  4060. SafeModeExceptionOccured ();
  4061. }
  4062. return FALSE;
  4063. }
  4064. BOOL
  4065. NewProgessProc(
  4066. IN HWND hdlg,
  4067. IN UINT msg,
  4068. IN WPARAM wParam,
  4069. IN LPARAM lParam
  4070. )
  4071. {
  4072. HWND hwndWizard = GetParent(hdlg);
  4073. hwndWizard = GetParent(hwndWizard);
  4074. if (hwndWizard)
  4075. {
  4076. switch (msg)
  4077. {
  4078. case PBM_DELTAPOS:
  4079. SendMessage(hwndWizard,WMX_PBM_DELTAPOS,wParam,lParam);
  4080. break;
  4081. case PBM_SETRANGE:
  4082. SendMessage(hwndWizard,WMX_PBM_SETRANGE,wParam,lParam);
  4083. break;
  4084. case PBM_STEPIT:
  4085. SendMessage(hwndWizard,WMX_PBM_STEPIT,wParam,lParam);
  4086. break;
  4087. case PBM_SETPOS:
  4088. SendMessage(hwndWizard,WMX_PBM_SETPOS,wParam,lParam);
  4089. break;
  4090. case PBM_SETSTEP:
  4091. SendMessage(hwndWizard,WMX_PBM_SETSTEP,wParam,lParam);
  4092. break;
  4093. }
  4094. }
  4095. return (BOOL)CallWindowProc(OldProgressProc,hdlg,msg,wParam,lParam);
  4096. }