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)
41 /* GLOBALS & LOCALS *********************************************************/
44 BOOLEAN IsUnattendedSetup
= FALSE
;
46 static USETUP_DATA USetupData
;
48 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
49 static WCHAR DestinationDriveLetter
;
54 PCWSTR SelectedLanguageId
;
55 static WCHAR DefaultLanguage
[20]; // Copy of string inside LanguageList
56 static WCHAR DefaultKBLayout
[20]; // Copy of string inside KeyboardList
58 static BOOLEAN RepairUpdateFlag
= FALSE
;
60 static PPARTLIST PartitionList
= NULL
;
61 static PPARTENTRY TempPartition
= NULL
;
62 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
63 static FORMATMACHINESTATE FormatState
= Start
;
65 /*****************************************************/
67 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
68 static PGENERIC_LIST NtOsInstallsList
= NULL
;
71 /* FUNCTIONS ****************************************************************/
74 PrintString(char* fmt
,...)
78 UNICODE_STRING UnicodeString
;
79 ANSI_STRING AnsiString
;
82 vsprintf(buffer
, fmt
, ap
);
85 RtlInitAnsiString(&AnsiString
, buffer
);
86 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
87 NtDisplayString(&UnicodeString
);
88 RtlFreeUnicodeString(&UnicodeString
);
93 DrawBox(IN SHORT xLeft
,
101 /* Draw upper left corner */
104 FillConsoleOutputCharacterA(StdOutput
,
110 /* Draw upper edge */
113 FillConsoleOutputCharacterA(StdOutput
,
119 /* Draw upper right corner */
120 coPos
.X
= xLeft
+ Width
- 1;
122 FillConsoleOutputCharacterA(StdOutput
,
128 /* Draw right edge, inner space and left edge */
129 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
132 FillConsoleOutputCharacterA(StdOutput
,
139 FillConsoleOutputCharacterA(StdOutput
,
145 coPos
.X
= xLeft
+ Width
- 1;
146 FillConsoleOutputCharacterA(StdOutput
,
153 /* Draw lower left corner */
155 coPos
.Y
= yTop
+ Height
- 1;
156 FillConsoleOutputCharacterA(StdOutput
,
162 /* Draw lower edge */
164 coPos
.Y
= yTop
+ Height
- 1;
165 FillConsoleOutputCharacterA(StdOutput
,
171 /* Draw lower right corner */
172 coPos
.X
= xLeft
+ Width
- 1;
173 coPos
.Y
= yTop
+ Height
- 1;
174 FillConsoleOutputCharacterA(StdOutput
,
183 PopupError(PCCH Text
,
201 /* Count text lines and longest line */
208 p
= strchr(pnext
, '\n');
212 Length
= strlen(pnext
);
217 Length
= (ULONG
)(p
- pnext
);
223 if (Length
> MaxLength
)
232 /* Check length of status line */
235 Length
= strlen(Status
);
237 if (Length
> MaxLength
)
241 Width
= MaxLength
+ 4;
247 yTop
= (yScreen
- Height
) / 2;
248 xLeft
= (xScreen
- Width
) / 2;
251 /* Set screen attributes */
253 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
255 FillConsoleOutputAttribute(StdOutput
,
256 FOREGROUND_RED
| BACKGROUND_WHITE
,
262 DrawBox(xLeft
, yTop
, Width
, Height
);
264 /* Print message text */
269 p
= strchr(pnext
, '\n');
273 Length
= strlen(pnext
);
278 Length
= (ULONG
)(p
- pnext
);
285 WriteConsoleOutputCharacterA(StdOutput
,
299 /* Print separator line and status text */
302 coPos
.Y
= yTop
+ Height
- 3;
304 FillConsoleOutputCharacterA(StdOutput
,
311 FillConsoleOutputCharacterA(StdOutput
,
317 coPos
.X
= xLeft
+ Width
- 1;
318 FillConsoleOutputCharacterA(StdOutput
,
326 WriteConsoleOutputCharacterA(StdOutput
,
328 min(strlen(Status
), (SIZE_T
)Width
- 4),
333 if (WaitEvent
== POPUP_WAIT_NONE
)
338 CONSOLE_ConInKey(Ir
);
340 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
341 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
353 * FALSE: Don't quit setup.
356 ConfirmQuit(PINPUT_RECORD Ir
)
359 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
363 CONSOLE_ConInKey(Ir
);
365 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
366 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
371 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
385 PGENERIC_LIST_ENTRY ListEntry
;
388 pszNewLayout
= MUIDefaultKeyboardLayout(SelectedLanguageId
);
390 if (USetupData
.LayoutList
== NULL
)
392 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
393 if (USetupData
.LayoutList
== NULL
)
395 /* FIXME: Handle error! */
400 /* Search for default layout (if provided) */
401 if (pszNewLayout
!= NULL
)
403 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
404 ListEntry
= GetNextListEntry(ListEntry
))
406 if (!wcscmp(pszNewLayout
, ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
))
408 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
418 GetSettingDescription(
419 IN PGENERIC_LIST_ENTRY Entry
,
421 IN SIZE_T cchBufferSize
)
423 return RtlStringCchPrintfA(Buffer
, cchBufferSize
, "%S",
424 ((PGENENTRY
)GetListEntryData(Entry
))->Value
);
429 GetNTOSInstallationName(
430 IN PGENERIC_LIST_ENTRY Entry
,
432 IN SIZE_T cchBufferSize
)
434 PNTOS_INSTALLATION NtOsInstall
= (PNTOS_INSTALLATION
)GetListEntryData(Entry
);
435 PPARTENTRY PartEntry
= NtOsInstall
->PartEntry
;
437 if (PartEntry
&& PartEntry
->DriveLetter
)
439 /* We have retrieved a partition that is mounted */
440 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
442 PartEntry
->DriveLetter
,
443 NtOsInstall
->PathComponent
,
444 NtOsInstall
->InstallationName
);
448 /* We failed somewhere, just show the NT path */
449 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
451 &NtOsInstall
->SystemNtPath
,
452 NtOsInstall
->InstallationName
);
458 * Displays the LanguagePage.
460 * Next pages: WelcomePage, QuitPage
463 * Init SelectedLanguageId
464 * Init USetupData.LanguageId
467 * Number of the next page.
470 LanguagePage(PINPUT_RECORD Ir
)
472 GENERIC_LIST_UI ListUi
;
473 PCWSTR NewLanguageId
;
474 BOOL RefreshPage
= FALSE
;
476 /* Initialize the computer settings list */
477 if (USetupData
.LanguageList
== NULL
)
479 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
480 if (USetupData
.LanguageList
== NULL
)
482 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
487 SelectedLanguageId
= DefaultLanguage
;
488 USetupData
.LanguageId
= 0;
491 SetConsoleCodePage();
495 * If there is no language or just a single one in the list,
496 * skip the language selection process altogether.
498 if (GetNumberOfListEntries(USetupData
.LanguageList
) <= 1)
500 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
504 InitGenericListUi(&ListUi
, USetupData
.LanguageList
, GetSettingDescription
);
505 DrawGenericList(&ListUi
,
510 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
512 MUIDisplayPage(LANGUAGE_PAGE
);
516 CONSOLE_ConInKey(Ir
);
518 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
519 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
521 ScrollDownGenericList(&ListUi
);
524 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
525 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
527 ScrollUpGenericList(&ListUi
);
530 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
531 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
533 ScrollPageDownGenericList(&ListUi
);
536 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
537 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
539 ScrollPageUpGenericList(&ListUi
);
542 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
543 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
548 RedrawGenericList(&ListUi
);
550 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
552 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
555 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
557 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
559 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
565 SetConsoleCodePage();
569 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
572 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
578 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
581 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
583 if (wcscmp(SelectedLanguageId
, NewLanguageId
))
585 /* Clear the language page */
586 MUIClearPage(LANGUAGE_PAGE
);
588 SelectedLanguageId
= NewLanguageId
;
591 SetConsoleCodePage();
593 /* Redraw language selection page in native language */
594 MUIDisplayPage(LANGUAGE_PAGE
);
609 * LanguagePage (at once, default)
610 * InstallIntroPage (at once, if unattended)
615 * Init USetupData.SourcePath
616 * Init USetupData.SourceRootPath
617 * Init USetupData.SourceRootDir
618 * Init USetupData.SetupInf
619 * Init USetupData.RequiredPartitionDiskSpace
620 * Init IsUnattendedSetup
621 * If unattended, init *List and sets the Codepage
622 * If unattended, init SelectedLanguageId
623 * If unattended, init USetupData.LanguageId
626 * Number of the next page.
629 SetupStartPage(PINPUT_RECORD Ir
)
632 PGENERIC_LIST_ENTRY ListEntry
;
635 MUIDisplayPage(SETUP_INIT_PAGE
);
637 /* Initialize Setup, phase 1 */
638 Error
= InitializeSetup(&USetupData
, 1);
639 if (Error
!= ERROR_SUCCESS
)
641 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
645 /* Initialize the user-mode PnP manager */
646 if (!EnableUserModePnpManager())
647 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
649 /* Wait for any immediate pending installations to finish */
650 if (WaitNoPendingInstallEvents(NULL
) != STATUS_WAIT_0
)
651 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
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
? "MBR" :
1987 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
1992 CONSOLE_PrintTextXY(6, 10,
1993 MUIGetString(STRING_HDINFOPARTCREATE_2
),
1996 DiskEntry
->DiskNumber
,
2000 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2001 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "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
? "MBR" :
2150 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2155 CONSOLE_PrintTextXY(6, 10,
2156 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2159 DiskEntry
->DiskNumber
,
2163 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2164 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "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
? "MBR" :
2312 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2317 CONSOLE_PrintTextXY(6, 10,
2318 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2321 DiskEntry
->DiskNumber
,
2325 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2326 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "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
? "MBR" :
2555 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2560 CONSOLE_PrintTextXY(6, 12,
2561 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2564 DiskEntry
->DiskNumber
,
2568 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
2569 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "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
? "MBR" :
2793 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "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
? "MBR" :
2856 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
2860 if (FileSystemList
== NULL
)
2864 if (IsUnattendedSetup
)
2866 switch (USetupData
.FsType
)
2868 /* 1 is for BtrFS */
2870 DefaultFs
= L
"BTRFS";
2873 /* If we don't understand input, default to FAT */
2881 /* By default select the "FAT" file system */
2885 /* Create the file system list */
2886 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, DefaultFs
);
2887 if (FileSystemList
== NULL
)
2889 /* FIXME: show an error dialog */
2894 if (RepairUpdateFlag
)
2896 return CHECK_FILE_SYSTEM_PAGE
;
2897 //return SELECT_PARTITION_PAGE;
2900 if (IsUnattendedSetup
)
2902 if (USetupData
.FormatPartition
)
2904 return FORMAT_PARTITION_PAGE
;
2907 return CHECK_FILE_SYSTEM_PAGE
;
2910 DrawFileSystemList(FileSystemList
);
2914 CONSOLE_ConInKey(Ir
);
2916 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2917 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2919 if (ConfirmQuit(Ir
))
2924 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2925 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2927 FormatState
= Start
;
2928 return SELECT_PARTITION_PAGE
;
2930 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2931 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2933 ScrollDownFileSystemList(FileSystemList
);
2935 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2936 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2938 ScrollUpFileSystemList(FileSystemList
);
2940 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2942 if (!FileSystemList
->Selected
->FileSystem
)
2943 return SELECT_FILE_SYSTEM_PAGE
;
2945 return FORMAT_PARTITION_PAGE
;
2949 FormatState
= PreviousFormatState
;
2951 return SELECT_FILE_SYSTEM_PAGE
;
2956 * Displays the FormatPartitionPage.
2959 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2960 * SelectPartitionPage (At once)
2964 * Sets PartitionList->CurrentPartition->FormatState
2965 * Sets USetupData.DestinationRootPath
2968 * Number of the next page.
2971 FormatPartitionPage(PINPUT_RECORD Ir
)
2974 PDISKENTRY DiskEntry
;
2975 PPARTENTRY PartEntry
;
2976 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2977 UNICODE_STRING PartitionRootPath
;
2978 WCHAR PathBuffer
[MAX_PATH
];
2979 CHAR Buffer
[MAX_PATH
];
2984 PPARTITION_INFORMATION PartitionInfo
;
2987 DPRINT("FormatPartitionPage()\n");
2989 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2991 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2993 /* FIXME: show an error dialog */
2997 PartEntry
= TempPartition
;
2998 DiskEntry
= PartEntry
->DiskEntry
;
3000 SelectedFileSystem
= FileSystemList
->Selected
;
3004 if (!IsUnattendedSetup
)
3006 CONSOLE_ConInKey(Ir
);
3009 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3010 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3012 if (ConfirmQuit(Ir
))
3017 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3019 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3021 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
3023 /* FIXME: show an error dialog */
3028 CONSOLE_PrintTextXY(6, 12,
3029 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3030 DiskEntry
->Cylinders
,
3031 DiskEntry
->TracksPerCylinder
,
3032 DiskEntry
->SectorsPerTrack
,
3033 DiskEntry
->BytesPerSector
,
3034 DiskEntry
->Dirty
? '*' : ' ');
3038 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3040 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3042 CONSOLE_PrintTextXY(6, Line
,
3043 "%2u: %2lu %c %12I64u %12I64u %02x",
3045 PartitionInfo
->PartitionNumber
,
3046 PartitionInfo
->BootIndicator
? 'A' : '-',
3047 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3048 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3049 PartitionInfo
->PartitionType
);
3054 /* Commit the partition changes to the disk */
3055 if (!WritePartitionsToDisk(PartitionList
))
3057 DPRINT("WritePartitionsToDisk() failed\n");
3058 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3062 /* Set PartitionRootPath */
3063 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3064 L
"\\Device\\Harddisk%lu\\Partition%lu",
3065 DiskEntry
->DiskNumber
,
3066 PartEntry
->PartitionNumber
);
3067 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3068 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3070 /* Format the partition */
3071 if (SelectedFileSystem
->FileSystem
)
3073 Status
= FormatPartition(&PartitionRootPath
,
3074 SelectedFileSystem
);
3075 if (Status
== STATUS_NOT_SUPPORTED
)
3078 "Setup is currently unable to format a partition in %S.\n"
3080 " \x07 Press ENTER to continue Setup.\n"
3081 " \x07 Press F3 to quit Setup.",
3082 SelectedFileSystem
->FileSystem
->FileSystemName
);
3085 MUIGetString(STRING_QUITCONTINUE
),
3086 NULL
, POPUP_WAIT_NONE
);
3090 CONSOLE_ConInKey(Ir
);
3092 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3093 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3095 if (ConfirmQuit(Ir
))
3098 return SELECT_FILE_SYSTEM_PAGE
;
3100 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3102 return SELECT_FILE_SYSTEM_PAGE
;
3106 else if (!NT_SUCCESS(Status
))
3108 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3109 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3113 PartEntry
->FormatState
= Formatted
;
3114 // PartEntry->FileSystem = FileSystem;
3115 PartEntry
->New
= FALSE
;
3119 CONSOLE_SetStatusText(" Done. Press any key ...");
3120 CONSOLE_ConInKey(Ir
);
3123 return SELECT_FILE_SYSTEM_PAGE
;
3127 return FORMAT_PARTITION_PAGE
;
3132 * Displays the CheckFileSystemPage.
3135 * InstallDirectoryPage (At once)
3139 * Inits or reloads FileSystemList
3142 * Number of the next page.
3145 CheckFileSystemPage(PINPUT_RECORD Ir
)
3148 PDISKENTRY DiskEntry
;
3149 PPARTENTRY PartEntry
;
3150 PFILE_SYSTEM CurrentFileSystem
;
3151 UNICODE_STRING PartitionRootPath
;
3152 WCHAR PathBuffer
[MAX_PATH
];
3153 CHAR Buffer
[MAX_PATH
];
3155 if (PartitionList
== NULL
)
3157 /* FIXME: show an error dialog */
3161 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3163 return INSTALL_DIRECTORY_PAGE
;
3166 /* Set PartitionRootPath */
3167 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3168 L
"\\Device\\Harddisk%lu\\Partition%lu",
3169 DiskEntry
->DiskNumber
,
3170 PartEntry
->PartitionNumber
);
3171 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3172 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3174 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3176 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3178 CurrentFileSystem
= PartEntry
->FileSystem
;
3179 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3180 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3182 /* HACK: Do not try to check a partition with an unknown filesystem */
3183 if (CurrentFileSystem
== NULL
)
3185 PartEntry
->NeedsCheck
= FALSE
;
3186 return CHECK_FILE_SYSTEM_PAGE
;
3189 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3190 if (Status
== STATUS_NOT_SUPPORTED
)
3193 "Setup is currently unable to check a partition formatted in %S.\n"
3195 " \x07 Press ENTER to continue Setup.\n"
3196 " \x07 Press F3 to quit Setup.",
3197 CurrentFileSystem
->FileSystemName
);
3200 MUIGetString(STRING_QUITCONTINUE
),
3201 NULL
, POPUP_WAIT_NONE
);
3205 CONSOLE_ConInKey(Ir
);
3207 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3208 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3210 if (ConfirmQuit(Ir
))
3213 return CHECK_FILE_SYSTEM_PAGE
;
3215 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3217 PartEntry
->NeedsCheck
= FALSE
;
3218 return CHECK_FILE_SYSTEM_PAGE
;
3222 else if (!NT_SUCCESS(Status
))
3224 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3225 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3226 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3227 "(Status 0x%08lx).\n", Status
);
3229 // MUIGetString(STRING_REBOOTCOMPUTER),
3230 MUIGetString(STRING_CONTINUE
),
3231 Ir
, POPUP_WAIT_ENTER
);
3233 // return QUIT_PAGE;
3236 PartEntry
->NeedsCheck
= FALSE
;
3237 return CHECK_FILE_SYSTEM_PAGE
;
3242 BuildInstallPaths(PWSTR InstallDir
,
3243 PDISKENTRY DiskEntry
,
3244 PPARTENTRY PartEntry
)
3248 Status
= InitDestinationPaths(&USetupData
, InstallDir
, DiskEntry
, PartEntry
);
3249 // TODO: Check Status
3250 UNREFERENCED_PARAMETER(Status
);
3252 /* Initialize DestinationDriveLetter */
3253 DestinationDriveLetter
= PartEntry
->DriveLetter
;
3259 IN PCWSTR InstallDir
)
3263 Length
= wcslen(InstallDir
);
3265 // TODO: Add check for 8.3 too.
3267 /* Path must be at least 2 characters long */
3271 /* Path must start with a backslash */
3272 // if (InstallDir[0] != L'\\')
3275 /* Path must not end with a backslash */
3276 if (InstallDir
[Length
- 1] == L
'\\')
3279 /* Path must not contain whitespace characters */
3280 for (i
= 0; i
< Length
; i
++)
3282 if (iswspace(InstallDir
[i
]))
3286 /* Path component must not end with a dot */
3287 for (i
= 0; i
< Length
; i
++)
3289 if (InstallDir
[i
] == L
'\\' && i
> 0)
3291 if (InstallDir
[i
- 1] == L
'.')
3296 if (InstallDir
[Length
- 1] == L
'.')
3304 * Displays the InstallDirectoryPage.
3311 * Number of the next page.
3314 InstallDirectoryPage(PINPUT_RECORD Ir
)
3316 PDISKENTRY DiskEntry
;
3317 PPARTENTRY PartEntry
;
3318 WCHAR InstallDir
[MAX_PATH
];
3322 /* We do not need the filesystem list anymore */
3323 if (FileSystemList
!= NULL
)
3325 DestroyFileSystemList(FileSystemList
);
3326 FileSystemList
= NULL
;
3329 if (PartitionList
== NULL
||
3330 PartitionList
->CurrentDisk
== NULL
||
3331 PartitionList
->CurrentPartition
== NULL
)
3333 /* FIXME: show an error dialog */
3337 DiskEntry
= PartitionList
->CurrentDisk
;
3338 PartEntry
= PartitionList
->CurrentPartition
;
3340 // if (IsUnattendedSetup)
3341 if (RepairUpdateFlag
)
3342 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3343 else if (USetupData
.InstallationDirectory
[0])
3344 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3346 wcscpy(InstallDir
, L
"\\ReactOS");
3349 * Check the validity of the predefined 'InstallDir'. If we are either
3350 * in unattended setup or in update/repair mode, and the installation path
3351 * is valid, just perform the installation. Otherwise (either in the case
3352 * of an invalid path, or we are in regular setup), display the UI and allow
3353 * the user to specify a new installation path.
3355 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3357 BuildInstallPaths(InstallDir
,
3362 * Check whether the user attempts to install ReactOS within the
3363 * installation source directory, or in a subdirectory thereof.
3364 * If so, fail with an error.
3366 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3368 PopupError("You cannot install ReactOS within the installation source directory!",
3369 MUIGetString(STRING_CONTINUE
),
3370 Ir
, POPUP_WAIT_ENTER
);
3371 return INSTALL_DIRECTORY_PAGE
;
3374 return PREPARE_COPY_PAGE
;
3377 Length
= wcslen(InstallDir
);
3380 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3381 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3382 CONSOLE_SetCursorXY(8 + Pos
, 11);
3383 CONSOLE_SetCursorType(TRUE
, TRUE
);
3387 CONSOLE_ConInKey(Ir
);
3389 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3390 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3392 CONSOLE_SetCursorType(TRUE
, FALSE
);
3394 if (ConfirmQuit(Ir
))
3397 CONSOLE_SetCursorType(TRUE
, TRUE
);
3400 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3401 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3405 memmove(&InstallDir
[Pos
],
3406 &InstallDir
[Pos
+ 1],
3407 (Length
- Pos
- 1) * sizeof(WCHAR
));
3408 InstallDir
[Length
- 1] = UNICODE_NULL
;
3411 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3412 CONSOLE_SetCursorXY(8 + Pos
, 11);