3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
30 #include <ntstrsafe.h>
42 /* GLOBALS & LOCALS *********************************************************/
45 BOOLEAN IsUnattendedSetup
= FALSE
;
47 static USETUP_DATA USetupData
;
49 /* The partition where to perform the installation */
50 static PPARTENTRY InstallPartition
= NULL
;
52 * The system partition we will actually use. It can be different from
53 * PartitionList->SystemPartition in case we don't support it, or we install
54 * on a removable disk.
55 * We may indeed not support the original system partition in case we do not
56 * have write support on it. Please note that this situation is partly a HACK
57 * and MUST NEVER happen on architectures where real system partitions are
58 * mandatory (because then they are formatted in FAT FS and we support write
61 static PPARTENTRY SystemPartition
= NULL
;
66 PCWSTR SelectedLanguageId
;
67 static WCHAR DefaultLanguage
[20]; // Copy of string inside LanguageList
68 static WCHAR DefaultKBLayout
[20]; // Copy of string inside KeyboardList
70 static BOOLEAN RepairUpdateFlag
= FALSE
;
72 /* Global partition list on the system */
73 static PPARTLIST PartitionList
= NULL
;
75 /* Currently selected partition entry in the list */
76 static PPARTENTRY CurrentPartition
= NULL
;
78 /* List of supported file systems for the partition to be formatted */
79 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
81 /* Machine state for the formatter */
82 static PPARTENTRY TempPartition
= NULL
;
83 static FORMATMACHINESTATE FormatState
= Start
;
85 /*****************************************************/
87 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
88 static PGENERIC_LIST NtOsInstallsList
= NULL
;
90 #ifdef __REACTOS__ /* HACK */
92 /* FONT SUBSTITUTION WORKAROUND *************************************************/
94 /* For font file check */
95 FONTSUBSTSETTINGS s_SubstSettings
= { FALSE
};
98 DoWatchDestFileName(LPCWSTR FileName
)
100 if (FileName
[0] == 'm' || FileName
[0] == 'M')
102 if (wcsicmp(FileName
, L
"mingliu.ttc") == 0)
104 DPRINT("mingliu.ttc found\n");
105 s_SubstSettings
.bFoundFontMINGLIU
= TRUE
;
107 else if (wcsicmp(FileName
, L
"msgothic.ttc") == 0)
109 DPRINT("msgothic.ttc found\n");
110 s_SubstSettings
.bFoundFontMSGOTHIC
= TRUE
;
112 else if (wcsicmp(FileName
, L
"msmincho.ttc") == 0)
114 DPRINT("msmincho.ttc found\n");
115 s_SubstSettings
.bFoundFontMSMINCHO
= TRUE
;
117 else if (wcsicmp(FileName
, L
"mssong.ttf") == 0)
119 DPRINT("mssong.ttf found\n");
120 s_SubstSettings
.bFoundFontMSSONG
= TRUE
;
125 if (wcsicmp(FileName
, L
"simsun.ttc") == 0)
127 DPRINT("simsun.ttc found\n");
128 s_SubstSettings
.bFoundFontSIMSUN
= TRUE
;
130 else if (wcsicmp(FileName
, L
"gulim.ttc") == 0)
132 DPRINT("gulim.ttc found\n");
133 s_SubstSettings
.bFoundFontGULIM
= TRUE
;
135 else if (wcsicmp(FileName
, L
"batang.ttc") == 0)
137 DPRINT("batang.ttc found\n");
138 s_SubstSettings
.bFoundFontBATANG
= TRUE
;
144 /* FUNCTIONS ****************************************************************/
147 PrintString(IN PCSTR fmt
,...)
151 UNICODE_STRING UnicodeString
;
152 ANSI_STRING AnsiString
;
155 vsprintf(buffer
, fmt
, ap
);
158 RtlInitAnsiString(&AnsiString
, buffer
);
159 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
160 NtDisplayString(&UnicodeString
);
161 RtlFreeUnicodeString(&UnicodeString
);
166 DrawBox(IN SHORT xLeft
,
174 /* Draw upper left corner */
177 FillConsoleOutputCharacterA(StdOutput
,
183 /* Draw upper edge */
186 FillConsoleOutputCharacterA(StdOutput
,
192 /* Draw upper right corner */
193 coPos
.X
= xLeft
+ Width
- 1;
195 FillConsoleOutputCharacterA(StdOutput
,
201 /* Draw right edge, inner space and left edge */
202 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
205 FillConsoleOutputCharacterA(StdOutput
,
212 FillConsoleOutputCharacterA(StdOutput
,
218 coPos
.X
= xLeft
+ Width
- 1;
219 FillConsoleOutputCharacterA(StdOutput
,
226 /* Draw lower left corner */
228 coPos
.Y
= yTop
+ Height
- 1;
229 FillConsoleOutputCharacterA(StdOutput
,
235 /* Draw lower edge */
237 coPos
.Y
= yTop
+ Height
- 1;
238 FillConsoleOutputCharacterA(StdOutput
,
244 /* Draw lower right corner */
245 coPos
.X
= xLeft
+ Width
- 1;
246 coPos
.Y
= yTop
+ Height
- 1;
247 FillConsoleOutputCharacterA(StdOutput
,
256 PopupError(PCCH Text
,
274 /* Count text lines and longest line */
281 p
= strchr(pnext
, '\n');
285 Length
= strlen(pnext
);
290 Length
= (ULONG
)(p
- pnext
);
296 if (Length
> MaxLength
)
305 /* Check length of status line */
308 Length
= strlen(Status
);
310 if (Length
> MaxLength
)
314 Width
= MaxLength
+ 4;
320 yTop
= (yScreen
- Height
) / 2;
321 xLeft
= (xScreen
- Width
) / 2;
324 /* Set screen attributes */
326 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
328 FillConsoleOutputAttribute(StdOutput
,
329 FOREGROUND_RED
| BACKGROUND_WHITE
,
335 DrawBox(xLeft
, yTop
, Width
, Height
);
337 /* Print message text */
342 p
= strchr(pnext
, '\n');
346 Length
= strlen(pnext
);
351 Length
= (ULONG
)(p
- pnext
);
358 WriteConsoleOutputCharacterA(StdOutput
,
372 /* Print separator line and status text */
375 coPos
.Y
= yTop
+ Height
- 3;
377 FillConsoleOutputCharacterA(StdOutput
,
384 FillConsoleOutputCharacterA(StdOutput
,
390 coPos
.X
= xLeft
+ Width
- 1;
391 FillConsoleOutputCharacterA(StdOutput
,
399 WriteConsoleOutputCharacterA(StdOutput
,
401 min(strlen(Status
), (SIZE_T
)Width
- 4),
406 if (WaitEvent
== POPUP_WAIT_NONE
)
411 CONSOLE_ConInKey(Ir
);
413 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
414 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
426 * FALSE: Don't quit setup.
429 ConfirmQuit(PINPUT_RECORD Ir
)
432 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
436 CONSOLE_ConInKey(Ir
);
438 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
439 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
444 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
458 PGENERIC_LIST_ENTRY ListEntry
;
461 pszNewLayout
= MUIDefaultKeyboardLayout(SelectedLanguageId
);
463 if (USetupData
.LayoutList
== NULL
)
465 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
466 if (USetupData
.LayoutList
== NULL
)
468 /* FIXME: Handle error! */
473 /* Search for default layout (if provided) */
474 if (pszNewLayout
!= NULL
)
476 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
477 ListEntry
= GetNextListEntry(ListEntry
))
479 if (!wcscmp(pszNewLayout
, ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
))
481 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
491 GetSettingDescription(
492 IN PGENERIC_LIST_ENTRY Entry
,
494 IN SIZE_T cchBufferSize
)
496 return RtlStringCchPrintfA(Buffer
, cchBufferSize
, "%S",
497 ((PGENENTRY
)GetListEntryData(Entry
))->Value
);
502 GetNTOSInstallationName(
503 IN PGENERIC_LIST_ENTRY Entry
,
505 IN SIZE_T cchBufferSize
)
507 PNTOS_INSTALLATION NtOsInstall
= (PNTOS_INSTALLATION
)GetListEntryData(Entry
);
508 PPARTENTRY PartEntry
= NtOsInstall
->PartEntry
;
510 if (PartEntry
&& PartEntry
->DriveLetter
)
512 /* We have retrieved a partition that is mounted */
513 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
515 PartEntry
->DriveLetter
,
516 NtOsInstall
->PathComponent
,
517 NtOsInstall
->InstallationName
);
521 /* We failed somewhere, just show the NT path */
522 return RtlStringCchPrintfA(Buffer
, cchBufferSize
,
524 &NtOsInstall
->SystemNtPath
,
525 NtOsInstall
->InstallationName
);
531 * Displays the LanguagePage.
533 * Next pages: WelcomePage, QuitPage
536 * Init SelectedLanguageId
537 * Init USetupData.LanguageId
540 * Number of the next page.
543 LanguagePage(PINPUT_RECORD Ir
)
545 GENERIC_LIST_UI ListUi
;
546 PCWSTR NewLanguageId
;
547 BOOL RefreshPage
= FALSE
;
549 /* Initialize the computer settings list */
550 if (USetupData
.LanguageList
== NULL
)
552 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
553 if (USetupData
.LanguageList
== NULL
)
555 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
560 SelectedLanguageId
= DefaultLanguage
;
561 USetupData
.LanguageId
= 0;
564 SetConsoleCodePage();
568 * If there is no language or just a single one in the list,
569 * skip the language selection process altogether.
571 if (GetNumberOfListEntries(USetupData
.LanguageList
) <= 1)
573 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
577 InitGenericListUi(&ListUi
, USetupData
.LanguageList
, GetSettingDescription
);
578 DrawGenericList(&ListUi
,
583 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
585 MUIDisplayPage(LANGUAGE_PAGE
);
589 CONSOLE_ConInKey(Ir
);
591 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
592 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
594 ScrollDownGenericList(&ListUi
);
597 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
598 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
600 ScrollUpGenericList(&ListUi
);
603 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
604 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
606 ScrollPageDownGenericList(&ListUi
);
609 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
610 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
612 ScrollPageUpGenericList(&ListUi
);
615 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
616 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
621 RedrawGenericList(&ListUi
);
623 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
625 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
628 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
630 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
632 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
638 SetConsoleCodePage();
642 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
645 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
651 ASSERT(GetNumberOfListEntries(USetupData
.LanguageList
) >= 1);
654 ((PGENENTRY
)GetListEntryData(GetCurrentListEntry(USetupData
.LanguageList
)))->Id
;
656 if (wcscmp(SelectedLanguageId
, NewLanguageId
))
658 /* Clear the language page */
659 MUIClearPage(LANGUAGE_PAGE
);
661 SelectedLanguageId
= NewLanguageId
;
664 SetConsoleCodePage();
666 /* Redraw language selection page in native language */
667 MUIDisplayPage(LANGUAGE_PAGE
);
682 * LanguagePage (at once, default)
683 * InstallIntroPage (at once, if unattended)
688 * Init USetupData.SourcePath
689 * Init USetupData.SourceRootPath
690 * Init USetupData.SourceRootDir
691 * Init USetupData.SetupInf
692 * Init USetupData.RequiredPartitionDiskSpace
693 * Init IsUnattendedSetup
694 * If unattended, init *List and sets the Codepage
695 * If unattended, init SelectedLanguageId
696 * If unattended, init USetupData.LanguageId
699 * Number of the next page.
702 SetupStartPage(PINPUT_RECORD Ir
)
705 PGENERIC_LIST_ENTRY ListEntry
;
708 MUIDisplayPage(SETUP_INIT_PAGE
);
710 /* Initialize Setup, phase 1 */
711 Error
= InitializeSetup(&USetupData
, 1);
712 if (Error
!= ERROR_SUCCESS
)
714 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
718 /* Initialize the user-mode PnP manager */
719 if (!EnableUserModePnpManager())
720 DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
722 /* Wait for any immediate pending installations to finish */
723 if (WaitNoPendingInstallEvents(NULL
) != STATUS_WAIT_0
)
724 DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
726 CheckUnattendedSetup(&USetupData
);
728 if (IsUnattendedSetup
)
730 // TODO: Read options from inf
731 /* Load the hardware, language and keyboard layout lists */
733 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
734 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
735 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
737 USetupData
.LanguageList
= CreateLanguageList(USetupData
.SetupInf
, DefaultLanguage
);
740 SelectedLanguageId
= DefaultLanguage
;
741 wcscpy(DefaultLanguage
, USetupData
.LocaleID
);
742 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
744 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
746 /* first we hack LanguageList */
747 for (ListEntry
= GetFirstListEntry(USetupData
.LanguageList
); ListEntry
;
748 ListEntry
= GetNextListEntry(ListEntry
))
750 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
751 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
753 DPRINT("found %S in LanguageList\n", LocaleId
);
754 SetCurrentListEntry(USetupData
.LanguageList
, ListEntry
);
760 for (ListEntry
= GetFirstListEntry(USetupData
.LayoutList
); ListEntry
;
761 ListEntry
= GetNextListEntry(ListEntry
))
763 LocaleId
= ((PGENENTRY
)GetListEntryData(ListEntry
))->Id
;
764 if (!wcsicmp(USetupData
.LocaleID
, LocaleId
))
766 DPRINT("found %S in LayoutList\n", LocaleId
);
767 SetCurrentListEntry(USetupData
.LayoutList
, ListEntry
);
772 SetConsoleCodePage();
774 return INSTALL_INTRO_PAGE
;
777 return LANGUAGE_PAGE
;
782 * Displays the WelcomePage.
785 * InstallIntroPage (default)
792 * Number of the next page.
795 WelcomePage(PINPUT_RECORD Ir
)
797 MUIDisplayPage(WELCOME_PAGE
);
801 CONSOLE_ConInKey(Ir
);
803 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
804 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
811 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
813 return INSTALL_INTRO_PAGE
;
815 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
817 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
819 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
830 * Displays the License page.
833 * WelcomePage (default)
836 * Number of the next page.
839 LicensePage(PINPUT_RECORD Ir
)
841 MUIDisplayPage(LICENSE_PAGE
);
845 CONSOLE_ConInKey(Ir
);
847 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
858 * Displays the RepairIntroPage.
861 * RebootPage (default)
867 * Number of the next page.
870 RepairIntroPage(PINPUT_RECORD Ir
)
872 MUIDisplayPage(REPAIR_INTRO_PAGE
);
876 CONSOLE_ConInKey(Ir
);
878 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
882 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
884 RepairUpdateFlag
= TRUE
;
885 return INSTALL_INTRO_PAGE
;
887 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
889 return RECOVERY_PAGE
;
891 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
897 return REPAIR_INTRO_PAGE
;
901 * Displays the UpgradeRepairPage.
904 * RebootPage (default)
910 * Number of the next page.
913 UpgradeRepairPage(PINPUT_RECORD Ir
)
915 GENERIC_LIST_UI ListUi
;
918 if (PartitionList
== NULL
)
920 PartitionList
= CreatePartitionList();
921 if (PartitionList
== NULL
)
923 /* FIXME: show an error dialog */
924 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
927 else if (IsListEmpty(&PartitionList
->DiskListHead
))
929 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
933 /* Reset the formatter machine state */
934 TempPartition
= NULL
;
939 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
940 if (!NtOsInstallsList
)
941 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
944 * If there is no available installation (or just a single one??) that can
945 * be updated in the list, just continue with the regular installation.
947 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
949 RepairUpdateFlag
= FALSE
;
951 // return INSTALL_INTRO_PAGE;
952 return DEVICE_SETTINGS_PAGE
;
953 // return SCSI_CONTROLLER_PAGE;
956 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
958 InitGenericListUi(&ListUi
, NtOsInstallsList
, GetNTOSInstallationName
);
959 DrawGenericList(&ListUi
,
964 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
967 CONSOLE_ConInKey(Ir
);
969 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
971 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
973 case VK_DOWN
: /* DOWN */
974 ScrollDownGenericList(&ListUi
);
977 ScrollUpGenericList(&ListUi
);
979 case VK_NEXT
: /* PAGE DOWN */
980 ScrollPageDownGenericList(&ListUi
);
982 case VK_PRIOR
: /* PAGE UP */
983 ScrollPageUpGenericList(&ListUi
);
990 RedrawGenericList(&ListUi
);
994 /* TODO: Temporarily kept until correct keyboard layout is in place.
995 * (Actual AsciiChar of ESCAPE should be 0x1B instead of 0.)
996 * Addendum to commit 8b94515b.
998 case VK_ESCAPE
: /* ESC */
1000 RestoreGenericListUiState(&ListUi
);
1001 // return nextPage; // prevPage;
1003 // return INSTALL_INTRO_PAGE;
1004 return DEVICE_SETTINGS_PAGE
;
1005 // return SCSI_CONTROLLER_PAGE;
1012 /* TODO: Restore this once correct keyboard layout is in place. */
1013 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
1015 RestoreGenericListUiState(&ListUi
);
1016 // return nextPage; // prevPage;
1018 // return INSTALL_INTRO_PAGE;
1019 return DEVICE_SETTINGS_PAGE
;
1020 // return SCSI_CONTROLLER_PAGE;
1025 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1026 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1027 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1029 /* Retrieve the current installation */
1030 ASSERT(GetNumberOfListEntries(NtOsInstallsList
) >= 1);
1032 CurrentInstallation
=
1033 (PNTOS_INSTALLATION
)GetListEntryData(GetCurrentListEntry(NtOsInstallsList
));
1035 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1036 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
1038 RepairUpdateFlag
= TRUE
;
1041 /***/return INSTALL_INTRO_PAGE
;/***/
1043 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
1044 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
1046 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1051 return UPGRADE_REPAIR_PAGE
;
1056 * Displays the InstallIntroPage.
1059 * DeviceSettingsPage (At once if repair or update is selected)
1060 * SelectPartitionPage (At once if unattended setup)
1061 * DeviceSettingsPage (default)
1065 * Number of the next page.
1068 InstallIntroPage(PINPUT_RECORD Ir
)
1070 if (RepairUpdateFlag
)
1072 #if 1 /* Old code that looks good */
1074 // return SELECT_PARTITION_PAGE;
1075 return DEVICE_SETTINGS_PAGE
;
1077 #else /* Possible new code? */
1079 return DEVICE_SETTINGS_PAGE
;
1080 // return SCSI_CONTROLLER_PAGE;
1085 if (IsUnattendedSetup
)
1086 return SELECT_PARTITION_PAGE
;
1088 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1092 CONSOLE_ConInKey(Ir
);
1094 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1095 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1097 if (ConfirmQuit(Ir
))
1102 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1104 return UPGRADE_REPAIR_PAGE
;
1108 return INSTALL_INTRO_PAGE
;
1114 ScsiControllerPage(PINPUT_RECORD Ir
)
1116 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1118 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1120 /* FIXME: print loaded mass storage driver descriptions */
1122 CONSOLE_SetTextXY(8, 10, "TEST device");
1125 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1129 CONSOLE_ConInKey(Ir
);
1131 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1132 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1134 if (ConfirmQuit(Ir
))
1139 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1141 return DEVICE_SETTINGS_PAGE
;
1145 return SCSI_CONTROLLER_PAGE
;
1149 OemDriverPage(PINPUT_RECORD Ir
)
1151 // MUIDisplayPage(OEM_DRIVER_PAGE);
1153 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1155 /* FIXME: Implement!! */
1157 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1161 CONSOLE_ConInKey(Ir
);
1163 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1164 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1166 if (ConfirmQuit(Ir
))
1171 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1173 return DEVICE_SETTINGS_PAGE
;
1177 return OEM_DRIVER_PAGE
;
1183 * Displays the DeviceSettingsPage.
1186 * SelectPartitionPage (At once if repair or update is selected)
1187 * ComputerSettingsPage
1188 * DisplaySettingsPage
1189 * KeyboardSettingsPage
1190 * LayoutsettingsPage
1191 * SelectPartitionPage
1195 * Init USetupData.ComputerList
1196 * Init USetupData.DisplayList
1197 * Init USetupData.KeyboardList
1198 * Init USetupData.LayoutList
1201 * Number of the next page.
1204 DeviceSettingsPage(PINPUT_RECORD Ir
)
1206 static ULONG Line
= 16;
1208 /* Initialize the computer settings list */
1209 if (USetupData
.ComputerList
== NULL
)
1211 USetupData
.ComputerList
= CreateComputerTypeList(USetupData
.SetupInf
);
1212 if (USetupData
.ComputerList
== NULL
)
1214 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1219 /* Initialize the display settings list */
1220 if (USetupData
.DisplayList
== NULL
)
1222 USetupData
.DisplayList
= CreateDisplayDriverList(USetupData
.SetupInf
);
1223 if (USetupData
.DisplayList
== NULL
)
1225 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1230 /* Initialize the keyboard settings list */
1231 if (USetupData
.KeyboardList
== NULL
)
1233 USetupData
.KeyboardList
= CreateKeyboardDriverList(USetupData
.SetupInf
);
1234 if (USetupData
.KeyboardList
== NULL
)
1236 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1241 /* Initialize the keyboard layout list */
1242 if (USetupData
.LayoutList
== NULL
)
1244 USetupData
.LayoutList
= CreateKeyboardLayoutList(USetupData
.SetupInf
, SelectedLanguageId
, DefaultKBLayout
);
1245 if (USetupData
.LayoutList
== NULL
)
1247 /* FIXME: report error */
1248 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1253 if (RepairUpdateFlag
)
1254 return SELECT_PARTITION_PAGE
;
1256 // if (IsUnattendedSetup)
1257 // return SELECT_PARTITION_PAGE;
1259 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1261 DrawGenericListCurrentItem(USetupData
.ComputerList
, GetSettingDescription
, 25, 11);
1262 DrawGenericListCurrentItem(USetupData
.DisplayList
, GetSettingDescription
, 25, 12);
1263 DrawGenericListCurrentItem(USetupData
.KeyboardList
, GetSettingDescription
, 25, 13);
1264 DrawGenericListCurrentItem(USetupData
.LayoutList
, GetSettingDescription
, 25, 14);
1266 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1270 CONSOLE_ConInKey(Ir
);
1272 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1273 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1275 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1279 else if (Line
== 16)
1284 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1286 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1287 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1289 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1293 else if (Line
== 16)
1298 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1300 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1301 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1303 if (ConfirmQuit(Ir
))
1308 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1311 return COMPUTER_SETTINGS_PAGE
;
1312 else if (Line
== 12)
1313 return DISPLAY_SETTINGS_PAGE
;
1314 else if (Line
== 13)
1315 return KEYBOARD_SETTINGS_PAGE
;
1316 else if (Line
== 14)
1317 return LAYOUT_SETTINGS_PAGE
;
1318 else if (Line
== 16)
1319 return SELECT_PARTITION_PAGE
;
1323 return DEVICE_SETTINGS_PAGE
;
1328 * Handles generic selection lists.
1331 * GenericList: The list to handle.
1332 * nextPage: The page it needs to jump to after this page.
1333 * Ir: The PINPUT_RECORD
1336 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1337 PAGE_NUMBER nextPage
,
1342 CONSOLE_ConInKey(Ir
);
1344 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1345 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1347 ScrollDownGenericList(ListUi
);
1349 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1350 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1352 ScrollUpGenericList(ListUi
);
1354 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1355 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1357 ScrollPageDownGenericList(ListUi
);
1359 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1360 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1362 ScrollPageUpGenericList(ListUi
);
1364 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1365 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1367 if (ConfirmQuit(Ir
))
1370 RedrawGenericList(ListUi
);
1372 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
1374 RestoreGenericListUiState(ListUi
);
1375 return nextPage
; // Use some "prevPage;" instead?
1377 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1381 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1384 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1391 * Displays the ComputerSettingsPage.
1394 * DeviceSettingsPage
1398 * Number of the next page.
1401 ComputerSettingsPage(PINPUT_RECORD Ir
)
1403 GENERIC_LIST_UI ListUi
;
1404 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1406 InitGenericListUi(&ListUi
, USetupData
.ComputerList
, GetSettingDescription
);
1407 DrawGenericList(&ListUi
,
1412 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1417 * Displays the DisplaySettingsPage.
1420 * DeviceSettingsPage
1424 * Number of the next page.
1427 DisplaySettingsPage(PINPUT_RECORD Ir
)
1429 GENERIC_LIST_UI ListUi
;
1430 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1432 InitGenericListUi(&ListUi
, USetupData
.DisplayList
, GetSettingDescription
);
1433 DrawGenericList(&ListUi
,
1438 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1443 * Displays the KeyboardSettingsPage.
1446 * DeviceSettingsPage
1450 * Number of the next page.
1453 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1455 GENERIC_LIST_UI ListUi
;
1456 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1458 InitGenericListUi(&ListUi
, USetupData
.KeyboardList
, GetSettingDescription
);
1459 DrawGenericList(&ListUi
,
1464 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1469 * Displays the LayoutSettingsPage.
1472 * DeviceSettingsPage
1476 * Number of the next page.
1479 LayoutSettingsPage(PINPUT_RECORD Ir
)
1481 GENERIC_LIST_UI ListUi
;
1482 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1484 InitGenericListUi(&ListUi
, USetupData
.LayoutList
, GetSettingDescription
);
1485 DrawGenericList(&ListUi
,
1490 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1495 IsDiskSizeValid(PPARTENTRY PartEntry
)
1499 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1500 size
= (size
+ (512 * KB
)) / MB
; /* in MBytes */
1502 if (size
< USetupData
.RequiredPartitionDiskSpace
)
1504 /* Partition is too small so ask for another one */
1505 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, USetupData
.RequiredPartitionDiskSpace
);
1516 * Displays the SelectPartitionPage.
1519 * SelectFileSystemPage (At once if unattended)
1520 * SelectFileSystemPage (Default if free space is selected)
1521 * CreatePrimaryPartitionPage
1522 * CreateExtendedPartitionPage
1523 * CreateLogicalPartitionPage
1524 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1525 * DeletePartitionPage
1529 * Set InstallShortcut (only if not unattended + free space is selected)
1532 * Number of the next page.
1535 SelectPartitionPage(PINPUT_RECORD Ir
)
1540 if (PartitionList
== NULL
)
1542 PartitionList
= CreatePartitionList();
1543 if (PartitionList
== NULL
)
1545 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1548 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1550 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1554 /* Reset the formatter machine state */
1555 TempPartition
= NULL
;
1556 FormatState
= Start
;
1559 if (RepairUpdateFlag
)
1561 ASSERT(CurrentInstallation
);
1563 /* Determine the selected installation disk & partition */
1564 InstallPartition
= SelectPartition(PartitionList
,
1565 CurrentInstallation
->DiskNumber
,
1566 CurrentInstallation
->PartitionNumber
);
1567 if (!InstallPartition
)
1569 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1572 ASSERT(!IsContainerPartition(InstallPartition
->PartitionType
));
1574 return SELECT_FILE_SYSTEM_PAGE
;
1577 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1579 InitPartitionListUi(&ListUi
, PartitionList
,
1584 DrawPartitionList(&ListUi
);
1586 if (IsUnattendedSetup
)
1588 /* Determine the selected installation disk & partition */
1589 InstallPartition
= SelectPartition(PartitionList
,
1590 USetupData
.DestinationDiskNumber
,
1591 USetupData
.DestinationPartitionNumber
);
1592 if (!InstallPartition
)
1594 CurrentPartition
= ListUi
.CurrentPartition
;
1596 if (USetupData
.AutoPartition
)
1598 ASSERT(CurrentPartition
!= NULL
);
1599 ASSERT(!IsContainerPartition(CurrentPartition
->PartitionType
));
1601 if (CurrentPartition
->LogicalPartition
)
1603 CreateLogicalPartition(PartitionList
,
1605 CurrentPartition
->SectorCount
.QuadPart
,
1610 CreatePrimaryPartition(PartitionList
,
1612 CurrentPartition
->SectorCount
.QuadPart
,
1616 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1617 if (!IsDiskSizeValid(CurrentPartition
))
1619 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1620 USetupData
.RequiredPartitionDiskSpace
);
1621 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1624 InstallPartition
= CurrentPartition
;
1625 return SELECT_FILE_SYSTEM_PAGE
;
1630 ASSERT(!IsContainerPartition(InstallPartition
->PartitionType
));
1632 DrawPartitionList(&ListUi
); // FIXME: Doesn't make much sense...
1634 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1635 if (!IsDiskSizeValid(InstallPartition
))
1637 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1638 USetupData
.RequiredPartitionDiskSpace
);
1639 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1642 return SELECT_FILE_SYSTEM_PAGE
;
1648 CurrentPartition
= ListUi
.CurrentPartition
;
1650 /* Update status text */
1651 if (CurrentPartition
== NULL
)
1653 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1655 else if (CurrentPartition
->LogicalPartition
)
1657 if (CurrentPartition
->IsPartitioned
)
1659 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1663 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1668 if (CurrentPartition
->IsPartitioned
)
1670 if (IsContainerPartition(CurrentPartition
->PartitionType
))
1672 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1676 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1681 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1685 CONSOLE_ConInKey(Ir
);
1687 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1688 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1690 if (ConfirmQuit(Ir
))
1692 DestroyPartitionList(PartitionList
);
1693 PartitionList
= NULL
;
1699 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1700 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1702 ScrollDownPartitionList(&ListUi
);
1704 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1705 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1707 ScrollUpPartitionList(&ListUi
);
1709 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1711 ASSERT(CurrentPartition
!= NULL
);
1713 if (IsContainerPartition(CurrentPartition
->PartitionType
))
1714 continue; // return SELECT_PARTITION_PAGE;
1717 * Check whether the user wants to install ReactOS on a disk that
1718 * is not recognized by the computer's firmware and if so, display
1719 * a warning since such disks may not be bootable.
1721 if (CurrentPartition
->DiskEntry
->MediaType
== FixedMedia
&&
1722 !CurrentPartition
->DiskEntry
->BiosFound
)
1724 PopupError("The disk you have selected for installing ReactOS\n"
1725 "is not visible by the firmware of your computer,\n"
1726 "and so may not be bootable.\n"
1727 "Press ENTER to continue nonetheless.",
1728 MUIGetString(STRING_CONTINUE
),
1729 Ir
, POPUP_WAIT_ENTER
);
1730 // return SELECT_PARTITION_PAGE;
1733 if (CurrentPartition
->IsPartitioned
== FALSE
)
1735 if (CurrentPartition
->LogicalPartition
)
1737 Error
= LogicalPartitionCreationChecks(CurrentPartition
);
1738 if (Error
!= NOT_AN_ERROR
)
1740 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1741 return SELECT_PARTITION_PAGE
;
1744 CreateLogicalPartition(PartitionList
,
1751 Error
= PrimaryPartitionCreationChecks(CurrentPartition
);
1752 if (Error
!= NOT_AN_ERROR
)
1754 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1755 return SELECT_PARTITION_PAGE
;
1758 CreatePrimaryPartition(PartitionList
,
1765 if (!IsDiskSizeValid(CurrentPartition
))
1767 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1768 USetupData
.RequiredPartitionDiskSpace
);
1769 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1772 InstallPartition
= CurrentPartition
;
1773 return SELECT_FILE_SYSTEM_PAGE
;
1775 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1777 ASSERT(CurrentPartition
!= NULL
);
1779 if (CurrentPartition
->LogicalPartition
== FALSE
)
1781 Error
= PrimaryPartitionCreationChecks(CurrentPartition
);
1782 if (Error
!= NOT_AN_ERROR
)
1784 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1785 return SELECT_PARTITION_PAGE
;
1788 return CREATE_PRIMARY_PARTITION_PAGE
;
1791 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1793 ASSERT(CurrentPartition
!= NULL
);
1795 if (CurrentPartition
->LogicalPartition
== FALSE
)
1797 Error
= ExtendedPartitionCreationChecks(CurrentPartition
);
1798 if (Error
!= NOT_AN_ERROR
)
1800 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1801 return SELECT_PARTITION_PAGE
;
1804 return CREATE_EXTENDED_PARTITION_PAGE
;
1807 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1809 ASSERT(CurrentPartition
!= NULL
);
1811 if (CurrentPartition
->LogicalPartition
)
1813 Error
= LogicalPartitionCreationChecks(CurrentPartition
);
1814 if (Error
!= NOT_AN_ERROR
)
1816 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1817 return SELECT_PARTITION_PAGE
;
1820 return CREATE_LOGICAL_PARTITION_PAGE
;
1823 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1825 UNICODE_STRING CurrentPartitionU
;
1826 WCHAR PathBuffer
[MAX_PATH
];
1828 ASSERT(CurrentPartition
!= NULL
);
1830 if (CurrentPartition
->IsPartitioned
== FALSE
)
1832 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1833 return SELECT_PARTITION_PAGE
;
1836 // TODO: Do something similar before trying to format the partition?
1837 if (!CurrentPartition
->New
&&
1838 !IsContainerPartition(CurrentPartition
->PartitionType
) &&
1839 CurrentPartition
->FormatState
!= Unformatted
)
1841 ASSERT(CurrentPartition
->PartitionNumber
!= 0);
1843 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
1844 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
1845 CurrentPartition
->DiskEntry
->DiskNumber
,
1846 CurrentPartition
->PartitionNumber
);
1847 RtlInitUnicodeString(&CurrentPartitionU
, PathBuffer
);
1850 * Check whether the user attempts to delete the partition on which
1851 * the installation source is present. If so, fail with an error.
1853 // &USetupData.SourceRootPath
1854 if (RtlPrefixUnicodeString(&CurrentPartitionU
, &USetupData
.SourcePath
, TRUE
))
1856 MUIDisplayError(ERROR_SOURCE_PATH
, Ir
, POPUP_WAIT_ENTER
);
1857 return SELECT_PARTITION_PAGE
;
1861 if (CurrentPartition
== PartitionList
->SystemPartition
||
1862 IsPartitionActive(CurrentPartition
))
1864 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1867 return DELETE_PARTITION_PAGE
;
1871 return SELECT_PARTITION_PAGE
;
1875 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1876 /* Restriction for MaxSize */
1877 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1880 ShowPartitionSizeInputBox(SHORT Left
,
1904 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1909 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1910 iLeft
= coPos
.X
+ (USHORT
)strlen(Buffer
) + 1;
1913 WriteConsoleOutputCharacterA(StdOutput
,
1919 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1920 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1922 WriteConsoleOutputCharacterA(StdOutput
,
1928 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1929 Length
= wcslen(InputBuffer
);
1931 CONSOLE_SetInputTextXY(iLeft
,
1933 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1935 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1936 CONSOLE_SetCursorType(TRUE
, TRUE
);
1940 CONSOLE_ConInKey(&Ir
);
1942 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1943 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1948 InputBuffer
[0] = UNICODE_NULL
;
1949 CONSOLE_SetCursorType(TRUE
, FALSE
);
1952 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1954 CONSOLE_SetCursorType(TRUE
, FALSE
);
1957 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
1962 InputBuffer
[0] = UNICODE_NULL
;
1963 CONSOLE_SetCursorType(TRUE
, FALSE
);
1966 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1967 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1970 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1972 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1973 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1976 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1978 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1979 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1984 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1987 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1988 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1993 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1996 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1997 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
2001 memmove(&InputBuffer
[Pos
],
2002 &InputBuffer
[Pos
+ 1],
2003 (Length
- Pos
- 1) * sizeof(WCHAR
));
2004 InputBuffer
[Length
- 1] = UNICODE_NULL
;
2007 CONSOLE_SetInputTextXY(iLeft
,
2009 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2011 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2014 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
2019 memmove(&InputBuffer
[Pos
- 1],
2021 (Length
- Pos
) * sizeof(WCHAR
));
2022 InputBuffer
[Length
- 1] = UNICODE_NULL
;
2026 CONSOLE_SetInputTextXY(iLeft
,
2028 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2030 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2033 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
2035 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
2037 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
2039 if ((ch
>= L
'0') && (ch
<= L
'9'))
2042 memmove(&InputBuffer
[Pos
+ 1],
2044 (Length
- Pos
) * sizeof(WCHAR
));
2045 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
2046 InputBuffer
[Pos
] = ch
;
2050 CONSOLE_SetInputTextXY(iLeft
,
2052 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2054 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2063 * Displays the CreatePrimaryPartitionPage.
2066 * SelectPartitionPage
2067 * SelectFileSystemPage (default)
2071 * Number of the next page.
2074 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
2076 PPARTENTRY PartEntry
;
2077 PDISKENTRY DiskEntry
;
2082 ULONGLONG SectorCount
;
2083 WCHAR InputBuffer
[50];
2084 CHAR LineBuffer
[100];
2086 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2088 /* FIXME: show an error dialog */
2092 PartEntry
= CurrentPartition
;
2093 DiskEntry
= CurrentPartition
->DiskEntry
;
2095 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2097 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
2099 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2100 CONSOLE_PrintTextXY(6, 10, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2103 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2106 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2107 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2110 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2112 PartEntry
= CurrentPartition
;
2115 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2117 if (MaxSize
> PARTITION_MAXSIZE
)
2118 MaxSize
= PARTITION_MAXSIZE
;
2120 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2121 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2125 if (ConfirmQuit(Ir
))
2132 return SELECT_PARTITION_PAGE
;
2136 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2144 if (PartSize
> MaxSize
)
2150 /* Convert to bytes */
2151 if (PartSize
== MaxSize
)
2153 /* Use all of the unpartitioned disk space */
2154 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2158 /* Calculate the sector count from the size in MB */
2159 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2161 /* But never get larger than the unpartitioned disk space */
2162 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2163 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2166 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2168 CreatePrimaryPartition(PartitionList
,
2173 return SELECT_PARTITION_PAGE
;
2177 return CREATE_PRIMARY_PARTITION_PAGE
;
2182 * Displays the CreateExtendedPartitionPage.
2185 * SelectPartitionPage (default)
2189 * Number of the next page.
2192 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2194 PPARTENTRY PartEntry
;
2195 PDISKENTRY DiskEntry
;
2200 ULONGLONG SectorCount
;
2201 WCHAR InputBuffer
[50];
2202 CHAR LineBuffer
[100];
2204 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2206 /* FIXME: show an error dialog */
2210 PartEntry
= CurrentPartition
;
2211 DiskEntry
= CurrentPartition
->DiskEntry
;
2213 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2215 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2217 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2218 CONSOLE_PrintTextXY(6, 10, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2221 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2224 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2225 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2228 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2230 PartEntry
= CurrentPartition
;
2233 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2235 if (MaxSize
> PARTITION_MAXSIZE
)
2236 MaxSize
= PARTITION_MAXSIZE
;
2238 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2239 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2243 if (ConfirmQuit(Ir
))
2250 return SELECT_PARTITION_PAGE
;
2254 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2262 if (PartSize
> MaxSize
)
2268 /* Convert to bytes */
2269 if (PartSize
== MaxSize
)
2271 /* Use all of the unpartitioned disk space */
2272 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2276 /* Calculate the sector count from the size in MB */
2277 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2279 /* But never get larger than the unpartitioned disk space */
2280 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2281 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2284 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2286 CreateExtendedPartition(PartitionList
,
2290 return SELECT_PARTITION_PAGE
;
2294 return CREATE_EXTENDED_PARTITION_PAGE
;
2299 * Displays the CreateLogicalPartitionPage.
2302 * SelectFileSystemPage (default)
2306 * Number of the next page.
2309 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2311 PPARTENTRY PartEntry
;
2312 PDISKENTRY DiskEntry
;
2317 ULONGLONG SectorCount
;
2318 WCHAR InputBuffer
[50];
2319 CHAR LineBuffer
[100];
2321 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2323 /* FIXME: show an error dialog */
2327 PartEntry
= CurrentPartition
;
2328 DiskEntry
= CurrentPartition
->DiskEntry
;
2330 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2332 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2334 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2335 CONSOLE_PrintTextXY(6, 10, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2338 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2341 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2342 CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2345 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2347 PartEntry
= CurrentPartition
;
2350 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2352 if (MaxSize
> PARTITION_MAXSIZE
)
2353 MaxSize
= PARTITION_MAXSIZE
;
2355 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2356 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2360 if (ConfirmQuit(Ir
))
2367 return SELECT_PARTITION_PAGE
;
2371 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2379 if (PartSize
> MaxSize
)
2385 /* Convert to bytes */
2386 if (PartSize
== MaxSize
)
2388 /* Use all of the unpartitioned disk space */
2389 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2393 /* Calculate the sector count from the size in MB */
2394 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2396 /* But never get larger than the unpartitioned disk space */
2397 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2398 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2401 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2403 CreateLogicalPartition(PartitionList
,
2408 return SELECT_PARTITION_PAGE
;
2412 return CREATE_LOGICAL_PARTITION_PAGE
;
2417 * Displays the ConfirmDeleteSystemPartitionPage.
2420 * DeletePartitionPage (default)
2421 * SelectPartitionPage
2424 * Number of the next page.
2427 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2429 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2433 CONSOLE_ConInKey(Ir
);
2435 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2436 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2438 if (ConfirmQuit(Ir
))
2443 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2445 return DELETE_PARTITION_PAGE
;
2447 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2449 return SELECT_PARTITION_PAGE
;
2453 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2458 * Displays the DeletePartitionPage.
2461 * SelectPartitionPage (default)
2465 * Number of the next page.
2468 DeletePartitionPage(PINPUT_RECORD Ir
)
2470 PPARTENTRY PartEntry
;
2471 PDISKENTRY DiskEntry
;
2472 CHAR LineBuffer
[100];
2474 if (PartitionList
== NULL
|| CurrentPartition
== NULL
)
2476 /* FIXME: show an error dialog */
2480 PartEntry
= CurrentPartition
;
2481 DiskEntry
= CurrentPartition
->DiskEntry
;
2483 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2485 PartitionDescription(PartEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2486 CONSOLE_PrintTextXY(6, 10, " %s", LineBuffer
);
2488 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2489 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTDELETE_1
),
2494 CONSOLE_ConInKey(Ir
);
2496 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2497 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2499 if (ConfirmQuit(Ir
))
2504 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2506 return SELECT_PARTITION_PAGE
;
2508 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
2510 DeletePartition(PartitionList
,
2513 return SELECT_PARTITION_PAGE
;
2517 return DELETE_PARTITION_PAGE
;
2522 ResetFileSystemList(VOID
)
2524 if (!FileSystemList
)
2527 DestroyFileSystemList(FileSystemList
);
2528 FileSystemList
= NULL
;
2532 * Displays the SelectFileSystemPage.
2535 * CheckFileSystemPage (At once if RepairUpdate is selected)
2536 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2537 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2538 * SelectPartitionPage (If the user aborts)
2539 * FormatPartitionPage (Default)
2543 * Calls UpdatePartitionType()
2544 * Calls FindSupportedSystemPartition()
2547 * Number of the next page.
2550 SelectFileSystemPage(PINPUT_RECORD Ir
)
2552 PPARTENTRY PartEntry
;
2553 PDISKENTRY DiskEntry
;
2554 FORMATMACHINESTATE PreviousFormatState
;
2556 CHAR LineBuffer
[100];
2558 DPRINT("SelectFileSystemPage()\n");
2560 if (PartitionList
== NULL
|| InstallPartition
== NULL
)
2562 /* FIXME: show an error dialog */
2566 /* Find or set the active system partition when starting formatting */
2567 if (FormatState
== Start
)
2570 * If we install on a fixed disk, try to find a supported system
2571 * partition on the system. Otherwise if we install on a removable disk
2572 * use the install partition as the system partition.
2574 if (InstallPartition
->DiskEntry
->MediaType
== FixedMedia
)
2576 SystemPartition
= FindSupportedSystemPartition(PartitionList
,
2578 InstallPartition
->DiskEntry
,
2580 /* Use the original system partition as the old active partition hint */
2581 PartEntry
= PartitionList
->SystemPartition
;
2583 if ( SystemPartition
&& PartitionList
->SystemPartition
&&
2584 (SystemPartition
!= PartitionList
->SystemPartition
) )
2586 DPRINT1("We are using a different system partition!!!!\n");
2588 MUIDisplayPage(CHANGE_SYSTEM_PARTITION
);
2591 PPARTENTRY PartEntry
; // Shadow variable
2593 PartEntry
= PartitionList
->SystemPartition
;
2594 DiskEntry
= PartEntry
->DiskEntry
;
2596 PartitionDescription(PartEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2597 CONSOLE_SetTextXY(8, 10, LineBuffer
);
2599 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2600 CONSOLE_PrintTextXY(8, 14, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2604 PartEntry
= SystemPartition
;
2605 DiskEntry
= PartEntry
->DiskEntry
;
2607 PartitionDescription(PartEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2608 CONSOLE_SetTextXY(8, 23, LineBuffer
);
2613 CONSOLE_ConInKey(Ir
);
2615 if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2619 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2621 return SELECT_PARTITION_PAGE
;
2625 CONSOLE_ClearScreen();
2629 else // if (InstallPartition->DiskEntry->MediaType == RemovableMedia)
2631 SystemPartition
= InstallPartition
;
2632 /* Don't specify any old active partition hint */
2636 if (!SystemPartition
)
2638 /* FIXME: improve the error dialog */
2640 // Error dialog should say that we cannot find a suitable
2641 // system partition and create one on the system. At this point,
2642 // it may be nice to ask the user whether he wants to continue,
2643 // or use an external drive as the system drive/partition
2644 // (e.g. floppy, USB drive, etc...)
2646 PopupError("The ReactOS Setup could not find a supported system partition\n"
2647 "on your system or could not create a new one. Without such partition\n"
2648 "the Setup program cannot install ReactOS.\n"
2649 "Press ENTER to return to the partition selection list.",
2650 MUIGetString(STRING_CONTINUE
),
2651 Ir
, POPUP_WAIT_ENTER
);
2652 return SELECT_PARTITION_PAGE
;
2656 * If the system partition can be created in some
2657 * non-partitioned space, create it now.
2659 if (!SystemPartition
->IsPartitioned
)
2661 CreatePrimaryPartition(PartitionList
,
2663 0LL, // SystemPartition->SectorCount.QuadPart,
2665 ASSERT(SystemPartition
->IsPartitioned
);
2668 /* Set it as such */
2669 if (!SetActivePartition(PartitionList
, SystemPartition
, PartEntry
))
2671 DPRINT1("SetActivePartition(0x%p) failed?!\n", SystemPartition
);
2675 /* Commit all partition changes to all the disks */
2676 if (!WritePartitionsToDisk(PartitionList
))
2678 DPRINT("WritePartitionsToDisk() failed\n");
2679 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
2684 * In all cases, whether or not we are going to perform a formatting,
2685 * we must perform a filesystem check of both the system and the
2686 * installation partitions.
2688 InstallPartition
->NeedsCheck
= TRUE
;
2689 if (SystemPartition
!= InstallPartition
)
2690 SystemPartition
->NeedsCheck
= TRUE
;
2693 * In case we just repair an existing installation, or make
2694 * an unattended setup without formatting, just go to the
2695 * filesystem check step.
2697 if (RepairUpdateFlag
)
2698 return CHECK_FILE_SYSTEM_PAGE
;
2700 if (IsUnattendedSetup
&& !USetupData
.FormatPartition
)
2701 return CHECK_FILE_SYSTEM_PAGE
;
2704 // ASSERT(SystemPartition->IsPartitioned);
2706 /* Reset the filesystem list for each partition that is to be formatted */
2707 ResetFileSystemList();
2709 PreviousFormatState
= FormatState
;
2710 switch (FormatState
)
2715 * We start by formatting the system partition in case it is new
2716 * (it didn't exist before) and is not the same as the installation
2717 * partition. Otherwise we just require a filesystem check on it,
2718 * and start by formatting the installation partition instead.
2721 ASSERT(SystemPartition
->IsPartitioned
);
2723 if ((SystemPartition
!= InstallPartition
) &&
2724 (SystemPartition
->FormatState
== Unformatted
))
2726 TempPartition
= SystemPartition
;
2727 TempPartition
->NeedsCheck
= TRUE
;
2729 // TODO: Should we let the user using a custom file-system,
2730 // or should we always use FAT(32) for it?
2731 // For "compatibility", FAT(32) would be best indeed.
2733 FormatState
= FormatSystemPartition
;
2734 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2738 TempPartition
= InstallPartition
;
2739 TempPartition
->NeedsCheck
= TRUE
;
2741 if (SystemPartition
!= InstallPartition
)
2743 /* The system partition is separate, so it had better be formatted! */
2744 ASSERT((SystemPartition
->FormatState
== Preformatted
) ||
2745 (SystemPartition
->FormatState
== Formatted
));
2747 /* Require a filesystem check on the system partition too */
2748 SystemPartition
->NeedsCheck
= TRUE
;
2751 FormatState
= FormatInstallPartition
;
2752 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2757 case FormatSystemPartition
:
2759 TempPartition
= InstallPartition
;
2760 TempPartition
->NeedsCheck
= TRUE
;
2762 FormatState
= FormatInstallPartition
;
2763 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2767 case FormatInstallPartition
:
2768 case FormatOtherPartition
:
2770 if (GetNextUnformattedPartition(PartitionList
,
2774 FormatState
= FormatOtherPartition
;
2775 TempPartition
->NeedsCheck
= TRUE
;
2777 if (FormatState
== FormatInstallPartition
)
2778 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2780 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2784 FormatState
= FormatDone
;
2786 if (FormatState
== FormatInstallPartition
)
2787 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2789 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2791 return CHECK_FILE_SYSTEM_PAGE
;
2798 DPRINT1("FormatState: FormatDone\n");
2799 return CHECK_FILE_SYSTEM_PAGE
;
2804 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2810 PartEntry
= TempPartition
;
2811 DiskEntry
= TempPartition
->DiskEntry
;
2813 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
2815 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2817 if (PartEntry
->AutoCreate
)
2819 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2822 PartitionDescription(PartEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2823 CONSOLE_SetTextXY(8, 10, LineBuffer
);
2826 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2827 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2830 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2832 PartEntry
->AutoCreate
= FALSE
;
2834 else if (PartEntry
->New
)
2836 switch (FormatState
)
2838 case FormatSystemPartition
:
2839 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2842 case FormatInstallPartition
:
2843 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2846 case FormatOtherPartition
:
2847 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2855 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2856 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTCREATE_1
),
2859 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2863 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2865 PartitionDescription(PartEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2866 CONSOLE_SetTextXY(8, 10, LineBuffer
);
2868 DiskDescription(DiskEntry
, LineBuffer
, ARRAYSIZE(LineBuffer
));
2869 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTDELETE_1
),
2873 ASSERT(FileSystemList
== NULL
);
2875 if (IsUnattendedSetup
)
2877 ASSERT(USetupData
.FormatPartition
);
2879 switch (USetupData
.FsType
)
2881 /* 1 is for BtrFS */
2883 DefaultFs
= L
"BTRFS";
2886 /* If we don't understand input, default to FAT */
2894 /* By default select the "FAT" file system */
2898 /* Create the file system list */
2899 // TODO: Display only the FSes compatible with the selected partition!
2900 FileSystemList
= CreateFileSystemList(6, 26,
2902 PartEntry
->FormatState
== Unformatted
,
2904 if (FileSystemList
== NULL
)
2906 /* FIXME: show an error dialog */
2910 if (IsUnattendedSetup
)
2912 ASSERT(USetupData
.FormatPartition
);
2913 return FORMAT_PARTITION_PAGE
;
2916 DrawFileSystemList(FileSystemList
);
2920 CONSOLE_ConInKey(Ir
);
2922 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2923 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2925 if (ConfirmQuit(Ir
))
2927 /* Reset the filesystem list */
2928 ResetFileSystemList();
2934 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2936 /* Reset the formatter machine state */
2937 TempPartition
= NULL
;
2938 FormatState
= Start
;
2940 /* Reset the filesystem list */
2941 ResetFileSystemList();
2943 return SELECT_PARTITION_PAGE
;
2945 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2946 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2948 ScrollDownFileSystemList(FileSystemList
);
2950 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2951 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2953 ScrollUpFileSystemList(FileSystemList
);
2955 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2957 if (!FileSystemList
->Selected
->FileSystem
)
2959 ASSERT(!TempPartition
->New
&& TempPartition
->FormatState
!= Unformatted
);
2962 * Skip formatting this partition. We will also ignore
2963 * filesystem checks on it, unless it is either the system
2964 * or the installation partition.
2966 if (TempPartition
!= SystemPartition
&&
2967 TempPartition
!= InstallPartition
)
2969 PartEntry
->NeedsCheck
= FALSE
;
2972 return SELECT_FILE_SYSTEM_PAGE
;
2976 /* Format this partition */
2977 return FORMAT_PARTITION_PAGE
;
2982 FormatState
= PreviousFormatState
;
2984 return SELECT_FILE_SYSTEM_PAGE
;
2989 * Displays the FormatPartitionPage.
2992 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2993 * SelectPartitionPage (At once)
2997 * Sets InstallPartition->FormatState
2998 * Sets USetupData.DestinationRootPath
3001 * Number of the next page.
3004 FormatPartitionPage(PINPUT_RECORD Ir
)
3007 PPARTENTRY PartEntry
;
3008 PDISKENTRY DiskEntry
;
3009 PFILE_SYSTEM_ITEM SelectedFileSystem
;
3010 WCHAR PathBuffer
[MAX_PATH
];
3011 CHAR Buffer
[MAX_PATH
];
3013 DPRINT("FormatPartitionPage()\n");
3015 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
3017 if (PartitionList
== NULL
|| TempPartition
== NULL
)
3019 /* FIXME: show an error dialog */
3023 PartEntry
= TempPartition
;
3024 DiskEntry
= TempPartition
->DiskEntry
;
3026 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
3028 SelectedFileSystem
= FileSystemList
->Selected
;
3029 ASSERT(SelectedFileSystem
&& SelectedFileSystem
->FileSystem
);
3033 if (!IsUnattendedSetup
)
3034 CONSOLE_ConInKey(Ir
);
3036 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3037 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3039 if (ConfirmQuit(Ir
))
3041 /* Reset the filesystem list */
3042 ResetFileSystemList();
3048 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3051 * Remove the "Press ENTER to continue" message prompt when the ENTER
3052 * key is pressed as the user wants to begin the partition formatting.
3054 MUIClearStyledText(FORMAT_PARTITION_PAGE
, TEXT_ID_FORMAT_PROMPT
, TEXT_TYPE_REGULAR
);
3055 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3057 /* Format the partition */
3058 Status
= DoFormat(PartEntry
,
3059 SelectedFileSystem
->FileSystem
,
3060 SelectedFileSystem
->QuickFormat
);
3061 if (Status
== STATUS_PARTITION_FAILURE
)
3063 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3065 /* Reset the filesystem list */
3066 ResetFileSystemList();
3069 else if (Status
== STATUS_UNRECOGNIZED_VOLUME
)
3071 /* FIXME: show an error dialog */
3072 // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
3074 /* Reset the filesystem list */
3075 ResetFileSystemList();
3078 else if (Status
== STATUS_NOT_SUPPORTED
)
3080 RtlStringCbPrintfA(Buffer
,
3082 "Setup is currently unable to format a partition in %S.\n"
3084 " \x07 Press ENTER to continue Setup.\n"
3085 " \x07 Press F3 to quit Setup.",
3086 SelectedFileSystem
->FileSystem
);
3089 MUIGetString(STRING_QUITCONTINUE
),
3090 NULL
, POPUP_WAIT_NONE
);
3094 CONSOLE_ConInKey(Ir
);
3096 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3097 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3099 if (ConfirmQuit(Ir
))
3101 /* Reset the filesystem list */
3102 ResetFileSystemList();
3107 return SELECT_FILE_SYSTEM_PAGE
;
3110 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3112 return SELECT_FILE_SYSTEM_PAGE
;
3116 else if (!NT_SUCCESS(Status
))
3119 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3120 L
"\\Device\\Harddisk%lu\\Partition%lu",
3121 DiskEntry
->DiskNumber
,
3122 PartEntry
->PartitionNumber
);
3124 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3125 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3127 /* Reset the filesystem list */
3128 ResetFileSystemList();
3132 return SELECT_FILE_SYSTEM_PAGE
;
3136 return FORMAT_PARTITION_PAGE
;
3141 * Displays the CheckFileSystemPage.
3144 * InstallDirectoryPage (At once)
3148 * Inits or reloads FileSystemList
3151 * Number of the next page.
3154 CheckFileSystemPage(PINPUT_RECORD Ir
)
3157 PPARTENTRY PartEntry
;
3158 CHAR Buffer
[MAX_PATH
];
3160 MUIDisplayPage(CHECK_FILE_SYSTEM_PAGE
);
3162 if (PartitionList
== NULL
)
3164 /* FIXME: show an error dialog */
3168 if (!GetNextUncheckedPartition(PartitionList
, NULL
, &PartEntry
))
3170 return INSTALL_DIRECTORY_PAGE
;
3173 ASSERT(PartEntry
->IsPartitioned
&& PartEntry
->PartitionNumber
!= 0);
3175 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
3176 PartEntry
->PartitionType
, (*PartEntry
->FileSystem
? PartEntry
->FileSystem
: L
"n/a"));
3178 /* Check the partition */
3179 Status
= DoChkdsk(PartEntry
);
3180 if (Status
== STATUS_NOT_SUPPORTED
)
3183 * Partition checking is not supported with the current filesystem,
3184 * so disable FS checks on it.
3186 PartEntry
->NeedsCheck
= FALSE
;
3188 RtlStringCbPrintfA(Buffer
,
3190 "Setup is currently unable to check a partition formatted in %S.\n"
3192 " \x07 Press ENTER to continue Setup.\n"
3193 " \x07 Press F3 to quit Setup.",
3194 PartEntry
->FileSystem
);
3197 MUIGetString(STRING_QUITCONTINUE
),
3198 NULL
, POPUP_WAIT_NONE
);
3202 CONSOLE_ConInKey(Ir
);
3204 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3205 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3207 if (ConfirmQuit(Ir
))
3210 return CHECK_FILE_SYSTEM_PAGE
;
3212 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3214 return CHECK_FILE_SYSTEM_PAGE
;
3218 else if (!NT_SUCCESS(Status
))
3220 DPRINT1("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3222 RtlStringCbPrintfA(Buffer
,
3224 "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n",
3228 MUIGetString(STRING_CONTINUE
),
3229 Ir
, POPUP_WAIT_ENTER
);
3232 PartEntry
->NeedsCheck
= FALSE
;
3233 return CHECK_FILE_SYSTEM_PAGE
;
3239 IN PCWSTR InstallDir
)
3243 Length
= wcslen(InstallDir
);
3245 // TODO: Add check for 8.3 too.
3247 /* Path must be at least 2 characters long */
3251 /* Path must start with a backslash */
3252 // if (InstallDir[0] != L'\\')
3255 /* Path must not end with a backslash */
3256 if (InstallDir
[Length
- 1] == L
'\\')
3259 /* Path must not contain whitespace characters */
3260 for (i
= 0; i
< Length
; i
++)
3262 if (iswspace(InstallDir
[i
]))
3266 /* Path component must not end with a dot */
3267 for (i
= 0; i
< Length
; i
++)
3269 if (InstallDir
[i
] == L
'\\' && i
> 0)
3271 if (InstallDir
[i
- 1] == L
'.')
3276 if (InstallDir
[Length
- 1] == L
'.')
3284 * Displays the InstallDirectoryPage.
3291 * Number of the next page.
3294 InstallDirectoryPage(PINPUT_RECORD Ir
)
3299 WCHAR InstallDir
[MAX_PATH
];
3301 /* We do not need the filesystem list anymore */
3302 ResetFileSystemList();
3304 if (PartitionList
== NULL
|| InstallPartition
== NULL
)
3306 /* FIXME: show an error dialog */
3310 // if (IsUnattendedSetup)
3311 if (RepairUpdateFlag
)
3312 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3313 else if (USetupData
.InstallationDirectory
[0])
3314 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3316 wcscpy(InstallDir
, L
"\\ReactOS");
3319 * Check the validity of the predefined 'InstallDir'. If we are either
3320 * in unattended setup or in update/repair mode, and the installation path
3321 * is valid, just perform the installation. Otherwise (either in the case
3322 * of an invalid path, or we are in regular setup), display the UI and allow
3323 * the user to specify a new installation path.
3325 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3327 Status
= InitDestinationPaths(&USetupData
, InstallDir
, InstallPartition
);
3328 if (!NT_SUCCESS(Status
))
3330 DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status
);
3331 MUIDisplayError(ERROR_NO_BUILD_PATH
, Ir
, POPUP_WAIT_ENTER
);
3336 * Check whether the user attempts to install ReactOS within the
3337 * installation source directory, or in a subdirectory thereof.
3338 * If so, fail with an error.
3340 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3342 MUIDisplayError(ERROR_SOURCE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3343 return INSTALL_DIRECTORY_PAGE
;
3346 return PREPARE_COPY_PAGE
;
3349 Length
= wcslen(InstallDir
);
3352 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3353 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3354 CONSOLE_SetCursorXY(8 + Pos
, 11);
3355 CONSOLE_SetCursorType(TRUE
, TRUE
);
3359 CONSOLE_ConInKey(Ir
);
3361 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3362 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3364 CONSOLE_SetCursorType(TRUE
, FALSE
);
3366 if (ConfirmQuit(Ir
))
3369 CONSOLE_SetCursorType(TRUE
, TRUE
);
3372 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3373 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3377 memmove(&InstallDir
[Pos
],
3378 &InstallDir
[Pos
+ 1],
3379 (Length
- Pos
- 1) * sizeof(WCHAR
));
3380 InstallDir
[Length
- 1] = UNICODE_NULL
;
3383 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3384 CONSOLE_SetCursorXY(8 + Pos
, 11);
3387 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3388 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3391 CONSOLE_SetCursorXY(8 + Pos
, 11);
3393 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3394 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3397 CONSOLE_SetCursorXY(8 + Pos
, 11);
3399 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3400 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3405 CONSOLE_SetCursorXY(8 + Pos
, 11);
3408 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3409 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3414 CONSOLE_SetCursorXY(8 + Pos
, 11);
3417 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3419 CONSOLE_SetCursorType(TRUE
, FALSE
);
3422 * Check for the validity of the installation directory and pop up
3423 * an error if it is not the case. Then the user can fix its input.
3425 if (!IsValidPath(InstallDir
))
3427 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3428 return INSTALL_DIRECTORY_PAGE
;
3431 Status
= InitDestinationPaths(&USetupData
, InstallDir
, InstallPartition
);
3432 if (!NT_SUCCESS(Status
))
3434 DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status
);
3435 MUIDisplayError(ERROR_NO_BUILD_PATH
, Ir
, POPUP_WAIT_ENTER
);
3440 * Check whether the user attempts to install ReactOS within the
3441 * installation source directory, or in a subdirectory thereof.
3442 * If so, fail with an error.
3444 if (RtlPrefixUnicodeString(&USetupData
.SourcePath
, &USetupData
.DestinationPath
, TRUE
))
3446 MUIDisplayError(ERROR_SOURCE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3447 return INSTALL_DIRECTORY_PAGE
;
3450 return PREPARE_COPY_PAGE
;
3452 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3457 memmove(&InstallDir
[Pos
- 1],
3459 (Length
- Pos
) * sizeof(WCHAR
));
3460 InstallDir
[Length
- 1] = UNICODE_NULL
;
3464 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3465 CONSOLE_SetCursorXY(8 + Pos
, 11);
3468 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3472 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3473 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3476 memmove(&InstallDir
[Pos
+ 1],
3478 (Length
- Pos
) * sizeof(WCHAR
));
3479 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3480 InstallDir
[Pos
] = c
;
3484 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3485 CONSOLE_SetCursorXY(8 + Pos
, 11);
3491 return INSTALL_DIRECTORY_PAGE
;
3495 // PSETUP_ERROR_ROUTINE
3499 IN PUSETUP_DATA pSetupData
,
3505 va_start(arg_ptr
, pSetupData
);
3507 if (pSetupData
->LastErrorNumber
>= ERROR_SUCCESS
&&
3508 pSetupData
->LastErrorNumber
< ERROR_LAST_ERROR_CODE
)
3510 // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
3511 MUIDisplayErrorV(pSetupData
->LastErrorNumber
, &Ir
, POPUP_WAIT_ENTER
, arg_ptr
);
3518 * Displays the PrepareCopyPage.
3521 * FileCopyPage(At once)
3525 * Calls PrepareFileCopy
3528 * Number of the next page.
3531 PrepareCopyPage(PINPUT_RECORD Ir
)
3533 // ERROR_NUMBER ErrorNumber;
3536 MUIDisplayPage(PREPARE_COPY_PAGE
);
3538 /* ErrorNumber = */ Success
= PrepareFileCopy(&USetupData
, NULL
);
3539 if (/*ErrorNumber != ERROR_SUCCESS*/ !Success
)
3541 // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
3545 return FILE_COPY_PAGE
;
3548 typedef struct _COPYCONTEXT
3550 ULONG TotalOperations
;
3551 ULONG CompletedOperations
;
3552 PPROGRESSBAR ProgressBar
;
3553 PPROGRESSBAR MemoryBars
[4];
3554 } COPYCONTEXT
, *PCOPYCONTEXT
;
3557 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3560 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3562 /* Get the memory information from the system */
3563 NtQuerySystemInformation(SystemPerformanceInformation
,
3568 /* Check if this is initial setup */
3571 /* Set maximum limits to be total RAM pages */
3572 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3573 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3574 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3577 /* Set current values */
3578 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3579 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3580 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3585 FileCopyCallback(PVOID Context
,
3590 PCOPYCONTEXT CopyContext
= (PCOPYCONTEXT
)Context
;
3591 PFILEPATHS_W FilePathInfo
;
3592 PCWSTR SrcFileName
, DstFileName
;
3594 switch (Notification
)
3596 case SPFILENOTIFY_STARTSUBQUEUE
:
3598 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3599 CopyContext
->CompletedOperations
= 0;
3600 ProgressSetStepCount(CopyContext
->ProgressBar
,
3601 CopyContext
->TotalOperations
);
3602 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3606 case SPFILENOTIFY_STARTDELETE
:
3607 case SPFILENOTIFY_STARTRENAME
:
3608 case SPFILENOTIFY_STARTCOPY
:
3610 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3612 if (Notification
== SPFILENOTIFY_STARTDELETE
)
3614 /* Display delete message */
3615 ASSERT(Param2
== FILEOP_DELETE
);
3617 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3618 if (DstFileName
) ++DstFileName
;
3619 else DstFileName
= FilePathInfo
->Target
;
3621 CONSOLE_SetStatusText(MUIGetString(STRING_DELETING
),
3624 else if (Notification
== SPFILENOTIFY_STARTRENAME
)
3626 /* Display move/rename message */
3627 ASSERT(Param2
== FILEOP_RENAME
);
3629 SrcFileName
= wcsrchr(FilePathInfo
->Source
, L
'\\');
3630 if (SrcFileName
) ++SrcFileName
;
3631 else SrcFileName
= FilePathInfo
->Source
;
3633 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3634 if (DstFileName
) ++DstFileName
;
3635 else DstFileName
= FilePathInfo
->Target
;
3637 if (!wcsicmp(SrcFileName
, DstFileName
))
3638 Param2
= STRING_MOVING
;
3640 Param2
= STRING_RENAMING
;
3642 CONSOLE_SetStatusText(MUIGetString(Param2
),
3643 SrcFileName
, DstFileName
);
3645 else if (Notification
== SPFILENOTIFY_STARTCOPY
)
3647 /* Display copy message */
3648 ASSERT(Param2
== FILEOP_COPY
);
3650 /* NOTE: When extracting from CABs the Source is the CAB name */
3651 DstFileName
= wcsrchr(FilePathInfo
->Target
, L
'\\');
3652 if (DstFileName
) ++DstFileName
;
3653 else DstFileName
= FilePathInfo
->Target
;
3655 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
),
3657 #ifdef __REACTOS__ /* HACK */
3658 DoWatchDestFileName(DstFileName
);
3662 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3666 case SPFILENOTIFY_COPYERROR
:
3668 FilePathInfo
= (PFILEPATHS_W
)Param1
;
3670 DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n",
3671 FilePathInfo
->Target
, FilePathInfo
->Win32Error
);
3675 case SPFILENOTIFY_ENDDELETE
:
3676 case SPFILENOTIFY_ENDRENAME
:
3677 case SPFILENOTIFY_ENDCOPY
:
3679 CopyContext
->CompletedOperations
++;
3681 /* SYSREG checkpoint */
3682 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3683 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3685 ProgressNextStep(CopyContext
->ProgressBar
);
3686 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3696 * Displays the FileCopyPage.
3699 * RegistryPage(At once)
3705 * Number of the next page.
3708 FileCopyPage(PINPUT_RECORD Ir
)
3710 COPYCONTEXT CopyContext
;
3713 MUIDisplayPage(FILE_COPY_PAGE
);
3715 /* Create context for the copy process */
3716 CopyContext
.TotalOperations
= 0;
3717 CopyContext
.CompletedOperations
= 0;
3719 /* Create the progress bar as well */
3720 CopyContext
.ProgressBar
= CreateProgressBar(13,
3727 MUIGetString(STRING_SETUPCOPYINGFILES
));
3729 // fit memory bars to screen width, distribute them uniform
3730 MemBarWidth
= (xScreen
- 26) / 5;
3731 MemBarWidth
-= MemBarWidth
% 2; // make even
3732 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3733 /* Create the paged pool progress bar */
3734 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3743 /* Create the non paged pool progress bar */
3744 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (MemBarWidth
/ 2),
3746 (xScreen
/ 2) + (MemBarWidth
/ 2),
3748 (xScreen
/ 2)- (MemBarWidth
/ 2),
3753 /* Create the global memory progress bar */
3754 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - MemBarWidth
,
3758 xScreen
- 13 - MemBarWidth
,
3763 /* Do the file copying */
3764 DoFileCopy(&USetupData
, FileCopyCallback
, &CopyContext
);
3766 /* If we get here, we're done, so cleanup the progress bar */
3767 DestroyProgressBar(CopyContext
.ProgressBar
);
3768 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
3769 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
3770 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
3772 /* Create the $winnt$.inf file */
3773 InstallSetupInfFile(&USetupData
);
3775 /* Go display the next page */
3776 return REGISTRY_PAGE
;
3782 RegistryStatus(IN REGISTRY_STATUS RegStatus
, ...)
3784 /* WARNING: Please keep this lookup table in sync with the resources! */
3785 static const UINT StringIDs
[] =
3787 STRING_DONE
, /* Success */
3788 STRING_REGHIVEUPDATE
, /* RegHiveUpdate */
3789 STRING_IMPORTFILE
, /* ImportRegHive */
3790 STRING_DISPLAYSETTINGSUPDATE
, /* DisplaySettingsUpdate */
3791 STRING_LOCALESETTINGSUPDATE
, /* LocaleSettingsUpdate */
3792 STRING_ADDKBLAYOUTS
, /* KeybLayouts */
3793 STRING_KEYBOARDSETTINGSUPDATE
, /* KeybSettingsUpdate */
3794 STRING_CODEPAGEINFOUPDATE
, /* CodePageInfoUpdate */
3799 if (RegStatus
< ARRAYSIZE(StringIDs
))
3801 va_start(args
, RegStatus
);
3802 CONSOLE_SetStatusTextV(MUIGetString(StringIDs
[RegStatus
]), args
);
3807 CONSOLE_SetStatusText("Unknown status %d", RegStatus
);
3812 * Displays the RegistryPage.
3815 * SuccessPage (if RepairUpdate)
3816 * BootLoaderPage (default)
3820 * Calls UpdateRegistry
3823 * Number of the next page.
3826 RegistryPage(PINPUT_RECORD Ir
)
3830 MUIDisplayPage(REGISTRY_PAGE
);
3832 Error
= UpdateRegistry(&USetupData
,
3835 InstallPartition
->DriveLetter
,
3839 if (Error
!= ERROR_SUCCESS
)
3841 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
3846 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
3847 return BOOT_LOADER_PAGE
;
3853 * Displays the BootLoaderPage.
3856 * SuccessPage (if RepairUpdate)
3857 * BootLoaderHarddiskMbrPage
3858 * BootLoaderHarddiskVbrPage
3859 * BootLoaderFloppyPage
3864 * Calls RegInitializeRegistry
3865 * Calls ImportRegistryFile
3866 * Calls SetDefaultPagefile
3867 * Calls SetMountedDeviceValues
3870 * Number of the next page.
3873 BootLoaderPage(PINPUT_RECORD Ir
)
3876 WCHAR PathBuffer
[MAX_PATH
];
3878 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3880 /* We must have a supported system partition by now */
3881 ASSERT(SystemPartition
&& SystemPartition
->IsPartitioned
&& SystemPartition
->PartitionNumber
!= 0);
3883 RtlFreeUnicodeString(&USetupData
.SystemRootPath
);
3884 RtlStringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3885 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
3886 SystemPartition
->DiskEntry
->DiskNumber
,
3887 SystemPartition
->PartitionNumber
);
3888 RtlCreateUnicodeString(&USetupData
.SystemRootPath
, PathBuffer
);
3889 DPRINT1("SystemRootPath: %wZ\n", &USetupData
.SystemRootPath
);
3891 /* For unattended setup, skip MBR installation or install on floppy if needed */
3892 if (IsUnattendedSetup
)
3894 if ((USetupData
.MBRInstallType
== 0) ||
3895 (USetupData
.MBRInstallType
== 1))
3902 * We may install an MBR or VBR, but before that, check whether
3903 * we need to actually install the VBR on floppy/removable media
3904 * if the system partition is not recognized.
3906 if ((SystemPartition
->DiskEntry
->DiskStyle
!= PARTITION_STYLE_MBR
) ||
3907 !IsRecognizedPartition(SystemPartition
->PartitionType
))
3909 USetupData
.MBRInstallType
= 1;
3913 /* Is it an unattended install on hdd? */
3914 if (IsUnattendedSetup
)
3916 if ((USetupData
.MBRInstallType
== 2) ||
3917 (USetupData
.MBRInstallType
== 3))
3923 MUIDisplayPage(BOOT_LOADER_PAGE
);
3924 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3928 CONSOLE_ConInKey(Ir
);
3930 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3931 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
3933 CONSOLE_NormalTextXY(8, Line
, 60, 1);
3942 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3944 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3945 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
3947 CONSOLE_NormalTextXY(8, Line
, 60, 1);
3956 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3958 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3959 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3961 CONSOLE_NormalTextXY(8, Line
, 60, 1);
3965 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3967 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3968 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3970 CONSOLE_NormalTextXY(8, Line
, 60, 1);
3974 CONSOLE_InvertTextXY(8, Line
, 60, 1);
3976 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3977 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3979 if (ConfirmQuit(Ir
))
3984 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3988 /* Install on both MBR and VBR */
3989 USetupData
.MBRInstallType
= 2;
3992 else if (Line
== 13)
3994 /* Install on VBR only */
3995 USetupData
.MBRInstallType
= 3;
3998 else if (Line
== 14)
4000 /* Install on floppy */
4001 USetupData
.MBRInstallType
= 1;
4004 else if (Line
== 15)
4006 /* Skip MBR installation */
4007 USetupData
.MBRInstallType
= 0;
4011 return BOOT_LOADER_PAGE
;
4016 switch (USetupData
.MBRInstallType
)
4018 /* Skip MBR installation */
4020 return SUCCESS_PAGE
;
4022 /* Install on floppy */
4024 return BOOT_LOADER_FLOPPY_PAGE
;
4026 /* Install on both MBR and VBR or VBR only */
4029 return BOOT_LOADER_INSTALLATION_PAGE
;
4032 return BOOT_LOADER_PAGE
;
4037 * Displays the BootLoaderFloppyPage.
4040 * SuccessPage (At once)
4044 * Calls InstallFatBootcodeToFloppy()
4047 * Number of the next page.
4050 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4054 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4056 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4060 CONSOLE_ConInKey(Ir
);
4062 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4063 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4065 if (ConfirmQuit(Ir
))
4070 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4072 Status
= InstallFatBootcodeToFloppy(&USetupData
.SourceRootPath
,
4073 &USetupData
.DestinationArcPath
);
4074 if (!NT_SUCCESS(Status
))
4076 if (Status
== STATUS_DEVICE_NOT_READY
)
4077 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4079 /* TODO: Print error message */
4080 return BOOT_LOADER_FLOPPY_PAGE
;
4083 return SUCCESS_PAGE
;
4087 return BOOT_LOADER_FLOPPY_PAGE
;
4092 * Displays the BootLoaderInstallationPage.
4095 * SuccessPage (At once)
4099 * Calls InstallVBRToPartition() if VBR installation is chosen.
4100 * Otherwise both InstallVBRToPartition() and InstallMbrBootCodeToDisk()
4101 * are called if both MBR and VBR installation is chosen.
4104 * Number of the next page.
4107 BootLoaderInstallationPage(PINPUT_RECORD Ir
)
4110 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4112 MUIDisplayPage(BOOT_LOADER_INSTALLATION_PAGE
);
4114 if (USetupData
.MBRInstallType
== 2)
4116 /* Step 1: Write the VBR */
4117 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4118 &USetupData
.SourceRootPath
,
4119 &USetupData
.DestinationArcPath
,
4120 SystemPartition
->FileSystem
);
4121 if (!NT_SUCCESS(Status
))
4123 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4124 SystemPartition
->FileSystem
);
4128 /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
4129 if (!IsSuperFloppy(SystemPartition
->DiskEntry
))
4131 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4132 L
"\\Device\\Harddisk%d\\Partition0",
4133 SystemPartition
->DiskEntry
->DiskNumber
);
4134 Status
= InstallMbrBootCodeToDisk(&USetupData
.SystemRootPath
,
4135 &USetupData
.SourceRootPath
,
4136 DestinationDevicePathBuffer
);
4137 if (!NT_SUCCESS(Status
))
4139 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status
);
4140 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
, L
"MBR");
4147 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4148 &USetupData
.SourceRootPath
,
4149 &USetupData
.DestinationArcPath
,
4150 SystemPartition
->FileSystem
);
4151 if (!NT_SUCCESS(Status
))
4153 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
,
4154 SystemPartition
->FileSystem
);
4159 return SUCCESS_PAGE
;
4164 * @name ProgressTimeOutStringHandler
4166 * Handles the generation (displaying) of the timeout
4167 * countdown to the screen dynamically.
4170 * A pointer to a progress bar.
4172 * @param AlwaysUpdate
4173 * Constantly update the progress bar (boolean type).
4176 * A pointer to a string buffer.
4178 * @param cchBufferSize
4179 * The buffer's size in number of characters.
4182 * TRUE or FALSE on function termination.
4187 ProgressTimeOutStringHandler(
4188 IN PPROGRESSBAR Bar
,
4189 IN BOOLEAN AlwaysUpdate
,
4191 IN SIZE_T cchBufferSize
)
4193 ULONG OldProgress
= Bar
->Progress
;
4195 if (Bar
->StepCount
== 0)
4201 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4204 /* Build the progress string if it has changed */
4205 if (Bar
->ProgressFormatText
&&
4206 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4208 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4209 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4218 * @name ProgressCountdown
4220 * Displays and draws a red-coloured progress bar with a countdown.
4221 * When the timeout is reached, the flush page is displayed for reboot.
4224 * A pointer to an input keyboard record.
4227 * Initial countdown value in seconds.
4235 IN PINPUT_RECORD Ir
,
4239 ULONG StartTime
, BarWidth
, TimerDiv
;
4241 LONG TimerValue
, OldTimerValue
;
4242 LARGE_INTEGER Timeout
;
4243 PPROGRESSBAR ProgressBar
;
4244 BOOLEAN RefreshProgress
= TRUE
;
4246 /* Bail out if the timeout is already zero */
4250 /* Create the timeout progress bar and set it up */
4251 ProgressBar
= CreateProgressBarEx(13,
4258 FOREGROUND_RED
| BACKGROUND_BLUE
,
4261 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4262 ProgressTimeOutStringHandler
);
4264 BarWidth
= max(1, ProgressBar
->Width
);
4265 TimerValue
= TimeOut
* BarWidth
;
4266 ProgressSetStepCount(ProgressBar
, TimerValue
);
4268 StartTime
= NtGetTickCount();
4271 TimerDiv
= 1000 / BarWidth
;
4272 TimerDiv
= max(1, TimerDiv
);
4273 OldTimerValue
= TimerValue
;
4276 /* Decrease the timer */
4279 * Compute how much time the previous operations took.
4280 * This allows us in particular to take account for any time
4281 * elapsed if something slowed down.
4283 TimeElapsed
= NtGetTickCount() - StartTime
;
4284 if (TimeElapsed
>= TimerDiv
)
4286 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4287 TimeElapsed
/= TimerDiv
;
4288 StartTime
+= (TimerDiv
* TimeElapsed
);
4290 if (TimeElapsed
<= TimerValue
)
4291 TimerValue
-= TimeElapsed
;
4295 RefreshProgress
= TRUE
;
4298 if (RefreshProgress
)
4300 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4301 RefreshProgress
= FALSE
;
4304 /* Stop when the timer reaches zero */
4305 if (TimerValue
<= 0)
4308 /* Check for user key presses */
4311 * If the timer is used, use a passive wait of maximum 1 second
4312 * while monitoring for incoming console input events, so that
4313 * we are still able to display the timing count.
4316 /* Wait a maximum of 1 second for input events */
4317 TimeElapsed
= NtGetTickCount() - StartTime
;
4318 if (TimeElapsed
< TimerDiv
)
4320 /* Convert the time to NT format */
4321 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4322 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4326 Status
= STATUS_TIMEOUT
;
4329 /* Check whether the input event has been signaled, or a timeout happened */
4330 if (Status
== STATUS_TIMEOUT
)
4334 if (Status
!= STATUS_WAIT_0
)
4336 /* An error happened, bail out */
4337 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4341 /* Check for an ENTER key press */
4342 while (CONSOLE_ConInKeyPeek(Ir
))
4344 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4346 /* Found it, stop waiting */
4353 /* Destroy the progress bar and quit */
4354 DestroyProgressBar(ProgressBar
);
4359 * Displays the QuitPage.
4362 * FlushPage (At once)
4368 * Number of the next page.
4371 QuitPage(PINPUT_RECORD Ir
)
4373 MUIDisplayPage(QUIT_PAGE
);
4375 /* Destroy the NTOS installations list */
4376 if (NtOsInstallsList
!= NULL
)
4378 DestroyGenericList(NtOsInstallsList
, TRUE
);
4379 NtOsInstallsList
= NULL
;
4382 /* Destroy the partition list */
4383 if (PartitionList
!= NULL
)
4385 DestroyPartitionList(PartitionList
);
4386 PartitionList
= NULL
;
4389 /* Reset the formatter machine state */
4390 TempPartition
= NULL
;
4391 FormatState
= Start
;
4393 /* Destroy the filesystem list */
4394 ResetFileSystemList();
4396 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4398 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4399 ProgressCountdown(Ir
, 15);
4405 * Displays the SuccessPage.
4408 * FlushPage (At once)
4414 * Number of the next page.
4417 SuccessPage(PINPUT_RECORD Ir
)
4419 MUIDisplayPage(SUCCESS_PAGE
);
4421 if (IsUnattendedSetup
)
4424 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4425 ProgressCountdown(Ir
, 15);
4431 * Displays the FlushPage.
4434 * RebootPage (At once)
4437 * Number of the next page.
4440 FlushPage(PINPUT_RECORD Ir
)
4442 MUIDisplayPage(FLUSH_PAGE
);
4448 * The start routine and page management
4458 InfSetHeap(ProcessHeap
);
4460 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4461 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4462 if (!NT_SUCCESS(Status
))
4463 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
4465 /* Initialize the user-mode PnP manager */
4466 Status
= InitializeUserModePnpManager(&USetupData
.SetupInf
);
4467 if (!NT_SUCCESS(Status
))
4470 DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status
);
4473 if (!CONSOLE_Init())
4475 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4476 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4477 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4479 /* We failed to initialize the video, just quit the installer */
4480 return STATUS_APP_INIT_FAILURE
;
4483 /* Initialize Setup, phase 0 */
4484 InitializeSetup(&USetupData
, 0);
4485 USetupData
.ErrorRoutine
= USetupErrorRoutine
;
4487 /* Hide the cursor and clear the screen and keyboard buffer */
4488 CONSOLE_SetCursorType(TRUE
, FALSE
);
4489 CONSOLE_ClearScreen();
4492 /* Global Initialization page */
4493 Page
= SetupStartPage(&Ir
);
4495 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4497 CONSOLE_ClearScreen();
4500 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4506 Page
= LanguagePage(&Ir
);
4511 Page
= WelcomePage(&Ir
);
4516 Page
= LicensePage(&Ir
);
4520 case INSTALL_INTRO_PAGE
:
4521 Page
= InstallIntroPage(&Ir
);
4525 case SCSI_CONTROLLER_PAGE
:
4526 Page
= ScsiControllerPage(&Ir
);
4529 case OEM_DRIVER_PAGE
:
4530 Page
= OemDriverPage(&Ir
);
4534 case DEVICE_SETTINGS_PAGE
:
4535 Page
= DeviceSettingsPage(&Ir
);
4538 case COMPUTER_SETTINGS_PAGE
:
4539 Page
= ComputerSettingsPage(&Ir
);
4542 case DISPLAY_SETTINGS_PAGE
:
4543 Page
= DisplaySettingsPage(&Ir
);
4546 case KEYBOARD_SETTINGS_PAGE
:
4547 Page
= KeyboardSettingsPage(&Ir
);
4550 case LAYOUT_SETTINGS_PAGE
:
4551 Page
= LayoutSettingsPage(&Ir
);
4554 /* Partitioning pages */
4555 case SELECT_PARTITION_PAGE
:
4556 Page
= SelectPartitionPage(&Ir
);
4559 case CREATE_PRIMARY_PARTITION_PAGE
:
4560 Page
= CreatePrimaryPartitionPage(&Ir
);
4563 case CREATE_EXTENDED_PARTITION_PAGE
:
4564 Page
= CreateExtendedPartitionPage(&Ir
);
4567 case CREATE_LOGICAL_PARTITION_PAGE
:
4568 Page
= CreateLogicalPartitionPage(&Ir
);
4571 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4572 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4575 case DELETE_PARTITION_PAGE
:
4576 Page
= DeletePartitionPage(&Ir
);
4579 /* Filesystem partition operations pages */
4580 case SELECT_FILE_SYSTEM_PAGE
:
4581 Page
= SelectFileSystemPage(&Ir
);
4584 case FORMAT_PARTITION_PAGE
:
4585 Page
= FormatPartitionPage(&Ir
);
4588 case CHECK_FILE_SYSTEM_PAGE
:
4589 Page
= CheckFileSystemPage(&Ir
);
4592 /* Installation pages */
4593 case INSTALL_DIRECTORY_PAGE
:
4594 Page
= InstallDirectoryPage(&Ir
);
4597 case PREPARE_COPY_PAGE
:
4598 Page
= PrepareCopyPage(&Ir
);
4601 case FILE_COPY_PAGE
:
4602 Page
= FileCopyPage(&Ir
);
4606 Page
= RegistryPage(&Ir
);
4609 /* Bootloader installation pages */
4610 case BOOT_LOADER_PAGE
:
4611 Page
= BootLoaderPage(&Ir
);
4614 case BOOT_LOADER_FLOPPY_PAGE
:
4615 Page
= BootLoaderFloppyPage(&Ir
);
4618 case BOOT_LOADER_INSTALLATION_PAGE
:
4619 Page
= BootLoaderInstallationPage(&Ir
);
4623 case REPAIR_INTRO_PAGE
:
4624 Page
= RepairIntroPage(&Ir
);
4627 case UPGRADE_REPAIR_PAGE
:
4628 Page
= UpgradeRepairPage(&Ir
);
4632 Page
= SuccessPage(&Ir
);
4636 Page
= FlushPage(&Ir
);
4640 Page
= QuitPage(&Ir
);
4644 case SETUP_INIT_PAGE
:
4654 /* Terminate the user-mode PnP manager */
4655 TerminateUserModePnpManager();
4657 /* Setup has finished */
4658 FinishSetup(&USetupData
);
4660 if (Page
== RECOVERY_PAGE
)
4666 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4667 NtShutdownSystem(ShutdownReboot
);
4668 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4670 return STATUS_SUCCESS
;
4675 NtProcessStartup(PPEB Peb
)
4680 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4682 ProcessHeap
= Peb
->ProcessHeap
;
4684 NtQuerySystemTime(&Time
);
4686 Status
= RunUSetup();
4688 if (NT_SUCCESS(Status
))
4691 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
4692 * a protective waiting.
4693 * This wait is needed because, since we are started as SMSS.EXE,
4694 * the NT kernel explicitly waits 5 seconds for the initial process
4695 * SMSS.EXE to initialize (as a protective measure), and otherwise
4696 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
4698 Time
.QuadPart
+= 50000000;
4699 NtDelayExecution(FALSE
, &Time
);
4703 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
4704 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4705 0, 0, NULL
, 0, NULL
);
4708 NtTerminateProcess(NtCurrentProcess(), Status
);