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

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