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)
40 /* GLOBALS & LOCALS *********************************************************/
43 BOOLEAN IsUnattendedSetup
= FALSE
;
45 static USETUP_DATA USetupData
;
47 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
48 static WCHAR DestinationDriveLetter
;
53 PCWSTR SelectedLanguageId
;
54 static WCHAR DefaultLanguage
[20]; // Copy of string inside LanguageList
55 static WCHAR DefaultKBLayout
[20]; // Copy of string inside KeyboardList
57 static BOOLEAN RepairUpdateFlag
= FALSE
;
59 static HANDLE hPnpThread
= NULL
;
61 static PPARTLIST PartitionList
= NULL
;
62 static PPARTENTRY TempPartition
= NULL
;
63 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
64 static FORMATMACHINESTATE FormatState
= Start
;
66 /*****************************************************/
68 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
69 static PGENERIC_LIST NtOsInstallsList
= NULL
;
72 /* FUNCTIONS ****************************************************************/
75 PrintString(char* fmt
,...)
79 UNICODE_STRING UnicodeString
;
80 ANSI_STRING AnsiString
;
83 vsprintf(buffer
, fmt
, ap
);
86 RtlInitAnsiString(&AnsiString
, buffer
);
87 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
88 NtDisplayString(&UnicodeString
);
89 RtlFreeUnicodeString(&UnicodeString
);
94 DrawBox(IN SHORT xLeft
,
102 /* Draw upper left corner */
105 FillConsoleOutputCharacterA(StdOutput
,
111 /* Draw upper edge */
114 FillConsoleOutputCharacterA(StdOutput
,
120 /* Draw upper right corner */
121 coPos
.X
= xLeft
+ Width
- 1;
123 FillConsoleOutputCharacterA(StdOutput
,
129 /* Draw right edge, inner space and left edge */
130 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
133 FillConsoleOutputCharacterA(StdOutput
,
140 FillConsoleOutputCharacterA(StdOutput
,
146 coPos
.X
= xLeft
+ Width
- 1;
147 FillConsoleOutputCharacterA(StdOutput
,
154 /* Draw lower left corner */
156 coPos
.Y
= yTop
+ Height
- 1;
157 FillConsoleOutputCharacterA(StdOutput
,
163 /* Draw lower edge */
165 coPos
.Y
= yTop
+ Height
- 1;
166 FillConsoleOutputCharacterA(StdOutput
,
172 /* Draw lower right corner */
173 coPos
.X
= xLeft
+ Width
- 1;
174 coPos
.Y
= yTop
+ Height
- 1;
175 FillConsoleOutputCharacterA(StdOutput
,
184 PopupError(PCCH Text
,
202 /* Count text lines and longest line */
209 p
= strchr(pnext
, '\n');
213 Length
= strlen(pnext
);
218 Length
= (ULONG
)(p
- pnext
);
224 if (Length
> MaxLength
)
233 /* Check length of status line */
236 Length
= strlen(Status
);
238 if (Length
> MaxLength
)
242 Width
= MaxLength
+ 4;
248 yTop
= (yScreen
- Height
) / 2;
249 xLeft
= (xScreen
- Width
) / 2;
252 /* Set screen attributes */
254 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
256 FillConsoleOutputAttribute(StdOutput
,
257 FOREGROUND_RED
| BACKGROUND_WHITE
,
263 DrawBox(xLeft
, yTop
, Width
, Height
);
265 /* Print message text */
270 p
= strchr(pnext
, '\n');
274 Length
= strlen(pnext
);
279 Length
= (ULONG
)(p
- pnext
);
286 WriteConsoleOutputCharacterA(StdOutput
,
300 /* Print separator line and status text */
303 coPos
.Y
= yTop
+ Height
- 3;
305 FillConsoleOutputCharacterA(StdOutput
,
312 FillConsoleOutputCharacterA(StdOutput
,
318 coPos
.X
= xLeft
+ Width
- 1;
319 FillConsoleOutputCharacterA(StdOutput
,
327 WriteConsoleOutputCharacterA(StdOutput
,
329 min(strlen(Status
), (SIZE_T
)Width
- 4),
334 if (WaitEvent
== POPUP_WAIT_NONE
)
339 CONSOLE_ConInKey(Ir
);
341 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
342 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
354 * FALSE: Don't quit setup.
357 ConfirmQuit(PINPUT_RECORD Ir
)
360 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
364 CONSOLE_ConInKey(Ir
);
366 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
367 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
372 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
386 PGENERIC_LIST_ENTRY ListEntry
;
389 pszNewLayout
= MUIDefaultKeyboardLayout(SelectedLanguageId
);
391 if (USetupData
.LayoutList
== NULL
)
393 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
394 if (USetupData
.LayoutList
== NULL
)
396 /* FIXME: Handle error! */
401 /* Search for default layout (if provided) */
402 if (pszNewLayout
!= NULL
)
404 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
405 ListEntry
= GetNextListEntry(ListEntry
))
407 if (!wcscmp(pszNewLayout
, ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
))
409 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
419 GetSettingDescription(
420 IN PGENERIC_LIST_ENTRY Entry
,
422 IN SIZE_T cchBufferSize
)
424 return RtlStringCchPrintfA(Buffer
, cchBufferSize
, "%S",
425 ((PGENENTRY
)GetListEntryData(Entry
))->Value
);
430 GetNTOSInstallationName(
431 IN PGENERIC_LIST_ENTRY Entry
,
433 IN SIZE_T cchBufferSize
)
435 PNTOS_INSTALLATION NtOsInstall
= (PNTOS_INSTALLATION
)GetListEntryData(Entry
);
436 PPARTENTRY PartEntry
= NtOsInstall
->PartEntry
;
438 if (PartEntry
&& PartEntry
->DriveLetter
)
440 /* We have retrieved a partition that is mounted */
441 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
443 PartEntry
->DriveLetter
,
444 NtOsInstall
->PathComponent
,
445 NtOsInstall
->InstallationName
);
449 /* We failed somewhere, just show the NT path */
450 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
452 &NtOsInstall
->SystemNtPath
,
453 NtOsInstall
->InstallationName
);
459 * Displays the LanguagePage.
461 * Next pages: WelcomePage, QuitPage
464 * Init SelectedLanguageId
465 * Init USetupData.LanguageId
468 * Number of the next page.
471 LanguagePage(PINPUT_RECORD Ir
)
473 GENERIC_LIST_UI ListUi
;
474 PCWSTR NewLanguageId
;
475 BOOL RefreshPage
= FALSE
;
477 /* Initialize the computer settings list */
478 if (USetupData
.LanguageList
== NULL
)
480 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
481 if (USetupData
.LanguageList
== NULL
)
483 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
488 SelectedLanguageId
= DefaultLanguage
;
489 USetupData
.LanguageId
= 0;
492 SetConsoleCodePage();
496 * If there is no language or just a single one in the list,
497 * skip the language selection process altogether.
499 if (GetNumberOfListEntries(USetupData
.LanguageList
) <= 1)
501 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
505 InitGenericListUi(&ListUi
, USetupData
.LanguageList
, GetSettingDescription
);
506 DrawGenericList(&ListUi
,
511 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
513 MUIDisplayPage(LANGUAGE_PAGE
);
517 CONSOLE_ConInKey(Ir
);
519 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
520 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
522 ScrollDownGenericList(&ListUi
);
525 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
526 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
528 ScrollUpGenericList(&ListUi
);
531 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
532 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
534 ScrollPageDownGenericList(&ListUi
);
537 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
538 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
540 ScrollPageUpGenericList(&ListUi
);
543 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
544 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
549 RedrawGenericList(&ListUi
);
551 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
553 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
556 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
558 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
560 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
566 SetConsoleCodePage();
570 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
573 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
579 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
582 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
584 if (wcscmp(SelectedLanguageId
, NewLanguageId
))
586 /* Clear the language page */
587 MUIClearPage(LANGUAGE_PAGE
);
589 SelectedLanguageId
= NewLanguageId
;
592 SetConsoleCodePage();
594 /* Redraw language selection page in native language */
595 MUIDisplayPage(LANGUAGE_PAGE
);
610 * LanguagePage (at once, default)
611 * InstallIntroPage (at once, if unattended)
616 * Init USetupData.SourcePath
617 * Init USetupData.SourceRootPath
618 * Init USetupData.SourceRootDir
619 * Init USetupData.SetupInf
620 * Init USetupData.RequiredPartitionDiskSpace
621 * Init IsUnattendedSetup
622 * If unattended, init *List and sets the Codepage
623 * If unattended, init SelectedLanguageId
624 * If unattended, init USetupData.LanguageId
627 * Number of the next page.
630 SetupStartPage(PINPUT_RECORD Ir
)
633 PGENERIC_LIST_ENTRY ListEntry
;
636 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
638 /* Initialize Setup, phase 1 */
639 Error
= InitializeSetup(&USetupData
, 1);
640 if (Error
!= ERROR_SUCCESS
)
642 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
646 /* Start the PnP thread */
647 if (hPnpThread
!= NULL
)
649 NtResumeThread(hPnpThread
, NULL
);
653 CheckUnattendedSetup(&USetupData
);
655 if (IsUnattendedSetup
)
657 // TODO: Read options from inf
658 /* Load the hardware, language and keyboard layout lists */
660 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
661 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
662 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
664 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
667 SelectedLanguageId
= DefaultLanguage
;
668 wcscpy(DefaultLanguage
, USetupData
.LocaleID
);
669 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
671 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
673 /* first we hack LanguageList */
674 for (ListEntry
= GetFirstListEntry(USetupData
.LanguageList
); ListEntry
;
675 ListEntry
= GetNextListEntry(ListEntry
))
677 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
678 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
680 DPRINT("found %S in LanguageList\n", LocaleId
);
681 SetCurrentListEntry(USetupData
.LanguageList
, ListEntry
);
687 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
688 ListEntry
= GetNextListEntry(ListEntry
))
690 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
691 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
693 DPRINT("found %S in LayoutList\n", LocaleId
);
694 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
699 SetConsoleCodePage();
701 return INSTALL_INTRO_PAGE
;
704 return LANGUAGE_PAGE
;
709 * Displays the WelcomePage.
712 * InstallIntroPage (default)
719 * Number of the next page.
722 WelcomePage(PINPUT_RECORD Ir
)
724 MUIDisplayPage(WELCOME_PAGE
);
728 CONSOLE_ConInKey(Ir
);
730 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
731 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
738 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
740 return INSTALL_INTRO_PAGE
;
742 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
744 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
746 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
757 * Displays the License page.
760 * WelcomePage (default)
763 * Number of the next page.
766 LicensePage(PINPUT_RECORD Ir
)
768 MUIDisplayPage(LICENSE_PAGE
);
772 CONSOLE_ConInKey(Ir
);
774 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
785 * Displays the RepairIntroPage.
788 * RebootPage (default)
794 * Number of the next page.
797 RepairIntroPage(PINPUT_RECORD Ir
)
799 MUIDisplayPage(REPAIR_INTRO_PAGE
);
803 CONSOLE_ConInKey(Ir
);
805 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
809 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
811 RepairUpdateFlag
= TRUE
;
812 return INSTALL_INTRO_PAGE
;
814 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
816 return RECOVERY_PAGE
;
818 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
819 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
825 return REPAIR_INTRO_PAGE
;
829 * Displays the UpgradeRepairPage.
832 * RebootPage (default)
838 * Number of the next page.
841 UpgradeRepairPage(PINPUT_RECORD Ir
)
843 GENERIC_LIST_UI ListUi
;
846 if (PartitionList
== NULL
)
848 PartitionList
= CreatePartitionList();
849 if (PartitionList
== NULL
)
851 /* FIXME: show an error dialog */
852 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
855 else if (IsListEmpty(&PartitionList
->DiskListHead
))
857 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
861 TempPartition
= NULL
;
866 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
867 if (!NtOsInstallsList
)
868 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
871 * If there is no available installation (or just a single one??) that can
872 * be updated in the list, just continue with the regular installation.
874 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
876 RepairUpdateFlag
= FALSE
;
878 // return INSTALL_INTRO_PAGE;
879 return DEVICE_SETTINGS_PAGE
;
880 // return SCSI_CONTROLLER_PAGE;
883 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
885 InitGenericListUi(&ListUi
, NtOsInstallsList
, GetNTOSInstallationName
);
886 DrawGenericList(&ListUi
,
891 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
894 CONSOLE_ConInKey(Ir
);
896 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
898 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
900 case VK_DOWN
: /* DOWN */
901 ScrollDownGenericList(&ListUi
);
904 ScrollUpGenericList(&ListUi
);
906 case VK_NEXT
: /* PAGE DOWN */
907 ScrollPageDownGenericList(&ListUi
);
909 case VK_PRIOR
: /* PAGE UP */
910 ScrollPageUpGenericList(&ListUi
);
917 RedrawGenericList(&ListUi
);
920 case VK_ESCAPE
: /* ESC */
922 RestoreGenericListUiState(&ListUi
);
923 // return nextPage; // prevPage;
925 // return INSTALL_INTRO_PAGE;
926 return DEVICE_SETTINGS_PAGE
;
927 // return SCSI_CONTROLLER_PAGE;
933 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
934 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
935 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
937 /* Retrieve the current installation */
938 ASSERT(GetNumberOfListEntries(NtOsInstallsList
) >= 1);
940 CurrentInstallation
=
941 (PNTOS_INSTALLATION
)GetListEntryData(GetCurrentListEntry(NtOsInstallsList
));
943 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
944 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
946 RepairUpdateFlag
= TRUE
;
949 /***/return INSTALL_INTRO_PAGE
;/***/
951 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
952 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
954 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
959 return UPGRADE_REPAIR_PAGE
;
964 * Displays the InstallIntroPage.
967 * DeviceSettingsPage (At once if repair or update is selected)
968 * SelectPartitionPage (At once if unattended setup)
969 * DeviceSettingsPage (default)
973 * Number of the next page.
976 InstallIntroPage(PINPUT_RECORD Ir
)
978 if (RepairUpdateFlag
)
980 #if 1 /* Old code that looks good */
982 // return SELECT_PARTITION_PAGE;
983 return DEVICE_SETTINGS_PAGE
;
985 #else /* Possible new code? */
987 return DEVICE_SETTINGS_PAGE
;
988 // return SCSI_CONTROLLER_PAGE;
993 if (IsUnattendedSetup
)
994 return SELECT_PARTITION_PAGE
;
996 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1000 CONSOLE_ConInKey(Ir
);
1002 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1003 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1005 if (ConfirmQuit(Ir
))
1010 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1012 return UPGRADE_REPAIR_PAGE
;
1016 return INSTALL_INTRO_PAGE
;
1022 ScsiControllerPage(PINPUT_RECORD Ir
)
1024 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1026 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1028 /* FIXME: print loaded mass storage driver descriptions */
1030 CONSOLE_SetTextXY(8, 10, "TEST device");
1033 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1037 CONSOLE_ConInKey(Ir
);
1039 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1040 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1042 if (ConfirmQuit(Ir
))
1047 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1049 return DEVICE_SETTINGS_PAGE
;
1053 return SCSI_CONTROLLER_PAGE
;
1057 OemDriverPage(PINPUT_RECORD Ir
)
1059 // MUIDisplayPage(OEM_DRIVER_PAGE);
1061 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1063 /* FIXME: Implement!! */
1065 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1069 CONSOLE_ConInKey(Ir
);
1071 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1072 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1074 if (ConfirmQuit(Ir
))
1079 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1081 return DEVICE_SETTINGS_PAGE
;
1085 return OEM_DRIVER_PAGE
;
1091 * Displays the DeviceSettingsPage.
1094 * SelectPartitionPage (At once if repair or update is selected)
1095 * ComputerSettingsPage
1096 * DisplaySettingsPage
1097 * KeyboardSettingsPage
1098 * LayoutsettingsPage
1099 * SelectPartitionPage
1103 * Init USetupData.ComputerList
1104 * Init USetupData.DisplayList
1105 * Init USetupData.KeyboardList
1106 * Init USetupData.LayoutList
1109 * Number of the next page.
1112 DeviceSettingsPage(PINPUT_RECORD Ir
)
1114 static ULONG Line
= 16;
1116 /* Initialize the computer settings list */
1117 if (USetupData
.ComputerList
== NULL
)
1119 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
1120 if (USetupData
.ComputerList
== NULL
)
1122 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1127 /* Initialize the display settings list */
1128 if (USetupData
.DisplayList
== NULL
)
1130 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
1131 if (USetupData
.DisplayList
== NULL
)
1133 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1138 /* Initialize the keyboard settings list */
1139 if (USetupData
.KeyboardList
== NULL
)
1141 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
1142 if (USetupData
.KeyboardList
== NULL
)
1144 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1149 /* Initialize the keyboard layout list */
1150 if (USetupData
.LayoutList
== NULL
)
1152 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
1153 if (USetupData
.LayoutList
== NULL
)
1155 /* FIXME: report error */
1156 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1161 if (RepairUpdateFlag
)
1162 return SELECT_PARTITION_PAGE
;
1164 // if (IsUnattendedSetup)
1165 // return SELECT_PARTITION_PAGE;
1167 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1169 DrawGenericListCurrentItem(USetupData
.ComputerList
, GetSettingDescription
, 25, 11);
1170 DrawGenericListCurrentItem(USetupData
.DisplayList
, GetSettingDescription
, 25, 12);
1171 DrawGenericListCurrentItem(USetupData
.KeyboardList
, GetSettingDescription
, 25, 13);
1172 DrawGenericListCurrentItem(USetupData
.LayoutList
, GetSettingDescription
, 25, 14);
1174 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1178 CONSOLE_ConInKey(Ir
);
1180 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1181 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1183 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1187 else if (Line
== 16)
1192 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1194 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1195 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
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_F3
)) /* F3 */
1211 if (ConfirmQuit(Ir
))
1216 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1219 return COMPUTER_SETTINGS_PAGE
;
1220 else if (Line
== 12)
1221 return DISPLAY_SETTINGS_PAGE
;
1222 else if (Line
== 13)
1223 return KEYBOARD_SETTINGS_PAGE
;
1224 else if (Line
== 14)
1225 return LAYOUT_SETTINGS_PAGE
;
1226 else if (Line
== 16)
1227 return SELECT_PARTITION_PAGE
;
1231 return DEVICE_SETTINGS_PAGE
;
1236 * Handles generic selection lists.
1239 * GenericList: The list to handle.
1240 * nextPage: The page it needs to jump to after this page.
1241 * Ir: The PINPUT_RECORD
1244 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1245 PAGE_NUMBER nextPage
,
1250 CONSOLE_ConInKey(Ir
);
1252 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1253 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1255 ScrollDownGenericList(ListUi
);
1257 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1258 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1260 ScrollUpGenericList(ListUi
);
1262 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1263 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1265 ScrollPageDownGenericList(ListUi
);
1267 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1268 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1270 ScrollPageUpGenericList(ListUi
);
1272 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1273 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1275 if (ConfirmQuit(Ir
))
1278 RedrawGenericList(ListUi
);
1280 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1281 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1283 RestoreGenericListUiState(ListUi
);
1284 return nextPage
; // Use some "prevPage;" instead?
1286 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1290 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1293 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1300 * Displays the ComputerSettingsPage.
1303 * DeviceSettingsPage
1307 * Number of the next page.
1310 ComputerSettingsPage(PINPUT_RECORD Ir
)
1312 GENERIC_LIST_UI ListUi
;
1313 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1315 InitGenericListUi(&ListUi
, USetupData
.ComputerList
, GetSettingDescription
);
1316 DrawGenericList(&ListUi
,
1321 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1326 * Displays the DisplaySettingsPage.
1329 * DeviceSettingsPage
1333 * Number of the next page.
1336 DisplaySettingsPage(PINPUT_RECORD Ir
)
1338 GENERIC_LIST_UI ListUi
;
1339 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1341 InitGenericListUi(&ListUi
, USetupData
.DisplayList
, GetSettingDescription
);
1342 DrawGenericList(&ListUi
,
1347 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1352 * Displays the KeyboardSettingsPage.
1355 * DeviceSettingsPage
1359 * Number of the next page.
1362 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1364 GENERIC_LIST_UI ListUi
;
1365 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1367 InitGenericListUi(&ListUi
, USetupData
.KeyboardList
, GetSettingDescription
);
1368 DrawGenericList(&ListUi
,
1373 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1378 * Displays the LayoutSettingsPage.
1381 * DeviceSettingsPage
1385 * Number of the next page.
1388 LayoutSettingsPage(PINPUT_RECORD Ir
)
1390 GENERIC_LIST_UI ListUi
;
1391 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1393 InitGenericListUi(&ListUi
, USetupData
.LayoutList
, GetSettingDescription
);
1394 DrawGenericList(&ListUi
,
1399 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1404 IsDiskSizeValid(PPARTENTRY PartEntry
)
1408 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1409 size
= (size
+ (512 * KB
)) / MB
; /* in MBytes */
1411 if (size
< USetupData
.RequiredPartitionDiskSpace
)
1413 /* Partition is too small so ask for another one */
1414 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, USetupData
.RequiredPartitionDiskSpace
);
1425 * Displays the SelectPartitionPage.
1428 * SelectFileSystemPage (At once if unattended)
1429 * SelectFileSystemPage (Default if free space is selected)
1430 * CreatePrimaryPartitionPage
1431 * CreateExtendedPartitionPage
1432 * CreateLogicalPartitionPage
1433 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1434 * DeletePartitionPage
1438 * Set InstallShortcut (only if not unattended + free space is selected)
1441 * Number of the next page.
1444 SelectPartitionPage(PINPUT_RECORD Ir
)
1449 if (PartitionList
== NULL
)
1451 PartitionList
= CreatePartitionList();
1452 if (PartitionList
== NULL
)
1454 /* FIXME: show an error dialog */
1455 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1458 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1460 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1464 TempPartition
= NULL
;
1465 FormatState
= Start
;
1468 if (RepairUpdateFlag
)
1470 /* Determine the selected installation disk & partition */
1471 if (!SelectPartition(PartitionList
,
1472 CurrentInstallation
->DiskNumber
,
1473 CurrentInstallation
->PartitionNumber
))
1475 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1479 return SELECT_FILE_SYSTEM_PAGE
;
1482 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1484 InitPartitionListUi(&ListUi
, PartitionList
,
1489 DrawPartitionList(&ListUi
);
1491 if (IsUnattendedSetup
)
1493 if (!SelectPartition(PartitionList
,
1494 USetupData
.DestinationDiskNumber
,
1495 USetupData
.DestinationPartitionNumber
))
1497 if (USetupData
.AutoPartition
)
1499 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1501 CreateLogicalPartition(PartitionList
,
1502 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1507 CreatePrimaryPartition(PartitionList
,
1508 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1512 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1513 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1515 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1516 USetupData
.RequiredPartitionDiskSpace
);
1517 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1520 return SELECT_FILE_SYSTEM_PAGE
;
1525 DrawPartitionList(&ListUi
);
1527 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1528 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1530 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1531 USetupData
.RequiredPartitionDiskSpace
);
1532 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1535 return SELECT_FILE_SYSTEM_PAGE
;
1541 /* Update status text */
1542 if (PartitionList
->CurrentPartition
== NULL
)
1544 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1546 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1548 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1550 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1554 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1559 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1561 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1563 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1567 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1572 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1576 CONSOLE_ConInKey(Ir
);
1578 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1579 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1581 if (ConfirmQuit(Ir
))
1583 DestroyPartitionList(PartitionList
);
1584 PartitionList
= NULL
;
1590 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1591 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1593 ScrollDownPartitionList(&ListUi
);
1595 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1596 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1598 ScrollUpPartitionList(&ListUi
);
1600 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1602 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1603 continue; // return SELECT_PARTITION_PAGE;
1605 if (PartitionList
->CurrentPartition
== NULL
||
1606 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1608 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1610 Error
= LogicalPartitionCreationChecks(PartitionList
);
1611 if (Error
!= NOT_AN_ERROR
)
1613 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1614 return SELECT_PARTITION_PAGE
;
1617 CreateLogicalPartition(PartitionList
,
1623 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1624 if (Error
!= NOT_AN_ERROR
)
1626 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1627 return SELECT_PARTITION_PAGE
;
1630 CreatePrimaryPartition(PartitionList
,
1636 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1638 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1639 USetupData
.RequiredPartitionDiskSpace
);
1640 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1643 return SELECT_FILE_SYSTEM_PAGE
;
1645 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1647 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1649 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1650 if (Error
!= NOT_AN_ERROR
)
1652 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1653 return SELECT_PARTITION_PAGE
;
1656 return CREATE_PRIMARY_PARTITION_PAGE
;
1659 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1661 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1663 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1664 if (Error
!= NOT_AN_ERROR
)
1666 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1667 return SELECT_PARTITION_PAGE
;
1670 return CREATE_EXTENDED_PARTITION_PAGE
;
1673 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1675 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1677 Error
= LogicalPartitionCreationChecks(PartitionList
);
1678 if (Error
!= NOT_AN_ERROR
)
1680 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1681 return SELECT_PARTITION_PAGE
;
1684 return CREATE_LOGICAL_PARTITION_PAGE
;
1687 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1689 WCHAR PathBuffer
[MAX_PATH
];
1690 UNICODE_STRING CurrentPartition
;
1692 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1694 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1695 return SELECT_PARTITION_PAGE
;
1698 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
1699 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
1700 PartitionList
->CurrentDisk
->DiskNumber
,
1701 PartitionList
->CurrentPartition
->PartitionNumber
);
1702 RtlInitUnicodeString(&CurrentPartition
, PathBuffer
);
1705 * Check whether the user attempts to delete the partition on which
1706 * the installation source is present. If so, fail with an error.
1708 // &USetupData.SourceRootPath
1709 if (RtlPrefixUnicodeString(&CurrentPartition
, &USetupData
.SourcePath
, TRUE
))
1711 PopupError("You cannot delete the partition containing the installation source!",
1712 MUIGetString(STRING_CONTINUE
),
1713 Ir
, POPUP_WAIT_ENTER
);
1714 return SELECT_PARTITION_PAGE
;
1717 if (PartitionList
->CurrentPartition
->BootIndicator
||
1718 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1720 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1723 return DELETE_PARTITION_PAGE
;
1727 return SELECT_PARTITION_PAGE
;
1731 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1732 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1733 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1736 ShowPartitionSizeInputBox(SHORT Left
,
1760 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1765 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1766 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1769 WriteConsoleOutputCharacterA(StdOutput
,
1775 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1776 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1778 WriteConsoleOutputCharacterA(StdOutput
,
1784 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1785 Length
= wcslen(InputBuffer
);
1787 CONSOLE_SetInputTextXY(iLeft
,
1789 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1791 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1792 CONSOLE_SetCursorType(TRUE
, TRUE
);
1796 CONSOLE_ConInKey(&Ir
);
1798 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1799 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1804 InputBuffer
[0] = UNICODE_NULL
;
1805 CONSOLE_SetCursorType(TRUE
, FALSE
);
1808 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1810 CONSOLE_SetCursorType(TRUE
, FALSE
);
1813 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1818 InputBuffer
[0] = UNICODE_NULL
;
1819 CONSOLE_SetCursorType(TRUE
, FALSE
);
1822 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1823 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1826 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1828 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1829 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1832 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1834 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1835 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1840 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1843 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1844 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1849 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1852 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1853 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1857 memmove(&InputBuffer
[Pos
],
1858 &InputBuffer
[Pos
+ 1],
1859 (Length
- Pos
- 1) * sizeof(WCHAR
));
1860 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1863 CONSOLE_SetInputTextXY(iLeft
,
1865 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1867 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1870 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1875 memmove(&InputBuffer
[Pos
- 1],
1877 (Length
- Pos
) * sizeof(WCHAR
));
1878 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1882 CONSOLE_SetInputTextXY(iLeft
,
1884 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1886 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1889 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1891 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1893 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1895 if ((ch
>= L
'0') && (ch
<= L
'9'))
1898 memmove(&InputBuffer
[Pos
+ 1],
1900 (Length
- Pos
) * sizeof(WCHAR
));
1901 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1902 InputBuffer
[Pos
] = ch
;
1906 CONSOLE_SetInputTextXY(iLeft
,
1908 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1910 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1919 * Displays the CreatePrimaryPartitionPage.
1922 * SelectPartitionPage
1923 * SelectFileSystemPage (default)
1927 * Number of the next page.
1930 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1932 PDISKENTRY DiskEntry
;
1933 PPARTENTRY PartEntry
;
1936 WCHAR InputBuffer
[50];
1940 ULONGLONG SectorCount
;
1943 if (PartitionList
== NULL
||
1944 PartitionList
->CurrentDisk
== NULL
||
1945 PartitionList
->CurrentPartition
== NULL
)
1947 /* FIXME: show an error dialog */
1951 DiskEntry
= PartitionList
->CurrentDisk
;
1952 PartEntry
= PartitionList
->CurrentPartition
;
1954 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1956 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1958 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1960 if (DiskSize
>= 10 * GB
) /* 10 GB */
1962 DiskSize
= DiskSize
/ GB
;
1963 Unit
= MUIGetString(STRING_GB
);
1968 DiskSize
= DiskSize
/ MB
;
1972 Unit
= MUIGetString(STRING_MB
);
1975 if (DiskEntry
->DriverName
.Length
> 0)
1977 CONSOLE_PrintTextXY(6, 10,
1978 MUIGetString(STRING_HDINFOPARTCREATE_1
),
1981 DiskEntry
->DiskNumber
,
1985 &DiskEntry
->DriverName
,
1986 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
1987 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
1992 CONSOLE_PrintTextXY(6, 10,
1993 MUIGetString(STRING_HDINFOPARTCREATE_2
),
1996 DiskEntry
->DiskNumber
,
2000 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2001 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2005 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2008 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2009 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2012 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2014 PartEntry
= PartitionList
->CurrentPartition
;
2017 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2019 if (MaxSize
> PARTITION_MAXSIZE
)
2020 MaxSize
= PARTITION_MAXSIZE
;
2022 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2023 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2027 if (ConfirmQuit(Ir
))
2034 return SELECT_PARTITION_PAGE
;
2038 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2046 if (PartSize
> MaxSize
)
2052 /* Convert to bytes */
2053 if (PartSize
== MaxSize
)
2055 /* Use all of the unpartitioned disk space */
2056 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2060 /* Calculate the sector count from the size in MB */
2061 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2063 /* But never get larger than the unpartitioned disk space */
2064 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2065 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2068 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2070 CreatePrimaryPartition(PartitionList
,
2074 return SELECT_PARTITION_PAGE
;
2078 return CREATE_PRIMARY_PARTITION_PAGE
;
2083 * Displays the CreateExtendedPartitionPage.
2086 * SelectPartitionPage (default)
2090 * Number of the next page.
2093 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2095 PDISKENTRY DiskEntry
;
2096 PPARTENTRY PartEntry
;
2099 WCHAR InputBuffer
[50];
2103 ULONGLONG SectorCount
;
2106 if (PartitionList
== NULL
||
2107 PartitionList
->CurrentDisk
== NULL
||
2108 PartitionList
->CurrentPartition
== NULL
)
2110 /* FIXME: show an error dialog */
2114 DiskEntry
= PartitionList
->CurrentDisk
;
2115 PartEntry
= PartitionList
->CurrentPartition
;
2117 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2119 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2121 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2123 if (DiskSize
>= 10 * GB
) /* 10 GB */
2125 DiskSize
= DiskSize
/ GB
;
2126 Unit
= MUIGetString(STRING_GB
);
2131 DiskSize
= DiskSize
/ MB
;
2135 Unit
= MUIGetString(STRING_MB
);
2138 if (DiskEntry
->DriverName
.Length
> 0)
2140 CONSOLE_PrintTextXY(6, 10,
2141 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2144 DiskEntry
->DiskNumber
,
2148 &DiskEntry
->DriverName
,
2149 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2150 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2155 CONSOLE_PrintTextXY(6, 10,
2156 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2159 DiskEntry
->DiskNumber
,
2163 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2164 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2168 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2171 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2172 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2175 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2177 PartEntry
= PartitionList
->CurrentPartition
;
2180 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2182 if (MaxSize
> PARTITION_MAXSIZE
)
2183 MaxSize
= PARTITION_MAXSIZE
;
2185 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2186 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2190 if (ConfirmQuit(Ir
))
2197 return SELECT_PARTITION_PAGE
;
2201 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2209 if (PartSize
> MaxSize
)
2215 /* Convert to bytes */
2216 if (PartSize
== MaxSize
)
2218 /* Use all of the unpartitioned disk space */
2219 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2223 /* Calculate the sector count from the size in MB */
2224 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2226 /* But never get larger than the unpartitioned disk space */
2227 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2228 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2231 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2233 CreateExtendedPartition(PartitionList
,
2236 return SELECT_PARTITION_PAGE
;
2240 return CREATE_EXTENDED_PARTITION_PAGE
;
2245 * Displays the CreateLogicalPartitionPage.
2248 * SelectFileSystemPage (default)
2252 * Number of the next page.
2255 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2257 PDISKENTRY DiskEntry
;
2258 PPARTENTRY PartEntry
;
2261 WCHAR InputBuffer
[50];
2265 ULONGLONG SectorCount
;
2268 if (PartitionList
== NULL
||
2269 PartitionList
->CurrentDisk
== NULL
||
2270 PartitionList
->CurrentPartition
== NULL
)
2272 /* FIXME: show an error dialog */
2276 DiskEntry
= PartitionList
->CurrentDisk
;
2277 PartEntry
= PartitionList
->CurrentPartition
;
2279 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2281 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2283 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2285 if (DiskSize
>= 10 * GB
) /* 10 GB */
2287 DiskSize
= DiskSize
/ GB
;
2288 Unit
= MUIGetString(STRING_GB
);
2293 DiskSize
= DiskSize
/ MB
;
2297 Unit
= MUIGetString(STRING_MB
);
2300 if (DiskEntry
->DriverName
.Length
> 0)
2302 CONSOLE_PrintTextXY(6, 10,
2303 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2306 DiskEntry
->DiskNumber
,
2310 &DiskEntry
->DriverName
,
2311 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2312 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2317 CONSOLE_PrintTextXY(6, 10,
2318 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2321 DiskEntry
->DiskNumber
,
2325 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2326 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2330 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2333 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2334 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2337 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2339 PartEntry
= PartitionList
->CurrentPartition
;
2342 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2344 if (MaxSize
> PARTITION_MAXSIZE
)
2345 MaxSize
= PARTITION_MAXSIZE
;
2347 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2348 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2352 if (ConfirmQuit(Ir
))
2359 return SELECT_PARTITION_PAGE
;
2363 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2371 if (PartSize
> MaxSize
)
2377 /* Convert to bytes */
2378 if (PartSize
== MaxSize
)
2380 /* Use all of the unpartitioned disk space */
2381 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2385 /* Calculate the sector count from the size in MB */
2386 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2388 /* But never get larger than the unpartitioned disk space */
2389 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2390 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2393 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2395 CreateLogicalPartition(PartitionList
,
2399 return SELECT_PARTITION_PAGE
;
2403 return CREATE_LOGICAL_PARTITION_PAGE
;
2408 * Displays the ConfirmDeleteSystemPartitionPage.
2411 * DeletePartitionPage (default)
2412 * SelectPartitionPage
2415 * Number of the next page.
2418 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2420 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2424 CONSOLE_ConInKey(Ir
);
2426 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2427 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2429 if (ConfirmQuit(Ir
))
2434 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2436 return DELETE_PARTITION_PAGE
;
2438 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2440 return SELECT_PARTITION_PAGE
;
2444 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2449 * Displays the DeletePartitionPage.
2452 * SelectPartitionPage (default)
2456 * Number of the next page.
2459 DeletePartitionPage(PINPUT_RECORD Ir
)
2461 PDISKENTRY DiskEntry
;
2462 PPARTENTRY PartEntry
;
2466 CHAR PartTypeString
[32];
2468 if (PartitionList
== NULL
||
2469 PartitionList
->CurrentDisk
== NULL
||
2470 PartitionList
->CurrentPartition
== NULL
)
2472 /* FIXME: show an error dialog */
2476 DiskEntry
= PartitionList
->CurrentDisk
;
2477 PartEntry
= PartitionList
->CurrentPartition
;
2479 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2481 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2483 ARRAYSIZE(PartTypeString
));
2485 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2487 if (PartSize
>= 10 * GB
) /* 10 GB */
2489 PartSize
= PartSize
/ GB
;
2490 Unit
= MUIGetString(STRING_GB
);
2494 if (PartSize
>= 10 * MB
) /* 10 MB */
2496 PartSize
= PartSize
/ MB
;
2497 Unit
= MUIGetString(STRING_MB
);
2501 PartSize
= PartSize
/ KB
;
2502 Unit
= MUIGetString(STRING_KB
);
2505 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2507 CONSOLE_PrintTextXY(6, 10,
2508 MUIGetString(STRING_HDDINFOUNK2
),
2509 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2510 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2511 PartEntry
->PartitionType
,
2517 CONSOLE_PrintTextXY(6, 10,
2518 " %c%c %s %I64u %s",
2519 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2520 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2526 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2528 if (DiskSize
>= 10 * GB
) /* 10 GB */
2530 DiskSize
= DiskSize
/ GB
;
2531 Unit
= MUIGetString(STRING_GB
);
2536 DiskSize
= DiskSize
/ MB
;
2540 Unit
= MUIGetString(STRING_MB
);
2543 if (DiskEntry
->DriverName
.Length
> 0)
2545 CONSOLE_PrintTextXY(6, 12,
2546 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2549 DiskEntry
->DiskNumber
,
2553 &DiskEntry
->DriverName
,
2554 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2555 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2560 CONSOLE_PrintTextXY(6, 12,
2561 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2564 DiskEntry
->DiskNumber
,
2568 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2569 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2575 CONSOLE_ConInKey(Ir
);
2577 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2578 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2580 if (ConfirmQuit(Ir
))
2585 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2587 return SELECT_PARTITION_PAGE
;
2589 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2591 DeleteCurrentPartition(PartitionList
);
2593 return SELECT_PARTITION_PAGE
;
2597 return DELETE_PARTITION_PAGE
;
2602 * Displays the SelectFileSystemPage.
2605 * CheckFileSystemPage (At once if RepairUpdate is selected)
2606 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2607 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2608 * SelectPartitionPage (If the user aborts)
2609 * FormatPartitionPage (Default)
2613 * Calls UpdatePartitionType()
2614 * Calls CheckActiveSystemPartition()
2617 * Number of the next page.
2620 SelectFileSystemPage(PINPUT_RECORD Ir
)
2622 PDISKENTRY DiskEntry
;
2623 PPARTENTRY PartEntry
;
2628 CHAR PartTypeString
[32];
2629 FORMATMACHINESTATE PreviousFormatState
;
2631 DPRINT("SelectFileSystemPage()\n");
2633 if (PartitionList
== NULL
||
2634 PartitionList
->CurrentDisk
== NULL
||
2635 PartitionList
->CurrentPartition
== NULL
)
2637 /* FIXME: show an error dialog */
2641 /* Find or set the active system partition */
2642 CheckActiveSystemPartition(PartitionList
);
2643 if (PartitionList
->SystemPartition
== NULL
)
2645 /* FIXME: show an error dialog */
2647 // Error dialog should say that we cannot find a suitable
2648 // system partition and create one on the system. At this point,
2649 // it may be nice to ask the user whether he wants to continue,
2650 // or use an external drive as the system drive/partition
2651 // (e.g. floppy, USB drive, etc...)
2656 PreviousFormatState
= FormatState
;
2657 switch (FormatState
)
2661 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2663 TempPartition
= PartitionList
->SystemPartition
;
2664 TempPartition
->NeedsCheck
= TRUE
;
2666 FormatState
= FormatSystemPartition
;
2667 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2671 TempPartition
= PartitionList
->CurrentPartition
;
2672 TempPartition
->NeedsCheck
= TRUE
;
2674 FormatState
= FormatInstallPartition
;
2675 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2680 case FormatSystemPartition
:
2682 TempPartition
= PartitionList
->CurrentPartition
;
2683 TempPartition
->NeedsCheck
= TRUE
;
2685 FormatState
= FormatInstallPartition
;
2686 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2690 case FormatInstallPartition
:
2692 if (GetNextUnformattedPartition(PartitionList
,
2696 FormatState
= FormatOtherPartition
;
2697 TempPartition
->NeedsCheck
= TRUE
;
2698 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2702 FormatState
= FormatDone
;
2703 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2704 return CHECK_FILE_SYSTEM_PAGE
;
2709 case FormatOtherPartition
:
2711 if (GetNextUnformattedPartition(PartitionList
,
2715 FormatState
= FormatOtherPartition
;
2716 TempPartition
->NeedsCheck
= TRUE
;
2717 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2721 FormatState
= FormatDone
;
2722 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2723 return CHECK_FILE_SYSTEM_PAGE
;
2730 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2731 /* FIXME: show an error dialog */
2736 PartEntry
= TempPartition
;
2737 DiskEntry
= PartEntry
->DiskEntry
;
2739 /* Adjust disk size */
2740 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2741 if (DiskSize
>= 10 * GB
) /* 10 GB */
2743 DiskSize
= DiskSize
/ GB
;
2744 DiskUnit
= MUIGetString(STRING_GB
);
2748 DiskSize
= DiskSize
/ MB
;
2749 DiskUnit
= MUIGetString(STRING_MB
);
2752 /* Adjust partition size */
2753 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2754 if (PartSize
>= 10 * GB
) /* 10 GB */
2756 PartSize
= PartSize
/ GB
;
2757 PartUnit
= MUIGetString(STRING_GB
);
2761 PartSize
= PartSize
/ MB
;
2762 PartUnit
= MUIGetString(STRING_MB
);
2765 /* Adjust partition type */
2766 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2768 ARRAYSIZE(PartTypeString
));
2770 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2772 if (PartEntry
->AutoCreate
)
2774 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2777 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2778 PartEntry
->PartitionNumber
,
2784 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2785 DiskEntry
->DiskNumber
,
2791 &DiskEntry
->DriverName
,
2792 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2793 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2796 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2798 PartEntry
->AutoCreate
= FALSE
;
2800 else if (PartEntry
->New
)
2802 switch (FormatState
)
2804 case FormatSystemPartition
:
2805 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2808 case FormatInstallPartition
:
2809 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2812 case FormatOtherPartition
:
2813 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2820 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2824 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2826 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2828 CONSOLE_PrintTextXY(8, 10,
2829 MUIGetString(STRING_HDDINFOUNK4
),
2830 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2831 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2832 PartEntry
->PartitionType
,
2838 CONSOLE_PrintTextXY(8, 10,
2840 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2841 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2847 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
2848 DiskEntry
->DiskNumber
,
2854 &DiskEntry
->DriverName
,
2855 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? L
"MBR" :
2856 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? L
"GPT" :
2860 if (FileSystemList
== NULL
)
2862 /* Create the file system list, and by default select the "FAT" file system */
2863 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2864 if (FileSystemList
== NULL
)
2866 /* FIXME: show an error dialog */
2871 if (RepairUpdateFlag
)
2873 return CHECK_FILE_SYSTEM_PAGE
;
2874 //return SELECT_PARTITION_PAGE;
2877 if (IsUnattendedSetup
)
2879 if (USetupData
.FormatPartition
)
2882 * We use whatever currently selected file system we have
2883 * (by default, this is "FAT", as per the initialization
2884 * performed above). Note that it may be interesting to specify
2885 * which file system to use in unattended installations, in the
2886 * txtsetup.sif file.
2888 return FORMAT_PARTITION_PAGE
;
2891 return CHECK_FILE_SYSTEM_PAGE
;
2894 DrawFileSystemList(FileSystemList
);
2898 CONSOLE_ConInKey(Ir
);
2900 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2901 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2903 if (ConfirmQuit(Ir
))
2908 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2909 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2911 FormatState
= Start
;
2912 return SELECT_PARTITION_PAGE
;
2914 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2915 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2917 ScrollDownFileSystemList(FileSystemList
);
2919 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2920 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2922 ScrollUpFileSystemList(FileSystemList
);
2924 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2926 if (!FileSystemList
->Selected
->FileSystem
)
2927 return SELECT_FILE_SYSTEM_PAGE
;
2929 return FORMAT_PARTITION_PAGE
;
2933 FormatState
= PreviousFormatState
;
2935 return SELECT_FILE_SYSTEM_PAGE
;
2940 * Displays the FormatPartitionPage.
2943 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2944 * SelectPartitionPage (At once)
2948 * Sets PartitionList->CurrentPartition->FormatState
2949 * Sets USetupData.DestinationRootPath
2952 * Number of the next page.
2955 FormatPartitionPage(PINPUT_RECORD Ir
)
2958 PDISKENTRY DiskEntry
;
2959 PPARTENTRY PartEntry
;
2960 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2961 UNICODE_STRING PartitionRootPath
;
2962 WCHAR PathBuffer
[MAX_PATH
];
2963 CHAR Buffer
[MAX_PATH
];
2968 PPARTITION_INFORMATION PartitionInfo
;
2971 DPRINT("FormatPartitionPage()\n");
2973 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2975 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2977 /* FIXME: show an error dialog */
2981 PartEntry
= TempPartition
;
2982 DiskEntry
= PartEntry
->DiskEntry
;
2984 SelectedFileSystem
= FileSystemList
->Selected
;
2988 if (!IsUnattendedSetup
)
2990 CONSOLE_ConInKey(Ir
);
2993 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2994 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2996 if (ConfirmQuit(Ir
))
3001 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3003 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3005 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
3007 /* FIXME: show an error dialog */
3012 CONSOLE_PrintTextXY(6, 12,
3013 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3014 DiskEntry
->Cylinders
,
3015 DiskEntry
->TracksPerCylinder
,
3016 DiskEntry
->SectorsPerTrack
,
3017 DiskEntry
->BytesPerSector
,
3018 DiskEntry
->Dirty
? '*' : ' ');
3022 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3024 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3026 CONSOLE_PrintTextXY(6, Line
,
3027 "%2u: %2lu %c %12I64u %12I64u %02x",
3029 PartitionInfo
->PartitionNumber
,
3030 PartitionInfo
->BootIndicator
? 'A' : '-',
3031 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3032 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3033 PartitionInfo
->PartitionType
);
3038 /* Commit the partition changes to the disk */
3039 if (!WritePartitionsToDisk(PartitionList
))
3041 DPRINT("WritePartitionsToDisk() failed\n");
3042 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3046 /* Set PartitionRootPath */
3047 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3048 L
"\\Device\\Harddisk%lu\\Partition%lu",
3049 DiskEntry
->DiskNumber
,
3050 PartEntry
->PartitionNumber
);
3051 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3052 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3054 /* Format the partition */
3055 if (SelectedFileSystem
->FileSystem
)
3057 Status
= FormatPartition(&PartitionRootPath
,
3058 SelectedFileSystem
);
3059 if (Status
== STATUS_NOT_SUPPORTED
)
3062 "Setup is currently unable to format a partition in %S.\n"
3064 " \x07 Press ENTER to continue Setup.\n"
3065 " \x07 Press F3 to quit Setup.",
3066 SelectedFileSystem
->FileSystem
->FileSystemName
);
3069 MUIGetString(STRING_QUITCONTINUE
),
3070 NULL
, POPUP_WAIT_NONE
);
3074 CONSOLE_ConInKey(Ir
);
3076 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3077 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3079 if (ConfirmQuit(Ir
))
3082 return SELECT_FILE_SYSTEM_PAGE
;
3084 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3086 return SELECT_FILE_SYSTEM_PAGE
;
3090 else if (!NT_SUCCESS(Status
))
3092 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3093 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3097 PartEntry
->FormatState
= Formatted
;
3098 // PartEntry->FileSystem = FileSystem;
3099 PartEntry
->New
= FALSE
;
3103 CONSOLE_SetStatusText(" Done. Press any key ...");
3104 CONSOLE_ConInKey(Ir
);
3107 return SELECT_FILE_SYSTEM_PAGE
;
3111 return FORMAT_PARTITION_PAGE
;
3116 * Displays the CheckFileSystemPage.
3119 * InstallDirectoryPage (At once)
3123 * Inits or reloads FileSystemList
3126 * Number of the next page.
3129 CheckFileSystemPage(PINPUT_RECORD Ir
)
3132 PDISKENTRY DiskEntry
;
3133 PPARTENTRY PartEntry
;
3134 PFILE_SYSTEM CurrentFileSystem
;
3135 UNICODE_STRING PartitionRootPath
;
3136 WCHAR PathBuffer
[MAX_PATH
];
3137 CHAR Buffer
[MAX_PATH
];
3139 if (PartitionList
== NULL
)
3141 /* FIXME: show an error dialog */
3145 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3147 return INSTALL_DIRECTORY_PAGE
;
3150 /* Set PartitionRootPath */
3151 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3152 L
"\\Device\\Harddisk%lu\\Partition%lu",
3153 DiskEntry
->DiskNumber
,
3154 PartEntry
->PartitionNumber
);
3155 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3156 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3158 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3160 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3162 CurrentFileSystem
= PartEntry
->FileSystem
;
3163 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3164 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3166 /* HACK: Do not try to check a partition with an unknown filesystem */
3167 if (CurrentFileSystem
== NULL
)
3169 PartEntry
->NeedsCheck
= FALSE
;
3170 return CHECK_FILE_SYSTEM_PAGE
;
3173 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3174 if (Status
== STATUS_NOT_SUPPORTED
)
3177 "Setup is currently unable to check a partition formatted in %S.\n"
3179 " \x07 Press ENTER to continue Setup.\n"
3180 " \x07 Press F3 to quit Setup.",
3181 CurrentFileSystem
->FileSystemName
);
3184 MUIGetString(STRING_QUITCONTINUE
),
3185 NULL
, POPUP_WAIT_NONE
);
3189 CONSOLE_ConInKey(Ir
);
3191 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3192 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3194 if (ConfirmQuit(Ir
))
3197 return CHECK_FILE_SYSTEM_PAGE
;
3199 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3201 PartEntry
->NeedsCheck
= FALSE
;
3202 return CHECK_FILE_SYSTEM_PAGE
;
3206 else if (!NT_SUCCESS(Status
))
3208 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3209 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3210 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3211 "(Status 0x%08lx).\n", Status
);
3213 // MUIGetString(STRING_REBOOTCOMPUTER),
3214 MUIGetString(STRING_CONTINUE
),
3215 Ir
, POPUP_WAIT_ENTER
);
3217 // return QUIT_PAGE;
3220 PartEntry
->NeedsCheck
= FALSE
;
3221 return CHECK_FILE_SYSTEM_PAGE
;
3226 BuildInstallPaths(PWSTR InstallDir
,
3227 PDISKENTRY DiskEntry
,
3228 PPARTENTRY PartEntry
)
3232 Status
= InitDestinationPaths(&USetupData
, InstallDir
, DiskEntry
, PartEntry
);
3233 // TODO: Check Status
3234 UNREFERENCED_PARAMETER(Status
);
3236 /* Initialize DestinationDriveLetter */
3237 DestinationDriveLetter
= PartEntry
->DriveLetter
;
3243 IN PCWSTR InstallDir
)
3247 Length
= wcslen(InstallDir
);
3249 // TODO: Add check for 8.3 too.
3251 /* Path must be at least 2 characters long */
3255 /* Path must start with a backslash */
3256 // if (InstallDir[0] != L'\\')
3259 /* Path must not end with a backslash */
3260 if (InstallDir
[Length
- 1] == L
'\\')
3263 /* Path must not contain whitespace characters */
3264 for (i
= 0; i
< Length
; i
++)
3266 if (iswspace(InstallDir
[i
]))
3270 /* Path component must not end with a dot */
3271 for (i
= 0; i
< Length
; i
++)
3273 if (InstallDir
[i
] == L
'\\' && i
> 0)
3275 if (InstallDir
[i
- 1] == L
'.')
3280 if (InstallDir
[Length
- 1] == L
'.')
3288 * Displays the InstallDirectoryPage.
3295 * Number of the next page.
3298 InstallDirectoryPage(PINPUT_RECORD Ir
)
3300 PDISKENTRY DiskEntry
;
3301 PPARTENTRY PartEntry
;
3302 WCHAR InstallDir
[MAX_PATH
];
3306 /* We do not need the filesystem list anymore */
3307 if (FileSystemList
!= NULL
)
3309 DestroyFileSystemList(FileSystemList
);
3310 FileSystemList
= NULL
;
3313 if (PartitionList
== NULL
||
3314 PartitionList
->CurrentDisk
== NULL
||
3315 PartitionList
->CurrentPartition
== NULL
)
3317 /* FIXME: show an error dialog */
3321 DiskEntry
= PartitionList
->CurrentDisk
;
3322 PartEntry
= PartitionList
->CurrentPartition
;
3324 // if (IsUnattendedSetup)
3325 if (RepairUpdateFlag
)
3326 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3327 else if (USetupData
.InstallationDirectory
[0])
3328 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3330 wcscpy(InstallDir
, L
"\\ReactOS");
3333 * Check the validity of the predefined 'InstallDir'. If we are either
3334 * in unattended setup or in update/repair mode, and the installation path
3335 * is valid, just perform the installation. Otherwise (either in the case
3336 * of an invalid path, or we are in regular setup), display the UI and allow
3337 * the user to specify a new installation path.
3339 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3341 BuildInstallPaths(InstallDir
,
3346 * Check whether the user attempts to install ReactOS within the
3347 * installation source directory, or in a subdirectory thereof.
3348 * If so, fail with an error.
3350 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3352 PopupError("You cannot install ReactOS within the installation source directory!",
3353 MUIGetString(STRING_CONTINUE
),
3354 Ir
, POPUP_WAIT_ENTER
);
3355 return INSTALL_DIRECTORY_PAGE
;
3358 return PREPARE_COPY_PAGE
;
3361 Length
= wcslen(InstallDir
);
3364 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3365 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3366 CONSOLE_SetCursorXY(8 + Pos
, 11);
3367 CONSOLE_SetCursorType(TRUE
, TRUE
);
3371 CONSOLE_ConInKey(Ir
);
3373 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3374 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3376 CONSOLE_SetCursorType(TRUE
, FALSE
);
3378 if (ConfirmQuit(Ir
))
3381 CONSOLE_SetCursorType(TRUE
, TRUE
);
3384 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3385 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3389 memmove(&InstallDir
[Pos
],
3390 &InstallDir
[Pos
+ 1],
3391 (Length
- Pos
- 1) * sizeof(WCHAR
));
3392 InstallDir
[Length
- 1] = UNICODE_NULL
;
3395 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3396 CONSOLE_SetCursorXY(8 + Pos
, 11);
3399 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3400 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3403 CONSOLE_SetCursorXY(8 + Pos
, 11);
3405 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3406 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3409 CONSOLE_SetCursorXY(8 + Pos
, 11);
3411 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3412 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3417 CONSOLE_SetCursorXY(8 + Pos
, 11);
3420 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3421 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3426 CONSOLE_SetCursorXY(8 + Pos
, 11);
3429 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3431 CONSOLE_SetCursorType(TRUE
, FALSE
);
3434 * Check for the validity of the installation directory and pop up
3435 * an error if it is not the case. Then the user can fix its input.
3437 if (!IsValidPath(InstallDir
))
3439 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3440 return INSTALL_DIRECTORY_PAGE
;
3443 BuildInstallPaths(InstallDir
,
3448 * Check whether the user attempts to install ReactOS within the
3449 * installation source directory, or in a subdirectory thereof.
3450 * If so, fail with an error.
3452 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3454 PopupError("You cannot install ReactOS within the installation source directory!",
3455 MUIGetString(STRING_CONTINUE
),
3456 Ir
, POPUP_WAIT_ENTER
);
3457 return INSTALL_DIRECTORY_PAGE
;
3460 return PREPARE_COPY_PAGE
;
3462 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3467 memmove(&InstallDir
[Pos
- 1],
3469 (Length
- Pos
) * sizeof(WCHAR
));
3470 InstallDir
[Length
- 1] = UNICODE_NULL
;
3474 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3475 CONSOLE_SetCursorXY(8 + Pos
, 11);
3478 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3482 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3483 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3486 memmove(&InstallDir
[Pos
+ 1],
3488 (Length
- Pos
) * sizeof(WCHAR
));
3489 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3490 InstallDir
[Pos
] = c
;
3494 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3495 CONSOLE_SetCursorXY(8 + Pos
, 11);
3501 return INSTALL_DIRECTORY_PAGE
;
3505 // PSETUP_ERROR_ROUTINE
3509 IN PUSETUP_DATA pSetupData
,
3515 va_start(arg_ptr
, pSetupData
);
3517 if (pSetupData
->LastErrorNumber
>= ERROR_SUCCESS
&&
3518 pSetupData
->LastErrorNumber
< ERROR_LAST_ERROR_CODE
)
3520 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3521 MUIDisplayErrorV(pSetupData
->LastErrorNumber
, &Ir
, POPUP_WAIT_ENTER
, arg_ptr
);
3528 * Displays the PrepareCopyPage.
3531 * FileCopyPage(At once)
3535 * Calls PrepareFileCopy
3538 * Number of the next page.
3541 PrepareCopyPage(PINPUT_RECORD Ir
)
3543 // ERROR_NUMBER ErrorNumber;
3546 MUIDisplayPage(PREPARE_COPY_PAGE
);
3548 /* ErrorNumber = */ Success
= PrepareFileCopy(&USetupData
, NULL
);
3549 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success
)
3551 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3555 return FILE_COPY_PAGE
;
3558 typedef struct _COPYCONTEXT
3560 ULONG TotalOperations
;
3561 ULONG CompletedOperations
;
3562 PPROGRESSBAR ProgressBar
;
3563 PPROGRESSBAR MemoryBars
[4];
3564 } COPYCONTEXT
, *PCOPYCONTEXT
;
3567 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3570 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3572 /* Get the memory information from the system */
3573 NtQuerySystemInformation(SystemPerformanceInformation
,
3578 /* Check if this is initial setup */
3581 /* Set maximum limits to be total RAM pages */
3582 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3583 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3584 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3587 /* Set current values */
3588 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3589 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3590 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3595 FileCopyCallback(PVOID Context
,
3600 PCOPYCONTEXT CopyContext
= (PCOPYCONTEXT
)Context
;
3601 PFILEPATHS_W FilePathInfo
;
3602 PCWSTR SrcFileName
, DstFileName
;
3604 switch (Notification
)
3606 case SPFILENOTIFY_STARTSUBQUEUE
:
3608 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3609 CopyContext
->CompletedOperations
= 0;
3610 ProgressSetStepCount(CopyContext
->ProgressBar
,
3611 CopyContext
->TotalOperations
);
3612 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3616 case SPFILENOTIFY_STARTDELETE
:
3617 case SPFILENOTIFY_STARTRENAME
:
3618 case SPFILENOTIFY_STARTCOPY
:
3620 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3622 if (Notification
== SPFILENOTIFY_STARTDELETE
)
3624 /* Display delete message */
3625 ASSERT(Param2
== FILEOP_DELETE
);
3627 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3628 if (DstFileName
) ++DstFileName
;
3629 else DstFileName
= FilePathInfo
->Target
;
3631 CONSOLE_SetStatusText(MUIGetString(STRING_DELETING
),
3634 else if (Notification
== SPFILENOTIFY_STARTRENAME
)
3636 /* Display move/rename message */
3637 ASSERT(Param2
== FILEOP_RENAME
);
3639 SrcFileName
= wcsrchr(FilePathInfo
->Source
, L
'\\');
3640 if (SrcFileName
) ++SrcFileName
;
3641 else SrcFileName
= FilePathInfo
->Source
;
3643 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3644 if (DstFileName
) ++DstFileName
;
3645 else DstFileName
= FilePathInfo
->Target
;
3647 if (!wcsicmp(SrcFileName
, DstFileName
))
3648 Param2
= STRING_MOVING
;
3650 Param2
= STRING_RENAMING
;
3652 CONSOLE_SetStatusText(MUIGetString(Param2
),
3653 SrcFileName
, DstFileName
);
3655 else if (Notification
== SPFILENOTIFY_STARTCOPY
)
3657 /* Display copy message */
3658 ASSERT(Param2
== FILEOP_COPY
);
3660 /* NOTE: When extracting from CABs the Source is the CAB name */
3661 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3662 if (DstFileName
) ++DstFileName
;
3663 else DstFileName
= FilePathInfo
->Target
;
3665 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
),
3669 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3673 case SPFILENOTIFY_COPYERROR
:
3675 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3677 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3678 FilePathInfo
->Target
, FilePathInfo
->Win32Error
);
3682 case SPFILENOTIFY_ENDDELETE
:
3683 case SPFILENOTIFY_ENDRENAME
:
3684 case SPFILENOTIFY_ENDCOPY
:
3686 CopyContext
->CompletedOperations
++;
3688 /* SYSREG checkpoint */
3689 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3690 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3692 ProgressNextStep(CopyContext
->ProgressBar
);
3693 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3703 * Displays the FileCopyPage.
3706 * RegistryPage(At once)
3712 * Number of the next page.
3715 FileCopyPage(PINPUT_RECORD Ir
)
3717 COPYCONTEXT CopyContext
;
3720 MUIDisplayPage(FILE_COPY_PAGE
);
3722 /* Create context for the copy process */
3723 CopyContext
.TotalOperations
= 0;
3724 CopyContext
.CompletedOperations
= 0;
3726 /* Create the progress bar as well */
3727 CopyContext
.ProgressBar
= CreateProgressBar(13,
3734 MUIGetString(STRING_SETUPCOPYINGFILES
));
3736 // fit memory bars to screen width, distribute them uniform
3737 MemBarWidth
= (xScreen
- 26) / 5;
3738 MemBarWidth
-= MemBarWidth
% 2; // make even
3739 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3740 /* Create the paged pool progress bar */
3741 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3750 /* Create the non paged pool progress bar */
3751 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (MemBarWidth
/ 2),
3753 (xScreen
/ 2) + (MemBarWidth
/ 2),
3755 (xScreen
/ 2)- (MemBarWidth
/ 2),
3760 /* Create the global memory progress bar */
3761 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - MemBarWidth
,
3765 xScreen
- 13 - MemBarWidth
,
3770 /* Do the file copying */
3771 DoFileCopy(&USetupData
, FileCopyCallback
, &CopyContext
);
3773 /* If we get here, we're done, so cleanup the progress bar */
3774 DestroyProgressBar(CopyContext
.ProgressBar
);
3775 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
3776 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
3777 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
3779 /* Create the $winnt$.inf file */
3780 InstallSetupInfFile(&USetupData
);
3782 /* Go display the next page */
3783 return REGISTRY_PAGE
;
3789 RegistryStatus(IN REGISTRY_STATUS RegStatus
, ...)
3791 /* WARNING: Please keep this lookup table in sync with the resources! */
3792 static const UINT StringIDs
[] =
3794 STRING_DONE
, /* Success */
3795 STRING_REGHIVEUPDATE
, /* RegHiveUpdate */
3796 STRING_IMPORTFILE
, /* ImportRegHive */
3797 STRING_DISPLAYSETTINGSUPDATE
, /* DisplaySettingsUpdate */
3798 STRING_LOCALESETTINGSUPDATE
, /* LocaleSettingsUpdate */
3799 STRING_ADDKBLAYOUTS
, /* KeybLayouts */
3800 STRING_KEYBOARDSETTINGSUPDATE
, /* KeybSettingsUpdate */
3801 STRING_CODEPAGEINFOUPDATE
, /* CodePageInfoUpdate */
3806 if (RegStatus
< ARRAYSIZE(StringIDs
))
3808 va_start(args
, RegStatus
);
3809 CONSOLE_SetStatusTextV(MUIGetString(StringIDs
[RegStatus
]), args
);
3814 CONSOLE_SetStatusText("Unknown status %d", RegStatus
);
3819 * Displays the RegistryPage.
3822 * SuccessPage (if RepairUpdate)
3823 * BootLoaderPage (default)
3827 * Calls UpdateRegistry
3830 * Number of the next page.
3833 RegistryPage(PINPUT_RECORD Ir
)
3837 MUIDisplayPage(REGISTRY_PAGE
);
3839 Error
= UpdateRegistry(&USetupData
,
3842 DestinationDriveLetter
,
3845 if (Error
!= ERROR_SUCCESS
)
3847 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
3852 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
3853 return BOOT_LOADER_PAGE
;
3859 * Displays the BootLoaderPage.
3862 * SuccessPage (if RepairUpdate)
3863 * BootLoaderHarddiskMbrPage
3864 * BootLoaderHarddiskVbrPage
3865 * BootLoaderFloppyPage
3870 * Calls RegInitializeRegistry
3871 * Calls ImportRegistryFile
3872 * Calls SetDefaultPagefile
3873 * Calls SetMountedDeviceValues
3876 * Number of the next page.
3879 BootLoaderPage(PINPUT_RECORD Ir
)
3881 UCHAR PartitionType
;
3882 BOOLEAN InstallOnFloppy
;
3884 WCHAR PathBuffer
[MAX_PATH
];
3886 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3888 RtlFreeUnicodeString(&USetupData
.SystemRootPath
);
3889 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3890 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
3891 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
3892 PartitionList
->SystemPartition
->PartitionNumber
);
3893 RtlCreateUnicodeString(&USetupData
.SystemRootPath
, PathBuffer
);
3894 DPRINT1("SystemRootPath: %wZ\n", &USetupData
.SystemRootPath
);
3896 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
3898 /* For unattended setup, skip MBR installation or install on floppy if needed */
3899 if (IsUnattendedSetup
)
3901 if ((USetupData
.MBRInstallType
== 0) ||
3902 (USetupData
.MBRInstallType
== 1))
3909 * We may install an MBR or VBR, but before that, check whether
3910 * we need to actually install the VBR on floppy.
3912 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
3914 DPRINT("Error: system partition invalid (unused)\n");
3915 InstallOnFloppy
= TRUE
;
3917 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
3919 /* OS/2 boot manager partition */
3920 DPRINT("Found OS/2 boot manager partition\n");
3921 InstallOnFloppy
= TRUE
;
3923 else if (PartitionType
== PARTITION_LINUX
)
3925 /* Linux partition */
3926 DPRINT("Found Linux native partition (ext2/ext3/ReiserFS/BTRFS/etc)\n");
3927 InstallOnFloppy
= FALSE
;
3929 else if (PartitionType
== PARTITION_IFS
)
3931 /* NTFS partition */
3932 DPRINT("Found NTFS partition\n");
3934 // FIXME: Make it FALSE when we'll support NTFS installation!
3935 InstallOnFloppy
= TRUE
;
3937 else if ((PartitionType
== PARTITION_FAT_12
) ||
3938 (PartitionType
== PARTITION_FAT_16
) ||
3939 (PartitionType
== PARTITION_HUGE
) ||
3940 (PartitionType
== PARTITION_XINT13
) ||
3941 (PartitionType
== PARTITION_FAT32
) ||
3942 (PartitionType
== PARTITION_FAT32_XINT13
))
3944 DPRINT("Found FAT partition\n");
3945 InstallOnFloppy
= FALSE
;
3949 /* Unknown partition */
3950 DPRINT("Unknown partition found\n");
3951 InstallOnFloppy
= TRUE
;
3954 /* We should install on floppy */
3955 if (InstallOnFloppy
)
3957 USetupData
.MBRInstallType
= 1;
3961 /* Is it an unattended install on hdd? */
3962 if (IsUnattendedSetup
)
3964 if ((USetupData
.MBRInstallType
== 2) ||
3965 (USetupData
.MBRInstallType
== 3))
3971 MUIDisplayPage(BOOT_LOADER_PAGE
);
3972 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3976 CONSOLE_ConInKey(Ir
);
3978 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3979 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
3981 CONSOLE_NormalTextXY(8, Line
, 60, 1);
3990 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3992 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3993 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
3995 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4004 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4006 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4007 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4009 if (ConfirmQuit(Ir
))
4014 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4018 /* Install on both MBR and VBR */
4019 USetupData
.MBRInstallType
= 2;
4022 else if (Line
== 13)
4024 /* Install on VBR only */
4025 USetupData
.MBRInstallType
= 3;
4028 else if (Line
== 14)
4030 /* Install on floppy */
4031 USetupData
.MBRInstallType
= 1;
4034 else if (Line
== 15)
4036 /* Skip MBR installation */
4037 USetupData
.MBRInstallType
= 0;
4041 return BOOT_LOADER_PAGE
;
4046 switch (USetupData
.MBRInstallType
)
4048 /* Skip MBR installation */
4050 return SUCCESS_PAGE
;
4052 /* Install on floppy */
4054 return BOOT_LOADER_FLOPPY_PAGE
;
4056 /* Install on both MBR and VBR */
4058 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4060 /* Install on VBR only */
4062 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4065 return BOOT_LOADER_PAGE
;
4070 * Displays the BootLoaderFloppyPage.
4073 * SuccessPage (At once)
4077 * Calls InstallFatBootcodeToFloppy()
4080 * Number of the next page.
4083 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4087 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4089 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4093 CONSOLE_ConInKey(Ir
);
4095 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4096 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4098 if (ConfirmQuit(Ir
))
4103 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4105 Status
= InstallFatBootcodeToFloppy(&USetupData
.SourceRootPath
,
4106 &USetupData
.DestinationArcPath
);
4107 if (!NT_SUCCESS(Status
))
4109 if (Status
== STATUS_DEVICE_NOT_READY
)
4110 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4112 /* TODO: Print error message */
4113 return BOOT_LOADER_FLOPPY_PAGE
;
4116 return SUCCESS_PAGE
;
4120 return BOOT_LOADER_FLOPPY_PAGE
;
4125 * Displays the BootLoaderHarddiskVbrPage.
4128 * SuccessPage (At once)
4132 * Calls InstallVBRToPartition()
4135 * Number of the next page.
4138 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4142 // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4143 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4144 &USetupData
.SourceRootPath
,
4145 &USetupData
.DestinationArcPath
,
4146 PartitionList
->SystemPartition
->PartitionType
);
4147 if (!NT_SUCCESS(Status
))
4149 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4150 PartitionList
->SystemPartition
->FileSystem
->FileSystemName
);
4154 return SUCCESS_PAGE
;
4159 * Displays the BootLoaderHarddiskMbrPage.
4162 * SuccessPage (At once)
4166 * Calls InstallVBRToPartition()
4167 * Calls InstallMbrBootCodeToDisk()
4170 * Number of the next page.
4173 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4176 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4178 /* Step 1: Write the VBR */
4179 // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
4180 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4181 &USetupData
.SourceRootPath
,
4182 &USetupData
.DestinationArcPath
,
4183 PartitionList
->SystemPartition
->PartitionType
);
4184 if (!NT_SUCCESS(Status
))
4186 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4187 PartitionList
->SystemPartition
->FileSystem
->FileSystemName
);
4191 /* Step 2: Write the MBR */
4192 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4193 L
"\\Device\\Harddisk%d\\Partition0",
4194 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4195 Status
= InstallMbrBootCodeToDisk(&USetupData
.SystemRootPath
,
4196 &USetupData
.SourceRootPath
,
4197 DestinationDevicePathBuffer
);
4198 if (!NT_SUCCESS(Status
))
4200 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status
);
4201 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
, L
"MBR");
4205 return SUCCESS_PAGE
;
4210 * @name ProgressTimeOutStringHandler
4212 * Handles the generation (displaying) of the timeout
4213 * countdown to the screen dynamically.
4216 * A pointer to a progress bar.
4218 * @param AlwaysUpdate
4219 * Constantly update the progress bar (boolean type).
4222 * A pointer to a string buffer.
4224 * @param cchBufferSize
4225 * The buffer's size in number of characters.
4228 * TRUE or FALSE on function termination.
4233 ProgressTimeOutStringHandler(
4234 IN PPROGRESSBAR Bar
,
4235 IN BOOLEAN AlwaysUpdate
,
4237 IN SIZE_T cchBufferSize
)
4239 ULONG OldProgress
= Bar
->Progress
;
4241 if (Bar
->StepCount
== 0)
4247 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4250 /* Build the progress string if it has changed */
4251 if (Bar
->ProgressFormatText
&&
4252 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4254 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4255 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4264 * @name ProgressCountdown
4266 * Displays and draws a red-coloured progress bar with a countdown.
4267 * When the timeout is reached, the flush page is displayed for reboot.
4270 * A pointer to an input keyboard record.
4273 * Initial countdown value in seconds.
4281 IN PINPUT_RECORD Ir
,
4285 ULONG StartTime
, BarWidth
, TimerDiv
;
4287 LONG TimerValue
, OldTimerValue
;
4288 LARGE_INTEGER Timeout
;
4289 PPROGRESSBAR ProgressBar
;
4290 BOOLEAN RefreshProgress
= TRUE
;
4292 /* Bail out if the timeout is already zero */
4296 /* Create the timeout progress bar and set it up */
4297 ProgressBar
= CreateProgressBarEx(13,
4304 FOREGROUND_RED
| BACKGROUND_BLUE
,
4307 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4308 ProgressTimeOutStringHandler
);
4310 BarWidth
= max(1, ProgressBar
->Width
);
4311 TimerValue
= TimeOut
* BarWidth
;
4312 ProgressSetStepCount(ProgressBar
, TimerValue
);
4314 StartTime
= NtGetTickCount();
4317 TimerDiv
= 1000 / BarWidth
;
4318 TimerDiv
= max(1, TimerDiv
);
4319 OldTimerValue
= TimerValue
;
4322 /* Decrease the timer */
4325 * Compute how much time the previous operations took.
4326 * This allows us in particular to take account for any time
4327 * elapsed if something slowed down.
4329 TimeElapsed
= NtGetTickCount() - StartTime
;
4330 if (TimeElapsed
>= TimerDiv
)
4332 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4333 TimeElapsed
/= TimerDiv
;
4334 StartTime
+= (TimerDiv
* TimeElapsed
);
4336 if (TimeElapsed
<= TimerValue
)
4337 TimerValue
-= TimeElapsed
;
4341 RefreshProgress
= TRUE
;
4344 if (RefreshProgress
)
4346 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4347 RefreshProgress
= FALSE
;
4350 /* Stop when the timer reaches zero */
4351 if (TimerValue
<= 0)
4354 /* Check for user key presses */
4357 * If the timer is used, use a passive wait of maximum 1 second
4358 * while monitoring for incoming console input events, so that
4359 * we are still able to display the timing count.
4362 /* Wait a maximum of 1 second for input events */
4363 TimeElapsed
= NtGetTickCount() - StartTime
;
4364 if (TimeElapsed
< TimerDiv
)
4366 /* Convert the time to NT Format */
4367 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4368 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4372 Status
= STATUS_TIMEOUT
;
4375 /* Check whether the input event has been signaled, or a timeout happened */
4376 if (Status
== STATUS_TIMEOUT
)
4380 if (Status
!= STATUS_WAIT_0
)
4382 /* An error happened, bail out */
4383 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4387 /* Check for an ENTER key press */
4388 while (CONSOLE_ConInKeyPeek(Ir
))
4390 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4392 /* Found it, stop waiting */
4399 /* Destroy the progress bar and quit */
4400 DestroyProgressBar(ProgressBar
);
4405 * Displays the QuitPage.
4408 * FlushPage (At once)
4414 * Number of the next page.
4417 QuitPage(PINPUT_RECORD Ir
)
4419 MUIDisplayPage(QUIT_PAGE
);
4421 /* Destroy the NTOS installations list */
4422 if (NtOsInstallsList
!= NULL
)
4424 DestroyGenericList(NtOsInstallsList
, TRUE
);
4425 NtOsInstallsList
= NULL
;
4428 /* Destroy the partition list */
4429 if (PartitionList
!= NULL
)
4431 DestroyPartitionList(PartitionList
);
4432 PartitionList
= NULL
;
4435 TempPartition
= NULL
;
4436 FormatState
= Start
;
4438 /* Destroy the filesystem list */
4439 if (FileSystemList
!= NULL
)
4441 DestroyFileSystemList(FileSystemList
);
4442 FileSystemList
= NULL
;
4445 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4447 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4448 ProgressCountdown(Ir
, 15);
4454 * Displays the SuccessPage.
4457 * FlushPage (At once)
4463 * Number of the next page.
4466 SuccessPage(PINPUT_RECORD Ir
)
4468 MUIDisplayPage(SUCCESS_PAGE
);
4470 if (IsUnattendedSetup
)
4473 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4474 ProgressCountdown(Ir
, 15);
4480 * Displays the FlushPage.
4483 * RebootPage (At once)
4486 * Number of the next page.
4489 FlushPage(PINPUT_RECORD Ir
)
4491 MUIDisplayPage(FLUSH_PAGE
);
4497 PnpEventThread(IN LPVOID lpParameter
);
4501 * The start routine and page management
4511 InfSetHeap(ProcessHeap
);
4513 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4514 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4515 if (!NT_SUCCESS(Status
))
4516 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
4518 /* Create the PnP thread in suspended state */
4519 Status
= RtlCreateUserThread(NtCurrentProcess(),
4526 &USetupData
.SetupInf
,
4529 if (!NT_SUCCESS(Status
))
4532 if (!CONSOLE_Init())
4534 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4535 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4536 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4538 /* We failed to initialize the video, just quit the installer */
4539 return STATUS_APP_INIT_FAILURE
;
4542 /* Initialize Setup, phase 0 */
4543 InitializeSetup(&USetupData
, 0);
4544 USetupData
.ErrorRoutine
= USetupErrorRoutine
;
4546 /* Hide the cursor */
4547 CONSOLE_SetCursorType(TRUE
, FALSE
);
4549 /* Global Initialization page */
4550 CONSOLE_ClearScreen();
4552 Page
= SetupStartPage(&Ir
);
4554 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4556 CONSOLE_ClearScreen();
4559 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4566 Page
= LanguagePage(&Ir
);
4571 Page
= WelcomePage(&Ir
);
4576 Page
= LicensePage(&Ir
);
4580 case INSTALL_INTRO_PAGE
:
4581 Page
= InstallIntroPage(&Ir
);
4585 case SCSI_CONTROLLER_PAGE
:
4586 Page
= ScsiControllerPage(&Ir
);
4589 case OEM_DRIVER_PAGE
:
4590 Page
= OemDriverPage(&Ir
);
4594 case DEVICE_SETTINGS_PAGE
:
4595 Page
= DeviceSettingsPage(&Ir
);
4598 case COMPUTER_SETTINGS_PAGE
:
4599 Page
= ComputerSettingsPage(&Ir
);
4602 case DISPLAY_SETTINGS_PAGE
:
4603 Page
= DisplaySettingsPage(&Ir
);
4606 case KEYBOARD_SETTINGS_PAGE
:
4607 Page
= KeyboardSettingsPage(&Ir
);
4610 case LAYOUT_SETTINGS_PAGE
:
4611 Page
= LayoutSettingsPage(&Ir
);
4614 case SELECT_PARTITION_PAGE
:
4615 Page
= SelectPartitionPage(&Ir
);
4618 case CREATE_PRIMARY_PARTITION_PAGE
:
4619 Page
= CreatePrimaryPartitionPage(&Ir
);
4622 case CREATE_EXTENDED_PARTITION_PAGE
:
4623 Page
= CreateExtendedPartitionPage(&Ir
);
4626 case CREATE_LOGICAL_PARTITION_PAGE
:
4627 Page
= CreateLogicalPartitionPage(&Ir
);
4630 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4631 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4634 case DELETE_PARTITION_PAGE
:
4635 Page
= DeletePartitionPage(&Ir
);
4638 case SELECT_FILE_SYSTEM_PAGE
:
4639 Page
= SelectFileSystemPage(&Ir
);
4642 case FORMAT_PARTITION_PAGE
:
4643 Page
= FormatPartitionPage(&Ir
);
4646 case CHECK_FILE_SYSTEM_PAGE
:
4647 Page
= CheckFileSystemPage(&Ir
);
4650 case INSTALL_DIRECTORY_PAGE
:
4651 Page
= InstallDirectoryPage(&Ir
);
4654 case PREPARE_COPY_PAGE
:
4655 Page
= PrepareCopyPage(&Ir
);
4658 case FILE_COPY_PAGE
:
4659 Page
= FileCopyPage(&Ir
);
4663 Page
= RegistryPage(&Ir
);
4666 case BOOT_LOADER_PAGE
:
4667 Page
= BootLoaderPage(&Ir
);
4670 case BOOT_LOADER_FLOPPY_PAGE
:
4671 Page
= BootLoaderFloppyPage(&Ir
);
4674 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4675 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4678 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4679 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4683 case REPAIR_INTRO_PAGE
:
4684 Page
= RepairIntroPage(&Ir
);
4687 case UPGRADE_REPAIR_PAGE
:
4688 Page
= UpgradeRepairPage(&Ir
);
4692 Page
= SuccessPage(&Ir
);
4696 Page
= FlushPage(&Ir
);
4700 Page
= QuitPage(&Ir
);
4709 /* Setup has finished */
4710 FinishSetup(&USetupData
);
4712 if (Page
== RECOVERY_PAGE
)
4718 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4719 NtShutdownSystem(ShutdownReboot
);
4720 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4722 return STATUS_SUCCESS
;
4727 NtProcessStartup(PPEB Peb
)
4732 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4734 ProcessHeap
= Peb
->ProcessHeap
;
4736 NtQuerySystemTime(&Time
);
4738 Status
= RunUSetup();
4740 if (NT_SUCCESS(Status
))
4743 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4744 * a protective waiting.
4745 * This wait is needed because, since we are started as SMSS.EXE,
4746 * the NT kernel explicitly waits 5 seconds for the initial process
4747 * SMSS.EXE to initialize (as a protective measure), and otherwise
4748 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4750 Time
.QuadPart
+= 50000000;
4751 NtDelayExecution(FALSE
, &Time
);
4755 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
4756 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4757 0, 0, NULL
, 0, NULL
);
4760 NtTerminateProcess(NtCurrentProcess(), Status
);