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 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
30 #include <ntstrsafe.h>
42 /* GLOBALS & LOCALS *********************************************************/
45 BOOLEAN IsUnattendedSetup
= FALSE
;
47 static USETUP_DATA USetupData
;
49 /* Partition where to perform the installation */
50 static PPARTENTRY InstallPartition
= NULL
;
51 // static PPARTENTRY SystemPartition = NULL; // The system partition we will actually use (can be different from PartitionList->SystemPartition in case we install on removable disk)
53 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
54 static WCHAR DestinationDriveLetter
;
59 PCWSTR 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 /* Global partition list on the system */
66 static PPARTLIST PartitionList
= NULL
;
68 /* Currently selected partition entry in the list */
69 static PPARTENTRY CurrentPartition
= NULL
;
71 /* List of supported file systems for the partition to be formatted */
72 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
74 /* Machine state for the formatter */
75 static PPARTENTRY TempPartition
= NULL
;
76 static FORMATMACHINESTATE FormatState
= Start
;
78 /*****************************************************/
80 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
81 static PGENERIC_LIST NtOsInstallsList
= NULL
;
84 /* FUNCTIONS ****************************************************************/
87 PrintString(char* fmt
,...)
91 UNICODE_STRING UnicodeString
;
92 ANSI_STRING AnsiString
;
95 vsprintf(buffer
, fmt
, ap
);
98 RtlInitAnsiString(&AnsiString
, buffer
);
99 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
100 NtDisplayString(&UnicodeString
);
101 RtlFreeUnicodeString(&UnicodeString
);
106 DrawBox(IN SHORT xLeft
,
114 /* Draw upper left corner */
117 FillConsoleOutputCharacterA(StdOutput
,
123 /* Draw upper edge */
126 FillConsoleOutputCharacterA(StdOutput
,
132 /* Draw upper right corner */
133 coPos
.X
= xLeft
+ Width
- 1;
135 FillConsoleOutputCharacterA(StdOutput
,
141 /* Draw right edge, inner space and left edge */
142 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
145 FillConsoleOutputCharacterA(StdOutput
,
152 FillConsoleOutputCharacterA(StdOutput
,
158 coPos
.X
= xLeft
+ Width
- 1;
159 FillConsoleOutputCharacterA(StdOutput
,
166 /* Draw lower left corner */
168 coPos
.Y
= yTop
+ Height
- 1;
169 FillConsoleOutputCharacterA(StdOutput
,
175 /* Draw lower edge */
177 coPos
.Y
= yTop
+ Height
- 1;
178 FillConsoleOutputCharacterA(StdOutput
,
184 /* Draw lower right corner */
185 coPos
.X
= xLeft
+ Width
- 1;
186 coPos
.Y
= yTop
+ Height
- 1;
187 FillConsoleOutputCharacterA(StdOutput
,
196 PopupError(PCCH Text
,
214 /* Count text lines and longest line */
221 p
= strchr(pnext
, '\n');
225 Length
= strlen(pnext
);
230 Length
= (ULONG
)(p
- pnext
);
236 if (Length
> MaxLength
)
245 /* Check length of status line */
248 Length
= strlen(Status
);
250 if (Length
> MaxLength
)
254 Width
= MaxLength
+ 4;
260 yTop
= (yScreen
- Height
) / 2;
261 xLeft
= (xScreen
- Width
) / 2;
264 /* Set screen attributes */
266 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
268 FillConsoleOutputAttribute(StdOutput
,
269 FOREGROUND_RED
| BACKGROUND_WHITE
,
275 DrawBox(xLeft
, yTop
, Width
, Height
);
277 /* Print message text */
282 p
= strchr(pnext
, '\n');
286 Length
= strlen(pnext
);
291 Length
= (ULONG
)(p
- pnext
);
298 WriteConsoleOutputCharacterA(StdOutput
,
312 /* Print separator line and status text */
315 coPos
.Y
= yTop
+ Height
- 3;
317 FillConsoleOutputCharacterA(StdOutput
,
324 FillConsoleOutputCharacterA(StdOutput
,
330 coPos
.X
= xLeft
+ Width
- 1;
331 FillConsoleOutputCharacterA(StdOutput
,
339 WriteConsoleOutputCharacterA(StdOutput
,
341 min(strlen(Status
), (SIZE_T
)Width
- 4),
346 if (WaitEvent
== POPUP_WAIT_NONE
)
351 CONSOLE_ConInKey(Ir
);
353 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
354 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
366 * FALSE: Don't quit setup.
369 ConfirmQuit(PINPUT_RECORD Ir
)
372 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
376 CONSOLE_ConInKey(Ir
);
378 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
379 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
384 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
398 PGENERIC_LIST_ENTRY ListEntry
;
401 pszNewLayout
= MUIDefaultKeyboardLayout(SelectedLanguageId
);
403 if (USetupData
.LayoutList
== NULL
)
405 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
406 if (USetupData
.LayoutList
== NULL
)
408 /* FIXME: Handle error! */
413 /* Search for default layout (if provided) */
414 if (pszNewLayout
!= NULL
)
416 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
417 ListEntry
= GetNextListEntry(ListEntry
))
419 if (!wcscmp(pszNewLayout
, ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
))
421 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
431 GetSettingDescription(
432 IN PGENERIC_LIST_ENTRY Entry
,
434 IN SIZE_T cchBufferSize
)
436 return RtlStringCchPrintfA(Buffer
, cchBufferSize
, "%S",
437 ((PGENENTRY
)GetListEntryData(Entry
))->Value
);
442 GetNTOSInstallationName(
443 IN PGENERIC_LIST_ENTRY Entry
,
445 IN SIZE_T cchBufferSize
)
447 PNTOS_INSTALLATION NtOsInstall
= (PNTOS_INSTALLATION
)GetListEntryData(Entry
);
448 PPARTENTRY PartEntry
= NtOsInstall
->PartEntry
;
450 if (PartEntry
&& PartEntry
->DriveLetter
)
452 /* We have retrieved a partition that is mounted */
453 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
455 PartEntry
->DriveLetter
,
456 NtOsInstall
->PathComponent
,
457 NtOsInstall
->InstallationName
);
461 /* We failed somewhere, just show the NT path */
462 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
464 &NtOsInstall
->SystemNtPath
,
465 NtOsInstall
->InstallationName
);
471 * Displays the LanguagePage.
473 * Next pages: WelcomePage, QuitPage
476 * Init SelectedLanguageId
477 * Init USetupData.LanguageId
480 * Number of the next page.
483 LanguagePage(PINPUT_RECORD Ir
)
485 GENERIC_LIST_UI ListUi
;
486 PCWSTR NewLanguageId
;
487 BOOL RefreshPage
= FALSE
;
489 /* Initialize the computer settings list */
490 if (USetupData
.LanguageList
== NULL
)
492 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
493 if (USetupData
.LanguageList
== NULL
)
495 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
500 SelectedLanguageId
= DefaultLanguage
;
501 USetupData
.LanguageId
= 0;
504 SetConsoleCodePage();
508 * If there is no language or just a single one in the list,
509 * skip the language selection process altogether.
511 if (GetNumberOfListEntries(USetupData
.LanguageList
) <= 1)
513 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
517 InitGenericListUi(&ListUi
, USetupData
.LanguageList
, GetSettingDescription
);
518 DrawGenericList(&ListUi
,
523 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
525 MUIDisplayPage(LANGUAGE_PAGE
);
529 CONSOLE_ConInKey(Ir
);
531 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
532 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
534 ScrollDownGenericList(&ListUi
);
537 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
538 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
540 ScrollUpGenericList(&ListUi
);
543 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
544 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
546 ScrollPageDownGenericList(&ListUi
);
549 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
550 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
552 ScrollPageUpGenericList(&ListUi
);
555 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
556 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
561 RedrawGenericList(&ListUi
);
563 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
565 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
568 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
570 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
572 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
578 SetConsoleCodePage();
582 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
585 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
591 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
594 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
596 if (wcscmp(SelectedLanguageId
, NewLanguageId
))
598 /* Clear the language page */
599 MUIClearPage(LANGUAGE_PAGE
);
601 SelectedLanguageId
= NewLanguageId
;
604 SetConsoleCodePage();
606 /* Redraw language selection page in native language */
607 MUIDisplayPage(LANGUAGE_PAGE
);
622 * LanguagePage (at once, default)
623 * InstallIntroPage (at once, if unattended)
628 * Init USetupData.SourcePath
629 * Init USetupData.SourceRootPath
630 * Init USetupData.SourceRootDir
631 * Init USetupData.SetupInf
632 * Init USetupData.RequiredPartitionDiskSpace
633 * Init IsUnattendedSetup
634 * If unattended, init *List and sets the Codepage
635 * If unattended, init SelectedLanguageId
636 * If unattended, init USetupData.LanguageId
639 * Number of the next page.
642 SetupStartPage(PINPUT_RECORD Ir
)
645 PGENERIC_LIST_ENTRY ListEntry
;
648 MUIDisplayPage(SETUP_INIT_PAGE
);
650 /* Initialize Setup, phase 1 */
651 Error
= InitializeSetup(&USetupData
, 1);
652 if (Error
!= ERROR_SUCCESS
)
654 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
658 /* Initialize the user-mode PnP manager */
659 if (!EnableUserModePnpManager())
660 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
662 /* Wait for any immediate pending installations to finish */
663 if (WaitNoPendingInstallEvents(NULL
) != STATUS_WAIT_0
)
664 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
666 CheckUnattendedSetup(&USetupData
);
668 if (IsUnattendedSetup
)
670 // TODO: Read options from inf
671 /* Load the hardware, language and keyboard layout lists */
673 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
674 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
675 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
677 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
680 SelectedLanguageId
= DefaultLanguage
;
681 wcscpy(DefaultLanguage
, USetupData
.LocaleID
);
682 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
684 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
686 /* first we hack LanguageList */
687 for (ListEntry
= GetFirstListEntry(USetupData
.LanguageList
); ListEntry
;
688 ListEntry
= GetNextListEntry(ListEntry
))
690 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
691 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
693 DPRINT("found %S in LanguageList\n", LocaleId
);
694 SetCurrentListEntry(USetupData
.LanguageList
, ListEntry
);
700 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
701 ListEntry
= GetNextListEntry(ListEntry
))
703 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
704 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
706 DPRINT("found %S in LayoutList\n", LocaleId
);
707 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
712 SetConsoleCodePage();
714 return INSTALL_INTRO_PAGE
;
717 return LANGUAGE_PAGE
;
722 * Displays the WelcomePage.
725 * InstallIntroPage (default)
732 * Number of the next page.
735 WelcomePage(PINPUT_RECORD Ir
)
737 MUIDisplayPage(WELCOME_PAGE
);
741 CONSOLE_ConInKey(Ir
);
743 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
744 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
751 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
753 return INSTALL_INTRO_PAGE
;
755 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
757 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
759 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
770 * Displays the License page.
773 * WelcomePage (default)
776 * Number of the next page.
779 LicensePage(PINPUT_RECORD Ir
)
781 MUIDisplayPage(LICENSE_PAGE
);
785 CONSOLE_ConInKey(Ir
);
787 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
798 * Displays the RepairIntroPage.
801 * RebootPage (default)
807 * Number of the next page.
810 RepairIntroPage(PINPUT_RECORD Ir
)
812 MUIDisplayPage(REPAIR_INTRO_PAGE
);
816 CONSOLE_ConInKey(Ir
);
818 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
822 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
824 RepairUpdateFlag
= TRUE
;
825 return INSTALL_INTRO_PAGE
;
827 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
829 return RECOVERY_PAGE
;
831 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
832 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
838 return REPAIR_INTRO_PAGE
;
842 * Displays the UpgradeRepairPage.
845 * RebootPage (default)
851 * Number of the next page.
854 UpgradeRepairPage(PINPUT_RECORD Ir
)
856 GENERIC_LIST_UI ListUi
;
859 if (PartitionList
== NULL
)
861 PartitionList
= CreatePartitionList();
862 if (PartitionList
== NULL
)
864 /* FIXME: show an error dialog */
865 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
868 else if (IsListEmpty(&PartitionList
->DiskListHead
))
870 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
874 /* Reset the formatter machine state */
875 TempPartition
= NULL
;
880 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
881 if (!NtOsInstallsList
)
882 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
885 * If there is no available installation (or just a single one??) that can
886 * be updated in the list, just continue with the regular installation.
888 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
890 RepairUpdateFlag
= FALSE
;
892 // return INSTALL_INTRO_PAGE;
893 return DEVICE_SETTINGS_PAGE
;
894 // return SCSI_CONTROLLER_PAGE;
897 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
899 InitGenericListUi(&ListUi
, NtOsInstallsList
, GetNTOSInstallationName
);
900 DrawGenericList(&ListUi
,
905 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
908 CONSOLE_ConInKey(Ir
);
910 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
912 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
914 case VK_DOWN
: /* DOWN */
915 ScrollDownGenericList(&ListUi
);
918 ScrollUpGenericList(&ListUi
);
920 case VK_NEXT
: /* PAGE DOWN */
921 ScrollPageDownGenericList(&ListUi
);
923 case VK_PRIOR
: /* PAGE UP */
924 ScrollPageUpGenericList(&ListUi
);
931 RedrawGenericList(&ListUi
);
934 case VK_ESCAPE
: /* ESC */
936 RestoreGenericListUiState(&ListUi
);
937 // return nextPage; // prevPage;
939 // return INSTALL_INTRO_PAGE;
940 return DEVICE_SETTINGS_PAGE
;
941 // return SCSI_CONTROLLER_PAGE;
947 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
948 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
949 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
951 /* Retrieve the current installation */
952 ASSERT(GetNumberOfListEntries(NtOsInstallsList
) >= 1);
954 CurrentInstallation
=
955 (PNTOS_INSTALLATION
)GetListEntryData(GetCurrentListEntry(NtOsInstallsList
));
957 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
958 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
960 RepairUpdateFlag
= TRUE
;
963 /***/return INSTALL_INTRO_PAGE
;/***/
965 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
966 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
968 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
973 return UPGRADE_REPAIR_PAGE
;
978 * Displays the InstallIntroPage.
981 * DeviceSettingsPage (At once if repair or update is selected)
982 * SelectPartitionPage (At once if unattended setup)
983 * DeviceSettingsPage (default)
987 * Number of the next page.
990 InstallIntroPage(PINPUT_RECORD Ir
)
992 if (RepairUpdateFlag
)
994 #if 1 /* Old code that looks good */
996 // return SELECT_PARTITION_PAGE;
997 return DEVICE_SETTINGS_PAGE
;
999 #else /* Possible new code? */
1001 return DEVICE_SETTINGS_PAGE
;
1002 // return SCSI_CONTROLLER_PAGE;
1007 if (IsUnattendedSetup
)
1008 return SELECT_PARTITION_PAGE
;
1010 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1014 CONSOLE_ConInKey(Ir
);
1016 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1017 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1019 if (ConfirmQuit(Ir
))
1024 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1026 return UPGRADE_REPAIR_PAGE
;
1030 return INSTALL_INTRO_PAGE
;
1036 ScsiControllerPage(PINPUT_RECORD Ir
)
1038 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1040 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1042 /* FIXME: print loaded mass storage driver descriptions */
1044 CONSOLE_SetTextXY(8, 10, "TEST device");
1047 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1051 CONSOLE_ConInKey(Ir
);
1053 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1054 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1056 if (ConfirmQuit(Ir
))
1061 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1063 return DEVICE_SETTINGS_PAGE
;
1067 return SCSI_CONTROLLER_PAGE
;
1071 OemDriverPage(PINPUT_RECORD Ir
)
1073 // MUIDisplayPage(OEM_DRIVER_PAGE);
1075 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1077 /* FIXME: Implement!! */
1079 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1083 CONSOLE_ConInKey(Ir
);
1085 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1086 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1088 if (ConfirmQuit(Ir
))
1093 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1095 return DEVICE_SETTINGS_PAGE
;
1099 return OEM_DRIVER_PAGE
;
1105 * Displays the DeviceSettingsPage.
1108 * SelectPartitionPage (At once if repair or update is selected)
1109 * ComputerSettingsPage
1110 * DisplaySettingsPage
1111 * KeyboardSettingsPage
1112 * LayoutsettingsPage
1113 * SelectPartitionPage
1117 * Init USetupData.ComputerList
1118 * Init USetupData.DisplayList
1119 * Init USetupData.KeyboardList
1120 * Init USetupData.LayoutList
1123 * Number of the next page.
1126 DeviceSettingsPage(PINPUT_RECORD Ir
)
1128 static ULONG Line
= 16;
1130 /* Initialize the computer settings list */
1131 if (USetupData
.ComputerList
== NULL
)
1133 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
1134 if (USetupData
.ComputerList
== NULL
)
1136 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1141 /* Initialize the display settings list */
1142 if (USetupData
.DisplayList
== NULL
)
1144 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
1145 if (USetupData
.DisplayList
== NULL
)
1147 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1152 /* Initialize the keyboard settings list */
1153 if (USetupData
.KeyboardList
== NULL
)
1155 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
1156 if (USetupData
.KeyboardList
== NULL
)
1158 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1163 /* Initialize the keyboard layout list */
1164 if (USetupData
.LayoutList
== NULL
)
1166 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
1167 if (USetupData
.LayoutList
== NULL
)
1169 /* FIXME: report error */
1170 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1175 if (RepairUpdateFlag
)
1176 return SELECT_PARTITION_PAGE
;
1178 // if (IsUnattendedSetup)
1179 // return SELECT_PARTITION_PAGE;
1181 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1183 DrawGenericListCurrentItem(USetupData
.ComputerList
, GetSettingDescription
, 25, 11);
1184 DrawGenericListCurrentItem(USetupData
.DisplayList
, GetSettingDescription
, 25, 12);
1185 DrawGenericListCurrentItem(USetupData
.KeyboardList
, GetSettingDescription
, 25, 13);
1186 DrawGenericListCurrentItem(USetupData
.LayoutList
, GetSettingDescription
, 25, 14);
1188 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1192 CONSOLE_ConInKey(Ir
);
1194 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1195 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1197 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1201 else if (Line
== 16)
1206 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1208 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1209 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1211 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1215 else if (Line
== 16)
1220 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1222 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1223 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1225 if (ConfirmQuit(Ir
))
1230 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1233 return COMPUTER_SETTINGS_PAGE
;
1234 else if (Line
== 12)
1235 return DISPLAY_SETTINGS_PAGE
;
1236 else if (Line
== 13)
1237 return KEYBOARD_SETTINGS_PAGE
;
1238 else if (Line
== 14)
1239 return LAYOUT_SETTINGS_PAGE
;
1240 else if (Line
== 16)
1241 return SELECT_PARTITION_PAGE
;
1245 return DEVICE_SETTINGS_PAGE
;
1250 * Handles generic selection lists.
1253 * GenericList: The list to handle.
1254 * nextPage: The page it needs to jump to after this page.
1255 * Ir: The PINPUT_RECORD
1258 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1259 PAGE_NUMBER nextPage
,
1264 CONSOLE_ConInKey(Ir
);
1266 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1267 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1269 ScrollDownGenericList(ListUi
);
1271 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1272 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1274 ScrollUpGenericList(ListUi
);
1276 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1277 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1279 ScrollPageDownGenericList(ListUi
);
1281 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1282 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1284 ScrollPageUpGenericList(ListUi
);
1286 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1287 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1289 if (ConfirmQuit(Ir
))
1292 RedrawGenericList(ListUi
);
1294 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1295 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1297 RestoreGenericListUiState(ListUi
);
1298 return nextPage
; // Use some "prevPage;" instead?
1300 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1304 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1307 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1314 * Displays the ComputerSettingsPage.
1317 * DeviceSettingsPage
1321 * Number of the next page.
1324 ComputerSettingsPage(PINPUT_RECORD Ir
)
1326 GENERIC_LIST_UI ListUi
;
1327 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1329 InitGenericListUi(&ListUi
, USetupData
.ComputerList
, GetSettingDescription
);
1330 DrawGenericList(&ListUi
,
1335 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1340 * Displays the DisplaySettingsPage.
1343 * DeviceSettingsPage
1347 * Number of the next page.
1350 DisplaySettingsPage(PINPUT_RECORD Ir
)
1352 GENERIC_LIST_UI ListUi
;
1353 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1355 InitGenericListUi(&ListUi
, USetupData
.DisplayList
, GetSettingDescription
);
1356 DrawGenericList(&ListUi
,
1361 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1366 * Displays the KeyboardSettingsPage.
1369 * DeviceSettingsPage
1373 * Number of the next page.
1376 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1378 GENERIC_LIST_UI ListUi
;
1379 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1381 InitGenericListUi(&ListUi
, USetupData
.KeyboardList
, GetSettingDescription
);
1382 DrawGenericList(&ListUi
,
1387 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1392 * Displays the LayoutSettingsPage.
1395 * DeviceSettingsPage
1399 * Number of the next page.
1402 LayoutSettingsPage(PINPUT_RECORD Ir
)
1404 GENERIC_LIST_UI ListUi
;
1405 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1407 InitGenericListUi(&ListUi
, USetupData
.LayoutList
, GetSettingDescription
);
1408 DrawGenericList(&ListUi
,
1413 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1418 IsDiskSizeValid(PPARTENTRY PartEntry
)
1422 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1423 size
= (size
+ (512 * KB
)) / MB
; /* in MBytes */
1425 if (size
< USetupData
.RequiredPartitionDiskSpace
)
1427 /* Partition is too small so ask for another one */
1428 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, USetupData
.RequiredPartitionDiskSpace
);
1439 * Displays the SelectPartitionPage.
1442 * SelectFileSystemPage (At once if unattended)
1443 * SelectFileSystemPage (Default if free space is selected)
1444 * CreatePrimaryPartitionPage
1445 * CreateExtendedPartitionPage
1446 * CreateLogicalPartitionPage
1447 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1448 * DeletePartitionPage
1452 * Set InstallShortcut (only if not unattended + free space is selected)
1455 * Number of the next page.
1458 SelectPartitionPage(PINPUT_RECORD Ir
)
1463 if (PartitionList
== NULL
)
1465 PartitionList
= CreatePartitionList();
1466 if (PartitionList
== NULL
)
1468 /* FIXME: show an error dialog */
1469 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1472 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1474 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1478 /* Reset the formatter machine state */
1479 TempPartition
= NULL
;
1480 FormatState
= Start
;
1483 if (RepairUpdateFlag
)
1485 ASSERT(CurrentInstallation
);
1487 /* Determine the selected installation disk & partition */
1488 InstallPartition
= SelectPartition(PartitionList
,
1489 CurrentInstallation
->DiskNumber
,
1490 CurrentInstallation
->PartitionNumber
);
1491 if (!InstallPartition
)
1493 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1496 ASSERT(!IsContainerPartition(InstallPartition
->PartitionType
));
1498 return SELECT_FILE_SYSTEM_PAGE
;
1501 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1503 InitPartitionListUi(&ListUi
, PartitionList
,
1508 DrawPartitionList(&ListUi
);
1510 if (IsUnattendedSetup
)
1512 /* Determine the selected installation disk & partition */
1513 InstallPartition
= SelectPartition(PartitionList
,
1514 USetupData
.DestinationDiskNumber
,
1515 USetupData
.DestinationPartitionNumber
);
1516 if (!InstallPartition
)
1518 CurrentPartition
= ListUi
.CurrentPartition
;
1520 if (USetupData
.AutoPartition
)
1522 ASSERT(CurrentPartition
!= NULL
);
1523 ASSERT(!IsContainerPartition(CurrentPartition
->PartitionType
));
1525 if (CurrentPartition
->LogicalPartition
)
1527 CreateLogicalPartition(PartitionList
,
1529 CurrentPartition
->SectorCount
.QuadPart
,
1534 CreatePrimaryPartition(PartitionList
,
1536 CurrentPartition
->SectorCount
.QuadPart
,
1540 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1541 if (!IsDiskSizeValid(CurrentPartition
))
1543 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1544 USetupData
.RequiredPartitionDiskSpace
);
1545 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1548 InstallPartition
= CurrentPartition
;
1549 return SELECT_FILE_SYSTEM_PAGE
;
1554 ASSERT(!IsContainerPartition(InstallPartition
->PartitionType
));
1556 DrawPartitionList(&ListUi
); // FIXME: Doesn't make much sense...
1558 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1559 if (!IsDiskSizeValid(InstallPartition
))
1561 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1562 USetupData
.RequiredPartitionDiskSpace
);
1563 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1566 return SELECT_FILE_SYSTEM_PAGE
;
1572 CurrentPartition
= ListUi
.CurrentPartition
;
1574 /* Update status text */
1575 if (CurrentPartition
== NULL
)
1577 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1579 else if (CurrentPartition
->LogicalPartition
)
1581 if (CurrentPartition
->IsPartitioned
)
1583 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1587 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1592 if (CurrentPartition
->IsPartitioned
)
1594 if (IsContainerPartition(CurrentPartition
->PartitionType
))
1596 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1600 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1605 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1609 CONSOLE_ConInKey(Ir
);
1611 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1612 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1614 if (ConfirmQuit(Ir
))
1616 DestroyPartitionList(PartitionList
);
1617 PartitionList
= NULL
;
1623 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1624 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1626 ScrollDownPartitionList(&ListUi
);
1628 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1629 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1631 ScrollUpPartitionList(&ListUi
);
1633 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1635 ASSERT(CurrentPartition
!= NULL
);
1637 if (IsContainerPartition(CurrentPartition
->PartitionType
))
1638 continue; // return SELECT_PARTITION_PAGE;
1641 * Check whether the user wants to install ReactOS on a disk that
1642 * is not recognized by the computer's firmware and if so, display
1643 * a warning since such disks may not be bootable.
1645 if (CurrentPartition
->DiskEntry
->MediaType
== FixedMedia
&&
1646 !CurrentPartition
->DiskEntry
->BiosFound
)
1648 PopupError("The disk you have selected for installing ReactOS\n"
1649 "is not visible by the firmware of your computer,\n"
1650 "and so may not be bootable.\n"
1651 "Press ENTER to continue nonetheless.",
1652 MUIGetString(STRING_CONTINUE
),
1653 Ir
, POPUP_WAIT_ENTER
);
1654 // return SELECT_PARTITION_PAGE;
1657 if (CurrentPartition
->IsPartitioned
== FALSE
)
1659 if (CurrentPartition
->LogicalPartition
)
1661 Error
= LogicalPartitionCreationChecks(CurrentPartition
);
1662 if (Error
!= NOT_AN_ERROR
)
1664 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1665 return SELECT_PARTITION_PAGE
;
1668 CreateLogicalPartition(PartitionList
,
1675 Error
= PrimaryPartitionCreationChecks(CurrentPartition
);
1676 if (Error
!= NOT_AN_ERROR
)
1678 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1679 return SELECT_PARTITION_PAGE
;
1682 CreatePrimaryPartition(PartitionList
,
1689 if (!IsDiskSizeValid(CurrentPartition
))
1691 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1692 USetupData
.RequiredPartitionDiskSpace
);
1693 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1696 InstallPartition
= CurrentPartition
;
1697 return SELECT_FILE_SYSTEM_PAGE
;
1699 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1701 ASSERT(CurrentPartition
!= NULL
);
1703 if (CurrentPartition
->LogicalPartition
== FALSE
)
1705 Error
= PrimaryPartitionCreationChecks(CurrentPartition
);
1706 if (Error
!= NOT_AN_ERROR
)
1708 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1709 return SELECT_PARTITION_PAGE
;
1712 return CREATE_PRIMARY_PARTITION_PAGE
;
1715 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1717 ASSERT(CurrentPartition
!= NULL
);
1719 if (CurrentPartition
->LogicalPartition
== FALSE
)
1721 Error
= ExtendedPartitionCreationChecks(CurrentPartition
);
1722 if (Error
!= NOT_AN_ERROR
)
1724 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1725 return SELECT_PARTITION_PAGE
;
1728 return CREATE_EXTENDED_PARTITION_PAGE
;
1731 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1733 ASSERT(CurrentPartition
!= NULL
);
1735 if (CurrentPartition
->LogicalPartition
)
1737 Error
= LogicalPartitionCreationChecks(CurrentPartition
);
1738 if (Error
!= NOT_AN_ERROR
)
1740 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1741 return SELECT_PARTITION_PAGE
;
1744 return CREATE_LOGICAL_PARTITION_PAGE
;
1747 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1749 UNICODE_STRING CurrentPartitionU
;
1750 WCHAR PathBuffer
[MAX_PATH
];
1752 ASSERT(CurrentPartition
!= NULL
);
1754 if (CurrentPartition
->IsPartitioned
== FALSE
)
1756 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1757 return SELECT_PARTITION_PAGE
;
1760 // TODO: Do something similar before trying to format the partition?
1761 if (!CurrentPartition
->New
&&
1762 !IsContainerPartition(CurrentPartition
->PartitionType
) &&
1763 CurrentPartition
->FormatState
!= Unformatted
)
1765 ASSERT(CurrentPartition
->PartitionNumber
!= 0);
1767 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
1768 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
1769 CurrentPartition
->DiskEntry
->DiskNumber
,
1770 CurrentPartition
->PartitionNumber
);
1771 RtlInitUnicodeString(&CurrentPartitionU
, PathBuffer
);
1774 * Check whether the user attempts to delete the partition on which
1775 * the installation source is present. If so, fail with an error.
1777 // &USetupData.SourceRootPath
1778 if (RtlPrefixUnicodeString(&CurrentPartitionU
, &USetupData
.SourcePath
, TRUE
))
1780 MUIDisplayError(ERROR_SOURCE_PATH
, Ir
, POPUP_WAIT_ENTER
);
1781 return SELECT_PARTITION_PAGE
;
1785 // FIXME TODO: PartitionList->SystemPartition is not yet initialized!!!!
1786 if (CurrentPartition
== PartitionList
->SystemPartition
||
1787 CurrentPartition
->BootIndicator
)
1789 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1792 return DELETE_PARTITION_PAGE
;
1796 return SELECT_PARTITION_PAGE
;
1800 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1801 /* Restriction for MaxSize */
1802 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1805 ShowPartitionSizeInputBox(SHORT Left
,
1829 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1834 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1835 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1838 WriteConsoleOutputCharacterA(StdOutput
,
1844 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1845 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1847 WriteConsoleOutputCharacterA(StdOutput
,
1853 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1854 Length
= wcslen(InputBuffer
);
1856 CONSOLE_SetInputTextXY(iLeft
,
1858 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1860 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1861 CONSOLE_SetCursorType(TRUE
, TRUE
);
1865 CONSOLE_ConInKey(&Ir
);
1867 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1868 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1873 InputBuffer
[0] = UNICODE_NULL
;
1874 CONSOLE_SetCursorType(TRUE
, FALSE
);
1877 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1879 CONSOLE_SetCursorType(TRUE
, FALSE
);
1882 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1887 InputBuffer
[0] = UNICODE_NULL
;
1888 CONSOLE_SetCursorType(TRUE
, FALSE
);
1891 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1892 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1895 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1897 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1898 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1901 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1903 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1904 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1909 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1912 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1913 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1918 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1921 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1922 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1926 memmove(&InputBuffer
[Pos
],
1927 &InputBuffer
[Pos
+ 1],
1928 (Length
- Pos
- 1) * sizeof(WCHAR
));
1929 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1932 CONSOLE_SetInputTextXY(iLeft
,
1934 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1936 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1939 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1944 memmove(&InputBuffer
[Pos
- 1],
1946 (Length
- Pos
) * sizeof(WCHAR
));
1947 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1951 CONSOLE_SetInputTextXY(iLeft
,
1953 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1955 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1958 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1960 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1962 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1964 if ((ch
>= L
'0') && (ch
<= L
'9'))
1967 memmove(&InputBuffer
[Pos
+ 1],
1969 (Length
- Pos
) * sizeof(WCHAR
));
1970 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1971 InputBuffer
[Pos
] = ch
;
1975 CONSOLE_SetInputTextXY(iLeft
,
1977 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1979 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1988 * Displays the CreatePrimaryPartitionPage.
1991 * SelectPartitionPage
1992 * SelectFileSystemPage (default)
1996 * Number of the next page.
1999 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
2001 PPARTENTRY PartEntry
;
2002 PDISKENTRY DiskEntry
;
2005 WCHAR InputBuffer
[50];
2009 ULONGLONG SectorCount
;
2012 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2014 /* FIXME: show an error dialog */
2018 PartEntry
= CurrentPartition
;
2019 DiskEntry
= CurrentPartition
->DiskEntry
;
2021 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2023 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
2025 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2027 if (DiskSize
>= 10 * GB
) /* 10 GB */
2029 DiskSize
= DiskSize
/ GB
;
2030 Unit
= MUIGetString(STRING_GB
);
2035 DiskSize
= DiskSize
/ MB
;
2039 Unit
= MUIGetString(STRING_MB
);
2042 if (DiskEntry
->DriverName
.Length
> 0)
2044 CONSOLE_PrintTextXY(6, 10,
2045 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2048 DiskEntry
->DiskNumber
,
2052 &DiskEntry
->DriverName
,
2053 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2054 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2059 CONSOLE_PrintTextXY(6, 10,
2060 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2063 DiskEntry
->DiskNumber
,
2067 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2068 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2072 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2075 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2076 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2079 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2081 PartEntry
= CurrentPartition
;
2084 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2086 if (MaxSize
> PARTITION_MAXSIZE
)
2087 MaxSize
= PARTITION_MAXSIZE
;
2089 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2090 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2094 if (ConfirmQuit(Ir
))
2101 return SELECT_PARTITION_PAGE
;
2105 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2113 if (PartSize
> MaxSize
)
2119 /* Convert to bytes */
2120 if (PartSize
== MaxSize
)
2122 /* Use all of the unpartitioned disk space */
2123 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2127 /* Calculate the sector count from the size in MB */
2128 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2130 /* But never get larger than the unpartitioned disk space */
2131 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2132 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2135 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2137 CreatePrimaryPartition(PartitionList
,
2142 return SELECT_PARTITION_PAGE
;
2146 return CREATE_PRIMARY_PARTITION_PAGE
;
2151 * Displays the CreateExtendedPartitionPage.
2154 * SelectPartitionPage (default)
2158 * Number of the next page.
2161 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2163 PPARTENTRY PartEntry
;
2164 PDISKENTRY DiskEntry
;
2167 WCHAR InputBuffer
[50];
2171 ULONGLONG SectorCount
;
2174 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2176 /* FIXME: show an error dialog */
2180 PartEntry
= CurrentPartition
;
2181 DiskEntry
= CurrentPartition
->DiskEntry
;
2183 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2185 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2187 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2189 if (DiskSize
>= 10 * GB
) /* 10 GB */
2191 DiskSize
= DiskSize
/ GB
;
2192 Unit
= MUIGetString(STRING_GB
);
2197 DiskSize
= DiskSize
/ MB
;
2201 Unit
= MUIGetString(STRING_MB
);
2204 if (DiskEntry
->DriverName
.Length
> 0)
2206 CONSOLE_PrintTextXY(6, 10,
2207 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2210 DiskEntry
->DiskNumber
,
2214 &DiskEntry
->DriverName
,
2215 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2216 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2221 CONSOLE_PrintTextXY(6, 10,
2222 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2225 DiskEntry
->DiskNumber
,
2229 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2230 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2234 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2237 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2238 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2241 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2243 PartEntry
= CurrentPartition
;
2246 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2248 if (MaxSize
> PARTITION_MAXSIZE
)
2249 MaxSize
= PARTITION_MAXSIZE
;
2251 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2252 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2256 if (ConfirmQuit(Ir
))
2263 return SELECT_PARTITION_PAGE
;
2267 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2275 if (PartSize
> MaxSize
)
2281 /* Convert to bytes */
2282 if (PartSize
== MaxSize
)
2284 /* Use all of the unpartitioned disk space */
2285 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2289 /* Calculate the sector count from the size in MB */
2290 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2292 /* But never get larger than the unpartitioned disk space */
2293 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2294 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2297 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2299 CreateExtendedPartition(PartitionList
,
2303 return SELECT_PARTITION_PAGE
;
2307 return CREATE_EXTENDED_PARTITION_PAGE
;
2312 * Displays the CreateLogicalPartitionPage.
2315 * SelectFileSystemPage (default)
2319 * Number of the next page.
2322 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2324 PPARTENTRY PartEntry
;
2325 PDISKENTRY DiskEntry
;
2328 WCHAR InputBuffer
[50];
2332 ULONGLONG SectorCount
;
2335 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2337 /* FIXME: show an error dialog */
2341 PartEntry
= CurrentPartition
;
2342 DiskEntry
= CurrentPartition
->DiskEntry
;
2344 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2346 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2348 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2350 if (DiskSize
>= 10 * GB
) /* 10 GB */
2352 DiskSize
= DiskSize
/ GB
;
2353 Unit
= MUIGetString(STRING_GB
);
2358 DiskSize
= DiskSize
/ MB
;
2362 Unit
= MUIGetString(STRING_MB
);
2365 if (DiskEntry
->DriverName
.Length
> 0)
2367 CONSOLE_PrintTextXY(6, 10,
2368 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2371 DiskEntry
->DiskNumber
,
2375 &DiskEntry
->DriverName
,
2376 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2377 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2382 CONSOLE_PrintTextXY(6, 10,
2383 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2386 DiskEntry
->DiskNumber
,
2390 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2391 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2395 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2398 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2399 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2402 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2404 PartEntry
= CurrentPartition
;
2407 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2409 if (MaxSize
> PARTITION_MAXSIZE
)
2410 MaxSize
= PARTITION_MAXSIZE
;
2412 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2413 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2417 if (ConfirmQuit(Ir
))
2424 return SELECT_PARTITION_PAGE
;
2428 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2436 if (PartSize
> MaxSize
)
2442 /* Convert to bytes */
2443 if (PartSize
== MaxSize
)
2445 /* Use all of the unpartitioned disk space */
2446 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2450 /* Calculate the sector count from the size in MB */
2451 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2453 /* But never get larger than the unpartitioned disk space */
2454 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2455 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2458 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2460 CreateLogicalPartition(PartitionList
,
2465 return SELECT_PARTITION_PAGE
;
2469 return CREATE_LOGICAL_PARTITION_PAGE
;
2474 * Displays the ConfirmDeleteSystemPartitionPage.
2477 * DeletePartitionPage (default)
2478 * SelectPartitionPage
2481 * Number of the next page.
2484 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2486 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2490 CONSOLE_ConInKey(Ir
);
2492 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2493 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2495 if (ConfirmQuit(Ir
))
2500 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2502 return DELETE_PARTITION_PAGE
;
2504 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2506 return SELECT_PARTITION_PAGE
;
2510 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2515 * Displays the DeletePartitionPage.
2518 * SelectPartitionPage (default)
2522 * Number of the next page.
2525 DeletePartitionPage(PINPUT_RECORD Ir
)
2527 PPARTENTRY PartEntry
;
2528 PDISKENTRY DiskEntry
;
2532 CHAR PartTypeString
[32];
2534 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2536 /* FIXME: show an error dialog */
2540 PartEntry
= CurrentPartition
;
2541 DiskEntry
= CurrentPartition
->DiskEntry
;
2543 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2545 /* Adjust partition type */
2546 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2548 ARRAYSIZE(PartTypeString
));
2550 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2552 if (PartSize
>= 10 * GB
) /* 10 GB */
2554 PartSize
= PartSize
/ GB
;
2555 Unit
= MUIGetString(STRING_GB
);
2559 if (PartSize
>= 10 * MB
) /* 10 MB */
2561 PartSize
= PartSize
/ MB
;
2562 Unit
= MUIGetString(STRING_MB
);
2566 PartSize
= PartSize
/ KB
;
2567 Unit
= MUIGetString(STRING_KB
);
2570 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2572 CONSOLE_PrintTextXY(6, 10,
2573 MUIGetString(STRING_HDDINFOUNK2
),
2574 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2575 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2576 PartEntry
->PartitionType
,
2582 CONSOLE_PrintTextXY(6, 10,
2583 " %c%c %s %I64u %s",
2584 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2585 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2591 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2593 if (DiskSize
>= 10 * GB
) /* 10 GB */
2595 DiskSize
= DiskSize
/ GB
;
2596 Unit
= MUIGetString(STRING_GB
);
2601 DiskSize
= DiskSize
/ MB
;
2605 Unit
= MUIGetString(STRING_MB
);
2608 if (DiskEntry
->DriverName
.Length
> 0)
2610 CONSOLE_PrintTextXY(6, 12,
2611 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2614 DiskEntry
->DiskNumber
,
2618 &DiskEntry
->DriverName
,
2619 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2620 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2625 CONSOLE_PrintTextXY(6, 12,
2626 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2629 DiskEntry
->DiskNumber
,
2633 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2634 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2640 CONSOLE_ConInKey(Ir
);
2642 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2643 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2645 if (ConfirmQuit(Ir
))
2650 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2652 return SELECT_PARTITION_PAGE
;
2654 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
2656 DeletePartition(PartitionList
,
2659 return SELECT_PARTITION_PAGE
;
2663 return DELETE_PARTITION_PAGE
;
2668 ResetFileSystemList(VOID
)
2670 if (!FileSystemList
)
2673 DestroyFileSystemList(FileSystemList
);
2674 FileSystemList
= NULL
;
2678 * Displays the SelectFileSystemPage.
2681 * CheckFileSystemPage (At once if RepairUpdate is selected)
2682 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2683 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2684 * SelectPartitionPage (If the user aborts)
2685 * FormatPartitionPage (Default)
2689 * Calls UpdatePartitionType()
2690 * Calls CheckActiveSystemPartition()
2693 * Number of the next page.
2696 SelectFileSystemPage(PINPUT_RECORD Ir
)
2698 PPARTENTRY PartEntry
;
2699 PDISKENTRY DiskEntry
;
2704 CHAR PartTypeString
[32];
2705 FORMATMACHINESTATE PreviousFormatState
;
2708 DPRINT("SelectFileSystemPage()\n");
2710 if (PartitionList
== NULL
|| InstallPartition
== NULL
)
2712 /* FIXME: show an error dialog */
2716 /* Find or set the active system partition when starting formatting */
2717 if (FormatState
== Start
)
2719 /* Find or set the active system partition */
2720 CheckActiveSystemPartition(PartitionList
,
2722 InstallPartition
->DiskEntry
,
2724 if (PartitionList
->SystemPartition
== NULL
)
2726 /* FIXME: show an error dialog */
2728 // Error dialog should say that we cannot find a suitable
2729 // system partition and create one on the system. At this point,
2730 // it may be nice to ask the user whether he wants to continue,
2731 // or use an external drive as the system drive/partition
2732 // (e.g. floppy, USB drive, etc...)
2738 * If the system partition can be created in some
2739 * non-partitioned space, create it now.
2741 if (!PartitionList
->SystemPartition
->IsPartitioned
)
2743 // if (IsUnattendedSetup)
2745 CreatePrimaryPartition(PartitionList
,
2746 PartitionList
->SystemPartition
,
2747 0LL, // PartitionList->SystemPartition->SectorCount.QuadPart,
2749 ASSERT(PartitionList
->SystemPartition
->IsPartitioned
);
2756 /* Commit all partition changes to all the disks */
2757 if (!WritePartitionsToDisk(PartitionList
))
2759 DPRINT("WritePartitionsToDisk() failed\n");
2760 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
2765 * In all cases, whether or not we are going to perform a formatting,
2766 * we must perform a filesystem check of both the system and the
2767 * installation partitions.
2769 InstallPartition
->NeedsCheck
= TRUE
;
2770 if (PartitionList
->SystemPartition
!= InstallPartition
)
2771 PartitionList
->SystemPartition
->NeedsCheck
= TRUE
;
2774 * In case we just repair an existing installation, or make
2775 * an unattended setup without formatting, just go to the
2776 * filesystem check step.
2778 if (RepairUpdateFlag
)
2779 return CHECK_FILE_SYSTEM_PAGE
;
2781 if (IsUnattendedSetup
&& !USetupData
.FormatPartition
)
2782 return CHECK_FILE_SYSTEM_PAGE
;
2785 // ASSERT(PartitionList->SystemPartition->IsPartitioned);
2787 /* Reset the filesystem list for each partition that is to be formatted */
2788 ResetFileSystemList();
2790 PreviousFormatState
= FormatState
;
2791 switch (FormatState
)
2796 * We start by formatting the system partition in case it is new
2797 * (it didn't exist before) and is not the same as the installation
2798 * partition. Otherwise we just require a filesystem check on it,
2799 * and start by formatting the installation partition instead.
2802 ASSERT(PartitionList
->SystemPartition
->IsPartitioned
);
2804 if ((PartitionList
->SystemPartition
!= InstallPartition
) &&
2805 (PartitionList
->SystemPartition
->FormatState
== Unformatted
))
2807 TempPartition
= PartitionList
->SystemPartition
;
2808 TempPartition
->NeedsCheck
= TRUE
;
2810 // TODO: Should we let the user using a custom file-system,
2811 // or should we always use FAT(32) for it?
2812 // For "compatibility", FAT(32) would be best indeed.
2814 FormatState
= FormatSystemPartition
;
2815 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2819 TempPartition
= InstallPartition
;
2820 TempPartition
->NeedsCheck
= TRUE
;
2822 if (PartitionList
->SystemPartition
!= InstallPartition
)
2824 /* The system partition is separate, so it had better be formatted! */
2825 ASSERT((PartitionList
->SystemPartition
->FormatState
== Preformatted
) ||
2826 (PartitionList
->SystemPartition
->FormatState
== Formatted
));
2828 /* Require a filesystem check on the system partition too */
2829 PartitionList
->SystemPartition
->NeedsCheck
= TRUE
;
2832 FormatState
= FormatInstallPartition
;
2833 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2838 case FormatSystemPartition
:
2840 TempPartition
= InstallPartition
;
2841 TempPartition
->NeedsCheck
= TRUE
;
2843 FormatState
= FormatInstallPartition
;
2844 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2848 case FormatInstallPartition
:
2849 case FormatOtherPartition
:
2851 if (GetNextUnformattedPartition(PartitionList
,
2855 FormatState
= FormatOtherPartition
;
2856 TempPartition
->NeedsCheck
= TRUE
;
2858 if (FormatState
== FormatInstallPartition
)
2859 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2861 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2865 FormatState
= FormatDone
;
2867 if (FormatState
== FormatInstallPartition
)
2868 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2870 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2872 return CHECK_FILE_SYSTEM_PAGE
;
2879 DPRINT1("FormatState: FormatDone\n");
2880 return CHECK_FILE_SYSTEM_PAGE
;
2885 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2886 /* FIXME: show an error dialog */
2891 PartEntry
= TempPartition
;
2892 DiskEntry
= TempPartition
->DiskEntry
;
2894 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
2896 /* Adjust disk size */
2897 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2898 if (DiskSize
>= 10 * GB
) /* 10 GB */
2900 DiskSize
= DiskSize
/ GB
;
2901 DiskUnit
= MUIGetString(STRING_GB
);
2905 DiskSize
= DiskSize
/ MB
;
2906 DiskUnit
= MUIGetString(STRING_MB
);
2909 /* Adjust partition size */
2910 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2911 if (PartSize
>= 10 * GB
) /* 10 GB */
2913 PartSize
= PartSize
/ GB
;
2914 PartUnit
= MUIGetString(STRING_GB
);
2918 PartSize
= PartSize
/ MB
;
2919 PartUnit
= MUIGetString(STRING_MB
);
2922 /* Adjust partition type */
2923 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2925 ARRAYSIZE(PartTypeString
));
2927 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2929 if (PartEntry
->AutoCreate
)
2931 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2934 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2935 PartEntry
->PartitionNumber
,
2941 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2942 DiskEntry
->DiskNumber
,
2948 &DiskEntry
->DriverName
,
2949 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2950 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2953 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2955 PartEntry
->AutoCreate
= FALSE
;
2957 else if (PartEntry
->New
)
2959 switch (FormatState
)
2961 case FormatSystemPartition
:
2962 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2965 case FormatInstallPartition
:
2966 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2969 case FormatOtherPartition
:
2970 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2977 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2981 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2983 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2985 CONSOLE_PrintTextXY(8, 10,
2986 MUIGetString(STRING_HDDINFOUNK4
),
2987 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2988 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2989 PartEntry
->PartitionType
,
2995 CONSOLE_PrintTextXY(8, 10,
2997 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2998 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
3004 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
3005 DiskEntry
->DiskNumber
,
3011 &DiskEntry
->DriverName
,
3012 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
3013 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
3017 ASSERT(FileSystemList
== NULL
);
3019 if (IsUnattendedSetup
)
3021 ASSERT(USetupData
.FormatPartition
);
3023 switch (USetupData
.FsType
)
3025 /* 1 is for BtrFS */
3027 DefaultFs
= L
"BTRFS";
3030 /* If we don't understand input, default to FAT */
3038 /* By default select the "FAT" file system */
3042 /* Create the file system list */
3043 // TODO: Display only the FSes compatible with the selected partition!
3044 FileSystemList
= CreateFileSystemList(6, 26,
3046 PartEntry
->FormatState
== Unformatted
,
3048 if (FileSystemList
== NULL
)
3050 /* FIXME: show an error dialog */
3054 if (IsUnattendedSetup
)
3056 ASSERT(USetupData
.FormatPartition
);
3057 return FORMAT_PARTITION_PAGE
;
3060 DrawFileSystemList(FileSystemList
);
3064 CONSOLE_ConInKey(Ir
);
3066 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3067 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3069 if (ConfirmQuit(Ir
))
3071 /* Reset the filesystem list */
3072 ResetFileSystemList();
3078 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3079 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
3081 /* Reset the formatter machine state */
3082 TempPartition
= NULL
;
3083 FormatState
= Start
;
3085 /* Reset the filesystem list */
3086 ResetFileSystemList();
3088 return SELECT_PARTITION_PAGE
;
3090 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3091 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
3093 ScrollDownFileSystemList(FileSystemList
);
3095 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3096 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
3098 ScrollUpFileSystemList(FileSystemList
);
3100 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
3102 if (!FileSystemList
->Selected
->FileSystem
)
3104 ASSERT(!TempPartition
->New
&& TempPartition
->FormatState
!= Unformatted
);
3107 * Skip formatting this partition. We will also ignore
3108 * filesystem checks on it, unless it is either the system
3109 * or the installation partition.
3111 if (TempPartition
!= PartitionList
->SystemPartition
&&
3112 TempPartition
!= InstallPartition
)
3114 PartEntry
->NeedsCheck
= FALSE
;
3117 return SELECT_FILE_SYSTEM_PAGE
;
3121 /* Format this partition */
3122 return FORMAT_PARTITION_PAGE
;
3127 FormatState
= PreviousFormatState
;
3129 return SELECT_FILE_SYSTEM_PAGE
;
3134 * Displays the FormatPartitionPage.
3137 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
3138 * SelectPartitionPage (At once)
3142 * Sets InstallPartition->FormatState
3143 * Sets USetupData.DestinationRootPath
3146 * Number of the next page.
3149 FormatPartitionPage(PINPUT_RECORD Ir
)
3152 PPARTENTRY PartEntry
;
3153 PDISKENTRY DiskEntry
;
3154 PFILE_SYSTEM_ITEM SelectedFileSystem
;
3155 UNICODE_STRING PartitionRootPath
;
3156 WCHAR PathBuffer
[MAX_PATH
];
3157 CHAR Buffer
[MAX_PATH
];
3162 PPARTITION_INFORMATION PartitionInfo
;
3165 DPRINT("FormatPartitionPage()\n");
3167 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
3169 if (PartitionList
== NULL
|| TempPartition
== NULL
)
3171 /* FIXME: show an error dialog */
3175 PartEntry
= TempPartition
;
3176 DiskEntry
= TempPartition
->DiskEntry
;
3178 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
3180 SelectedFileSystem
= FileSystemList
->Selected
;
3181 ASSERT(SelectedFileSystem
&& SelectedFileSystem
->FileSystem
);
3185 if (!IsUnattendedSetup
)
3186 CONSOLE_ConInKey(Ir
);
3188 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3189 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3191 if (ConfirmQuit(Ir
))
3193 /* Reset the filesystem list */
3194 ResetFileSystemList();
3200 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3202 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3204 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
3206 /* FIXME: show an error dialog */
3208 /* Reset the filesystem list */
3209 ResetFileSystemList();
3215 CONSOLE_PrintTextXY(6, 12,
3216 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3217 DiskEntry
->Cylinders
,
3218 DiskEntry
->TracksPerCylinder
,
3219 DiskEntry
->SectorsPerTrack
,
3220 DiskEntry
->BytesPerSector
,
3221 DiskEntry
->Dirty
? '*' : ' ');
3225 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3227 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3229 CONSOLE_PrintTextXY(6, Line
,
3230 "%2u: %2lu %c %12I64u %12I64u %02x",
3232 PartitionInfo
->PartitionNumber
,
3233 PartitionInfo
->BootIndicator
? 'A' : '-',
3234 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3235 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3236 PartitionInfo
->PartitionType
);
3241 /* Commit the partition changes to the disk */
3242 Status
= WritePartitions(DiskEntry
);
3243 if (!NT_SUCCESS(Status
))
3245 DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
3246 DiskEntry
->DiskNumber
, Status
);
3248 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3250 /* Reset the filesystem list */
3251 ResetFileSystemList();
3256 /* Set PartitionRootPath */
3257 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3258 L
"\\Device\\Harddisk%lu\\Partition%lu",
3259 DiskEntry
->DiskNumber
,
3260 PartEntry
->PartitionNumber
);
3261 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3262 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3264 /* Format the partition */
3265 Status
= FormatPartition(&PartitionRootPath
,
3266 SelectedFileSystem
->FileSystem
,
3267 SelectedFileSystem
->QuickFormat
);
3268 if (Status
== STATUS_NOT_SUPPORTED
)
3271 "Setup is currently unable to format a partition in %S.\n"
3273 " \x07 Press ENTER to continue Setup.\n"
3274 " \x07 Press F3 to quit Setup.",
3275 SelectedFileSystem
->FileSystem
);
3278 MUIGetString(STRING_QUITCONTINUE
),
3279 NULL
, POPUP_WAIT_NONE
);
3283 CONSOLE_ConInKey(Ir
);
3285 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3286 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3288 if (ConfirmQuit(Ir
))
3290 /* Reset the filesystem list */
3291 ResetFileSystemList();
3296 return SELECT_FILE_SYSTEM_PAGE
;
3299 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3301 return SELECT_FILE_SYSTEM_PAGE
;
3305 else if (!NT_SUCCESS(Status
))
3307 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3308 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3310 /* Reset the filesystem list */
3311 ResetFileSystemList();
3317 // TODO: Here, call a partlist.c function that update the actual FS name
3318 // and the label fields of the volume.
3320 PartEntry
->FormatState
= Formatted
;
3321 // PartEntry->FileSystem = FileSystem;
3322 PartEntry
->New
= FALSE
;
3325 CONSOLE_SetStatusText(" Done. Press any key ...");
3326 CONSOLE_ConInKey(Ir
);
3329 return SELECT_FILE_SYSTEM_PAGE
;
3333 return FORMAT_PARTITION_PAGE
;
3338 * Displays the CheckFileSystemPage.
3341 * InstallDirectoryPage (At once)
3345 * Inits or reloads FileSystemList
3348 * Number of the next page.
3351 CheckFileSystemPage(PINPUT_RECORD Ir
)
3354 PDISKENTRY DiskEntry
;
3355 PPARTENTRY PartEntry
;
3356 UNICODE_STRING PartitionRootPath
;
3357 WCHAR PathBuffer
[MAX_PATH
];
3358 CHAR Buffer
[MAX_PATH
];
3360 if (PartitionList
== NULL
)
3362 /* FIXME: show an error dialog */
3366 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3368 return INSTALL_DIRECTORY_PAGE
;
3371 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
3373 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3375 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3377 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
3378 PartEntry
->PartitionType
, (*PartEntry
->FileSystem
? PartEntry
->FileSystem
: L
"n/a"));
3380 /* HACK: Do not try to check a partition with an unknown filesystem */
3381 if (!*PartEntry
->FileSystem
)
3383 PartEntry
->NeedsCheck
= FALSE
;
3384 return CHECK_FILE_SYSTEM_PAGE
;
3387 /* Set PartitionRootPath */
3388 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3389 L
"\\Device\\Harddisk%lu\\Partition%lu",
3390 DiskEntry
->DiskNumber
,
3391 PartEntry
->PartitionNumber
);
3392 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3393 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3395 /* Check the partition */
3396 Status
= ChkdskPartition(&PartitionRootPath
, PartEntry
->FileSystem
);
3397 if (Status
== STATUS_NOT_SUPPORTED
)
3400 * Partition checking is not supported with the current filesystem,
3401 * so disable FS checks on it.
3403 PartEntry
->NeedsCheck
= FALSE
;
3405 RtlStringCbPrintfA(Buffer
,
3407 "Setup is currently unable to check a partition formatted in %S.\n"
3409 " \x07 Press ENTER to continue Setup.\n"
3410 " \x07 Press F3 to quit Setup.",
3411 PartEntry
->FileSystem
);
3414 MUIGetString(STRING_QUITCONTINUE
),
3415 NULL
, POPUP_WAIT_NONE
);
3419 CONSOLE_ConInKey(Ir
);
3421 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3422 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3424 if (ConfirmQuit(Ir
))
3427 return CHECK_FILE_SYSTEM_PAGE
;
3429 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3431 return CHECK_FILE_SYSTEM_PAGE
;
3435 else if (!NT_SUCCESS(Status
))
3437 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3438 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3439 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3440 "(Status 0x%08lx).\n", Status
);
3442 // MUIGetString(STRING_REBOOTCOMPUTER),
3443 MUIGetString(STRING_CONTINUE
),
3444 Ir
, POPUP_WAIT_ENTER
);
3446 // return QUIT_PAGE;
3449 PartEntry
->NeedsCheck
= FALSE
;
3450 return CHECK_FILE_SYSTEM_PAGE
;
3456 IN PCWSTR InstallDir
,
3457 IN PPARTENTRY PartEntry
)
3461 Status
= InitDestinationPaths(&USetupData
, InstallDir
, PartEntry
);
3463 if (!NT_SUCCESS(Status
))
3465 DPRINT1("InitDestinationPaths() failed with status 0x%08lx\n", Status
);
3469 /* Initialize DestinationDriveLetter */
3470 DestinationDriveLetter
= PartEntry
->DriveLetter
;
3472 return STATUS_SUCCESS
;
3478 IN PCWSTR InstallDir
)
3482 Length
= wcslen(InstallDir
);
3484 // TODO: Add check for 8.3 too.
3486 /* Path must be at least 2 characters long */
3490 /* Path must start with a backslash */
3491 // if (InstallDir[0] != L'\\')
3494 /* Path must not end with a backslash */
3495 if (InstallDir
[Length
- 1] == L
'\\')
3498 /* Path must not contain whitespace characters */
3499 for (i
= 0; i
< Length
; i
++)
3501 if (iswspace(InstallDir
[i
]))
3505 /* Path component must not end with a dot */
3506 for (i
= 0; i
< Length
; i
++)
3508 if (InstallDir
[i
] == L
'\\' && i
> 0)
3510 if (InstallDir
[i
- 1] == L
'.')
3515 if (InstallDir
[Length
- 1] == L
'.')
3523 * Displays the InstallDirectoryPage.
3530 * Number of the next page.
3533 InstallDirectoryPage(PINPUT_RECORD Ir
)
3538 WCHAR InstallDir
[MAX_PATH
];
3540 /* We do not need the filesystem list anymore */
3541 ResetFileSystemList();
3543 if (PartitionList
== NULL
|| InstallPartition
== NULL
)
3545 /* FIXME: show an error dialog */
3549 // if (IsUnattendedSetup)
3550 if (RepairUpdateFlag
)
3551 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3552 else if (USetupData
.InstallationDirectory
[0])
3553 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3555 wcscpy(InstallDir
, L
"\\ReactOS");
3558 * Check the validity of the predefined 'InstallDir'. If we are either
3559 * in unattended setup or in update/repair mode, and the installation path
3560 * is valid, just perform the installation. Otherwise (either in the case
3561 * of an invalid path, or we are in regular setup), display the UI and allow
3562 * the user to specify a new installation path.
3564 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3566 Status
= BuildInstallPaths(InstallDir
, InstallPartition
);
3567 if (!NT_SUCCESS(Status
))
3569 DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status
);
3570 MUIDisplayError(ERROR_NO_BUILD_PATH
, Ir
, POPUP_WAIT_ENTER
);
3575 * Check whether the user attempts to install ReactOS within the
3576 * installation source directory, or in a subdirectory thereof.
3577 * If so, fail with an error.
3579 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3581 MUIDisplayError(ERROR_SOURCE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3582 return INSTALL_DIRECTORY_PAGE
;
3585 return PREPARE_COPY_PAGE
;
3588 Length
= wcslen(InstallDir
);
3591 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3592 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3593 CONSOLE_SetCursorXY(8 + Pos
, 11);
3594 CONSOLE_SetCursorType(TRUE
, TRUE
);
3598 CONSOLE_ConInKey(Ir
);
3600 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3601 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3603 CONSOLE_SetCursorType(TRUE
, FALSE
);
3605 if (ConfirmQuit(Ir
))
3608 CONSOLE_SetCursorType(TRUE
, TRUE
);
3611 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3612 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3616 memmove(&InstallDir
[Pos
],
3617 &InstallDir
[Pos
+ 1],
3618 (Length
- Pos
- 1) * sizeof(WCHAR
));
3619 InstallDir
[Length
- 1] = UNICODE_NULL
;
3622 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3623 CONSOLE_SetCursorXY(8 + Pos
, 11);
3626 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3627 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3630 CONSOLE_SetCursorXY(8 + Pos
, 11);
3632 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3633 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3636 CONSOLE_SetCursorXY(8 + Pos
, 11);
3638 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3639 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3644 CONSOLE_SetCursorXY(8 + Pos
, 11);
3647 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3648 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3653 CONSOLE_SetCursorXY(8 + Pos
, 11);
3656 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3658 CONSOLE_SetCursorType(TRUE
, FALSE
);
3661 * Check for the validity of the installation directory and pop up
3662 * an error if it is not the case. Then the user can fix its input.
3664 if (!IsValidPath(InstallDir
))
3666 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3667 return INSTALL_DIRECTORY_PAGE
;
3670 Status
= BuildInstallPaths(InstallDir
, InstallPartition
);
3671 if (!NT_SUCCESS(Status
))
3673 DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status
);
3674 MUIDisplayError(ERROR_NO_BUILD_PATH
, Ir
, POPUP_WAIT_ENTER
);
3679 * Check whether the user attempts to install ReactOS within the
3680 * installation source directory, or in a subdirectory thereof.
3681 * If so, fail with an error.
3683 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3685 MUIDisplayError(ERROR_SOURCE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3686 return INSTALL_DIRECTORY_PAGE
;
3689 return PREPARE_COPY_PAGE
;
3691 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3696 memmove(&InstallDir
[Pos
- 1],
3698 (Length
- Pos
) * sizeof(WCHAR
));
3699 InstallDir
[Length
- 1] = UNICODE_NULL
;
3703 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3704 CONSOLE_SetCursorXY(8 + Pos
, 11);
3707 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3711 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3712 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3715 memmove(&InstallDir
[Pos
+ 1],
3717 (Length
- Pos
) * sizeof(WCHAR
));
3718 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3719 InstallDir
[Pos
] = c
;
3723 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3724 CONSOLE_SetCursorXY(8 + Pos
, 11);
3730 return INSTALL_DIRECTORY_PAGE
;
3734 // PSETUP_ERROR_ROUTINE
3738 IN PUSETUP_DATA pSetupData
,
3744 va_start(arg_ptr
, pSetupData
);
3746 if (pSetupData
->LastErrorNumber
>= ERROR_SUCCESS
&&
3747 pSetupData
->LastErrorNumber
< ERROR_LAST_ERROR_CODE
)
3749 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3750 MUIDisplayErrorV(pSetupData
->LastErrorNumber
, &Ir
, POPUP_WAIT_ENTER
, arg_ptr
);
3757 * Displays the PrepareCopyPage.
3760 * FileCopyPage(At once)
3764 * Calls PrepareFileCopy
3767 * Number of the next page.
3770 PrepareCopyPage(PINPUT_RECORD Ir
)
3772 // ERROR_NUMBER ErrorNumber;
3775 MUIDisplayPage(PREPARE_COPY_PAGE
);
3777 /* ErrorNumber = */ Success
= PrepareFileCopy(&USetupData
, NULL
);
3778 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success
)
3780 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3784 return FILE_COPY_PAGE
;
3787 typedef struct _COPYCONTEXT
3789 ULONG TotalOperations
;
3790 ULONG CompletedOperations
;
3791 PPROGRESSBAR ProgressBar
;
3792 PPROGRESSBAR MemoryBars
[4];
3793 } COPYCONTEXT
, *PCOPYCONTEXT
;
3796 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3799 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3801 /* Get the memory information from the system */
3802 NtQuerySystemInformation(SystemPerformanceInformation
,
3807 /* Check if this is initial setup */
3810 /* Set maximum limits to be total RAM pages */
3811 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3812 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3813 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3816 /* Set current values */
3817 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3818 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3819 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3824 FileCopyCallback(PVOID Context
,
3829 PCOPYCONTEXT CopyContext
= (PCOPYCONTEXT
)Context
;
3830 PFILEPATHS_W FilePathInfo
;
3831 PCWSTR SrcFileName
, DstFileName
;
3833 switch (Notification
)
3835 case SPFILENOTIFY_STARTSUBQUEUE
:
3837 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3838 CopyContext
->CompletedOperations
= 0;
3839 ProgressSetStepCount(CopyContext
->ProgressBar
,
3840 CopyContext
->TotalOperations
);
3841 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3845 case SPFILENOTIFY_STARTDELETE
:
3846 case SPFILENOTIFY_STARTRENAME
:
3847 case SPFILENOTIFY_STARTCOPY
:
3849 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3851 if (Notification
== SPFILENOTIFY_STARTDELETE
)
3853 /* Display delete message */
3854 ASSERT(Param2
== FILEOP_DELETE
);
3856 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3857 if (DstFileName
) ++DstFileName
;
3858 else DstFileName
= FilePathInfo
->Target
;
3860 CONSOLE_SetStatusText(MUIGetString(STRING_DELETING
),
3863 else if (Notification
== SPFILENOTIFY_STARTRENAME
)
3865 /* Display move/rename message */
3866 ASSERT(Param2
== FILEOP_RENAME
);
3868 SrcFileName
= wcsrchr(FilePathInfo
->Source
, L
'\\');
3869 if (SrcFileName
) ++SrcFileName
;
3870 else SrcFileName
= FilePathInfo
->Source
;
3872 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3873 if (DstFileName
) ++DstFileName
;
3874 else DstFileName
= FilePathInfo
->Target
;
3876 if (!wcsicmp(SrcFileName
, DstFileName
))
3877 Param2
= STRING_MOVING
;
3879 Param2
= STRING_RENAMING
;
3881 CONSOLE_SetStatusText(MUIGetString(Param2
),
3882 SrcFileName
, DstFileName
);
3884 else if (Notification
== SPFILENOTIFY_STARTCOPY
)
3886 /* Display copy message */
3887 ASSERT(Param2
== FILEOP_COPY
);
3889 /* NOTE: When extracting from CABs the Source is the CAB name */
3890 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3891 if (DstFileName
) ++DstFileName
;
3892 else DstFileName
= FilePathInfo
->Target
;
3894 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
),
3898 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3902 case SPFILENOTIFY_COPYERROR
:
3904 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3906 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3907 FilePathInfo
->Target
, FilePathInfo
->Win32Error
);
3911 case SPFILENOTIFY_ENDDELETE
:
3912 case SPFILENOTIFY_ENDRENAME
:
3913 case SPFILENOTIFY_ENDCOPY
:
3915 CopyContext
->CompletedOperations
++;
3917 /* SYSREG checkpoint */
3918 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3919 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3921 ProgressNextStep(CopyContext
->ProgressBar
);
3922 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3932 * Displays the FileCopyPage.
3935 * RegistryPage(At once)
3941 * Number of the next page.
3944 FileCopyPage(PINPUT_RECORD Ir
)
3946 COPYCONTEXT CopyContext
;
3949 MUIDisplayPage(FILE_COPY_PAGE
);
3951 /* Create context for the copy process */
3952 CopyContext
.TotalOperations
= 0;
3953 CopyContext
.CompletedOperations
= 0;
3955 /* Create the progress bar as well */
3956 CopyContext
.ProgressBar
= CreateProgressBar(13,
3963 MUIGetString(STRING_SETUPCOPYINGFILES
));
3965 // fit memory bars to screen width, distribute them uniform
3966 MemBarWidth
= (xScreen
- 26) / 5;
3967 MemBarWidth
-= MemBarWidth
% 2; // make even
3968 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3969 /* Create the paged pool progress bar */
3970 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3979 /* Create the non paged pool progress bar */
3980 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (MemBarWidth
/ 2),
3982 (xScreen
/ 2) + (MemBarWidth
/ 2),
3984 (xScreen
/ 2)- (MemBarWidth
/ 2),
3989 /* Create the global memory progress bar */
3990 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - MemBarWidth
,
3994 xScreen
- 13 - MemBarWidth
,
3999 /* Do the file copying */
4000 DoFileCopy(&USetupData
, FileCopyCallback
, &CopyContext
);
4002 /* If we get here, we're done, so cleanup the progress bar */
4003 DestroyProgressBar(CopyContext
.ProgressBar
);
4004 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4005 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4006 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4008 /* Create the $winnt$.inf file */
4009 InstallSetupInfFile(&USetupData
);
4011 /* Go display the next page */
4012 return REGISTRY_PAGE
;
4018 RegistryStatus(IN REGISTRY_STATUS RegStatus
, ...)
4020 /* WARNING: Please keep this lookup table in sync with the resources! */
4021 static const UINT StringIDs
[] =
4023 STRING_DONE
, /* Success */
4024 STRING_REGHIVEUPDATE
, /* RegHiveUpdate */
4025 STRING_IMPORTFILE
, /* ImportRegHive */
4026 STRING_DISPLAYSETTINGSUPDATE
, /* DisplaySettingsUpdate */
4027 STRING_LOCALESETTINGSUPDATE
, /* LocaleSettingsUpdate */
4028 STRING_ADDKBLAYOUTS
, /* KeybLayouts */
4029 STRING_KEYBOARDSETTINGSUPDATE
, /* KeybSettingsUpdate */
4030 STRING_CODEPAGEINFOUPDATE
, /* CodePageInfoUpdate */
4035 if (RegStatus
< ARRAYSIZE(StringIDs
))
4037 va_start(args
, RegStatus
);
4038 CONSOLE_SetStatusTextV(MUIGetString(StringIDs
[RegStatus
]), args
);
4043 CONSOLE_SetStatusText("Unknown status %d", RegStatus
);
4048 * Displays the RegistryPage.
4051 * SuccessPage (if RepairUpdate)
4052 * BootLoaderPage (default)
4056 * Calls UpdateRegistry
4059 * Number of the next page.
4062 RegistryPage(PINPUT_RECORD Ir
)
4066 MUIDisplayPage(REGISTRY_PAGE
);
4068 Error
= UpdateRegistry(&USetupData
,
4071 DestinationDriveLetter
,
4074 if (Error
!= ERROR_SUCCESS
)
4076 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
4081 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4082 return BOOT_LOADER_PAGE
;
4088 * Displays the BootLoaderPage.
4091 * SuccessPage (if RepairUpdate)
4092 * BootLoaderHarddiskMbrPage
4093 * BootLoaderHarddiskVbrPage
4094 * BootLoaderFloppyPage
4099 * Calls RegInitializeRegistry
4100 * Calls ImportRegistryFile
4101 * Calls SetDefaultPagefile
4102 * Calls SetMountedDeviceValues
4105 * Number of the next page.
4108 BootLoaderPage(PINPUT_RECORD Ir
)
4110 UCHAR PartitionType
;
4111 BOOLEAN InstallOnFloppy
;
4113 WCHAR PathBuffer
[MAX_PATH
];
4115 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4117 ASSERT(PartitionList
->SystemPartition
->IsPartitioned
&& PartitionList
->SystemPartition
->PartitionNumber
!= 0);
4119 RtlFreeUnicodeString(&USetupData
.SystemRootPath
);
4120 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
4121 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
4122 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4123 PartitionList
->SystemPartition
->PartitionNumber
);
4124 RtlCreateUnicodeString(&USetupData
.SystemRootPath
, PathBuffer
);
4125 DPRINT1("SystemRootPath: %wZ\n", &USetupData
.SystemRootPath
);
4127 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4129 /* For unattended setup, skip MBR installation or install on floppy if needed */
4130 if (IsUnattendedSetup
)
4132 if ((USetupData
.MBRInstallType
== 0) ||
4133 (USetupData
.MBRInstallType
== 1))
4140 * We may install an MBR or VBR, but before that, check whether
4141 * we need to actually install the VBR on floppy.
4143 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4145 DPRINT("Error: system partition invalid (unused)\n");
4146 InstallOnFloppy
= TRUE
;
4148 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4150 /* OS/2 boot manager partition */
4151 DPRINT("Found OS/2 boot manager partition\n");
4152 InstallOnFloppy
= TRUE
;
4154 else if (PartitionType
== PARTITION_LINUX
)
4156 /* Linux partition */
4157 DPRINT("Found Linux native partition (ext2/ext3/ReiserFS/BTRFS/etc)\n");
4158 InstallOnFloppy
= FALSE
;
4160 else if (PartitionType
== PARTITION_IFS
)
4162 /* NTFS partition */
4163 DPRINT("Found NTFS partition\n");
4165 // FIXME: Make it FALSE when we'll support NTFS installation!
4166 InstallOnFloppy
= TRUE
;
4168 else if ((PartitionType
== PARTITION_FAT_12
) ||
4169 (PartitionType
== PARTITION_FAT_16
) ||
4170 (PartitionType
== PARTITION_HUGE
) ||
4171 (PartitionType
== PARTITION_XINT13
) ||
4172 (PartitionType
== PARTITION_FAT32
) ||
4173 (PartitionType
== PARTITION_FAT32_XINT13
))
4175 DPRINT("Found FAT partition\n");
4176 InstallOnFloppy
= FALSE
;
4180 /* Unknown partition */
4181 DPRINT("Unknown partition found\n");
4182 InstallOnFloppy
= TRUE
;
4185 /* We should install on floppy */
4186 if (InstallOnFloppy
)
4188 USetupData
.MBRInstallType
= 1;
4192 /* Is it an unattended install on hdd? */
4193 if (IsUnattendedSetup
)
4195 if ((USetupData
.MBRInstallType
== 2) ||
4196 (USetupData
.MBRInstallType
== 3))
4202 MUIDisplayPage(BOOT_LOADER_PAGE
);
4203 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4207 CONSOLE_ConInKey(Ir
);
4209 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4210 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4212 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4221 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4223 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4224 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4226 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4235 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4237 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4238 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
4240 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4244 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4246 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4247 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
4249 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4253 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4255 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4256 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4258 if (ConfirmQuit(Ir
))
4263 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4267 /* Install on both MBR and VBR */
4268 USetupData
.MBRInstallType
= 2;
4271 else if (Line
== 13)
4273 /* Install on VBR only */
4274 USetupData
.MBRInstallType
= 3;
4277 else if (Line
== 14)
4279 /* Install on floppy */
4280 USetupData
.MBRInstallType
= 1;
4283 else if (Line
== 15)
4285 /* Skip MBR installation */
4286 USetupData
.MBRInstallType
= 0;
4290 return BOOT_LOADER_PAGE
;
4295 switch (USetupData
.MBRInstallType
)
4297 /* Skip MBR installation */
4299 return SUCCESS_PAGE
;
4301 /* Install on floppy */
4303 return BOOT_LOADER_FLOPPY_PAGE
;
4305 /* Install on both MBR and VBR */
4307 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4309 /* Install on VBR only */
4311 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4314 return BOOT_LOADER_PAGE
;
4319 * Displays the BootLoaderFloppyPage.
4322 * SuccessPage (At once)
4326 * Calls InstallFatBootcodeToFloppy()
4329 * Number of the next page.
4332 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4336 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4338 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4342 CONSOLE_ConInKey(Ir
);
4344 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4345 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4347 if (ConfirmQuit(Ir
))
4352 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4354 Status
= InstallFatBootcodeToFloppy(&USetupData
.SourceRootPath
,
4355 &USetupData
.DestinationArcPath
);
4356 if (!NT_SUCCESS(Status
))
4358 if (Status
== STATUS_DEVICE_NOT_READY
)
4359 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4361 /* TODO: Print error message */
4362 return BOOT_LOADER_FLOPPY_PAGE
;
4365 return SUCCESS_PAGE
;
4369 return BOOT_LOADER_FLOPPY_PAGE
;
4374 * Displays the BootLoaderHarddiskVbrPage.
4377 * SuccessPage (At once)
4381 * Calls InstallVBRToPartition()
4384 * Number of the next page.
4387 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4391 // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4392 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4393 &USetupData
.SourceRootPath
,
4394 &USetupData
.DestinationArcPath
,
4395 PartitionList
->SystemPartition
->PartitionType
);
4396 if (!NT_SUCCESS(Status
))
4398 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4399 PartitionList
->SystemPartition
->FileSystem
);
4403 return SUCCESS_PAGE
;
4408 * Displays the BootLoaderHarddiskMbrPage.
4411 * SuccessPage (At once)
4415 * Calls InstallVBRToPartition()
4416 * Calls InstallMbrBootCodeToDisk()
4419 * Number of the next page.
4422 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4425 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4427 /* Step 1: Write the VBR */
4428 // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4429 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4430 &USetupData
.SourceRootPath
,
4431 &USetupData
.DestinationArcPath
,
4432 PartitionList
->SystemPartition
->PartitionType
);
4433 if (!NT_SUCCESS(Status
))
4435 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4436 PartitionList
->SystemPartition
->FileSystem
);
4440 /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
4441 if (!IsSuperFloppy(PartitionList
->SystemPartition
->DiskEntry
))
4443 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4444 L
"\\Device\\Harddisk%d\\Partition0",
4445 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4446 Status
= InstallMbrBootCodeToDisk(&USetupData
.SystemRootPath
,
4447 &USetupData
.SourceRootPath
,
4448 DestinationDevicePathBuffer
);
4449 if (!NT_SUCCESS(Status
))
4451 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status
);
4452 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
, L
"MBR");
4457 return SUCCESS_PAGE
;
4462 * @name ProgressTimeOutStringHandler
4464 * Handles the generation (displaying) of the timeout
4465 * countdown to the screen dynamically.
4468 * A pointer to a progress bar.
4470 * @param AlwaysUpdate
4471 * Constantly update the progress bar (boolean type).
4474 * A pointer to a string buffer.
4476 * @param cchBufferSize
4477 * The buffer's size in number of characters.
4480 * TRUE or FALSE on function termination.
4485 ProgressTimeOutStringHandler(
4486 IN PPROGRESSBAR Bar
,
4487 IN BOOLEAN AlwaysUpdate
,
4489 IN SIZE_T cchBufferSize
)
4491 ULONG OldProgress
= Bar
->Progress
;
4493 if (Bar
->StepCount
== 0)
4499 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4502 /* Build the progress string if it has changed */
4503 if (Bar
->ProgressFormatText
&&
4504 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4506 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4507 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4516 * @name ProgressCountdown
4518 * Displays and draws a red-coloured progress bar with a countdown.
4519 * When the timeout is reached, the flush page is displayed for reboot.
4522 * A pointer to an input keyboard record.
4525 * Initial countdown value in seconds.
4533 IN PINPUT_RECORD Ir
,
4537 ULONG StartTime
, BarWidth
, TimerDiv
;
4539 LONG TimerValue
, OldTimerValue
;
4540 LARGE_INTEGER Timeout
;
4541 PPROGRESSBAR ProgressBar
;
4542 BOOLEAN RefreshProgress
= TRUE
;
4544 /* Bail out if the timeout is already zero */
4548 /* Create the timeout progress bar and set it up */
4549 ProgressBar
= CreateProgressBarEx(13,
4556 FOREGROUND_RED
| BACKGROUND_BLUE
,
4559 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4560 ProgressTimeOutStringHandler
);
4562 BarWidth
= max(1, ProgressBar
->Width
);
4563 TimerValue
= TimeOut
* BarWidth
;
4564 ProgressSetStepCount(ProgressBar
, TimerValue
);
4566 StartTime
= NtGetTickCount();
4569 TimerDiv
= 1000 / BarWidth
;
4570 TimerDiv
= max(1, TimerDiv
);
4571 OldTimerValue
= TimerValue
;
4574 /* Decrease the timer */
4577 * Compute how much time the previous operations took.
4578 * This allows us in particular to take account for any time
4579 * elapsed if something slowed down.
4581 TimeElapsed
= NtGetTickCount() - StartTime
;
4582 if (TimeElapsed
>= TimerDiv
)
4584 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4585 TimeElapsed
/= TimerDiv
;
4586 StartTime
+= (TimerDiv
* TimeElapsed
);
4588 if (TimeElapsed
<= TimerValue
)
4589 TimerValue
-= TimeElapsed
;
4593 RefreshProgress
= TRUE
;
4596 if (RefreshProgress
)
4598 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4599 RefreshProgress
= FALSE
;
4602 /* Stop when the timer reaches zero */
4603 if (TimerValue
<= 0)
4606 /* Check for user key presses */
4609 * If the timer is used, use a passive wait of maximum 1 second
4610 * while monitoring for incoming console input events, so that
4611 * we are still able to display the timing count.
4614 /* Wait a maximum of 1 second for input events */
4615 TimeElapsed
= NtGetTickCount() - StartTime
;
4616 if (TimeElapsed
< TimerDiv
)
4618 /* Convert the time to NT Format */
4619 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4620 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4624 Status
= STATUS_TIMEOUT
;
4627 /* Check whether the input event has been signaled, or a timeout happened */
4628 if (Status
== STATUS_TIMEOUT
)
4632 if (Status
!= STATUS_WAIT_0
)
4634 /* An error happened, bail out */
4635 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4639 /* Check for an ENTER key press */
4640 while (CONSOLE_ConInKeyPeek(Ir
))
4642 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4644 /* Found it, stop waiting */
4651 /* Destroy the progress bar and quit */
4652 DestroyProgressBar(ProgressBar
);
4657 * Displays the QuitPage.
4660 * FlushPage (At once)
4666 * Number of the next page.
4669 QuitPage(PINPUT_RECORD Ir
)
4671 MUIDisplayPage(QUIT_PAGE
);
4673 /* Destroy the NTOS installations list */
4674 if (NtOsInstallsList
!= NULL
)
4676 DestroyGenericList(NtOsInstallsList
, TRUE
);
4677 NtOsInstallsList
= NULL
;
4680 /* Destroy the partition list */
4681 if (PartitionList
!= NULL
)
4683 DestroyPartitionList(PartitionList
);
4684 PartitionList
= NULL
;
4687 /* Reset the formatter machine state */
4688 TempPartition
= NULL
;
4689 FormatState
= Start
;
4691 /* Destroy the filesystem list */
4692 ResetFileSystemList();
4694 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4696 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4697 ProgressCountdown(Ir
, 15);
4703 * Displays the SuccessPage.
4706 * FlushPage (At once)
4712 * Number of the next page.
4715 SuccessPage(PINPUT_RECORD Ir
)
4717 MUIDisplayPage(SUCCESS_PAGE
);
4719 if (IsUnattendedSetup
)
4722 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4723 ProgressCountdown(Ir
, 15);
4729 * Displays the FlushPage.
4732 * RebootPage (At once)
4735 * Number of the next page.
4738 FlushPage(PINPUT_RECORD Ir
)
4740 MUIDisplayPage(FLUSH_PAGE
);
4746 * The start routine and page management
4756 InfSetHeap(ProcessHeap
);
4758 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4759 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4760 if (!NT_SUCCESS(Status
))
4761 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
4763 /* Initialize the user-mode PnP manager */
4764 Status
= InitializeUserModePnpManager(&USetupData
.SetupInf
);
4765 if (!NT_SUCCESS(Status
))
4768 DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status
);
4771 if (!CONSOLE_Init())
4773 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4774 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4775 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4777 /* We failed to initialize the video, just quit the installer */
4778 return STATUS_APP_INIT_FAILURE
;
4781 /* Initialize Setup, phase 0 */
4782 InitializeSetup(&USetupData
, 0);
4783 USetupData
.ErrorRoutine
= USetupErrorRoutine
;
4785 /* Hide the cursor and clear the screen and keyboard buffer */
4786 CONSOLE_SetCursorType(TRUE
, FALSE
);
4787 CONSOLE_ClearScreen();
4790 /* Global Initialization page */
4791 Page
= SetupStartPage(&Ir
);
4793 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4795 CONSOLE_ClearScreen();
4798 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4805 Page
= LanguagePage(&Ir
);
4810 Page
= WelcomePage(&Ir
);
4815 Page
= LicensePage(&Ir
);
4819 case INSTALL_INTRO_PAGE
:
4820 Page
= InstallIntroPage(&Ir
);
4824 case SCSI_CONTROLLER_PAGE
:
4825 Page
= ScsiControllerPage(&Ir
);
4828 case OEM_DRIVER_PAGE
:
4829 Page
= OemDriverPage(&Ir
);
4833 case DEVICE_SETTINGS_PAGE
:
4834 Page
= DeviceSettingsPage(&Ir
);
4837 case COMPUTER_SETTINGS_PAGE
:
4838 Page
= ComputerSettingsPage(&Ir
);
4841 case DISPLAY_SETTINGS_PAGE
:
4842 Page
= DisplaySettingsPage(&Ir
);
4845 case KEYBOARD_SETTINGS_PAGE
:
4846 Page
= KeyboardSettingsPage(&Ir
);
4849 case LAYOUT_SETTINGS_PAGE
:
4850 Page
= LayoutSettingsPage(&Ir
);
4853 case SELECT_PARTITION_PAGE
:
4854 Page
= SelectPartitionPage(&Ir
);
4857 case CREATE_PRIMARY_PARTITION_PAGE
:
4858 Page
= CreatePrimaryPartitionPage(&Ir
);
4861 case CREATE_EXTENDED_PARTITION_PAGE
:
4862 Page
= CreateExtendedPartitionPage(&Ir
);
4865 case CREATE_LOGICAL_PARTITION_PAGE
:
4866 Page
= CreateLogicalPartitionPage(&Ir
);
4869 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4870 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4873 case DELETE_PARTITION_PAGE
:
4874 Page
= DeletePartitionPage(&Ir
);
4877 case SELECT_FILE_SYSTEM_PAGE
:
4878 Page
= SelectFileSystemPage(&Ir
);
4881 case FORMAT_PARTITION_PAGE
:
4882 Page
= FormatPartitionPage(&Ir
);
4885 case CHECK_FILE_SYSTEM_PAGE
:
4886 Page
= CheckFileSystemPage(&Ir
);
4889 case INSTALL_DIRECTORY_PAGE
:
4890 Page
= InstallDirectoryPage(&Ir
);
4893 case PREPARE_COPY_PAGE
:
4894 Page
= PrepareCopyPage(&Ir
);
4897 case FILE_COPY_PAGE
:
4898 Page
= FileCopyPage(&Ir
);
4902 Page
= RegistryPage(&Ir
);
4905 case BOOT_LOADER_PAGE
:
4906 Page
= BootLoaderPage(&Ir
);
4909 case BOOT_LOADER_FLOPPY_PAGE
:
4910 Page
= BootLoaderFloppyPage(&Ir
);
4913 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4914 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4917 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4918 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4922 case REPAIR_INTRO_PAGE
:
4923 Page
= RepairIntroPage(&Ir
);
4926 case UPGRADE_REPAIR_PAGE
:
4927 Page
= UpgradeRepairPage(&Ir
);
4931 Page
= SuccessPage(&Ir
);
4935 Page
= FlushPage(&Ir
);
4939 Page
= QuitPage(&Ir
);
4943 case SETUP_INIT_PAGE
:
4950 /* Terminate the user-mode PnP manager */
4951 TerminateUserModePnpManager();
4953 /* Setup has finished */
4954 FinishSetup(&USetupData
);
4956 if (Page
== RECOVERY_PAGE
)
4962 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4963 NtShutdownSystem(ShutdownReboot
);
4964 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4966 return STATUS_SUCCESS
;
4971 NtProcessStartup(PPEB Peb
)
4976 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4978 ProcessHeap
= Peb
->ProcessHeap
;
4980 NtQuerySystemTime(&Time
);
4982 Status
= RunUSetup();
4984 if (NT_SUCCESS(Status
))
4987 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4988 * a protective waiting.
4989 * This wait is needed because, since we are started as SMSS.EXE,
4990 * the NT kernel explicitly waits 5 seconds for the initial process
4991 * SMSS.EXE to initialize (as a protective measure), and otherwise
4992 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4994 Time
.QuadPart
+= 50000000;
4995 NtDelayExecution(FALSE
, &Time
);
4999 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
5000 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
5001 0, 0, NULL
, 0, NULL
);
5004 NtTerminateProcess(NtCurrentProcess(), Status
);