3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
40 /* GLOBALS & LOCALS *********************************************************/
44 BOOLEAN IsUnattendedSetup
= FALSE
;
45 static USETUP_DATA USetupData
;
48 * NOTE: Technically only used for the COPYCONTEXT InstallPath member
49 * for the filequeue functionality.
51 static UNICODE_STRING InstallPath
;
53 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
54 static WCHAR DestinationDriveLetter
;
59 PWCHAR SelectedLanguageId
;
60 static WCHAR DefaultLanguage
[20]; // Copy of string inside LanguageList
61 static WCHAR DefaultKBLayout
[20]; // Copy of string inside KeyboardList
63 static BOOLEAN RepairUpdateFlag
= FALSE
;
65 static HANDLE hPnpThread
= NULL
;
67 static PPARTLIST PartitionList
= NULL
;
68 static PPARTENTRY TempPartition
= NULL
;
69 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
70 static FORMATMACHINESTATE FormatState
= Start
;
72 /*****************************************************/
76 static HSPFILEQ SetupFileQueue
= NULL
;
78 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
79 static PGENERIC_LIST NtOsInstallsList
= NULL
;
81 static PGENERIC_LIST ComputerList
= NULL
;
82 static PGENERIC_LIST DisplayList
= NULL
;
83 static PGENERIC_LIST KeyboardList
= NULL
;
84 static PGENERIC_LIST LayoutList
= NULL
;
85 static PGENERIC_LIST LanguageList
= NULL
;
88 /* FUNCTIONS ****************************************************************/
91 PrintString(char* fmt
,...)
95 UNICODE_STRING UnicodeString
;
96 ANSI_STRING AnsiString
;
99 vsprintf(buffer
, fmt
, ap
);
102 RtlInitAnsiString(&AnsiString
, buffer
);
103 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
104 NtDisplayString(&UnicodeString
);
105 RtlFreeUnicodeString(&UnicodeString
);
110 DrawBox(IN SHORT xLeft
,
118 /* Draw upper left corner */
121 FillConsoleOutputCharacterA(StdOutput
,
127 /* Draw upper edge */
130 FillConsoleOutputCharacterA(StdOutput
,
136 /* Draw upper right corner */
137 coPos
.X
= xLeft
+ Width
- 1;
139 FillConsoleOutputCharacterA(StdOutput
,
145 /* Draw right edge, inner space and left edge */
146 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
149 FillConsoleOutputCharacterA(StdOutput
,
156 FillConsoleOutputCharacterA(StdOutput
,
162 coPos
.X
= xLeft
+ Width
- 1;
163 FillConsoleOutputCharacterA(StdOutput
,
170 /* Draw lower left corner */
172 coPos
.Y
= yTop
+ Height
- 1;
173 FillConsoleOutputCharacterA(StdOutput
,
179 /* Draw lower edge */
181 coPos
.Y
= yTop
+ Height
- 1;
182 FillConsoleOutputCharacterA(StdOutput
,
188 /* Draw lower right corner */
189 coPos
.X
= xLeft
+ Width
- 1;
190 coPos
.Y
= yTop
+ Height
- 1;
191 FillConsoleOutputCharacterA(StdOutput
,
200 PopupError(PCCH Text
,
218 /* Count text lines and longest line */
225 p
= strchr(pnext
, '\n');
229 Length
= strlen(pnext
);
234 Length
= (ULONG
)(p
- pnext
);
240 if (Length
> MaxLength
)
249 /* Check length of status line */
252 Length
= strlen(Status
);
254 if (Length
> MaxLength
)
258 Width
= MaxLength
+ 4;
264 yTop
= (yScreen
- Height
) / 2;
265 xLeft
= (xScreen
- Width
) / 2;
268 /* Set screen attributes */
270 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
272 FillConsoleOutputAttribute(StdOutput
,
273 FOREGROUND_RED
| BACKGROUND_WHITE
,
279 DrawBox(xLeft
, yTop
, Width
, Height
);
281 /* Print message text */
286 p
= strchr(pnext
, '\n');
290 Length
= strlen(pnext
);
295 Length
= (ULONG
)(p
- pnext
);
302 WriteConsoleOutputCharacterA(StdOutput
,
316 /* Print separator line and status text */
319 coPos
.Y
= yTop
+ Height
- 3;
321 FillConsoleOutputCharacterA(StdOutput
,
328 FillConsoleOutputCharacterA(StdOutput
,
334 coPos
.X
= xLeft
+ Width
- 1;
335 FillConsoleOutputCharacterA(StdOutput
,
343 WriteConsoleOutputCharacterA(StdOutput
,
345 min(strlen(Status
), (SIZE_T
)Width
- 4),
350 if (WaitEvent
== POPUP_WAIT_NONE
)
355 CONSOLE_ConInKey(Ir
);
357 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
358 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
370 * FALSE: Don't quit setup.
373 ConfirmQuit(PINPUT_RECORD Ir
)
376 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
380 CONSOLE_ConInKey(Ir
);
382 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
383 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
388 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
402 PGENERIC_LIST_ENTRY ListEntry
;
405 pszNewLayout
= MUIDefaultKeyboardLayout(SelectedLanguageId
);
407 if (LayoutList
== NULL
)
409 LayoutList
= CreateKeyboardLayoutList(SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
410 if (LayoutList
== NULL
)
412 /* FIXME: Handle error! */
417 ListEntry
= GetFirstListEntry(LayoutList
);
419 /* Search for default layout (if provided) */
420 if (pszNewLayout
!= NULL
)
422 while (ListEntry
!= NULL
)
424 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
426 SetCurrentListEntry(LayoutList
, ListEntry
);
430 ListEntry
= GetNextListEntry(ListEntry
);
437 * Displays the LanguagePage.
439 * Next pages: WelcomePage, QuitPage
442 * Init SelectedLanguageId
443 * Init USetupData.LanguageId
446 * Number of the next page.
449 LanguagePage(PINPUT_RECORD Ir
)
451 GENERIC_LIST_UI ListUi
;
452 PWCHAR NewLanguageId
;
453 BOOL RefreshPage
= FALSE
;
455 /* Initialize the computer settings list */
456 if (LanguageList
== NULL
)
458 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
459 if (LanguageList
== NULL
)
461 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
466 SelectedLanguageId
= DefaultLanguage
;
467 USetupData
.LanguageId
= 0;
470 SetConsoleCodePage();
473 /* If there's just a single language in the list skip
474 * the language selection process altogether! */
475 if (GenericListHasSingleEntry(LanguageList
))
477 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
481 InitGenericListUi(&ListUi
, LanguageList
);
482 DrawGenericList(&ListUi
,
488 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
490 MUIDisplayPage(LANGUAGE_PAGE
);
494 CONSOLE_ConInKey(Ir
);
496 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
497 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
499 ScrollDownGenericList(&ListUi
);
502 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
503 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
505 ScrollUpGenericList(&ListUi
);
508 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
509 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
511 ScrollPageDownGenericList(&ListUi
);
514 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
515 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
517 ScrollPageUpGenericList(&ListUi
);
520 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
521 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
526 RedrawGenericList(&ListUi
);
528 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
530 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
532 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
534 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
540 SetConsoleCodePage();
544 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
547 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
553 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
555 if (wcscmp(SelectedLanguageId
, NewLanguageId
))
557 /* Clear the language page */
558 MUIClearPage(LANGUAGE_PAGE
);
560 SelectedLanguageId
= NewLanguageId
;
563 SetConsoleCodePage();
565 /* Redraw language selection page in native language */
566 MUIDisplayPage(LANGUAGE_PAGE
);
581 * LanguagePage (at once, default)
582 * InstallIntroPage (at once, if unattended)
587 * Init USetupData.SourcePath
588 * Init USetupData.SourceRootPath
589 * Init USetupData.SourceRootDir
591 * Init USetupData.RequiredPartitionDiskSpace
592 * Init IsUnattendedSetup
593 * If unattended, init *List and sets the Codepage
594 * If unattended, init SelectedLanguageId
595 * If unattended, init USetupData.LanguageId
598 * Number of the next page.
601 SetupStartPage(PINPUT_RECORD Ir
)
605 PGENERIC_LIST_ENTRY ListEntry
;
607 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
609 /* Get the source path and source root path */
610 Status
= GetSourcePaths(&USetupData
.SourcePath
,
611 &USetupData
.SourceRootPath
,
612 &USetupData
.SourceRootDir
);
613 if (!NT_SUCCESS(Status
))
615 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
616 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
619 DPRINT1("SourcePath: '%wZ'\n", &USetupData
.SourcePath
);
620 DPRINT1("SourceRootPath: '%wZ'\n", &USetupData
.SourceRootPath
);
621 DPRINT1("SourceRootDir: '%wZ'\n", &USetupData
.SourceRootDir
);
623 /* Load 'txtsetup.sif' from the installation media */
624 Error
= LoadSetupInf(&SetupInf
, &USetupData
);
625 if (Error
!= ERROR_SUCCESS
)
627 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
631 /* Start the PnP thread */
632 if (hPnpThread
!= NULL
)
634 NtResumeThread(hPnpThread
, NULL
);
638 CheckUnattendedSetup(&USetupData
);
640 if (IsUnattendedSetup
)
642 // TODO: Read options from inf
643 ComputerList
= CreateComputerTypeList(SetupInf
);
644 DisplayList
= CreateDisplayDriverList(SetupInf
);
645 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
647 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
650 SelectedLanguageId
= DefaultLanguage
;
651 wcscpy(SelectedLanguageId
, USetupData
.LocaleID
);
652 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
654 LayoutList
= CreateKeyboardLayoutList(SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
656 /* first we hack LanguageList */
657 ListEntry
= GetFirstListEntry(LanguageList
);
658 while (ListEntry
!= NULL
)
660 if (!wcsicmp(USetupData
.LocaleID
, GetListEntryUserData(ListEntry
)))
662 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
663 SetCurrentListEntry(LanguageList
, ListEntry
);
667 ListEntry
= GetNextListEntry(ListEntry
);
671 ListEntry
= GetFirstListEntry(LayoutList
);
672 while (ListEntry
!= NULL
)
674 if (!wcsicmp(USetupData
.LocaleID
, GetListEntryUserData(ListEntry
)))
676 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
677 SetCurrentListEntry(LayoutList
, ListEntry
);
681 ListEntry
= GetNextListEntry(ListEntry
);
684 SetConsoleCodePage();
686 return INSTALL_INTRO_PAGE
;
689 return LANGUAGE_PAGE
;
694 * Displays the WelcomePage.
697 * InstallIntroPage (default)
704 * Number of the next page.
707 WelcomePage(PINPUT_RECORD Ir
)
709 MUIDisplayPage(WELCOME_PAGE
);
713 CONSOLE_ConInKey(Ir
);
715 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
716 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
723 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
725 return INSTALL_INTRO_PAGE
;
727 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
729 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
731 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
742 * Displays the License page.
745 * WelcomePage (default)
748 * Number of the next page.
751 LicensePage(PINPUT_RECORD Ir
)
753 MUIDisplayPage(LICENSE_PAGE
);
757 CONSOLE_ConInKey(Ir
);
759 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
770 * Displays the RepairIntroPage.
773 * RebootPage (default)
779 * Number of the next page.
782 RepairIntroPage(PINPUT_RECORD Ir
)
784 MUIDisplayPage(REPAIR_INTRO_PAGE
);
788 CONSOLE_ConInKey(Ir
);
790 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
794 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
796 RepairUpdateFlag
= TRUE
;
797 return INSTALL_INTRO_PAGE
;
799 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
801 return RECOVERY_PAGE
;
803 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
804 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
810 return REPAIR_INTRO_PAGE
;
814 * Displays the UpgradeRepairPage.
817 * RebootPage (default)
823 * Number of the next page.
826 UpgradeRepairPage(PINPUT_RECORD Ir
)
828 GENERIC_LIST_UI ListUi
;
831 if (PartitionList
== NULL
)
833 PartitionList
= CreatePartitionList();
834 if (PartitionList
== NULL
)
836 /* FIXME: show an error dialog */
837 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
840 else if (IsListEmpty(&PartitionList
->DiskListHead
))
842 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
846 TempPartition
= NULL
;
851 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
852 if (!NtOsInstallsList
)
853 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
854 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
856 RepairUpdateFlag
= FALSE
;
858 // return INSTALL_INTRO_PAGE;
859 return DEVICE_SETTINGS_PAGE
;
860 // return SCSI_CONTROLLER_PAGE;
863 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
865 InitGenericListUi(&ListUi
, NtOsInstallsList
);
866 DrawGenericList(&ListUi
,
871 SaveGenericListState(NtOsInstallsList
);
873 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
876 CONSOLE_ConInKey(Ir
);
878 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
880 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
882 case VK_DOWN
: /* DOWN */
883 ScrollDownGenericList(&ListUi
);
886 ScrollUpGenericList(&ListUi
);
888 case VK_NEXT
: /* PAGE DOWN */
889 ScrollPageDownGenericList(&ListUi
);
891 case VK_PRIOR
: /* PAGE UP */
892 ScrollPageUpGenericList(&ListUi
);
899 RedrawGenericList(&ListUi
);
902 case VK_ESCAPE
: /* ESC */
904 RestoreGenericListState(NtOsInstallsList
);
905 // return nextPage; // prevPage;
907 // return INSTALL_INTRO_PAGE;
908 return DEVICE_SETTINGS_PAGE
;
909 // return SCSI_CONTROLLER_PAGE;
915 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
916 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
917 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
919 /* Retrieve the current installation */
920 CurrentInstallation
= (PNTOS_INSTALLATION
)GetListEntryUserData(GetCurrentListEntry(NtOsInstallsList
));
921 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
922 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
924 RepairUpdateFlag
= TRUE
;
927 /***/return INSTALL_INTRO_PAGE
;/***/
929 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
930 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
932 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
937 return UPGRADE_REPAIR_PAGE
;
942 * Displays the InstallIntroPage.
945 * DeviceSettingsPage (At once if repair or update is selected)
946 * SelectPartitionPage (At once if unattended setup)
947 * DeviceSettingsPage (default)
951 * Number of the next page.
954 InstallIntroPage(PINPUT_RECORD Ir
)
956 if (RepairUpdateFlag
)
958 #if 1 /* Old code that looks good */
960 // return SELECT_PARTITION_PAGE;
961 return DEVICE_SETTINGS_PAGE
;
963 #else /* Possible new code? */
965 return DEVICE_SETTINGS_PAGE
;
966 // return SCSI_CONTROLLER_PAGE;
971 if (IsUnattendedSetup
)
972 return SELECT_PARTITION_PAGE
;
974 MUIDisplayPage(INSTALL_INTRO_PAGE
);
978 CONSOLE_ConInKey(Ir
);
980 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
981 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
988 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
990 return UPGRADE_REPAIR_PAGE
;
994 return INSTALL_INTRO_PAGE
;
1000 ScsiControllerPage(PINPUT_RECORD Ir
)
1002 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1004 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1006 /* FIXME: print loaded mass storage driver descriptions */
1008 CONSOLE_SetTextXY(8, 10, "TEST device");
1011 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1015 CONSOLE_ConInKey(Ir
);
1017 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1018 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1020 if (ConfirmQuit(Ir
))
1025 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1027 return DEVICE_SETTINGS_PAGE
;
1031 return SCSI_CONTROLLER_PAGE
;
1035 OemDriverPage(PINPUT_RECORD Ir
)
1037 // MUIDisplayPage(OEM_DRIVER_PAGE);
1039 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1041 /* FIXME: Implement!! */
1043 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1047 CONSOLE_ConInKey(Ir
);
1049 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1050 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1052 if (ConfirmQuit(Ir
))
1057 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1059 return DEVICE_SETTINGS_PAGE
;
1063 return OEM_DRIVER_PAGE
;
1069 * Displays the DeviceSettingsPage.
1072 * SelectPartitionPage (At once if repair or update is selected)
1073 * ComputerSettingsPage
1074 * DisplaySettingsPage
1075 * KeyboardSettingsPage
1076 * LayoutsettingsPage
1077 * SelectPartitionPage
1087 * Number of the next page.
1090 DeviceSettingsPage(PINPUT_RECORD Ir
)
1092 static ULONG Line
= 16;
1093 CHAR CurrentItemText
[256];
1095 /* Initialize the computer settings list */
1096 if (ComputerList
== NULL
)
1098 ComputerList
= CreateComputerTypeList(SetupInf
);
1099 if (ComputerList
== NULL
)
1101 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1106 /* Initialize the display settings list */
1107 if (DisplayList
== NULL
)
1109 DisplayList
= CreateDisplayDriverList(SetupInf
);
1110 if (DisplayList
== NULL
)
1112 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1117 /* Initialize the keyboard settings list */
1118 if (KeyboardList
== NULL
)
1120 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1121 if (KeyboardList
== NULL
)
1123 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1128 /* Initialize the keyboard layout list */
1129 if (LayoutList
== NULL
)
1131 LayoutList
= CreateKeyboardLayoutList(SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
1132 if (LayoutList
== NULL
)
1134 /* FIXME: report error */
1135 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1140 if (RepairUpdateFlag
)
1141 return SELECT_PARTITION_PAGE
;
1143 // if (IsUnattendedSetup)
1144 // return SELECT_PARTITION_PAGE;
1146 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1148 sprintf(CurrentItemText
, "%S", GetListEntryText(GetCurrentListEntry(ComputerList
)));
1149 CONSOLE_SetTextXY(25, 11, CurrentItemText
);
1150 sprintf(CurrentItemText
, "%S", GetListEntryText(GetCurrentListEntry(DisplayList
)));
1151 CONSOLE_SetTextXY(25, 12, CurrentItemText
);
1152 sprintf(CurrentItemText
, "%S", GetListEntryText(GetCurrentListEntry(KeyboardList
)));
1153 CONSOLE_SetTextXY(25, 13, CurrentItemText
);
1154 sprintf(CurrentItemText
, "%S", GetListEntryText(GetCurrentListEntry(LayoutList
)));
1155 CONSOLE_SetTextXY(25, 14, CurrentItemText
);
1157 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1161 CONSOLE_ConInKey(Ir
);
1163 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1164 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1166 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1170 else if (Line
== 16)
1175 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1177 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1178 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1180 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1184 else if (Line
== 16)
1189 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1191 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1192 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1194 if (ConfirmQuit(Ir
))
1199 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1202 return COMPUTER_SETTINGS_PAGE
;
1203 else if (Line
== 12)
1204 return DISPLAY_SETTINGS_PAGE
;
1205 else if (Line
== 13)
1206 return KEYBOARD_SETTINGS_PAGE
;
1207 else if (Line
== 14)
1208 return LAYOUT_SETTINGS_PAGE
;
1209 else if (Line
== 16)
1210 return SELECT_PARTITION_PAGE
;
1214 return DEVICE_SETTINGS_PAGE
;
1219 * Handles generic selection lists.
1222 * GenericList: The list to handle.
1223 * nextPage: The page it needs to jump to after this page.
1224 * Ir: The PINPUT_RECORD
1227 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1228 PAGE_NUMBER nextPage
,
1233 CONSOLE_ConInKey(Ir
);
1235 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1236 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1238 ScrollDownGenericList(ListUi
);
1240 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1241 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1243 ScrollUpGenericList(ListUi
);
1245 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1246 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1248 ScrollPageDownGenericList(ListUi
);
1250 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1251 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1253 ScrollPageUpGenericList(ListUi
);
1255 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1256 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1258 if (ConfirmQuit(Ir
))
1261 RedrawGenericList(ListUi
);
1263 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1264 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1266 RestoreGenericListState(ListUi
->List
);
1267 return nextPage
; // Use some "prevPage;" instead?
1269 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1273 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1276 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1283 * Displays the ComputerSettingsPage.
1286 * DeviceSettingsPage
1290 * Number of the next page.
1293 ComputerSettingsPage(PINPUT_RECORD Ir
)
1295 GENERIC_LIST_UI ListUi
;
1296 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1298 InitGenericListUi(&ListUi
, ComputerList
);
1299 DrawGenericList(&ListUi
,
1305 SaveGenericListState(ComputerList
);
1307 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1312 * Displays the DisplaySettingsPage.
1315 * DeviceSettingsPage
1319 * Number of the next page.
1322 DisplaySettingsPage(PINPUT_RECORD Ir
)
1324 GENERIC_LIST_UI ListUi
;
1325 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1327 InitGenericListUi(&ListUi
, DisplayList
);
1328 DrawGenericList(&ListUi
,
1334 SaveGenericListState(DisplayList
);
1336 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1341 * Displays the KeyboardSettingsPage.
1344 * DeviceSettingsPage
1348 * Number of the next page.
1351 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1353 GENERIC_LIST_UI ListUi
;
1354 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1356 InitGenericListUi(&ListUi
, KeyboardList
);
1357 DrawGenericList(&ListUi
,
1363 SaveGenericListState(KeyboardList
);
1365 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1370 * Displays the LayoutSettingsPage.
1373 * DeviceSettingsPage
1377 * Number of the next page.
1380 LayoutSettingsPage(PINPUT_RECORD Ir
)
1382 GENERIC_LIST_UI ListUi
;
1383 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1385 InitGenericListUi(&ListUi
, LayoutList
);
1386 DrawGenericList(&ListUi
,
1392 SaveGenericListState(LayoutList
);
1394 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1399 IsDiskSizeValid(PPARTENTRY PartEntry
)
1403 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1404 size
= (size
+ (512 * KB
)) / MB
; /* in MBytes */
1406 if (size
< USetupData
.RequiredPartitionDiskSpace
)
1408 /* Partition is too small so ask for another one */
1409 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, USetupData
.RequiredPartitionDiskSpace
);
1420 * Displays the SelectPartitionPage.
1423 * SelectFileSystemPage (At once if unattended)
1424 * SelectFileSystemPage (Default if free space is selected)
1425 * CreatePrimaryPartitionPage
1426 * CreateExtendedPartitionPage
1427 * CreateLogicalPartitionPage
1428 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1429 * DeletePartitionPage
1433 * Set InstallShortcut (only if not unattended + free space is selected)
1436 * Number of the next page.
1439 SelectPartitionPage(PINPUT_RECORD Ir
)
1444 if (PartitionList
== NULL
)
1446 PartitionList
= CreatePartitionList();
1447 if (PartitionList
== NULL
)
1449 /* FIXME: show an error dialog */
1450 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1453 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1455 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1459 TempPartition
= NULL
;
1460 FormatState
= Start
;
1463 if (RepairUpdateFlag
)
1465 /* Determine the selected installation disk & partition */
1466 if (!SelectPartition(PartitionList
,
1467 CurrentInstallation
->DiskNumber
,
1468 CurrentInstallation
->PartitionNumber
))
1470 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1474 return SELECT_FILE_SYSTEM_PAGE
;
1477 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1479 InitPartitionListUi(&ListUi
, PartitionList
,
1484 DrawPartitionList(&ListUi
);
1486 if (IsUnattendedSetup
)
1488 if (!SelectPartition(PartitionList
,
1489 USetupData
.DestinationDiskNumber
,
1490 USetupData
.DestinationPartitionNumber
))
1492 if (USetupData
.AutoPartition
)
1494 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1496 CreateLogicalPartition(PartitionList
,
1497 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1502 CreatePrimaryPartition(PartitionList
,
1503 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1507 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1508 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1510 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1511 USetupData
.RequiredPartitionDiskSpace
);
1512 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1515 return SELECT_FILE_SYSTEM_PAGE
;
1520 DrawPartitionList(&ListUi
);
1522 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1523 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1525 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1526 USetupData
.RequiredPartitionDiskSpace
);
1527 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1530 return SELECT_FILE_SYSTEM_PAGE
;
1536 /* Update status text */
1537 if (PartitionList
->CurrentPartition
== NULL
)
1539 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1541 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1543 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1545 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1549 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1554 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1556 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1558 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1562 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1567 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1571 CONSOLE_ConInKey(Ir
);
1573 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1574 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1576 if (ConfirmQuit(Ir
))
1578 DestroyPartitionList(PartitionList
);
1579 PartitionList
= NULL
;
1585 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1586 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1588 ScrollDownPartitionList(&ListUi
);
1590 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1591 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1593 ScrollUpPartitionList(&ListUi
);
1595 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1597 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1598 continue; // return SELECT_PARTITION_PAGE;
1600 if (PartitionList
->CurrentPartition
== NULL
||
1601 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1603 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1605 CreateLogicalPartition(PartitionList
,
1611 CreatePrimaryPartition(PartitionList
,
1617 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1619 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1620 USetupData
.RequiredPartitionDiskSpace
);
1621 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1624 return SELECT_FILE_SYSTEM_PAGE
;
1626 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1628 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1630 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1631 if (Error
!= NOT_AN_ERROR
)
1633 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1634 return SELECT_PARTITION_PAGE
;
1637 return CREATE_PRIMARY_PARTITION_PAGE
;
1640 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1642 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1644 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1645 if (Error
!= NOT_AN_ERROR
)
1647 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1648 return SELECT_PARTITION_PAGE
;
1651 return CREATE_EXTENDED_PARTITION_PAGE
;
1654 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1656 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1658 Error
= LogicalPartitionCreationChecks(PartitionList
);
1659 if (Error
!= NOT_AN_ERROR
)
1661 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1662 return SELECT_PARTITION_PAGE
;
1665 return CREATE_LOGICAL_PARTITION_PAGE
;
1668 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1670 WCHAR PathBuffer
[MAX_PATH
];
1671 UNICODE_STRING CurrentPartition
;
1673 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1675 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1676 return SELECT_PARTITION_PAGE
;
1679 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
1680 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
1681 PartitionList
->CurrentDisk
->DiskNumber
,
1682 PartitionList
->CurrentPartition
->PartitionNumber
);
1683 RtlInitUnicodeString(&CurrentPartition
, PathBuffer
);
1686 * Check whether the user attempts to delete the partition on which
1687 * the installation source is present. If so, fail with an error.
1689 // &USetupData.SourceRootPath
1690 if (RtlPrefixUnicodeString(&CurrentPartition
, &USetupData
.SourcePath
, TRUE
))
1692 PopupError("You cannot delete the partition containing the installation source!",
1693 MUIGetString(STRING_CONTINUE
),
1694 Ir
, POPUP_WAIT_ENTER
);
1695 return SELECT_PARTITION_PAGE
;
1698 if (PartitionList
->CurrentPartition
->BootIndicator
||
1699 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1701 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1704 return DELETE_PARTITION_PAGE
;
1708 return SELECT_PARTITION_PAGE
;
1712 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1713 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1714 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1717 ShowPartitionSizeInputBox(SHORT Left
,
1741 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1746 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1747 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1750 WriteConsoleOutputCharacterA(StdOutput
,
1756 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1757 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1759 WriteConsoleOutputCharacterA(StdOutput
,
1765 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1766 Length
= wcslen(InputBuffer
);
1768 CONSOLE_SetInputTextXY(iLeft
,
1770 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1772 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1773 CONSOLE_SetCursorType(TRUE
, TRUE
);
1777 CONSOLE_ConInKey(&Ir
);
1779 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1780 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1785 InputBuffer
[0] = UNICODE_NULL
;
1786 CONSOLE_SetCursorType(TRUE
, FALSE
);
1789 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1791 CONSOLE_SetCursorType(TRUE
, FALSE
);
1794 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1799 InputBuffer
[0] = UNICODE_NULL
;
1800 CONSOLE_SetCursorType(TRUE
, FALSE
);
1803 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1804 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1807 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1809 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1810 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1813 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1815 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1816 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1821 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1824 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1825 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1830 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1833 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1834 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1838 memmove(&InputBuffer
[Pos
],
1839 &InputBuffer
[Pos
+ 1],
1840 (Length
- Pos
- 1) * sizeof(WCHAR
));
1841 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1844 CONSOLE_SetInputTextXY(iLeft
,
1846 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1848 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1851 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1856 memmove(&InputBuffer
[Pos
- 1],
1858 (Length
- Pos
) * sizeof(WCHAR
));
1859 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1863 CONSOLE_SetInputTextXY(iLeft
,
1865 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1867 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1870 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1872 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1874 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1876 if ((ch
>= L
'0') && (ch
<= L
'9'))
1879 memmove(&InputBuffer
[Pos
+ 1],
1881 (Length
- Pos
) * sizeof(WCHAR
));
1882 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1883 InputBuffer
[Pos
] = ch
;
1887 CONSOLE_SetInputTextXY(iLeft
,
1889 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1891 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1900 * Displays the CreatePrimaryPartitionPage.
1903 * SelectPartitionPage
1904 * SelectFileSystemPage (default)
1908 * Number of the next page.
1911 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1913 PDISKENTRY DiskEntry
;
1914 PPARTENTRY PartEntry
;
1917 WCHAR InputBuffer
[50];
1921 ULONGLONG SectorCount
;
1924 if (PartitionList
== NULL
||
1925 PartitionList
->CurrentDisk
== NULL
||
1926 PartitionList
->CurrentPartition
== NULL
)
1928 /* FIXME: show an error dialog */
1932 DiskEntry
= PartitionList
->CurrentDisk
;
1933 PartEntry
= PartitionList
->CurrentPartition
;
1935 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1937 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1939 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1941 if (DiskSize
>= 10 * GB
) /* 10 GB */
1943 DiskSize
= DiskSize
/ GB
;
1944 Unit
= MUIGetString(STRING_GB
);
1949 DiskSize
= DiskSize
/ MB
;
1953 Unit
= MUIGetString(STRING_MB
);
1956 if (DiskEntry
->DriverName
.Length
> 0)
1958 CONSOLE_PrintTextXY(6, 10,
1959 MUIGetString(STRING_HDINFOPARTCREATE_1
),
1962 DiskEntry
->DiskNumber
,
1966 &DiskEntry
->DriverName
,
1967 DiskEntry
->NoMbr
? "GPT" : "MBR");
1971 CONSOLE_PrintTextXY(6, 10,
1972 MUIGetString(STRING_HDINFOPARTCREATE_2
),
1975 DiskEntry
->DiskNumber
,
1979 DiskEntry
->NoMbr
? "GPT" : "MBR");
1982 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
1985 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1986 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
1989 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
1991 PartEntry
= PartitionList
->CurrentPartition
;
1994 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
1996 if (MaxSize
> PARTITION_MAXSIZE
)
1997 MaxSize
= PARTITION_MAXSIZE
;
1999 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2000 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2004 if (ConfirmQuit(Ir
))
2011 return SELECT_PARTITION_PAGE
;
2015 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2023 if (PartSize
> MaxSize
)
2029 /* Convert to bytes */
2030 if (PartSize
== MaxSize
)
2032 /* Use all of the unpartitioned disk space */
2033 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2037 /* Calculate the sector count from the size in MB */
2038 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2040 /* But never get larger than the unpartitioned disk space */
2041 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2042 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2045 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2047 CreatePrimaryPartition(PartitionList
,
2051 return SELECT_PARTITION_PAGE
;
2055 return CREATE_PRIMARY_PARTITION_PAGE
;
2060 * Displays the CreateExtendedPartitionPage.
2063 * SelectPartitionPage (default)
2067 * Number of the next page.
2070 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2072 PDISKENTRY DiskEntry
;
2073 PPARTENTRY PartEntry
;
2076 WCHAR InputBuffer
[50];
2080 ULONGLONG SectorCount
;
2083 if (PartitionList
== NULL
||
2084 PartitionList
->CurrentDisk
== NULL
||
2085 PartitionList
->CurrentPartition
== NULL
)
2087 /* FIXME: show an error dialog */
2091 DiskEntry
= PartitionList
->CurrentDisk
;
2092 PartEntry
= PartitionList
->CurrentPartition
;
2094 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2096 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2098 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2100 if (DiskSize
>= 10 * GB
) /* 10 GB */
2102 DiskSize
= DiskSize
/ GB
;
2103 Unit
= MUIGetString(STRING_GB
);
2108 DiskSize
= DiskSize
/ MB
;
2112 Unit
= MUIGetString(STRING_MB
);
2115 if (DiskEntry
->DriverName
.Length
> 0)
2117 CONSOLE_PrintTextXY(6, 10,
2118 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2121 DiskEntry
->DiskNumber
,
2125 &DiskEntry
->DriverName
,
2126 DiskEntry
->NoMbr
? "GPT" : "MBR");
2130 CONSOLE_PrintTextXY(6, 10,
2131 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2134 DiskEntry
->DiskNumber
,
2138 DiskEntry
->NoMbr
? "GPT" : "MBR");
2141 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2144 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2145 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2148 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2150 PartEntry
= PartitionList
->CurrentPartition
;
2153 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2155 if (MaxSize
> PARTITION_MAXSIZE
)
2156 MaxSize
= PARTITION_MAXSIZE
;
2158 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2159 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2163 if (ConfirmQuit(Ir
))
2170 return SELECT_PARTITION_PAGE
;
2174 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2182 if (PartSize
> MaxSize
)
2188 /* Convert to bytes */
2189 if (PartSize
== MaxSize
)
2191 /* Use all of the unpartitioned disk space */
2192 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2196 /* Calculate the sector count from the size in MB */
2197 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2199 /* But never get larger than the unpartitioned disk space */
2200 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2201 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2204 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2206 CreateExtendedPartition(PartitionList
,
2209 return SELECT_PARTITION_PAGE
;
2213 return CREATE_EXTENDED_PARTITION_PAGE
;
2218 * Displays the CreateLogicalPartitionPage.
2221 * SelectFileSystemPage (default)
2225 * Number of the next page.
2228 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2230 PDISKENTRY DiskEntry
;
2231 PPARTENTRY PartEntry
;
2234 WCHAR InputBuffer
[50];
2238 ULONGLONG SectorCount
;
2241 if (PartitionList
== NULL
||
2242 PartitionList
->CurrentDisk
== NULL
||
2243 PartitionList
->CurrentPartition
== NULL
)
2245 /* FIXME: show an error dialog */
2249 DiskEntry
= PartitionList
->CurrentDisk
;
2250 PartEntry
= PartitionList
->CurrentPartition
;
2252 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2254 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2256 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2258 if (DiskSize
>= 10 * GB
) /* 10 GB */
2260 DiskSize
= DiskSize
/ GB
;
2261 Unit
= MUIGetString(STRING_GB
);
2266 DiskSize
= DiskSize
/ MB
;
2270 Unit
= MUIGetString(STRING_MB
);
2273 if (DiskEntry
->DriverName
.Length
> 0)
2275 CONSOLE_PrintTextXY(6, 10,
2276 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2279 DiskEntry
->DiskNumber
,
2283 &DiskEntry
->DriverName
,
2284 DiskEntry
->NoMbr
? "GPT" : "MBR");
2288 CONSOLE_PrintTextXY(6, 10,
2289 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2292 DiskEntry
->DiskNumber
,
2296 DiskEntry
->NoMbr
? "GPT" : "MBR");
2299 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2302 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2303 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2306 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2308 PartEntry
= PartitionList
->CurrentPartition
;
2311 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2313 if (MaxSize
> PARTITION_MAXSIZE
)
2314 MaxSize
= PARTITION_MAXSIZE
;
2316 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2317 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2321 if (ConfirmQuit(Ir
))
2328 return SELECT_PARTITION_PAGE
;
2332 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2340 if (PartSize
> MaxSize
)
2346 /* Convert to bytes */
2347 if (PartSize
== MaxSize
)
2349 /* Use all of the unpartitioned disk space */
2350 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2354 /* Calculate the sector count from the size in MB */
2355 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2357 /* But never get larger than the unpartitioned disk space */
2358 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2359 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2362 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2364 CreateLogicalPartition(PartitionList
,
2368 return SELECT_PARTITION_PAGE
;
2372 return CREATE_LOGICAL_PARTITION_PAGE
;
2377 * Displays the ConfirmDeleteSystemPartitionPage.
2380 * DeletePartitionPage (default)
2381 * SelectPartitionPage
2384 * Number of the next page.
2387 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2389 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2393 CONSOLE_ConInKey(Ir
);
2395 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2396 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2398 if (ConfirmQuit(Ir
))
2403 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2405 return DELETE_PARTITION_PAGE
;
2407 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2409 return SELECT_PARTITION_PAGE
;
2413 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2418 * Displays the DeletePartitionPage.
2421 * SelectPartitionPage (default)
2425 * Number of the next page.
2428 DeletePartitionPage(PINPUT_RECORD Ir
)
2430 PDISKENTRY DiskEntry
;
2431 PPARTENTRY PartEntry
;
2435 CHAR PartTypeString
[32];
2437 if (PartitionList
== NULL
||
2438 PartitionList
->CurrentDisk
== NULL
||
2439 PartitionList
->CurrentPartition
== NULL
)
2441 /* FIXME: show an error dialog */
2445 DiskEntry
= PartitionList
->CurrentDisk
;
2446 PartEntry
= PartitionList
->CurrentPartition
;
2448 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2450 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2452 ARRAYSIZE(PartTypeString
));
2454 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2456 if (PartSize
>= 10 * GB
) /* 10 GB */
2458 PartSize
= PartSize
/ GB
;
2459 Unit
= MUIGetString(STRING_GB
);
2463 if (PartSize
>= 10 * MB
) /* 10 MB */
2465 PartSize
= PartSize
/ MB
;
2466 Unit
= MUIGetString(STRING_MB
);
2470 PartSize
= PartSize
/ KB
;
2471 Unit
= MUIGetString(STRING_KB
);
2474 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2476 CONSOLE_PrintTextXY(6, 10,
2477 MUIGetString(STRING_HDDINFOUNK2
),
2478 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2479 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2480 PartEntry
->PartitionType
,
2486 CONSOLE_PrintTextXY(6, 10,
2487 " %c%c %s %I64u %s",
2488 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2489 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2495 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2497 if (DiskSize
>= 10 * GB
) /* 10 GB */
2499 DiskSize
= DiskSize
/ GB
;
2500 Unit
= MUIGetString(STRING_GB
);
2505 DiskSize
= DiskSize
/ MB
;
2509 Unit
= MUIGetString(STRING_MB
);
2512 if (DiskEntry
->DriverName
.Length
> 0)
2514 CONSOLE_PrintTextXY(6, 12,
2515 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2518 DiskEntry
->DiskNumber
,
2522 &DiskEntry
->DriverName
,
2523 DiskEntry
->NoMbr
? "GPT" : "MBR");
2527 CONSOLE_PrintTextXY(6, 12,
2528 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2531 DiskEntry
->DiskNumber
,
2535 DiskEntry
->NoMbr
? "GPT" : "MBR");
2540 CONSOLE_ConInKey(Ir
);
2542 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2543 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2545 if (ConfirmQuit(Ir
))
2550 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2552 return SELECT_PARTITION_PAGE
;
2554 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2556 DeleteCurrentPartition(PartitionList
);
2558 return SELECT_PARTITION_PAGE
;
2562 return DELETE_PARTITION_PAGE
;
2567 * Displays the SelectFileSystemPage.
2570 * CheckFileSystemPage (At once if RepairUpdate is selected)
2571 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2572 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2573 * SelectPartitionPage (If the user aborts)
2574 * FormatPartitionPage (Default)
2578 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2579 * Calls CheckActiveSystemPartition()
2582 * Number of the next page.
2585 SelectFileSystemPage(PINPUT_RECORD Ir
)
2587 PDISKENTRY DiskEntry
;
2588 PPARTENTRY PartEntry
;
2593 CHAR PartTypeString
[32];
2594 FORMATMACHINESTATE PreviousFormatState
;
2596 DPRINT("SelectFileSystemPage()\n");
2598 if (PartitionList
== NULL
||
2599 PartitionList
->CurrentDisk
== NULL
||
2600 PartitionList
->CurrentPartition
== NULL
)
2602 /* FIXME: show an error dialog */
2606 /* Find or set the active system partition */
2607 CheckActiveSystemPartition(PartitionList
);
2608 if (PartitionList
->SystemPartition
== NULL
)
2610 /* FIXME: show an error dialog */
2612 // Error dialog should say that we cannot find a suitable
2613 // system partition and create one on the system. At this point,
2614 // it may be nice to ask the user whether he wants to continue,
2615 // or use an external drive as the system drive/partition
2616 // (e.g. floppy, USB drive, etc...)
2621 PreviousFormatState
= FormatState
;
2622 switch (FormatState
)
2626 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2628 TempPartition
= PartitionList
->SystemPartition
;
2629 TempPartition
->NeedsCheck
= TRUE
;
2631 FormatState
= FormatSystemPartition
;
2632 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2636 TempPartition
= PartitionList
->CurrentPartition
;
2637 TempPartition
->NeedsCheck
= TRUE
;
2639 FormatState
= FormatInstallPartition
;
2640 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2645 case FormatSystemPartition
:
2647 TempPartition
= PartitionList
->CurrentPartition
;
2648 TempPartition
->NeedsCheck
= TRUE
;
2650 FormatState
= FormatInstallPartition
;
2651 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2655 case FormatInstallPartition
:
2657 if (GetNextUnformattedPartition(PartitionList
,
2661 FormatState
= FormatOtherPartition
;
2662 TempPartition
->NeedsCheck
= TRUE
;
2663 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2667 FormatState
= FormatDone
;
2668 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2669 return CHECK_FILE_SYSTEM_PAGE
;
2674 case FormatOtherPartition
:
2676 if (GetNextUnformattedPartition(PartitionList
,
2680 FormatState
= FormatOtherPartition
;
2681 TempPartition
->NeedsCheck
= TRUE
;
2682 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2686 FormatState
= FormatDone
;
2687 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2688 return CHECK_FILE_SYSTEM_PAGE
;
2695 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2696 /* FIXME: show an error dialog */
2701 PartEntry
= TempPartition
;
2702 DiskEntry
= PartEntry
->DiskEntry
;
2704 /* Adjust disk size */
2705 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2706 if (DiskSize
>= 10 * GB
) /* 10 GB */
2708 DiskSize
= DiskSize
/ GB
;
2709 DiskUnit
= MUIGetString(STRING_GB
);
2713 DiskSize
= DiskSize
/ MB
;
2714 DiskUnit
= MUIGetString(STRING_MB
);
2717 /* Adjust partition size */
2718 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2719 if (PartSize
>= 10 * GB
) /* 10 GB */
2721 PartSize
= PartSize
/ GB
;
2722 PartUnit
= MUIGetString(STRING_GB
);
2726 PartSize
= PartSize
/ MB
;
2727 PartUnit
= MUIGetString(STRING_MB
);
2730 /* Adjust partition type */
2731 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2733 ARRAYSIZE(PartTypeString
));
2735 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2737 if (PartEntry
->AutoCreate
)
2739 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2742 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2743 PartEntry
->PartitionNumber
,
2749 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2750 DiskEntry
->DiskNumber
,
2756 &DiskEntry
->DriverName
,
2757 DiskEntry
->NoMbr
? "GPT" : "MBR");
2759 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2761 PartEntry
->AutoCreate
= FALSE
;
2763 else if (PartEntry
->New
)
2765 switch (FormatState
)
2767 case FormatSystemPartition
:
2768 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2771 case FormatInstallPartition
:
2772 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2775 case FormatOtherPartition
:
2776 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2783 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2787 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2789 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2791 CONSOLE_PrintTextXY(8, 10,
2792 MUIGetString(STRING_HDDINFOUNK4
),
2793 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2794 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2795 PartEntry
->PartitionType
,
2801 CONSOLE_PrintTextXY(8, 10,
2803 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2804 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2810 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
2811 DiskEntry
->DiskNumber
,
2817 &DiskEntry
->DriverName
,
2818 DiskEntry
->NoMbr
? "GPT" : "MBR");
2821 if (FileSystemList
== NULL
)
2823 /* Create the file system list, and by default select the "FAT" file system */
2824 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2825 if (FileSystemList
== NULL
)
2827 /* FIXME: show an error dialog */
2832 if (RepairUpdateFlag
)
2834 return CHECK_FILE_SYSTEM_PAGE
;
2835 //return SELECT_PARTITION_PAGE;
2838 if (IsUnattendedSetup
)
2840 if (USetupData
.FormatPartition
)
2843 * We use whatever currently selected file system we have
2844 * (by default, this is "FAT", as per the initialization
2845 * performed above). Note that it may be interesting to specify
2846 * which file system to use in unattended installations, in the
2847 * txtsetup.sif file.
2849 return FORMAT_PARTITION_PAGE
;
2852 return CHECK_FILE_SYSTEM_PAGE
;
2855 DrawFileSystemList(FileSystemList
);
2859 CONSOLE_ConInKey(Ir
);
2861 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2862 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2864 if (ConfirmQuit(Ir
))
2869 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2870 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2872 FormatState
= Start
;
2873 return SELECT_PARTITION_PAGE
;
2875 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2876 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2878 ScrollDownFileSystemList(FileSystemList
);
2880 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2881 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2883 ScrollUpFileSystemList(FileSystemList
);
2885 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2887 if (!FileSystemList
->Selected
->FileSystem
)
2888 return SELECT_FILE_SYSTEM_PAGE
;
2890 return FORMAT_PARTITION_PAGE
;
2894 FormatState
= PreviousFormatState
;
2896 return SELECT_FILE_SYSTEM_PAGE
;
2901 * Displays the FormatPartitionPage.
2904 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2905 * SelectPartitionPage (At once)
2909 * Sets PartitionList->CurrentPartition->FormatState
2910 * Sets USetupData.DestinationRootPath
2913 * Number of the next page.
2916 FormatPartitionPage(PINPUT_RECORD Ir
)
2919 PDISKENTRY DiskEntry
;
2920 PPARTENTRY PartEntry
;
2921 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2922 UNICODE_STRING PartitionRootPath
;
2923 WCHAR PathBuffer
[MAX_PATH
];
2924 CHAR Buffer
[MAX_PATH
];
2929 PPARTITION_INFORMATION PartitionInfo
;
2932 DPRINT("FormatPartitionPage()\n");
2934 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2936 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2938 /* FIXME: show an error dialog */
2942 PartEntry
= TempPartition
;
2943 DiskEntry
= PartEntry
->DiskEntry
;
2945 SelectedFileSystem
= FileSystemList
->Selected
;
2949 if (!IsUnattendedSetup
)
2951 CONSOLE_ConInKey(Ir
);
2954 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2955 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2957 if (ConfirmQuit(Ir
))
2962 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2964 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2966 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2968 /* FIXME: show an error dialog */
2973 CONSOLE_PrintTextXY(6, 12,
2974 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
2975 DiskEntry
->Cylinders
,
2976 DiskEntry
->TracksPerCylinder
,
2977 DiskEntry
->SectorsPerTrack
,
2978 DiskEntry
->BytesPerSector
,
2979 DiskEntry
->Dirty
? '*' : ' ');
2983 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
2985 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
2987 CONSOLE_PrintTextXY(6, Line
,
2988 "%2u: %2lu %c %12I64u %12I64u %02x",
2990 PartitionInfo
->PartitionNumber
,
2991 PartitionInfo
->BootIndicator
? 'A' : '-',
2992 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
2993 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
2994 PartitionInfo
->PartitionType
);
2999 /* Commit the partition changes to the disk */
3000 if (!WritePartitionsToDisk(PartitionList
))
3002 DPRINT("WritePartitionsToDisk() failed\n");
3003 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3007 /* Set PartitionRootPath */
3008 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3009 L
"\\Device\\Harddisk%lu\\Partition%lu",
3010 DiskEntry
->DiskNumber
,
3011 PartEntry
->PartitionNumber
);
3012 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3013 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3015 /* Format the partition */
3016 if (SelectedFileSystem
->FileSystem
)
3018 Status
= FormatPartition(&PartitionRootPath
,
3019 SelectedFileSystem
);
3020 if (Status
== STATUS_NOT_SUPPORTED
)
3023 "Setup is currently unable to format a partition in %S.\n"
3025 " \x07 Press ENTER to continue Setup.\n"
3026 " \x07 Press F3 to quit Setup.",
3027 SelectedFileSystem
->FileSystem
->FileSystemName
);
3030 MUIGetString(STRING_QUITCONTINUE
),
3031 NULL
, POPUP_WAIT_NONE
);
3035 CONSOLE_ConInKey(Ir
);
3037 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3038 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3040 if (ConfirmQuit(Ir
))
3043 return SELECT_FILE_SYSTEM_PAGE
;
3045 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3047 return SELECT_FILE_SYSTEM_PAGE
;
3051 else if (!NT_SUCCESS(Status
))
3053 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3054 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3058 PartEntry
->FormatState
= Formatted
;
3059 // PartEntry->FileSystem = FileSystem;
3060 PartEntry
->New
= FALSE
;
3064 CONSOLE_SetStatusText(" Done. Press any key ...");
3065 CONSOLE_ConInKey(Ir
);
3068 return SELECT_FILE_SYSTEM_PAGE
;
3072 return FORMAT_PARTITION_PAGE
;
3077 * Displays the CheckFileSystemPage.
3080 * InstallDirectoryPage (At once)
3084 * Inits or reloads FileSystemList
3087 * Number of the next page.
3090 CheckFileSystemPage(PINPUT_RECORD Ir
)
3093 PDISKENTRY DiskEntry
;
3094 PPARTENTRY PartEntry
;
3095 PFILE_SYSTEM CurrentFileSystem
;
3096 UNICODE_STRING PartitionRootPath
;
3097 WCHAR PathBuffer
[MAX_PATH
];
3098 CHAR Buffer
[MAX_PATH
];
3100 if (PartitionList
== NULL
)
3102 /* FIXME: show an error dialog */
3106 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3108 return INSTALL_DIRECTORY_PAGE
;
3111 /* Set PartitionRootPath */
3112 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3113 L
"\\Device\\Harddisk%lu\\Partition%lu",
3114 DiskEntry
->DiskNumber
,
3115 PartEntry
->PartitionNumber
);
3116 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3117 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3119 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3121 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3123 CurrentFileSystem
= PartEntry
->FileSystem
;
3124 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3125 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3127 /* HACK: Do not try to check a partition with an unknown filesystem */
3128 if (CurrentFileSystem
== NULL
)
3130 PartEntry
->NeedsCheck
= FALSE
;
3131 return CHECK_FILE_SYSTEM_PAGE
;
3134 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3135 if (Status
== STATUS_NOT_SUPPORTED
)
3138 "Setup is currently unable to check a partition formatted in %S.\n"
3140 " \x07 Press ENTER to continue Setup.\n"
3141 " \x07 Press F3 to quit Setup.",
3142 CurrentFileSystem
->FileSystemName
);
3145 MUIGetString(STRING_QUITCONTINUE
),
3146 NULL
, POPUP_WAIT_NONE
);
3150 CONSOLE_ConInKey(Ir
);
3152 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3153 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3155 if (ConfirmQuit(Ir
))
3158 return CHECK_FILE_SYSTEM_PAGE
;
3160 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3162 PartEntry
->NeedsCheck
= FALSE
;
3163 return CHECK_FILE_SYSTEM_PAGE
;
3167 else if (!NT_SUCCESS(Status
))
3169 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3170 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3171 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3172 "(Status 0x%08lx).\n", Status
);
3174 // MUIGetString(STRING_REBOOTCOMPUTER),
3175 MUIGetString(STRING_CONTINUE
),
3176 Ir
, POPUP_WAIT_ENTER
);
3178 // return QUIT_PAGE;
3181 PartEntry
->NeedsCheck
= FALSE
;
3182 return CHECK_FILE_SYSTEM_PAGE
;
3187 BuildInstallPaths(PWSTR InstallDir
,
3188 PDISKENTRY DiskEntry
,
3189 PPARTENTRY PartEntry
)
3191 WCHAR PathBuffer
[MAX_PATH
];
3193 /** Equivalent of 'NTOS_INSTALLATION::PathComponent' **/
3194 /* Create 'InstallPath' string */
3195 RtlFreeUnicodeString(&InstallPath
);
3196 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3198 /* Create 'USetupData.DestinationRootPath' string */
3199 RtlFreeUnicodeString(&USetupData
.DestinationRootPath
);
3200 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3201 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
3202 DiskEntry
->DiskNumber
,
3203 PartEntry
->PartitionNumber
);
3204 RtlCreateUnicodeString(&USetupData
.DestinationRootPath
, PathBuffer
);
3205 DPRINT("DestinationRootPath: %wZ\n", &USetupData
.DestinationRootPath
);
3207 /** Equivalent of 'NTOS_INSTALLATION::SystemNtPath' **/
3208 /* Create 'USetupData.DestinationPath' string */
3209 RtlFreeUnicodeString(&USetupData
.DestinationPath
);
3210 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3211 USetupData
.DestinationRootPath
.Buffer
, InstallDir
);
3212 RtlCreateUnicodeString(&USetupData
.DestinationPath
, PathBuffer
);
3214 /** Equivalent of 'NTOS_INSTALLATION::SystemArcPath' **/
3215 /* Create 'USetupData.DestinationArcPath' */
3216 RtlFreeUnicodeString(&USetupData
.DestinationArcPath
);
3217 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3218 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
3219 DiskEntry
->BiosDiskNumber
,
3220 PartEntry
->PartitionNumber
);
3221 ConcatPaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 1, InstallDir
);
3222 RtlCreateUnicodeString(&USetupData
.DestinationArcPath
, PathBuffer
);
3224 /* Initialize DestinationDriveLetter */
3225 DestinationDriveLetter
= (WCHAR
)PartEntry
->DriveLetter
;
3230 * Displays the InstallDirectoryPage.
3237 * Number of the next page.
3240 InstallDirectoryPage(PINPUT_RECORD Ir
)
3242 PDISKENTRY DiskEntry
;
3243 PPARTENTRY PartEntry
;
3244 WCHAR InstallDir
[MAX_PATH
];
3248 /* We do not need the filesystem list anymore */
3249 if (FileSystemList
!= NULL
)
3251 DestroyFileSystemList(FileSystemList
);
3252 FileSystemList
= NULL
;
3255 if (PartitionList
== NULL
||
3256 PartitionList
->CurrentDisk
== NULL
||
3257 PartitionList
->CurrentPartition
== NULL
)
3259 /* FIXME: show an error dialog */
3263 DiskEntry
= PartitionList
->CurrentDisk
;
3264 PartEntry
= PartitionList
->CurrentPartition
;
3266 // if (IsUnattendedSetup)
3267 if (RepairUpdateFlag
)
3268 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3269 else if (USetupData
.InstallationDirectory
[0])
3270 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3272 wcscpy(InstallDir
, L
"\\ReactOS");
3275 * Check the validity of the predefined 'InstallDir'. If we are either
3276 * in unattended setup or in update/repair mode, and the installation path
3277 * is valid, just perform the installation. Otherwise (either in the case
3278 * of an invalid path, or we are in regular setup), display the UI and allow
3279 * the user to specify a new installation path.
3281 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3283 BuildInstallPaths(InstallDir
,
3288 * Check whether the user attempts to install ReactOS within the
3289 * installation source directory, or in a subdirectory thereof.
3290 * If so, fail with an error.
3292 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3294 PopupError("You cannot install ReactOS within the installation source directory!",
3295 MUIGetString(STRING_CONTINUE
),
3296 Ir
, POPUP_WAIT_ENTER
);
3297 return INSTALL_DIRECTORY_PAGE
;
3300 return PREPARE_COPY_PAGE
;
3303 Length
= wcslen(InstallDir
);
3306 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3307 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3308 CONSOLE_SetCursorXY(8 + Pos
, 11);
3309 CONSOLE_SetCursorType(TRUE
, TRUE
);
3313 CONSOLE_ConInKey(Ir
);
3315 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3316 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3318 CONSOLE_SetCursorType(TRUE
, FALSE
);
3320 if (ConfirmQuit(Ir
))
3323 CONSOLE_SetCursorType(TRUE
, TRUE
);
3326 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3327 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3331 memmove(&InstallDir
[Pos
],
3332 &InstallDir
[Pos
+ 1],
3333 (Length
- Pos
- 1) * sizeof(WCHAR
));
3334 InstallDir
[Length
- 1] = UNICODE_NULL
;
3337 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3338 CONSOLE_SetCursorXY(8 + Pos
, 11);
3341 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3342 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3345 CONSOLE_SetCursorXY(8 + Pos
, 11);
3347 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3348 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3351 CONSOLE_SetCursorXY(8 + Pos
, 11);
3353 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3354 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3359 CONSOLE_SetCursorXY(8 + Pos
, 11);
3362 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3363 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3368 CONSOLE_SetCursorXY(8 + Pos
, 11);
3371 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3373 CONSOLE_SetCursorType(TRUE
, FALSE
);
3376 * Check for the validity of the installation directory and pop up
3377 * an error if it is not the case. Then the user can fix its input.
3379 if (!IsValidPath(InstallDir
))
3381 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3382 return INSTALL_DIRECTORY_PAGE
;
3385 BuildInstallPaths(InstallDir
,
3390 * Check whether the user attempts to install ReactOS within the
3391 * installation source directory, or in a subdirectory thereof.
3392 * If so, fail with an error.
3394 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3396 PopupError("You cannot install ReactOS within the installation source directory!",
3397 MUIGetString(STRING_CONTINUE
),
3398 Ir
, POPUP_WAIT_ENTER
);
3399 return INSTALL_DIRECTORY_PAGE
;
3402 return PREPARE_COPY_PAGE
;
3404 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3409 memmove(&InstallDir
[Pos
- 1],
3411 (Length
- Pos
) * sizeof(WCHAR
));
3412 InstallDir
[Length
- 1] = UNICODE_NULL
;
3416 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3417 CONSOLE_SetCursorXY(8 + Pos
, 11);
3420 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3424 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3425 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3428 memmove(&InstallDir
[Pos
+ 1],
3430 (Length
- Pos
) * sizeof(WCHAR
));
3431 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3432 InstallDir
[Pos
] = c
;
3436 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3437 CONSOLE_SetCursorXY(8 + Pos
, 11);
3443 return INSTALL_DIRECTORY_PAGE
;
3448 AddSectionToCopyQueueCab(HINF InfFile
,
3450 PWCHAR SourceCabinet
,
3451 PCUNICODE_STRING DestinationPath
,
3454 INFCONTEXT FilesContext
;
3455 INFCONTEXT DirContext
;
3457 PWCHAR FileKeyValue
;
3459 PWCHAR TargetFileName
;
3462 * This code enumerates the list of files in reactos.dff / reactos.inf
3463 * that need to be extracted from reactos.cab and be installed in their
3464 * respective directories.
3467 /* Search for the SectionName section */
3468 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3471 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3472 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3477 * Enumerate the files in the section and add them to the file queue.
3481 /* Get source file name and target directory id */
3482 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3484 /* FIXME: Handle error! */
3485 DPRINT1("INF_GetData() failed\n");
3489 /* Get optional target file name */
3490 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3491 TargetFileName
= NULL
;
3493 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3495 /* Lookup target directory */
3496 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3498 /* FIXME: Handle error! */
3499 DPRINT1("SetupFindFirstLine() failed\n");
3500 INF_FreeData(FileKeyName
);
3501 INF_FreeData(FileKeyValue
);
3502 INF_FreeData(TargetFileName
);
3506 INF_FreeData(FileKeyValue
);
3508 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3510 /* FIXME: Handle error! */
3511 DPRINT1("INF_GetData() failed\n");
3512 INF_FreeData(FileKeyName
);
3513 INF_FreeData(TargetFileName
);
3517 if (!SetupQueueCopy(SetupFileQueue
,
3519 USetupData
.SourceRootPath
.Buffer
,
3520 USetupData
.SourceRootDir
.Buffer
,
3525 /* FIXME: Handle error! */
3526 DPRINT1("SetupQueueCopy() failed\n");
3529 INF_FreeData(FileKeyName
);
3530 INF_FreeData(TargetFileName
);
3531 INF_FreeData(DirKeyValue
);
3532 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3539 AddSectionToCopyQueue(HINF InfFile
,
3541 PWCHAR SourceCabinet
,
3542 PCUNICODE_STRING DestinationPath
,
3545 INFCONTEXT FilesContext
;
3546 INFCONTEXT DirContext
;
3548 PWCHAR FileKeyValue
;
3550 PWCHAR TargetFileName
;
3551 WCHAR CompleteOrigDirName
[512]; // FIXME: MAX_PATH is not enough?
3554 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3557 * This code enumerates the list of files in txtsetup.sif
3558 * that need to be installed in their respective directories.
3561 /* Search for the SectionName section */
3562 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3565 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3566 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3571 * Enumerate the files in the section and add them to the file queue.
3575 /* Get source file name */
3576 if (!INF_GetDataField(&FilesContext
, 0, &FileKeyName
))
3578 /* FIXME: Handle error! */
3579 DPRINT1("INF_GetData() failed\n");
3583 /* Get target directory id */
3584 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3586 /* FIXME: Handle error! */
3587 DPRINT1("INF_GetData() failed\n");
3588 INF_FreeData(FileKeyName
);
3592 /* Get optional target file name */
3593 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3594 TargetFileName
= NULL
;
3595 else if (!*TargetFileName
)
3596 TargetFileName
= NULL
;
3598 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3600 /* Lookup target directory */
3601 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3603 /* FIXME: Handle error! */
3604 DPRINT1("SetupFindFirstLine() failed\n");
3605 INF_FreeData(FileKeyName
);
3606 INF_FreeData(FileKeyValue
);
3607 INF_FreeData(TargetFileName
);
3611 INF_FreeData(FileKeyValue
);
3613 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3615 /* FIXME: Handle error! */
3616 DPRINT1("INF_GetData() failed\n");
3617 INF_FreeData(FileKeyName
);
3618 INF_FreeData(TargetFileName
);
3622 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3624 /* Installation path */
3625 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3627 RtlStringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3628 USetupData
.SourceRootDir
.Buffer
);
3630 DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName
);
3632 else if (DirKeyValue
[0] == L
'\\')
3635 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3637 RtlStringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3640 DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName
);
3642 else // if (DirKeyValue[0] != L'\\')
3644 /* Path relative to the installation path */
3645 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3647 CombinePaths(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
), 2,
3648 USetupData
.SourceRootDir
.Buffer
, DirKeyValue
);
3650 DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName
);
3653 if (!SetupQueueCopy(SetupFileQueue
,
3655 USetupData
.SourceRootPath
.Buffer
,
3656 CompleteOrigDirName
,
3661 /* FIXME: Handle error! */
3662 DPRINT1("SetupQueueCopy() failed\n");
3665 INF_FreeData(FileKeyName
);
3666 INF_FreeData(TargetFileName
);
3667 INF_FreeData(DirKeyValue
);
3668 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3675 PrepareCopyPageInfFile(HINF InfFile
,
3676 PWCHAR SourceCabinet
,
3680 INFCONTEXT DirContext
;
3681 PWCHAR AdditionalSectionName
= NULL
;
3683 WCHAR PathBuffer
[MAX_PATH
];
3685 /* Add common files */
3686 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &USetupData
.DestinationPath
, Ir
))
3689 /* Add specific files depending of computer type */
3690 if (SourceCabinet
== NULL
)
3692 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3695 if (AdditionalSectionName
)
3697 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &USetupData
.DestinationPath
, Ir
))
3702 /* Create directories */
3706 * Copying files to USetupData.DestinationRootPath should be done from within
3707 * the SystemPartitionFiles section.
3708 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3709 * For installing to USetupData.DestinationPath specify just '\' .
3712 /* Get destination path */
3713 RtlStringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
), USetupData
.DestinationPath
.Buffer
);
3715 DPRINT("FullPath(1): '%S'\n", PathBuffer
);
3717 /* Create the install directory */
3718 Status
= SetupCreateDirectory(PathBuffer
);
3719 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3721 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer
, Status
);
3722 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3726 /* Search for the 'Directories' section */
3727 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3731 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3735 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3741 /* Enumerate the directory values and create the subdirectories */
3744 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3750 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3752 /* Installation path */
3753 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3755 RtlStringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3756 USetupData
.DestinationPath
.Buffer
);
3758 DPRINT("InstallationPath(2): '%S'\n", PathBuffer
);
3760 else if (DirKeyValue
[0] == L
'\\')
3763 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3765 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3766 USetupData
.DestinationRootPath
.Buffer
, DirKeyValue
);
3768 DPRINT("AbsolutePath(2): '%S'\n", PathBuffer
);
3770 Status
= SetupCreateDirectory(PathBuffer
);
3771 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3773 INF_FreeData(DirKeyValue
);
3774 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3775 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3779 else // if (DirKeyValue[0] != L'\\')
3781 /* Path relative to the installation path */
3782 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3784 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3785 USetupData
.DestinationPath
.Buffer
, DirKeyValue
);
3787 DPRINT("RelativePath(2): '%S'\n", PathBuffer
);
3789 Status
= SetupCreateDirectory(PathBuffer
);
3790 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3792 INF_FreeData(DirKeyValue
);
3793 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3794 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3799 INF_FreeData(DirKeyValue
);
3800 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3807 * Displays the PrepareCopyPage.
3810 * FileCopyPage(At once)
3814 * Inits SetupFileQueue
3815 * Calls PrepareCopyPageInfFile
3818 * Number of the next page.
3821 PrepareCopyPage(PINPUT_RECORD Ir
)
3824 WCHAR PathBuffer
[MAX_PATH
];
3825 INFCONTEXT CabinetsContext
;
3831 MUIDisplayPage(PREPARE_COPY_PAGE
);
3833 /* Create the file queue */
3834 SetupFileQueue
= SetupOpenFileQueue();
3835 if (SetupFileQueue
== NULL
)
3837 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3841 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3843 /* FIXME: show an error dialog */
3847 /* Search for the 'Cabinets' section */
3848 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3850 return FILE_COPY_PAGE
;
3854 * Enumerate the directory values in the 'Cabinets'
3855 * section and parse their inf files.
3859 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3862 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3863 USetupData
.SourcePath
.Buffer
, KeyValue
);
3865 CabinetInitialize();
3866 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3867 CabinetSetCabinetName(PathBuffer
);
3869 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3871 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3873 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3874 if (InfFileData
== NULL
)
3876 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3882 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3883 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3887 InfHandle
= INF_OpenBufferedFileA((PSTR
)InfFileData
,
3891 USetupData
.LanguageId
,
3894 if (InfHandle
== INVALID_HANDLE_VALUE
)
3896 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3902 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3904 /* FIXME: show an error dialog */
3907 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3909 return FILE_COPY_PAGE
;
3915 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3918 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3920 /* Get the memory information from the system */
3921 NtQuerySystemInformation(SystemPerformanceInformation
,
3926 /* Check if this is initial setup */
3929 /* Set maximum limits to be total RAM pages */
3930 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3931 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3932 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3935 /* Set current values */
3936 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3937 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3938 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3944 FileCopyCallback(PVOID Context
,
3949 PCOPYCONTEXT CopyContext
;
3951 CopyContext
= (PCOPYCONTEXT
)Context
;
3953 switch (Notification
)
3955 case SPFILENOTIFY_STARTSUBQUEUE
:
3956 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3957 ProgressSetStepCount(CopyContext
->ProgressBar
,
3958 CopyContext
->TotalOperations
);
3959 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3962 case SPFILENOTIFY_STARTCOPY
:
3963 /* Display copy message */
3964 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3965 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3968 case SPFILENOTIFY_ENDCOPY
:
3969 CopyContext
->CompletedOperations
++;
3971 /* SYSREG checkpoint */
3972 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3973 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3975 ProgressNextStep(CopyContext
->ProgressBar
);
3976 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3985 * Displays the FileCopyPage.
3988 * RegistryPage(At once)
3991 * Calls SetupCommitFileQueueW
3992 * Calls SetupCloseFileQueue
3995 * Number of the next page.
3998 FileCopyPage(PINPUT_RECORD Ir
)
4000 COPYCONTEXT CopyContext
;
4001 unsigned int mem_bar_width
;
4003 MUIDisplayPage(FILE_COPY_PAGE
);
4005 /* Create context for the copy process */
4006 CopyContext
.DestinationRootPath
= USetupData
.DestinationRootPath
.Buffer
;
4007 CopyContext
.InstallPath
= InstallPath
.Buffer
;
4008 CopyContext
.TotalOperations
= 0;
4009 CopyContext
.CompletedOperations
= 0;
4011 /* Create the progress bar as well */
4012 CopyContext
.ProgressBar
= CreateProgressBar(13,
4019 MUIGetString(STRING_SETUPCOPYINGFILES
));
4021 // fit memory bars to screen width, distribute them uniform
4022 mem_bar_width
= (xScreen
- 26) / 5;
4023 mem_bar_width
-= mem_bar_width
% 2; // make even
4024 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4025 /* Create the paged pool progress bar */
4026 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
4035 /* Create the non paged pool progress bar */
4036 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
4038 (xScreen
/ 2) + (mem_bar_width
/ 2),
4040 (xScreen
/ 2)- (mem_bar_width
/ 2),
4045 /* Create the global memory progress bar */
4046 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
4050 xScreen
- 13 - mem_bar_width
,
4055 /* Do the file copying */
4056 SetupCommitFileQueueW(NULL
,
4061 /* If we get here, we're done, so cleanup the queue and progress bar */
4062 SetupCloseFileQueue(SetupFileQueue
);
4063 DestroyProgressBar(CopyContext
.ProgressBar
);
4064 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4065 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4066 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4068 /* Create the $winnt$.inf file */
4069 InstallSetupInfFile(&USetupData
);
4071 /* Go display the next page */
4072 return REGISTRY_PAGE
;
4077 * Displays the RegistryPage.
4080 * SuccessPage (if RepairUpdate)
4081 * BootLoaderPage (default)
4085 * Calls RegInitializeRegistry
4086 * Calls ImportRegistryFile
4087 * Calls SetDefaultPagefile
4088 * Calls SetMountedDeviceValues
4091 * Number of the next page.
4094 RegistryPage(PINPUT_RECORD Ir
)
4097 INFCONTEXT InfContext
;
4102 BOOLEAN ShouldRepairRegistry
= FALSE
;
4105 MUIDisplayPage(REGISTRY_PAGE
);
4107 if (RepairUpdateFlag
)
4109 DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n");
4111 /* Verify the registry hives and check whether we need to update or repair any of them */
4112 Status
= VerifyRegistryHives(&USetupData
.DestinationPath
, &ShouldRepairRegistry
);
4113 if (!NT_SUCCESS(Status
))
4115 DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status
);
4116 ShouldRepairRegistry
= FALSE
;
4118 if (!ShouldRepairRegistry
)
4119 DPRINT1("No need to repair the registry\n");
4123 /* Update the registry */
4124 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4126 /* Initialize the registry and setup the registry hives */
4127 Status
= RegInitializeRegistry(&USetupData
.DestinationPath
);
4128 if (!NT_SUCCESS(Status
))
4130 DPRINT1("RegInitializeRegistry() failed\n");
4131 /********** HACK!!!!!!!!!!! **********/
4132 if (Status
== STATUS_NOT_IMPLEMENTED
)
4134 /* The hack was called, display its corresponding error */
4135 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4138 /*************************************/
4140 /* Something else failed */
4141 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4146 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4149 * We fully setup the hives, in case we are doing a fresh installation
4150 * (RepairUpdateFlag == FALSE), or in case we are doing an update
4151 * (RepairUpdateFlag == TRUE) BUT we have some registry hives to
4152 * "repair" (aka. recreate: ShouldRepairRegistry == TRUE).
4155 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Fresh", NULL
, &InfContext
); // Windows-compatible
4157 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
); // ReactOS-specific
4161 DPRINT1("SetupFindFirstLine() failed\n");
4162 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4166 else // if (RepairUpdateFlag && !ShouldRepairRegistry)
4169 * In case we are doing an update (RepairUpdateFlag == TRUE) and
4170 * NO registry hives need a repair (ShouldRepairRegistry == FALSE),
4171 * we only update the hives.
4174 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Upgrade", NULL
, &InfContext
);
4177 /* Nothing to do for update! */
4178 DPRINT1("No update needed for the registry!\n");
4185 INF_GetDataField(&InfContext
, 0, &Action
);
4186 INF_GetDataField(&InfContext
, 1, &File
);
4187 INF_GetDataField(&InfContext
, 2, &Section
);
4189 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4193 INF_FreeData(Action
);
4195 INF_FreeData(Section
);
4199 if (!_wcsicmp(Action
, L
"AddReg"))
4201 else if (!_wcsicmp(Action
, L
"DelReg"))
4205 DPRINT1("Unrecognized registry INF action '%S'\n", Action
);
4206 INF_FreeData(Action
);
4208 INF_FreeData(Section
);
4212 INF_FreeData(Action
);
4214 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4216 if (!ImportRegistryFile(USetupData
.SourcePath
.Buffer
, File
, Section
, USetupData
.LanguageId
, Delete
))
4218 DPRINT1("Importing %S failed\n", File
);
4220 INF_FreeData(Section
);
4221 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4224 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4226 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4228 /* See the explanation for this test above */
4230 /* Update display registry settings */
4231 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYSETTINGSUPDATE
));
4232 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4234 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4238 /* Set the locale */
4239 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4240 if (!ProcessLocaleRegistry(LanguageList
))
4242 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4246 /* Add keyboard layouts */
4247 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4248 if (!AddKeyboardLayouts(SelectedLanguageId
))
4250 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4255 if (!SetGeoID(MUIGetGeoID(SelectedLanguageId
)))
4257 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4261 if (!IsUnattendedSetup
)
4263 /* Update keyboard layout settings */
4264 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4265 if (!ProcessKeyboardLayoutRegistry(LayoutList
, SelectedLanguageId
))
4267 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4272 /* Add codepage information to registry */
4273 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4274 if (!AddCodePage(SelectedLanguageId
))
4276 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4280 /* Set the default pagefile entry */
4281 SetDefaultPagefile(DestinationDriveLetter
);
4283 /* Update the mounted devices list */
4284 // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
4285 SetMountedDeviceValues(PartitionList
);
4290 // TODO: Unload all the registry stuff, perform cleanup,
4291 // and copy the created hive files into .sav files.
4293 RegCleanupRegistry(&USetupData
.DestinationPath
);
4296 * Check whether we were in update/repair mode but we were actually
4297 * repairing the registry hives. If so, we have finished repairing them,
4298 * and we now reset the flag and run the proper registry update.
4299 * Otherwise we have finished the registry update!
4301 if (RepairUpdateFlag
&& ShouldRepairRegistry
)
4303 ShouldRepairRegistry
= FALSE
;
4307 if (NT_SUCCESS(Status
))
4309 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4310 return BOOT_LOADER_PAGE
;
4320 * Displays the BootLoaderPage.
4323 * SuccessPage (if RepairUpdate)
4324 * BootLoaderHarddiskMbrPage
4325 * BootLoaderHarddiskVbrPage
4326 * BootLoaderFloppyPage
4331 * Calls RegInitializeRegistry
4332 * Calls ImportRegistryFile
4333 * Calls SetDefaultPagefile
4334 * Calls SetMountedDeviceValues
4337 * Number of the next page.
4340 BootLoaderPage(PINPUT_RECORD Ir
)
4342 UCHAR PartitionType
;
4343 BOOLEAN InstallOnFloppy
;
4345 WCHAR PathBuffer
[MAX_PATH
];
4347 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4349 RtlFreeUnicodeString(&USetupData
.SystemRootPath
);
4350 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
4351 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
4352 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4353 PartitionList
->SystemPartition
->PartitionNumber
);
4354 RtlCreateUnicodeString(&USetupData
.SystemRootPath
, PathBuffer
);
4355 DPRINT1("SystemRootPath: %wZ\n", &USetupData
.SystemRootPath
);
4357 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4359 /* For unattended setup, skip MBR installation or install on floppy if needed */
4360 if (IsUnattendedSetup
)
4362 if ((USetupData
.MBRInstallType
== 0) ||
4363 (USetupData
.MBRInstallType
== 1))
4370 * We may install an MBR or VBR, but before that, check whether
4371 * we need to actually install the VBR on floppy.
4373 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4375 DPRINT("Error: system partition invalid (unused)\n");
4376 InstallOnFloppy
= TRUE
;
4378 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4380 /* OS/2 boot manager partition */
4381 DPRINT("Found OS/2 boot manager partition\n");
4382 InstallOnFloppy
= TRUE
;
4384 else if (PartitionType
== PARTITION_EXT2
)
4386 /* Linux EXT2 partition */
4387 DPRINT("Found Linux EXT2 partition\n");
4388 InstallOnFloppy
= FALSE
;
4390 else if (PartitionType
== PARTITION_IFS
)
4392 /* NTFS partition */
4393 DPRINT("Found NTFS partition\n");
4395 // FIXME: Make it FALSE when we'll support NTFS installation!
4396 InstallOnFloppy
= TRUE
;
4398 else if ((PartitionType
== PARTITION_FAT_12
) ||
4399 (PartitionType
== PARTITION_FAT_16
) ||
4400 (PartitionType
== PARTITION_HUGE
) ||
4401 (PartitionType
== PARTITION_XINT13
) ||
4402 (PartitionType
== PARTITION_FAT32
) ||
4403 (PartitionType
== PARTITION_FAT32_XINT13
))
4405 DPRINT("Found FAT partition\n");
4406 InstallOnFloppy
= FALSE
;
4410 /* Unknown partition */
4411 DPRINT("Unknown partition found\n");
4412 InstallOnFloppy
= TRUE
;
4415 /* We should install on floppy */
4416 if (InstallOnFloppy
)
4418 USetupData
.MBRInstallType
= 1;
4422 /* Is it an unattended install on hdd? */
4423 if (IsUnattendedSetup
)
4425 if ((USetupData
.MBRInstallType
== 2) ||
4426 (USetupData
.MBRInstallType
== 3))
4432 MUIDisplayPage(BOOT_LOADER_PAGE
);
4433 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4437 CONSOLE_ConInKey(Ir
);
4439 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4440 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4442 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4451 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4453 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4454 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4456 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4465 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4467 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4468 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4470 if (ConfirmQuit(Ir
))
4475 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4479 /* Install on both MBR and VBR */
4480 USetupData
.MBRInstallType
= 2;
4483 else if (Line
== 13)
4485 /* Install on VBR only */
4486 USetupData
.MBRInstallType
= 3;
4489 else if (Line
== 14)
4491 /* Install on floppy */
4492 USetupData
.MBRInstallType
= 1;
4495 else if (Line
== 15)
4497 /* Skip MBR installation */
4498 USetupData
.MBRInstallType
= 0;
4502 return BOOT_LOADER_PAGE
;
4507 switch (USetupData
.MBRInstallType
)
4509 /* Skip MBR installation */
4511 return SUCCESS_PAGE
;
4513 /* Install on floppy */
4515 return BOOT_LOADER_FLOPPY_PAGE
;
4517 /* Install on both MBR and VBR */
4519 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4521 /* Install on VBR only */
4523 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4526 return BOOT_LOADER_PAGE
;
4531 * Displays the BootLoaderFloppyPage.
4534 * SuccessPage (At once)
4538 * Calls InstallFatBootcodeToFloppy()
4541 * Number of the next page.
4544 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4548 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4550 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4554 CONSOLE_ConInKey(Ir
);
4556 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4557 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4559 if (ConfirmQuit(Ir
))
4564 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4566 Status
= InstallFatBootcodeToFloppy(&USetupData
.SourceRootPath
,
4567 &USetupData
.DestinationArcPath
);
4568 if (!NT_SUCCESS(Status
))
4570 if (Status
== STATUS_DEVICE_NOT_READY
)
4571 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4573 /* TODO: Print error message */
4574 return BOOT_LOADER_FLOPPY_PAGE
;
4577 return SUCCESS_PAGE
;
4581 return BOOT_LOADER_FLOPPY_PAGE
;
4586 * Displays the BootLoaderHarddiskVbrPage.
4589 * SuccessPage (At once)
4593 * Calls InstallVBRToPartition()
4596 * Number of the next page.
4599 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4603 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4604 &USetupData
.SourceRootPath
,
4605 &USetupData
.DestinationArcPath
,
4606 PartitionList
->SystemPartition
->PartitionType
);
4607 if (!NT_SUCCESS(Status
))
4609 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4613 return SUCCESS_PAGE
;
4618 * Displays the BootLoaderHarddiskMbrPage.
4621 * SuccessPage (At once)
4625 * Calls InstallVBRToPartition()
4626 * Calls InstallMbrBootCodeToDisk()
4629 * Number of the next page.
4632 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4635 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4637 /* Step 1: Write the VBR */
4638 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4639 &USetupData
.SourceRootPath
,
4640 &USetupData
.DestinationArcPath
,
4641 PartitionList
->SystemPartition
->PartitionType
);
4642 if (!NT_SUCCESS(Status
))
4644 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4648 /* Step 2: Write the MBR */
4649 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4650 L
"\\Device\\Harddisk%d\\Partition0",
4651 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4652 Status
= InstallMbrBootCodeToDisk(&USetupData
.SystemRootPath
,
4653 &USetupData
.SourceRootPath
,
4654 DestinationDevicePathBuffer
);
4655 if (!NT_SUCCESS(Status
))
4657 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status
);
4658 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4662 return SUCCESS_PAGE
;
4667 * @name ProgressTimeOutStringHandler
4669 * Handles the generation (displaying) of the timeout
4670 * countdown to the screen dynamically.
4673 * A pointer to a progress bar.
4675 * @param AlwaysUpdate
4676 * Constantly update the progress bar (boolean type).
4679 * A pointer to a string buffer.
4681 * @param cchBufferSize
4682 * The buffer's size in number of characters.
4685 * TRUE or FALSE on function termination.
4690 ProgressTimeOutStringHandler(
4691 IN PPROGRESSBAR Bar
,
4692 IN BOOLEAN AlwaysUpdate
,
4694 IN SIZE_T cchBufferSize
)
4696 ULONG OldProgress
= Bar
->Progress
;
4698 if (Bar
->StepCount
== 0)
4704 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4707 /* Build the progress string if it has changed */
4708 if (Bar
->ProgressFormatText
&&
4709 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4711 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4712 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4721 * @name ProgressCountdown
4723 * Displays and draws a red-coloured progress bar with a countdown.
4724 * When the timeout is reached, the flush page is displayed for reboot.
4727 * A pointer to an input keyboard record.
4730 * Initial countdown value in seconds.
4738 IN PINPUT_RECORD Ir
,
4742 ULONG StartTime
, BarWidth
, TimerDiv
;
4744 LONG TimerValue
, OldTimerValue
;
4745 LARGE_INTEGER Timeout
;
4746 PPROGRESSBAR ProgressBar
;
4747 BOOLEAN RefreshProgress
= TRUE
;
4749 /* Bail out if the timeout is already zero */
4753 /* Create the timeout progress bar and set it up */
4754 ProgressBar
= CreateProgressBarEx(13,
4761 FOREGROUND_RED
| BACKGROUND_BLUE
,
4764 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4765 ProgressTimeOutStringHandler
);
4767 BarWidth
= max(1, ProgressBar
->Width
);
4768 TimerValue
= TimeOut
* BarWidth
;
4769 ProgressSetStepCount(ProgressBar
, TimerValue
);
4771 StartTime
= NtGetTickCount();
4774 TimerDiv
= 1000 / BarWidth
;
4775 TimerDiv
= max(1, TimerDiv
);
4776 OldTimerValue
= TimerValue
;
4779 /* Decrease the timer */
4782 * Compute how much time the previous operations took.
4783 * This allows us in particular to take account for any time
4784 * elapsed if something slowed down.
4786 TimeElapsed
= NtGetTickCount() - StartTime
;
4787 if (TimeElapsed
>= TimerDiv
)
4789 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4790 TimeElapsed
/= TimerDiv
;
4791 StartTime
+= (TimerDiv
* TimeElapsed
);
4793 if (TimeElapsed
<= TimerValue
)
4794 TimerValue
-= TimeElapsed
;
4798 RefreshProgress
= TRUE
;
4801 if (RefreshProgress
)
4803 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4804 RefreshProgress
= FALSE
;
4807 /* Stop when the timer reaches zero */
4808 if (TimerValue
<= 0)
4811 /* Check for user key presses */
4814 * If the timer is used, use a passive wait of maximum 1 second
4815 * while monitoring for incoming console input events, so that
4816 * we are still able to display the timing count.
4819 /* Wait a maximum of 1 second for input events */
4820 TimeElapsed
= NtGetTickCount() - StartTime
;
4821 if (TimeElapsed
< TimerDiv
)
4823 /* Convert the time to NT Format */
4824 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4825 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4829 Status
= STATUS_TIMEOUT
;
4832 /* Check whether the input event has been signaled, or a timeout happened */
4833 if (Status
== STATUS_TIMEOUT
)
4837 if (Status
!= STATUS_WAIT_0
)
4839 /* An error happened, bail out */
4840 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4844 /* Check for an ENTER key press */
4845 while (CONSOLE_ConInKeyPeek(Ir
))
4847 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4849 /* Found it, stop waiting */
4856 /* Destroy the progress bar and quit */
4857 DestroyProgressBar(ProgressBar
);
4862 * Displays the QuitPage.
4865 * FlushPage (At once)
4871 * Number of the next page.
4874 QuitPage(PINPUT_RECORD Ir
)
4876 MUIDisplayPage(QUIT_PAGE
);
4878 /* Destroy the NTOS installations list */
4879 if (NtOsInstallsList
!= NULL
)
4881 DestroyGenericList(NtOsInstallsList
, TRUE
);
4882 NtOsInstallsList
= NULL
;
4885 /* Destroy the partition list */
4886 if (PartitionList
!= NULL
)
4888 DestroyPartitionList(PartitionList
);
4889 PartitionList
= NULL
;
4891 TempPartition
= NULL
;
4892 FormatState
= Start
;
4894 /* Destroy the filesystem list */
4895 if (FileSystemList
!= NULL
)
4897 DestroyFileSystemList(FileSystemList
);
4898 FileSystemList
= NULL
;
4901 /* Destroy the computer settings list */
4902 if (ComputerList
!= NULL
)
4904 DestroyGenericList(ComputerList
, TRUE
);
4905 ComputerList
= NULL
;
4908 /* Destroy the display settings list */
4909 if (DisplayList
!= NULL
)
4911 DestroyGenericList(DisplayList
, TRUE
);
4915 /* Destroy the keyboard settings list */
4916 if (KeyboardList
!= NULL
)
4918 DestroyGenericList(KeyboardList
, TRUE
);
4919 KeyboardList
= NULL
;
4922 /* Destroy the keyboard layout list */
4923 if (LayoutList
!= NULL
)
4925 DestroyGenericList(LayoutList
, TRUE
);
4929 /* Destroy the languages list */
4930 if (LanguageList
!= NULL
)
4932 DestroyGenericList(LanguageList
, FALSE
);
4933 LanguageList
= NULL
;
4936 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4938 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4939 ProgressCountdown(Ir
, 15);
4945 * Displays the SuccessPage.
4948 * FlushPage (At once)
4954 * Number of the next page.
4957 SuccessPage(PINPUT_RECORD Ir
)
4959 MUIDisplayPage(SUCCESS_PAGE
);
4961 if (IsUnattendedSetup
)
4964 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4965 ProgressCountdown(Ir
, 15);
4971 * Displays the FlushPage.
4974 * RebootPage (At once)
4977 * Number of the next page.
4980 FlushPage(PINPUT_RECORD Ir
)
4982 MUIDisplayPage(FLUSH_PAGE
);
4988 PnpEventThread(IN LPVOID lpParameter
);
4992 * The start routine and page management
5002 InfSetHeap(ProcessHeap
);
5004 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
5005 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
5006 if (!NT_SUCCESS(Status
))
5007 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
5009 /* Create the PnP thread in suspended state */
5010 Status
= RtlCreateUserThread(NtCurrentProcess(),
5020 if (!NT_SUCCESS(Status
))
5023 if (!CONSOLE_Init())
5025 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
5026 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
5027 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
5029 /* We failed to initialize the video, just quit the installer */
5030 return STATUS_APP_INIT_FAILURE
;
5033 /* Initialize global unicode strings */
5034 RtlInitUnicodeString(&USetupData
.SourcePath
, NULL
);
5035 RtlInitUnicodeString(&USetupData
.SourceRootPath
, NULL
);
5036 RtlInitUnicodeString(&USetupData
.SourceRootDir
, NULL
);
5037 RtlInitUnicodeString(&InstallPath
, NULL
);
5038 RtlInitUnicodeString(&USetupData
.DestinationPath
, NULL
);
5039 RtlInitUnicodeString(&USetupData
.DestinationArcPath
, NULL
);
5040 RtlInitUnicodeString(&USetupData
.DestinationRootPath
, NULL
);
5041 RtlInitUnicodeString(&USetupData
.SystemRootPath
, NULL
);
5043 /* Hide the cursor */
5044 CONSOLE_SetCursorType(TRUE
, FALSE
);
5046 /* Global Initialization page */
5047 CONSOLE_ClearScreen();
5049 Page
= SetupStartPage(&Ir
);
5051 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
5053 CONSOLE_ClearScreen();
5056 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
5063 Page
= LanguagePage(&Ir
);
5068 Page
= WelcomePage(&Ir
);
5073 Page
= LicensePage(&Ir
);
5077 case INSTALL_INTRO_PAGE
:
5078 Page
= InstallIntroPage(&Ir
);
5082 case SCSI_CONTROLLER_PAGE
:
5083 Page
= ScsiControllerPage(&Ir
);
5086 case OEM_DRIVER_PAGE
:
5087 Page
= OemDriverPage(&Ir
);
5091 case DEVICE_SETTINGS_PAGE
:
5092 Page
= DeviceSettingsPage(&Ir
);
5095 case COMPUTER_SETTINGS_PAGE
:
5096 Page
= ComputerSettingsPage(&Ir
);
5099 case DISPLAY_SETTINGS_PAGE
:
5100 Page
= DisplaySettingsPage(&Ir
);
5103 case KEYBOARD_SETTINGS_PAGE
:
5104 Page
= KeyboardSettingsPage(&Ir
);
5107 case LAYOUT_SETTINGS_PAGE
:
5108 Page
= LayoutSettingsPage(&Ir
);
5111 case SELECT_PARTITION_PAGE
:
5112 Page
= SelectPartitionPage(&Ir
);
5115 case CREATE_PRIMARY_PARTITION_PAGE
:
5116 Page
= CreatePrimaryPartitionPage(&Ir
);
5119 case CREATE_EXTENDED_PARTITION_PAGE
:
5120 Page
= CreateExtendedPartitionPage(&Ir
);
5123 case CREATE_LOGICAL_PARTITION_PAGE
:
5124 Page
= CreateLogicalPartitionPage(&Ir
);
5127 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
5128 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
5131 case DELETE_PARTITION_PAGE
:
5132 Page
= DeletePartitionPage(&Ir
);
5135 case SELECT_FILE_SYSTEM_PAGE
:
5136 Page
= SelectFileSystemPage(&Ir
);
5139 case FORMAT_PARTITION_PAGE
:
5140 Page
= FormatPartitionPage(&Ir
);
5143 case CHECK_FILE_SYSTEM_PAGE
:
5144 Page
= CheckFileSystemPage(&Ir
);
5147 case INSTALL_DIRECTORY_PAGE
:
5148 Page
= InstallDirectoryPage(&Ir
);
5151 case PREPARE_COPY_PAGE
:
5152 Page
= PrepareCopyPage(&Ir
);
5155 case FILE_COPY_PAGE
:
5156 Page
= FileCopyPage(&Ir
);
5160 Page
= RegistryPage(&Ir
);
5163 case BOOT_LOADER_PAGE
:
5164 Page
= BootLoaderPage(&Ir
);
5167 case BOOT_LOADER_FLOPPY_PAGE
:
5168 Page
= BootLoaderFloppyPage(&Ir
);
5171 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
5172 Page
= BootLoaderHarddiskMbrPage(&Ir
);
5175 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
5176 Page
= BootLoaderHarddiskVbrPage(&Ir
);
5180 case REPAIR_INTRO_PAGE
:
5181 Page
= RepairIntroPage(&Ir
);
5184 case UPGRADE_REPAIR_PAGE
:
5185 Page
= UpgradeRepairPage(&Ir
);
5189 Page
= SuccessPage(&Ir
);
5193 Page
= FlushPage(&Ir
);
5197 Page
= QuitPage(&Ir
);
5206 SetupCloseInfFile(SetupInf
);
5208 if (Page
== RECOVERY_PAGE
)
5214 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
5215 NtShutdownSystem(ShutdownReboot
);
5216 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
5218 return STATUS_SUCCESS
;
5223 NtProcessStartup(PPEB Peb
)
5228 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
5230 ProcessHeap
= Peb
->ProcessHeap
;
5232 NtQuerySystemTime(&Time
);
5234 Status
= RunUSetup();
5236 if (NT_SUCCESS(Status
))
5239 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
5240 * a protective waiting.
5241 * This wait is needed because, since we are started as SMSS.EXE,
5242 * the NT kernel explicitly waits 5 seconds for the initial process
5243 * SMSS.EXE to initialize (as a protective measure), and otherwise
5244 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
5246 Time
.QuadPart
+= 50000000;
5247 NtDelayExecution(FALSE
, &Time
);
5251 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
5252 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
5253 0, 0, NULL
, 0, NULL
);
5256 NtTerminateProcess(NtCurrentProcess(), Status
);