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
->NoMbr
? "GPT" : "MBR");
1990 CONSOLE_PrintTextXY(6, 10,
1991 MUIGetString(STRING_HDINFOPARTCREATE_2
),
1994 DiskEntry
->DiskNumber
,
1998 DiskEntry
->NoMbr
? "GPT" : "MBR");
2001 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2004 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2005 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2008 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2010 PartEntry
= PartitionList
->CurrentPartition
;
2013 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2015 if (MaxSize
> PARTITION_MAXSIZE
)
2016 MaxSize
= PARTITION_MAXSIZE
;
2018 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2019 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2023 if (ConfirmQuit(Ir
))
2030 return SELECT_PARTITION_PAGE
;
2034 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2042 if (PartSize
> MaxSize
)
2048 /* Convert to bytes */
2049 if (PartSize
== MaxSize
)
2051 /* Use all of the unpartitioned disk space */
2052 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2056 /* Calculate the sector count from the size in MB */
2057 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2059 /* But never get larger than the unpartitioned disk space */
2060 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2061 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2064 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2066 CreatePrimaryPartition(PartitionList
,
2070 return SELECT_PARTITION_PAGE
;
2074 return CREATE_PRIMARY_PARTITION_PAGE
;
2079 * Displays the CreateExtendedPartitionPage.
2082 * SelectPartitionPage (default)
2086 * Number of the next page.
2089 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2091 PDISKENTRY DiskEntry
;
2092 PPARTENTRY PartEntry
;
2095 WCHAR InputBuffer
[50];
2099 ULONGLONG SectorCount
;
2102 if (PartitionList
== NULL
||
2103 PartitionList
->CurrentDisk
== NULL
||
2104 PartitionList
->CurrentPartition
== NULL
)
2106 /* FIXME: show an error dialog */
2110 DiskEntry
= PartitionList
->CurrentDisk
;
2111 PartEntry
= PartitionList
->CurrentPartition
;
2113 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2115 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2117 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2119 if (DiskSize
>= 10 * GB
) /* 10 GB */
2121 DiskSize
= DiskSize
/ GB
;
2122 Unit
= MUIGetString(STRING_GB
);
2127 DiskSize
= DiskSize
/ MB
;
2131 Unit
= MUIGetString(STRING_MB
);
2134 if (DiskEntry
->DriverName
.Length
> 0)
2136 CONSOLE_PrintTextXY(6, 10,
2137 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2140 DiskEntry
->DiskNumber
,
2144 &DiskEntry
->DriverName
,
2145 DiskEntry
->NoMbr
? "GPT" : "MBR");
2149 CONSOLE_PrintTextXY(6, 10,
2150 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2153 DiskEntry
->DiskNumber
,
2157 DiskEntry
->NoMbr
? "GPT" : "MBR");
2160 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2163 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2164 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2167 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2169 PartEntry
= PartitionList
->CurrentPartition
;
2172 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2174 if (MaxSize
> PARTITION_MAXSIZE
)
2175 MaxSize
= PARTITION_MAXSIZE
;
2177 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2178 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2182 if (ConfirmQuit(Ir
))
2189 return SELECT_PARTITION_PAGE
;
2193 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2201 if (PartSize
> MaxSize
)
2207 /* Convert to bytes */
2208 if (PartSize
== MaxSize
)
2210 /* Use all of the unpartitioned disk space */
2211 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2215 /* Calculate the sector count from the size in MB */
2216 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2218 /* But never get larger than the unpartitioned disk space */
2219 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2220 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2223 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2225 CreateExtendedPartition(PartitionList
,
2228 return SELECT_PARTITION_PAGE
;
2232 return CREATE_EXTENDED_PARTITION_PAGE
;
2237 * Displays the CreateLogicalPartitionPage.
2240 * SelectFileSystemPage (default)
2244 * Number of the next page.
2247 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2249 PDISKENTRY DiskEntry
;
2250 PPARTENTRY PartEntry
;
2253 WCHAR InputBuffer
[50];
2257 ULONGLONG SectorCount
;
2260 if (PartitionList
== NULL
||
2261 PartitionList
->CurrentDisk
== NULL
||
2262 PartitionList
->CurrentPartition
== NULL
)
2264 /* FIXME: show an error dialog */
2268 DiskEntry
= PartitionList
->CurrentDisk
;
2269 PartEntry
= PartitionList
->CurrentPartition
;
2271 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2273 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2275 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2277 if (DiskSize
>= 10 * GB
) /* 10 GB */
2279 DiskSize
= DiskSize
/ GB
;
2280 Unit
= MUIGetString(STRING_GB
);
2285 DiskSize
= DiskSize
/ MB
;
2289 Unit
= MUIGetString(STRING_MB
);
2292 if (DiskEntry
->DriverName
.Length
> 0)
2294 CONSOLE_PrintTextXY(6, 10,
2295 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2298 DiskEntry
->DiskNumber
,
2302 &DiskEntry
->DriverName
,
2303 DiskEntry
->NoMbr
? "GPT" : "MBR");
2307 CONSOLE_PrintTextXY(6, 10,
2308 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2311 DiskEntry
->DiskNumber
,
2315 DiskEntry
->NoMbr
? "GPT" : "MBR");
2318 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2321 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2322 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2325 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2327 PartEntry
= PartitionList
->CurrentPartition
;
2330 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2332 if (MaxSize
> PARTITION_MAXSIZE
)
2333 MaxSize
= PARTITION_MAXSIZE
;
2335 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2336 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2340 if (ConfirmQuit(Ir
))
2347 return SELECT_PARTITION_PAGE
;
2351 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2359 if (PartSize
> MaxSize
)
2365 /* Convert to bytes */
2366 if (PartSize
== MaxSize
)
2368 /* Use all of the unpartitioned disk space */
2369 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2373 /* Calculate the sector count from the size in MB */
2374 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2376 /* But never get larger than the unpartitioned disk space */
2377 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2378 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2381 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2383 CreateLogicalPartition(PartitionList
,
2387 return SELECT_PARTITION_PAGE
;
2391 return CREATE_LOGICAL_PARTITION_PAGE
;
2396 * Displays the ConfirmDeleteSystemPartitionPage.
2399 * DeletePartitionPage (default)
2400 * SelectPartitionPage
2403 * Number of the next page.
2406 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2408 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2412 CONSOLE_ConInKey(Ir
);
2414 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2415 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2417 if (ConfirmQuit(Ir
))
2422 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2424 return DELETE_PARTITION_PAGE
;
2426 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2428 return SELECT_PARTITION_PAGE
;
2432 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2437 * Displays the DeletePartitionPage.
2440 * SelectPartitionPage (default)
2444 * Number of the next page.
2447 DeletePartitionPage(PINPUT_RECORD Ir
)
2449 PDISKENTRY DiskEntry
;
2450 PPARTENTRY PartEntry
;
2454 CHAR PartTypeString
[32];
2456 if (PartitionList
== NULL
||
2457 PartitionList
->CurrentDisk
== NULL
||
2458 PartitionList
->CurrentPartition
== NULL
)
2460 /* FIXME: show an error dialog */
2464 DiskEntry
= PartitionList
->CurrentDisk
;
2465 PartEntry
= PartitionList
->CurrentPartition
;
2467 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2469 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2471 ARRAYSIZE(PartTypeString
));
2473 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2475 if (PartSize
>= 10 * GB
) /* 10 GB */
2477 PartSize
= PartSize
/ GB
;
2478 Unit
= MUIGetString(STRING_GB
);
2482 if (PartSize
>= 10 * MB
) /* 10 MB */
2484 PartSize
= PartSize
/ MB
;
2485 Unit
= MUIGetString(STRING_MB
);
2489 PartSize
= PartSize
/ KB
;
2490 Unit
= MUIGetString(STRING_KB
);
2493 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2495 CONSOLE_PrintTextXY(6, 10,
2496 MUIGetString(STRING_HDDINFOUNK2
),
2497 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2498 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2499 PartEntry
->PartitionType
,
2505 CONSOLE_PrintTextXY(6, 10,
2506 " %c%c %s %I64u %s",
2507 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2508 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2514 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2516 if (DiskSize
>= 10 * GB
) /* 10 GB */
2518 DiskSize
= DiskSize
/ GB
;
2519 Unit
= MUIGetString(STRING_GB
);
2524 DiskSize
= DiskSize
/ MB
;
2528 Unit
= MUIGetString(STRING_MB
);
2531 if (DiskEntry
->DriverName
.Length
> 0)
2533 CONSOLE_PrintTextXY(6, 12,
2534 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2537 DiskEntry
->DiskNumber
,
2541 &DiskEntry
->DriverName
,
2542 DiskEntry
->NoMbr
? "GPT" : "MBR");
2546 CONSOLE_PrintTextXY(6, 12,
2547 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2550 DiskEntry
->DiskNumber
,
2554 DiskEntry
->NoMbr
? "GPT" : "MBR");
2559 CONSOLE_ConInKey(Ir
);
2561 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2562 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2564 if (ConfirmQuit(Ir
))
2569 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2571 return SELECT_PARTITION_PAGE
;
2573 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2575 DeleteCurrentPartition(PartitionList
);
2577 return SELECT_PARTITION_PAGE
;
2581 return DELETE_PARTITION_PAGE
;
2586 * Displays the SelectFileSystemPage.
2589 * CheckFileSystemPage (At once if RepairUpdate is selected)
2590 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2591 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2592 * SelectPartitionPage (If the user aborts)
2593 * FormatPartitionPage (Default)
2597 * Calls UpdatePartitionType()
2598 * Calls CheckActiveSystemPartition()
2601 * Number of the next page.
2604 SelectFileSystemPage(PINPUT_RECORD Ir
)
2606 PDISKENTRY DiskEntry
;
2607 PPARTENTRY PartEntry
;
2612 CHAR PartTypeString
[32];
2613 FORMATMACHINESTATE PreviousFormatState
;
2615 DPRINT("SelectFileSystemPage()\n");
2617 if (PartitionList
== NULL
||
2618 PartitionList
->CurrentDisk
== NULL
||
2619 PartitionList
->CurrentPartition
== NULL
)
2621 /* FIXME: show an error dialog */
2625 /* Find or set the active system partition */
2626 CheckActiveSystemPartition(PartitionList
);
2627 if (PartitionList
->SystemPartition
== NULL
)
2629 /* FIXME: show an error dialog */
2631 // Error dialog should say that we cannot find a suitable
2632 // system partition and create one on the system. At this point,
2633 // it may be nice to ask the user whether he wants to continue,
2634 // or use an external drive as the system drive/partition
2635 // (e.g. floppy, USB drive, etc...)
2640 PreviousFormatState
= FormatState
;
2641 switch (FormatState
)
2645 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2647 TempPartition
= PartitionList
->SystemPartition
;
2648 TempPartition
->NeedsCheck
= TRUE
;
2650 FormatState
= FormatSystemPartition
;
2651 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2655 TempPartition
= PartitionList
->CurrentPartition
;
2656 TempPartition
->NeedsCheck
= TRUE
;
2658 FormatState
= FormatInstallPartition
;
2659 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2664 case FormatSystemPartition
:
2666 TempPartition
= PartitionList
->CurrentPartition
;
2667 TempPartition
->NeedsCheck
= TRUE
;
2669 FormatState
= FormatInstallPartition
;
2670 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2674 case FormatInstallPartition
:
2676 if (GetNextUnformattedPartition(PartitionList
,
2680 FormatState
= FormatOtherPartition
;
2681 TempPartition
->NeedsCheck
= TRUE
;
2682 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2686 FormatState
= FormatDone
;
2687 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2688 return CHECK_FILE_SYSTEM_PAGE
;
2693 case FormatOtherPartition
:
2695 if (GetNextUnformattedPartition(PartitionList
,
2699 FormatState
= FormatOtherPartition
;
2700 TempPartition
->NeedsCheck
= TRUE
;
2701 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2705 FormatState
= FormatDone
;
2706 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2707 return CHECK_FILE_SYSTEM_PAGE
;
2714 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2715 /* FIXME: show an error dialog */
2720 PartEntry
= TempPartition
;
2721 DiskEntry
= PartEntry
->DiskEntry
;
2723 /* Adjust disk size */
2724 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2725 if (DiskSize
>= 10 * GB
) /* 10 GB */
2727 DiskSize
= DiskSize
/ GB
;
2728 DiskUnit
= MUIGetString(STRING_GB
);
2732 DiskSize
= DiskSize
/ MB
;
2733 DiskUnit
= MUIGetString(STRING_MB
);
2736 /* Adjust partition size */
2737 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2738 if (PartSize
>= 10 * GB
) /* 10 GB */
2740 PartSize
= PartSize
/ GB
;
2741 PartUnit
= MUIGetString(STRING_GB
);
2745 PartSize
= PartSize
/ MB
;
2746 PartUnit
= MUIGetString(STRING_MB
);
2749 /* Adjust partition type */
2750 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2752 ARRAYSIZE(PartTypeString
));
2754 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2756 if (PartEntry
->AutoCreate
)
2758 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2761 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2762 PartEntry
->PartitionNumber
,
2768 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2769 DiskEntry
->DiskNumber
,
2775 &DiskEntry
->DriverName
,
2776 DiskEntry
->NoMbr
? "GPT" : "MBR");
2778 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2780 PartEntry
->AutoCreate
= FALSE
;
2782 else if (PartEntry
->New
)
2784 switch (FormatState
)
2786 case FormatSystemPartition
:
2787 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2790 case FormatInstallPartition
:
2791 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2794 case FormatOtherPartition
:
2795 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2802 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2806 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2808 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2810 CONSOLE_PrintTextXY(8, 10,
2811 MUIGetString(STRING_HDDINFOUNK4
),
2812 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2813 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2814 PartEntry
->PartitionType
,
2820 CONSOLE_PrintTextXY(8, 10,
2822 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
2823 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2829 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
2830 DiskEntry
->DiskNumber
,
2836 &DiskEntry
->DriverName
,
2837 DiskEntry
->NoMbr
? "GPT" : "MBR");
2840 if (FileSystemList
== NULL
)
2842 /* Create the file system list, and by default select the "FAT" file system */
2843 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2844 if (FileSystemList
== NULL
)
2846 /* FIXME: show an error dialog */
2851 if (RepairUpdateFlag
)
2853 return CHECK_FILE_SYSTEM_PAGE
;
2854 //return SELECT_PARTITION_PAGE;
2857 if (IsUnattendedSetup
)
2859 if (USetupData
.FormatPartition
)
2862 * We use whatever currently selected file system we have
2863 * (by default, this is "FAT", as per the initialization
2864 * performed above). Note that it may be interesting to specify
2865 * which file system to use in unattended installations, in the
2866 * txtsetup.sif file.
2868 return FORMAT_PARTITION_PAGE
;
2871 return CHECK_FILE_SYSTEM_PAGE
;
2874 DrawFileSystemList(FileSystemList
);
2878 CONSOLE_ConInKey(Ir
);
2880 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2881 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2883 if (ConfirmQuit(Ir
))
2888 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2889 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2891 FormatState
= Start
;
2892 return SELECT_PARTITION_PAGE
;
2894 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2895 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2897 ScrollDownFileSystemList(FileSystemList
);
2899 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2900 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2902 ScrollUpFileSystemList(FileSystemList
);
2904 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2906 if (!FileSystemList
->Selected
->FileSystem
)
2907 return SELECT_FILE_SYSTEM_PAGE
;
2909 return FORMAT_PARTITION_PAGE
;
2913 FormatState
= PreviousFormatState
;
2915 return SELECT_FILE_SYSTEM_PAGE
;
2920 * Displays the FormatPartitionPage.
2923 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2924 * SelectPartitionPage (At once)
2928 * Sets PartitionList->CurrentPartition->FormatState
2929 * Sets USetupData.DestinationRootPath
2932 * Number of the next page.
2935 FormatPartitionPage(PINPUT_RECORD Ir
)
2938 PDISKENTRY DiskEntry
;
2939 PPARTENTRY PartEntry
;
2940 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2941 UNICODE_STRING PartitionRootPath
;
2942 WCHAR PathBuffer
[MAX_PATH
];
2943 CHAR Buffer
[MAX_PATH
];
2948 PPARTITION_INFORMATION PartitionInfo
;
2951 DPRINT("FormatPartitionPage()\n");
2953 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2955 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2957 /* FIXME: show an error dialog */
2961 PartEntry
= TempPartition
;
2962 DiskEntry
= PartEntry
->DiskEntry
;
2964 SelectedFileSystem
= FileSystemList
->Selected
;
2968 if (!IsUnattendedSetup
)
2970 CONSOLE_ConInKey(Ir
);
2973 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2974 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2976 if (ConfirmQuit(Ir
))
2981 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2983 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2985 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2987 /* FIXME: show an error dialog */
2992 CONSOLE_PrintTextXY(6, 12,
2993 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
2994 DiskEntry
->Cylinders
,
2995 DiskEntry
->TracksPerCylinder
,
2996 DiskEntry
->SectorsPerTrack
,
2997 DiskEntry
->BytesPerSector
,
2998 DiskEntry
->Dirty
? '*' : ' ');
3002 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3004 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3006 CONSOLE_PrintTextXY(6, Line
,
3007 "%2u: %2lu %c %12I64u %12I64u %02x",
3009 PartitionInfo
->PartitionNumber
,
3010 PartitionInfo
->BootIndicator
? 'A' : '-',
3011 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3012 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3013 PartitionInfo
->PartitionType
);
3018 /* Commit the partition changes to the disk */
3019 if (!WritePartitionsToDisk(PartitionList
))
3021 DPRINT("WritePartitionsToDisk() failed\n");
3022 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3026 /* Set PartitionRootPath */
3027 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3028 L
"\\Device\\Harddisk%lu\\Partition%lu",
3029 DiskEntry
->DiskNumber
,
3030 PartEntry
->PartitionNumber
);
3031 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3032 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3034 /* Format the partition */
3035 if (SelectedFileSystem
->FileSystem
)
3037 Status
= FormatPartition(&PartitionRootPath
,
3038 SelectedFileSystem
);
3039 if (Status
== STATUS_NOT_SUPPORTED
)
3042 "Setup is currently unable to format a partition in %S.\n"
3044 " \x07 Press ENTER to continue Setup.\n"
3045 " \x07 Press F3 to quit Setup.",
3046 SelectedFileSystem
->FileSystem
->FileSystemName
);
3049 MUIGetString(STRING_QUITCONTINUE
),
3050 NULL
, POPUP_WAIT_NONE
);
3054 CONSOLE_ConInKey(Ir
);
3056 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3057 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3059 if (ConfirmQuit(Ir
))
3062 return SELECT_FILE_SYSTEM_PAGE
;
3064 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3066 return SELECT_FILE_SYSTEM_PAGE
;
3070 else if (!NT_SUCCESS(Status
))
3072 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3073 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3077 PartEntry
->FormatState
= Formatted
;
3078 // PartEntry->FileSystem = FileSystem;
3079 PartEntry
->New
= FALSE
;
3083 CONSOLE_SetStatusText(" Done. Press any key ...");
3084 CONSOLE_ConInKey(Ir
);
3087 return SELECT_FILE_SYSTEM_PAGE
;
3091 return FORMAT_PARTITION_PAGE
;
3096 * Displays the CheckFileSystemPage.
3099 * InstallDirectoryPage (At once)
3103 * Inits or reloads FileSystemList
3106 * Number of the next page.
3109 CheckFileSystemPage(PINPUT_RECORD Ir
)
3112 PDISKENTRY DiskEntry
;
3113 PPARTENTRY PartEntry
;
3114 PFILE_SYSTEM CurrentFileSystem
;
3115 UNICODE_STRING PartitionRootPath
;
3116 WCHAR PathBuffer
[MAX_PATH
];
3117 CHAR Buffer
[MAX_PATH
];
3119 if (PartitionList
== NULL
)
3121 /* FIXME: show an error dialog */
3125 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3127 return INSTALL_DIRECTORY_PAGE
;
3130 /* Set PartitionRootPath */
3131 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3132 L
"\\Device\\Harddisk%lu\\Partition%lu",
3133 DiskEntry
->DiskNumber
,
3134 PartEntry
->PartitionNumber
);
3135 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3136 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3138 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3140 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3142 CurrentFileSystem
= PartEntry
->FileSystem
;
3143 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3144 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3146 /* HACK: Do not try to check a partition with an unknown filesystem */
3147 if (CurrentFileSystem
== NULL
)
3149 PartEntry
->NeedsCheck
= FALSE
;
3150 return CHECK_FILE_SYSTEM_PAGE
;
3153 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3154 if (Status
== STATUS_NOT_SUPPORTED
)
3157 "Setup is currently unable to check a partition formatted in %S.\n"
3159 " \x07 Press ENTER to continue Setup.\n"
3160 " \x07 Press F3 to quit Setup.",
3161 CurrentFileSystem
->FileSystemName
);
3164 MUIGetString(STRING_QUITCONTINUE
),
3165 NULL
, POPUP_WAIT_NONE
);
3169 CONSOLE_ConInKey(Ir
);
3171 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3172 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3174 if (ConfirmQuit(Ir
))
3177 return CHECK_FILE_SYSTEM_PAGE
;
3179 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3181 PartEntry
->NeedsCheck
= FALSE
;
3182 return CHECK_FILE_SYSTEM_PAGE
;
3186 else if (!NT_SUCCESS(Status
))
3188 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3189 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3190 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3191 "(Status 0x%08lx).\n", Status
);
3193 // MUIGetString(STRING_REBOOTCOMPUTER),
3194 MUIGetString(STRING_CONTINUE
),
3195 Ir
, POPUP_WAIT_ENTER
);
3197 // return QUIT_PAGE;
3200 PartEntry
->NeedsCheck
= FALSE
;
3201 return CHECK_FILE_SYSTEM_PAGE
;
3206 BuildInstallPaths(PWSTR InstallDir
,
3207 PDISKENTRY DiskEntry
,
3208 PPARTENTRY PartEntry
)
3212 Status
= InitDestinationPaths(&USetupData
, InstallDir
, DiskEntry
, PartEntry
);
3213 // TODO: Check Status
3214 UNREFERENCED_PARAMETER(Status
);
3216 /* Initialize DestinationDriveLetter */
3217 DestinationDriveLetter
= PartEntry
->DriveLetter
;
3223 IN PCWSTR InstallDir
)
3227 Length
= wcslen(InstallDir
);
3229 // TODO: Add check for 8.3 too.
3231 /* Path must be at least 2 characters long */
3235 /* Path must start with a backslash */
3236 // if (InstallDir[0] != L'\\')
3239 /* Path must not end with a backslash */
3240 if (InstallDir
[Length
- 1] == L
'\\')
3243 /* Path must not contain whitespace characters */
3244 for (i
= 0; i
< Length
; i
++)
3246 if (iswspace(InstallDir
[i
]))
3250 /* Path component must not end with a dot */
3251 for (i
= 0; i
< Length
; i
++)
3253 if (InstallDir
[i
] == L
'\\' && i
> 0)
3255 if (InstallDir
[i
- 1] == L
'.')
3260 if (InstallDir
[Length
- 1] == L
'.')
3268 * Displays the InstallDirectoryPage.
3275 * Number of the next page.
3278 InstallDirectoryPage(PINPUT_RECORD Ir
)
3280 PDISKENTRY DiskEntry
;
3281 PPARTENTRY PartEntry
;
3282 WCHAR InstallDir
[MAX_PATH
];
3286 /* We do not need the filesystem list anymore */
3287 if (FileSystemList
!= NULL
)
3289 DestroyFileSystemList(FileSystemList
);
3290 FileSystemList
= NULL
;
3293 if (PartitionList
== NULL
||
3294 PartitionList
->CurrentDisk
== NULL
||
3295 PartitionList
->CurrentPartition
== NULL
)
3297 /* FIXME: show an error dialog */
3301 DiskEntry
= PartitionList
->CurrentDisk
;
3302 PartEntry
= PartitionList
->CurrentPartition
;
3304 // if (IsUnattendedSetup)
3305 if (RepairUpdateFlag
)
3306 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3307 else if (USetupData
.InstallationDirectory
[0])
3308 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3310 wcscpy(InstallDir
, L
"\\ReactOS");
3313 * Check the validity of the predefined 'InstallDir'. If we are either
3314 * in unattended setup or in update/repair mode, and the installation path
3315 * is valid, just perform the installation. Otherwise (either in the case
3316 * of an invalid path, or we are in regular setup), display the UI and allow
3317 * the user to specify a new installation path.
3319 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3321 BuildInstallPaths(InstallDir
,
3326 * Check whether the user attempts to install ReactOS within the
3327 * installation source directory, or in a subdirectory thereof.
3328 * If so, fail with an error.
3330 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3332 PopupError("You cannot install ReactOS within the installation source directory!",
3333 MUIGetString(STRING_CONTINUE
),
3334 Ir
, POPUP_WAIT_ENTER
);
3335 return INSTALL_DIRECTORY_PAGE
;
3338 return PREPARE_COPY_PAGE
;
3341 Length
= wcslen(InstallDir
);
3344 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3345 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3346 CONSOLE_SetCursorXY(8 + Pos
, 11);
3347 CONSOLE_SetCursorType(TRUE
, TRUE
);
3351 CONSOLE_ConInKey(Ir
);
3353 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3354 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3356 CONSOLE_SetCursorType(TRUE
, FALSE
);
3358 if (ConfirmQuit(Ir
))
3361 CONSOLE_SetCursorType(TRUE
, TRUE
);
3364 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3365 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3369 memmove(&InstallDir
[Pos
],
3370 &InstallDir
[Pos
+ 1],
3371 (Length
- Pos
- 1) * sizeof(WCHAR
));
3372 InstallDir
[Length
- 1] = UNICODE_NULL
;
3375 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3376 CONSOLE_SetCursorXY(8 + Pos
, 11);
3379 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3380 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3383 CONSOLE_SetCursorXY(8 + Pos
, 11);
3385 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3386 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3389 CONSOLE_SetCursorXY(8 + Pos
, 11);
3391 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3392 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3397 CONSOLE_SetCursorXY(8 + Pos
, 11);
3400 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3401 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3406 CONSOLE_SetCursorXY(8 + Pos
, 11);
3409 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3411 CONSOLE_SetCursorType(TRUE
, FALSE
);