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 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
44 /* GLOBALS & LOCALS *********************************************************/
48 BOOLEAN IsUnattendedSetup
= FALSE
;
49 static USETUP_DATA USetupData
;
52 * NOTE: Technically only used for the COPYCONTEXT InstallPath member
53 * for the filequeue functionality.
55 static UNICODE_STRING InstallPath
;
57 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
58 static WCHAR DestinationDriveLetter
;
63 PWCHAR SelectedLanguageId
;
64 static WCHAR DefaultLanguage
[20]; // Copy of string inside LanguageList
65 static WCHAR DefaultKBLayout
[20]; // Copy of string inside KeyboardList
67 static BOOLEAN RepairUpdateFlag
= FALSE
;
69 static HANDLE hPnpThread
= NULL
;
71 static PPARTLIST PartitionList
= NULL
;
72 static PPARTENTRY TempPartition
= NULL
;
73 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
74 static FORMATMACHINESTATE FormatState
= Start
;
76 /*****************************************************/
80 static HSPFILEQ SetupFileQueue
= NULL
;
82 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
83 static PGENERIC_LIST NtOsInstallsList
= NULL
;
85 static PGENERIC_LIST ComputerList
= NULL
;
86 static PGENERIC_LIST DisplayList
= NULL
;
87 static PGENERIC_LIST KeyboardList
= NULL
;
88 static PGENERIC_LIST LayoutList
= NULL
;
89 static PGENERIC_LIST LanguageList
= NULL
;
92 /* FUNCTIONS ****************************************************************/
95 PrintString(char* fmt
,...)
99 UNICODE_STRING UnicodeString
;
100 ANSI_STRING AnsiString
;
103 vsprintf(buffer
, fmt
, ap
);
106 RtlInitAnsiString(&AnsiString
, buffer
);
107 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
108 NtDisplayString(&UnicodeString
);
109 RtlFreeUnicodeString(&UnicodeString
);
114 DrawBox(IN SHORT xLeft
,
122 /* Draw upper left corner */
125 FillConsoleOutputCharacterA(StdOutput
,
131 /* Draw upper edge */
134 FillConsoleOutputCharacterA(StdOutput
,
140 /* Draw upper right corner */
141 coPos
.X
= xLeft
+ Width
- 1;
143 FillConsoleOutputCharacterA(StdOutput
,
149 /* Draw right edge, inner space and left edge */
150 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
153 FillConsoleOutputCharacterA(StdOutput
,
160 FillConsoleOutputCharacterA(StdOutput
,
166 coPos
.X
= xLeft
+ Width
- 1;
167 FillConsoleOutputCharacterA(StdOutput
,
174 /* Draw lower left corner */
176 coPos
.Y
= yTop
+ Height
- 1;
177 FillConsoleOutputCharacterA(StdOutput
,
183 /* Draw lower edge */
185 coPos
.Y
= yTop
+ Height
- 1;
186 FillConsoleOutputCharacterA(StdOutput
,
192 /* Draw lower right corner */
193 coPos
.X
= xLeft
+ Width
- 1;
194 coPos
.Y
= yTop
+ Height
- 1;
195 FillConsoleOutputCharacterA(StdOutput
,
204 PopupError(PCCH Text
,
222 /* Count text lines and longest line */
229 p
= strchr(pnext
, '\n');
233 Length
= strlen(pnext
);
238 Length
= (ULONG
)(p
- pnext
);
244 if (Length
> MaxLength
)
253 /* Check length of status line */
256 Length
= strlen(Status
);
258 if (Length
> MaxLength
)
262 Width
= MaxLength
+ 4;
268 yTop
= (yScreen
- Height
) / 2;
269 xLeft
= (xScreen
- Width
) / 2;
272 /* Set screen attributes */
274 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
276 FillConsoleOutputAttribute(StdOutput
,
277 FOREGROUND_RED
| BACKGROUND_WHITE
,
283 DrawBox(xLeft
, yTop
, Width
, Height
);
285 /* Print message text */
290 p
= strchr(pnext
, '\n');
294 Length
= strlen(pnext
);
299 Length
= (ULONG
)(p
- pnext
);
306 WriteConsoleOutputCharacterA(StdOutput
,
320 /* Print separator line and status text */
323 coPos
.Y
= yTop
+ Height
- 3;
325 FillConsoleOutputCharacterA(StdOutput
,
332 FillConsoleOutputCharacterA(StdOutput
,
338 coPos
.X
= xLeft
+ Width
- 1;
339 FillConsoleOutputCharacterA(StdOutput
,
347 WriteConsoleOutputCharacterA(StdOutput
,
349 min(strlen(Status
), (SIZE_T
)Width
- 4),
354 if (WaitEvent
== POPUP_WAIT_NONE
)
359 CONSOLE_ConInKey(Ir
);
361 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
362 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
374 * FALSE: Don't quit setup.
377 ConfirmQuit(PINPUT_RECORD Ir
)
380 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
384 CONSOLE_ConInKey(Ir
);
386 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
387 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
392 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
406 PGENERIC_LIST_ENTRY ListEntry
;
407 LPCWSTR pszNewLayout
;
409 pszNewLayout
= MUIDefaultKeyboardLayout();
411 if (LayoutList
== NULL
)
413 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
414 if (LayoutList
== NULL
)
416 /* FIXME: Handle error! */
421 ListEntry
= GetFirstListEntry(LayoutList
);
423 /* Search for default layout (if provided) */
424 if (pszNewLayout
!= NULL
)
426 while (ListEntry
!= NULL
)
428 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
430 SetCurrentListEntry(LayoutList
, ListEntry
);
434 ListEntry
= GetNextListEntry(ListEntry
);
441 * Displays the LanguagePage.
443 * Next pages: WelcomePage, QuitPage
446 * Init SelectedLanguageId
447 * Init USetupData.LanguageId
450 * Number of the next page.
453 LanguagePage(PINPUT_RECORD Ir
)
455 GENERIC_LIST_UI ListUi
;
456 PWCHAR NewLanguageId
;
457 BOOL RefreshPage
= FALSE
;
459 /* Initialize the computer settings list */
460 if (LanguageList
== NULL
)
462 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
463 if (LanguageList
== NULL
)
465 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
471 USetupData
.LanguageId
= 0;
472 SelectedLanguageId
= DefaultLanguage
;
473 SetConsoleCodePage();
476 /* If there's just a single language in the list skip
477 * the language selection process altogether! */
478 if (GenericListHasSingleEntry(LanguageList
))
480 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
484 InitGenericListUi(&ListUi
, LanguageList
);
485 DrawGenericList(&ListUi
,
491 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
493 MUIDisplayPage(LANGUAGE_PAGE
);
497 CONSOLE_ConInKey(Ir
);
499 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
500 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
502 ScrollDownGenericList(&ListUi
);
505 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
506 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
508 ScrollUpGenericList(&ListUi
);
511 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
512 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
514 ScrollPageDownGenericList(&ListUi
);
517 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
518 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
520 ScrollPageUpGenericList(&ListUi
);
523 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
524 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
529 RedrawGenericList(&ListUi
);
531 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
533 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
535 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
537 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
543 SetConsoleCodePage();
547 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
550 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
556 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
558 if (SelectedLanguageId
!= NewLanguageId
)
560 /* Clear the language page */
561 MUIClearPage(LANGUAGE_PAGE
);
563 SelectedLanguageId
= NewLanguageId
;
566 SetConsoleCodePage();
568 /* Redraw language selection page in native language */
569 MUIDisplayPage(LANGUAGE_PAGE
);
584 * LanguagePage (at once, default)
585 * InstallIntroPage (at once, if unattended)
590 * Init USetupData.SourcePath
591 * Init USetupData.SourceRootPath
592 * Init USetupData.SourceRootDir
594 * Init USetupData.RequiredPartitionDiskSpace
595 * Init IsUnattendedSetup
596 * If unattended, init *List and sets the Codepage
597 * If unattended, init SelectedLanguageId
598 * If unattended, init USetupData.LanguageId
601 * Number of the next page.
604 SetupStartPage(PINPUT_RECORD Ir
)
608 PGENERIC_LIST_ENTRY ListEntry
;
610 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
612 /* Get the source path and source root path */
613 Status
= GetSourcePaths(&USetupData
.SourcePath
,
614 &USetupData
.SourceRootPath
,
615 &USetupData
.SourceRootDir
);
616 if (!NT_SUCCESS(Status
))
618 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
619 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
622 DPRINT1("SourcePath: '%wZ'\n", &USetupData
.SourcePath
);
623 DPRINT1("SourceRootPath: '%wZ'\n", &USetupData
.SourceRootPath
);
624 DPRINT1("SourceRootDir: '%wZ'\n", &USetupData
.SourceRootDir
);
626 /* Load 'txtsetup.sif' from the installation media */
627 Error
= LoadSetupInf(&SetupInf
, &USetupData
);
628 if (Error
!= ERROR_SUCCESS
)
630 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ENTER
);
634 /* Start the PnP thread */
635 if (hPnpThread
!= NULL
)
637 NtResumeThread(hPnpThread
, NULL
);
641 CheckUnattendedSetup(&USetupData
);
643 if (IsUnattendedSetup
)
645 // TODO: Read options from inf
646 ComputerList
= CreateComputerTypeList(SetupInf
);
647 DisplayList
= CreateDisplayDriverList(SetupInf
);
648 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
649 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
650 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
653 wcscpy(SelectedLanguageId
, USetupData
.LocaleID
);
654 USetupData
.LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
656 /* first we hack LanguageList */
657 ListEntry
= GetFirstListEntry(LanguageList
);
658 while (ListEntry
!= NULL
)
660 if (!wcsicmp(USetupData
.LocaleID
, GetListEntryUserData(ListEntry
)))
662 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
663 SetCurrentListEntry(LanguageList
, ListEntry
);
667 ListEntry
= GetNextListEntry(ListEntry
);
671 ListEntry
= GetFirstListEntry(LayoutList
);
672 while (ListEntry
!= NULL
)
674 if (!wcsicmp(USetupData
.LocaleID
, GetListEntryUserData(ListEntry
)))
676 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
677 SetCurrentListEntry(LayoutList
, ListEntry
);
681 ListEntry
= GetNextListEntry(ListEntry
);
684 SetConsoleCodePage();
686 return INSTALL_INTRO_PAGE
;
689 return LANGUAGE_PAGE
;
694 * Displays the WelcomePage.
697 * InstallIntroPage (default)
704 * Number of the next page.
707 WelcomePage(PINPUT_RECORD Ir
)
709 MUIDisplayPage(WELCOME_PAGE
);
713 CONSOLE_ConInKey(Ir
);
715 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
716 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
723 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
725 return INSTALL_INTRO_PAGE
;
727 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
729 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
731 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
742 * Displays the License page.
745 * WelcomePage (default)
748 * Number of the next page.
751 LicensePage(PINPUT_RECORD Ir
)
753 MUIDisplayPage(LICENSE_PAGE
);
757 CONSOLE_ConInKey(Ir
);
759 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
770 * Displays the RepairIntroPage.
773 * RebootPage (default)
779 * Number of the next page.
782 RepairIntroPage(PINPUT_RECORD Ir
)
784 MUIDisplayPage(REPAIR_INTRO_PAGE
);
788 CONSOLE_ConInKey(Ir
);
790 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
794 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
796 RepairUpdateFlag
= TRUE
;
797 return INSTALL_INTRO_PAGE
;
799 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
801 return RECOVERY_PAGE
;
803 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
804 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
810 return REPAIR_INTRO_PAGE
;
814 * Displays the UpgradeRepairPage.
817 * RebootPage (default)
823 * Number of the next page.
826 UpgradeRepairPage(PINPUT_RECORD Ir
)
828 GENERIC_LIST_UI ListUi
;
831 if (PartitionList
== NULL
)
833 PartitionList
= CreatePartitionList();
834 if (PartitionList
== NULL
)
836 /* FIXME: show an error dialog */
837 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
840 else if (IsListEmpty(&PartitionList
->DiskListHead
))
842 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
846 TempPartition
= NULL
;
851 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
852 if (!NtOsInstallsList
)
853 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
854 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
856 RepairUpdateFlag
= FALSE
;
858 // return INSTALL_INTRO_PAGE;
859 return DEVICE_SETTINGS_PAGE
;
860 // return SCSI_CONTROLLER_PAGE;
863 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
865 InitGenericListUi(&ListUi
, NtOsInstallsList
);
866 DrawGenericList(&ListUi
,
871 SaveGenericListState(NtOsInstallsList
);
873 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
876 CONSOLE_ConInKey(Ir
);
878 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
880 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
882 case VK_DOWN
: /* DOWN */
883 ScrollDownGenericList(&ListUi
);
886 ScrollUpGenericList(&ListUi
);
888 case VK_NEXT
: /* PAGE DOWN */
889 ScrollPageDownGenericList(&ListUi
);
891 case VK_PRIOR
: /* PAGE UP */
892 ScrollPageUpGenericList(&ListUi
);
899 RedrawGenericList(&ListUi
);
902 case VK_ESCAPE
: /* ESC */
904 RestoreGenericListState(NtOsInstallsList
);
905 // return nextPage; // prevPage;
907 // return INSTALL_INTRO_PAGE;
908 return DEVICE_SETTINGS_PAGE
;
909 // return SCSI_CONTROLLER_PAGE;
915 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
916 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
917 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
919 /* Retrieve the current installation */
920 CurrentInstallation
= (PNTOS_INSTALLATION
)GetListEntryUserData(GetCurrentListEntry(NtOsInstallsList
));
921 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
922 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
924 RepairUpdateFlag
= TRUE
;
927 /***/return INSTALL_INTRO_PAGE
;/***/
929 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
930 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
932 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
937 return UPGRADE_REPAIR_PAGE
;
942 * Displays the InstallIntroPage.
945 * DeviceSettingsPage (At once if repair or update is selected)
946 * SelectPartitionPage (At once if unattended setup)
947 * DeviceSettingsPage (default)
951 * Number of the next page.
954 InstallIntroPage(PINPUT_RECORD Ir
)
956 if (RepairUpdateFlag
)
958 #if 1 /* Old code that looks good */
960 // return SELECT_PARTITION_PAGE;
961 return DEVICE_SETTINGS_PAGE
;
963 #else /* Possible new code? */
965 return DEVICE_SETTINGS_PAGE
;
966 // return SCSI_CONTROLLER_PAGE;
971 if (IsUnattendedSetup
)
972 return SELECT_PARTITION_PAGE
;
974 MUIDisplayPage(INSTALL_INTRO_PAGE
);
978 CONSOLE_ConInKey(Ir
);
980 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
981 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
988 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
990 return UPGRADE_REPAIR_PAGE
;
994 return INSTALL_INTRO_PAGE
;
1000 ScsiControllerPage(PINPUT_RECORD Ir
)
1002 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1004 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1006 /* FIXME: print loaded mass storage driver descriptions */
1008 CONSOLE_SetTextXY(8, 10, "TEST device");
1011 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1015 CONSOLE_ConInKey(Ir
);
1017 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1018 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1020 if (ConfirmQuit(Ir
))
1025 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1027 return DEVICE_SETTINGS_PAGE
;
1031 return SCSI_CONTROLLER_PAGE
;
1035 OemDriverPage(PINPUT_RECORD Ir
)
1037 // MUIDisplayPage(OEM_DRIVER_PAGE);
1039 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1041 /* FIXME: Implement!! */
1043 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1047 CONSOLE_ConInKey(Ir
);
1049 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1050 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1052 if (ConfirmQuit(Ir
))
1057 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1059 return DEVICE_SETTINGS_PAGE
;
1063 return OEM_DRIVER_PAGE
;
1069 * Displays the DeviceSettingsPage.
1072 * SelectPartitionPage (At once if repair or update is selected)
1073 * ComputerSettingsPage
1074 * DisplaySettingsPage
1075 * KeyboardSettingsPage
1076 * LayoutsettingsPage
1077 * SelectPartitionPage
1087 * Number of the next page.
1090 DeviceSettingsPage(PINPUT_RECORD Ir
)
1092 static ULONG Line
= 16;
1094 /* Initialize the computer settings list */
1095 if (ComputerList
== NULL
)
1097 ComputerList
= CreateComputerTypeList(SetupInf
);
1098 if (ComputerList
== NULL
)
1100 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1105 /* Initialize the display settings list */
1106 if (DisplayList
== NULL
)
1108 DisplayList
= CreateDisplayDriverList(SetupInf
);
1109 if (DisplayList
== NULL
)
1111 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1116 /* Initialize the keyboard settings list */
1117 if (KeyboardList
== NULL
)
1119 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1120 if (KeyboardList
== NULL
)
1122 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1127 /* Initialize the keyboard layout list */
1128 if (LayoutList
== NULL
)
1130 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1131 if (LayoutList
== NULL
)
1133 /* FIXME: report error */
1134 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1139 if (RepairUpdateFlag
)
1140 return SELECT_PARTITION_PAGE
;
1142 // if (IsUnattendedSetup)
1143 // return SELECT_PARTITION_PAGE;
1145 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1147 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry(ComputerList
)));
1148 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry(DisplayList
)));
1149 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry(KeyboardList
)));
1150 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry(LayoutList
)));
1152 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1156 CONSOLE_ConInKey(Ir
);
1158 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1159 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1161 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1165 else if (Line
== 16)
1170 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1172 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1173 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1175 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1179 else if (Line
== 16)
1184 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1186 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1187 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1189 if (ConfirmQuit(Ir
))
1194 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1197 return COMPUTER_SETTINGS_PAGE
;
1198 else if (Line
== 12)
1199 return DISPLAY_SETTINGS_PAGE
;
1200 else if (Line
== 13)
1201 return KEYBOARD_SETTINGS_PAGE
;
1202 else if (Line
== 14)
1203 return LAYOUT_SETTINGS_PAGE
;
1204 else if (Line
== 16)
1205 return SELECT_PARTITION_PAGE
;
1209 return DEVICE_SETTINGS_PAGE
;
1214 * Handles generic selection lists.
1217 * GenericList: The list to handle.
1218 * nextPage: The page it needs to jump to after this page.
1219 * Ir: The PINPUT_RECORD
1222 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1223 PAGE_NUMBER nextPage
,
1228 CONSOLE_ConInKey(Ir
);
1230 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1231 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1233 ScrollDownGenericList(ListUi
);
1235 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1236 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1238 ScrollUpGenericList(ListUi
);
1240 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1241 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1243 ScrollPageDownGenericList(ListUi
);
1245 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1246 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1248 ScrollPageUpGenericList(ListUi
);
1250 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1251 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1253 if (ConfirmQuit(Ir
))
1256 RedrawGenericList(ListUi
);
1258 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1259 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1261 RestoreGenericListState(ListUi
->List
);
1262 return nextPage
; // Use some "prevPage;" instead?
1264 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1268 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1271 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1278 * Displays the ComputerSettingsPage.
1281 * DeviceSettingsPage
1285 * Number of the next page.
1288 ComputerSettingsPage(PINPUT_RECORD Ir
)
1290 GENERIC_LIST_UI ListUi
;
1291 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1293 InitGenericListUi(&ListUi
, ComputerList
);
1294 DrawGenericList(&ListUi
,
1300 SaveGenericListState(ComputerList
);
1302 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1307 * Displays the DisplaySettingsPage.
1310 * DeviceSettingsPage
1314 * Number of the next page.
1317 DisplaySettingsPage(PINPUT_RECORD Ir
)
1319 GENERIC_LIST_UI ListUi
;
1320 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1322 InitGenericListUi(&ListUi
, DisplayList
);
1323 DrawGenericList(&ListUi
,
1329 SaveGenericListState(DisplayList
);
1331 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1336 * Displays the KeyboardSettingsPage.
1339 * DeviceSettingsPage
1343 * Number of the next page.
1346 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1348 GENERIC_LIST_UI ListUi
;
1349 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1351 InitGenericListUi(&ListUi
, KeyboardList
);
1352 DrawGenericList(&ListUi
,
1358 SaveGenericListState(KeyboardList
);
1360 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1365 * Displays the LayoutSettingsPage.
1368 * DeviceSettingsPage
1372 * Number of the next page.
1375 LayoutSettingsPage(PINPUT_RECORD Ir
)
1377 GENERIC_LIST_UI ListUi
;
1378 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1380 InitGenericListUi(&ListUi
, LayoutList
);
1381 DrawGenericList(&ListUi
,
1387 SaveGenericListState(LayoutList
);
1389 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1394 IsDiskSizeValid(PPARTENTRY PartEntry
)
1398 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1399 size
= (size
+ (512 * KB
)) / MB
; /* in MBytes */
1401 if (size
< USetupData
.RequiredPartitionDiskSpace
)
1403 /* Partition is too small so ask for another one */
1404 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, USetupData
.RequiredPartitionDiskSpace
);
1415 * Displays the SelectPartitionPage.
1418 * SelectFileSystemPage (At once if unattended)
1419 * SelectFileSystemPage (Default if free space is selected)
1420 * CreatePrimaryPartitionPage
1421 * CreateExtendedPartitionPage
1422 * CreateLogicalPartitionPage
1423 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1424 * DeletePartitionPage
1428 * Set InstallShortcut (only if not unattended + free space is selected)
1431 * Number of the next page.
1434 SelectPartitionPage(PINPUT_RECORD Ir
)
1439 if (PartitionList
== NULL
)
1441 PartitionList
= CreatePartitionList();
1442 if (PartitionList
== NULL
)
1444 /* FIXME: show an error dialog */
1445 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1448 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1450 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1454 TempPartition
= NULL
;
1455 FormatState
= Start
;
1458 if (RepairUpdateFlag
)
1460 /* Determine the selected installation disk & partition */
1461 if (!SelectPartition(PartitionList
,
1462 CurrentInstallation
->DiskNumber
,
1463 CurrentInstallation
->PartitionNumber
))
1465 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1469 return SELECT_FILE_SYSTEM_PAGE
;
1472 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1474 InitPartitionListUi(&ListUi
, PartitionList
,
1479 DrawPartitionList(&ListUi
);
1481 if (IsUnattendedSetup
)
1483 if (!SelectPartition(PartitionList
,
1484 USetupData
.DestinationDiskNumber
,
1485 USetupData
.DestinationPartitionNumber
))
1487 if (USetupData
.AutoPartition
)
1489 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1491 CreateLogicalPartition(PartitionList
,
1492 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1497 CreatePrimaryPartition(PartitionList
,
1498 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1502 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1503 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1505 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1506 USetupData
.RequiredPartitionDiskSpace
);
1507 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1510 return SELECT_FILE_SYSTEM_PAGE
;
1515 DrawPartitionList(&ListUi
);
1517 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1518 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1520 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1521 USetupData
.RequiredPartitionDiskSpace
);
1522 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1525 return SELECT_FILE_SYSTEM_PAGE
;
1531 /* Update status text */
1532 if (PartitionList
->CurrentPartition
== NULL
)
1534 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1536 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1538 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1540 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1544 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1549 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1551 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1553 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1557 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1562 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1566 CONSOLE_ConInKey(Ir
);
1568 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1569 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1571 if (ConfirmQuit(Ir
))
1573 DestroyPartitionList(PartitionList
);
1574 PartitionList
= NULL
;
1580 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1581 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1583 ScrollDownPartitionList(&ListUi
);
1585 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1586 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1588 ScrollUpPartitionList(&ListUi
);
1590 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1592 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1593 continue; // return SELECT_PARTITION_PAGE;
1595 if (PartitionList
->CurrentPartition
== NULL
||
1596 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1598 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1600 CreateLogicalPartition(PartitionList
,
1606 CreatePrimaryPartition(PartitionList
,
1612 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1614 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1615 USetupData
.RequiredPartitionDiskSpace
);
1616 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1619 return SELECT_FILE_SYSTEM_PAGE
;
1621 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1623 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1625 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1626 if (Error
!= NOT_AN_ERROR
)
1628 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1629 return SELECT_PARTITION_PAGE
;
1632 return CREATE_PRIMARY_PARTITION_PAGE
;
1635 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1637 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1639 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1640 if (Error
!= NOT_AN_ERROR
)
1642 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1643 return SELECT_PARTITION_PAGE
;
1646 return CREATE_EXTENDED_PARTITION_PAGE
;
1649 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1651 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1653 Error
= LogicalPartitionCreationChecks(PartitionList
);
1654 if (Error
!= NOT_AN_ERROR
)
1656 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1657 return SELECT_PARTITION_PAGE
;
1660 return CREATE_LOGICAL_PARTITION_PAGE
;
1663 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1665 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1667 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1668 return SELECT_PARTITION_PAGE
;
1671 if (PartitionList
->CurrentPartition
->BootIndicator
||
1672 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1674 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1677 return DELETE_PARTITION_PAGE
;
1681 return SELECT_PARTITION_PAGE
;
1685 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1686 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1687 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1690 ShowPartitionSizeInputBox(SHORT Left
,
1714 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1719 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1720 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1723 WriteConsoleOutputCharacterA(StdOutput
,
1729 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1730 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1732 WriteConsoleOutputCharacterA(StdOutput
,
1738 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1739 Length
= wcslen(InputBuffer
);
1741 CONSOLE_SetInputTextXY(iLeft
,
1743 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1745 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1746 CONSOLE_SetCursorType(TRUE
, TRUE
);
1750 CONSOLE_ConInKey(&Ir
);
1752 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1753 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1758 InputBuffer
[0] = UNICODE_NULL
;
1759 CONSOLE_SetCursorType(TRUE
, FALSE
);
1762 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1764 CONSOLE_SetCursorType(TRUE
, FALSE
);
1767 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1772 InputBuffer
[0] = UNICODE_NULL
;
1773 CONSOLE_SetCursorType(TRUE
, FALSE
);
1776 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1777 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1780 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1782 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1783 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1786 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1788 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1789 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1794 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1797 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1798 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1803 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1806 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1807 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1811 memmove(&InputBuffer
[Pos
],
1812 &InputBuffer
[Pos
+ 1],
1813 (Length
- Pos
- 1) * sizeof(WCHAR
));
1814 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1817 CONSOLE_SetInputTextXY(iLeft
,
1819 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1821 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1824 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1829 memmove(&InputBuffer
[Pos
- 1],
1831 (Length
- Pos
) * sizeof(WCHAR
));
1832 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1836 CONSOLE_SetInputTextXY(iLeft
,
1838 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1840 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1843 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1845 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1847 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1849 if ((ch
>= L
'0') && (ch
<= L
'9'))
1852 memmove(&InputBuffer
[Pos
+ 1],
1854 (Length
- Pos
) * sizeof(WCHAR
));
1855 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1856 InputBuffer
[Pos
] = ch
;
1860 CONSOLE_SetInputTextXY(iLeft
,
1862 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1864 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1873 * Displays the CreatePrimaryPartitionPage.
1876 * SelectPartitionPage
1877 * SelectFileSystemPage (default)
1881 * Number of the next page.
1884 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1886 PDISKENTRY DiskEntry
;
1887 PPARTENTRY PartEntry
;
1890 WCHAR InputBuffer
[50];
1894 ULONGLONG SectorCount
;
1897 if (PartitionList
== NULL
||
1898 PartitionList
->CurrentDisk
== NULL
||
1899 PartitionList
->CurrentPartition
== NULL
)
1901 /* FIXME: show an error dialog */
1905 DiskEntry
= PartitionList
->CurrentDisk
;
1906 PartEntry
= PartitionList
->CurrentPartition
;
1908 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1910 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1912 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1914 if (DiskSize
>= 10 * GB
) /* 10 GB */
1916 DiskSize
= DiskSize
/ GB
;
1917 Unit
= MUIGetString(STRING_GB
);
1922 DiskSize
= DiskSize
/ MB
;
1926 Unit
= MUIGetString(STRING_MB
);
1929 if (DiskEntry
->DriverName
.Length
> 0)
1931 CONSOLE_PrintTextXY(6, 10,
1932 MUIGetString(STRING_HDINFOPARTCREATE_1
),
1935 DiskEntry
->DiskNumber
,
1939 &DiskEntry
->DriverName
,
1940 DiskEntry
->NoMbr
? "GPT" : "MBR");
1944 CONSOLE_PrintTextXY(6, 10,
1945 MUIGetString(STRING_HDINFOPARTCREATE_2
),
1948 DiskEntry
->DiskNumber
,
1952 DiskEntry
->NoMbr
? "GPT" : "MBR");
1955 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
1958 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
1959 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
1962 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
1964 PartEntry
= PartitionList
->CurrentPartition
;
1967 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
1969 if (MaxSize
> PARTITION_MAXSIZE
)
1970 MaxSize
= PARTITION_MAXSIZE
;
1972 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
1973 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
1977 if (ConfirmQuit(Ir
))
1984 return SELECT_PARTITION_PAGE
;
1988 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
1996 if (PartSize
> MaxSize
)
2002 /* Convert to bytes */
2003 if (PartSize
== MaxSize
)
2005 /* Use all of the unpartitioned disk space */
2006 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2010 /* Calculate the sector count from the size in MB */
2011 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2013 /* But never get larger than the unpartitioned disk space */
2014 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2015 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2018 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2020 CreatePrimaryPartition(PartitionList
,
2024 return SELECT_PARTITION_PAGE
;
2028 return CREATE_PRIMARY_PARTITION_PAGE
;
2033 * Displays the CreateExtendedPartitionPage.
2036 * SelectPartitionPage (default)
2040 * Number of the next page.
2043 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2045 PDISKENTRY DiskEntry
;
2046 PPARTENTRY PartEntry
;
2049 WCHAR InputBuffer
[50];
2053 ULONGLONG SectorCount
;
2056 if (PartitionList
== NULL
||
2057 PartitionList
->CurrentDisk
== NULL
||
2058 PartitionList
->CurrentPartition
== NULL
)
2060 /* FIXME: show an error dialog */
2064 DiskEntry
= PartitionList
->CurrentDisk
;
2065 PartEntry
= PartitionList
->CurrentPartition
;
2067 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2069 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2071 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2073 if (DiskSize
>= 10 * GB
) /* 10 GB */
2075 DiskSize
= DiskSize
/ GB
;
2076 Unit
= MUIGetString(STRING_GB
);
2081 DiskSize
= DiskSize
/ MB
;
2085 Unit
= MUIGetString(STRING_MB
);
2088 if (DiskEntry
->DriverName
.Length
> 0)
2090 CONSOLE_PrintTextXY(6, 10,
2091 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2094 DiskEntry
->DiskNumber
,
2098 &DiskEntry
->DriverName
,
2099 DiskEntry
->NoMbr
? "GPT" : "MBR");
2103 CONSOLE_PrintTextXY(6, 10,
2104 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2107 DiskEntry
->DiskNumber
,
2111 DiskEntry
->NoMbr
? "GPT" : "MBR");
2114 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2117 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2118 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2121 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2123 PartEntry
= PartitionList
->CurrentPartition
;
2126 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2128 if (MaxSize
> PARTITION_MAXSIZE
)
2129 MaxSize
= PARTITION_MAXSIZE
;
2131 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2132 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2136 if (ConfirmQuit(Ir
))
2143 return SELECT_PARTITION_PAGE
;
2147 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2155 if (PartSize
> MaxSize
)
2161 /* Convert to bytes */
2162 if (PartSize
== MaxSize
)
2164 /* Use all of the unpartitioned disk space */
2165 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2169 /* Calculate the sector count from the size in MB */
2170 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2172 /* But never get larger than the unpartitioned disk space */
2173 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2174 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2177 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2179 CreateExtendedPartition(PartitionList
,
2182 return SELECT_PARTITION_PAGE
;
2186 return CREATE_EXTENDED_PARTITION_PAGE
;
2191 * Displays the CreateLogicalPartitionPage.
2194 * SelectFileSystemPage (default)
2198 * Number of the next page.
2201 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2203 PDISKENTRY DiskEntry
;
2204 PPARTENTRY PartEntry
;
2207 WCHAR InputBuffer
[50];
2211 ULONGLONG SectorCount
;
2214 if (PartitionList
== NULL
||
2215 PartitionList
->CurrentDisk
== NULL
||
2216 PartitionList
->CurrentPartition
== NULL
)
2218 /* FIXME: show an error dialog */
2222 DiskEntry
= PartitionList
->CurrentDisk
;
2223 PartEntry
= PartitionList
->CurrentPartition
;
2225 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2227 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2229 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2231 if (DiskSize
>= 10 * GB
) /* 10 GB */
2233 DiskSize
= DiskSize
/ GB
;
2234 Unit
= MUIGetString(STRING_GB
);
2239 DiskSize
= DiskSize
/ MB
;
2243 Unit
= MUIGetString(STRING_MB
);
2246 if (DiskEntry
->DriverName
.Length
> 0)
2248 CONSOLE_PrintTextXY(6, 10,
2249 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2252 DiskEntry
->DiskNumber
,
2256 &DiskEntry
->DriverName
,
2257 DiskEntry
->NoMbr
? "GPT" : "MBR");
2261 CONSOLE_PrintTextXY(6, 10,
2262 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2265 DiskEntry
->DiskNumber
,
2269 DiskEntry
->NoMbr
? "GPT" : "MBR");
2272 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2275 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2276 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ MB
);
2279 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2281 PartEntry
= PartitionList
->CurrentPartition
;
2284 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / MB
; /* in MBytes (rounded) */
2286 if (MaxSize
> PARTITION_MAXSIZE
)
2287 MaxSize
= PARTITION_MAXSIZE
;
2289 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2290 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2294 if (ConfirmQuit(Ir
))
2301 return SELECT_PARTITION_PAGE
;
2305 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2313 if (PartSize
> MaxSize
)
2319 /* Convert to bytes */
2320 if (PartSize
== MaxSize
)
2322 /* Use all of the unpartitioned disk space */
2323 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2327 /* Calculate the sector count from the size in MB */
2328 SectorCount
= PartSize
* MB
/ DiskEntry
->BytesPerSector
;
2330 /* But never get larger than the unpartitioned disk space */
2331 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2332 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2335 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2337 CreateLogicalPartition(PartitionList
,
2341 return SELECT_PARTITION_PAGE
;
2345 return CREATE_LOGICAL_PARTITION_PAGE
;
2350 * Displays the ConfirmDeleteSystemPartitionPage.
2353 * DeletePartitionPage (default)
2354 * SelectPartitionPage
2357 * Number of the next page.
2360 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2362 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2366 CONSOLE_ConInKey(Ir
);
2368 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2369 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2371 if (ConfirmQuit(Ir
))
2376 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2378 return DELETE_PARTITION_PAGE
;
2380 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2382 return SELECT_PARTITION_PAGE
;
2386 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2391 * Displays the DeletePartitionPage.
2394 * SelectPartitionPage (default)
2398 * Number of the next page.
2401 DeletePartitionPage(PINPUT_RECORD Ir
)
2403 PDISKENTRY DiskEntry
;
2404 PPARTENTRY PartEntry
;
2408 CHAR PartTypeString
[32];
2410 if (PartitionList
== NULL
||
2411 PartitionList
->CurrentDisk
== NULL
||
2412 PartitionList
->CurrentPartition
== NULL
)
2414 /* FIXME: show an error dialog */
2418 DiskEntry
= PartitionList
->CurrentDisk
;
2419 PartEntry
= PartitionList
->CurrentPartition
;
2421 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2423 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2425 ARRAYSIZE(PartTypeString
));
2427 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2429 if (PartSize
>= 10 * GB
) /* 10 GB */
2431 PartSize
= PartSize
/ GB
;
2432 Unit
= MUIGetString(STRING_GB
);
2436 if (PartSize
>= 10 * MB
) /* 10 MB */
2438 PartSize
= PartSize
/ MB
;
2439 Unit
= MUIGetString(STRING_MB
);
2443 PartSize
= PartSize
/ KB
;
2444 Unit
= MUIGetString(STRING_KB
);
2447 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2449 CONSOLE_PrintTextXY(6, 10,
2450 MUIGetString(STRING_HDDINFOUNK2
),
2451 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2452 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2453 PartEntry
->PartitionType
,
2459 CONSOLE_PrintTextXY(6, 10,
2460 " %c%c %s %I64u %s",
2461 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2462 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2468 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2470 if (DiskSize
>= 10 * GB
) /* 10 GB */
2472 DiskSize
= DiskSize
/ GB
;
2473 Unit
= MUIGetString(STRING_GB
);
2478 DiskSize
= DiskSize
/ MB
;
2482 Unit
= MUIGetString(STRING_MB
);
2485 if (DiskEntry
->DriverName
.Length
> 0)
2487 CONSOLE_PrintTextXY(6, 12,
2488 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2491 DiskEntry
->DiskNumber
,
2495 &DiskEntry
->DriverName
,
2496 DiskEntry
->NoMbr
? "GPT" : "MBR");
2500 CONSOLE_PrintTextXY(6, 12,
2501 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2504 DiskEntry
->DiskNumber
,
2508 DiskEntry
->NoMbr
? "GPT" : "MBR");
2513 CONSOLE_ConInKey(Ir
);
2515 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2516 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2518 if (ConfirmQuit(Ir
))
2523 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2525 return SELECT_PARTITION_PAGE
;
2527 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2529 DeleteCurrentPartition(PartitionList
);
2531 return SELECT_PARTITION_PAGE
;
2535 return DELETE_PARTITION_PAGE
;
2540 * Displays the SelectFileSystemPage.
2543 * CheckFileSystemPage (At once if RepairUpdate is selected)
2544 * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition)
2545 * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
2546 * SelectPartitionPage (If the user aborts)
2547 * FormatPartitionPage (Default)
2551 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2552 * Calls CheckActiveSystemPartition()
2555 * Number of the next page.
2558 SelectFileSystemPage(PINPUT_RECORD Ir
)
2560 PDISKENTRY DiskEntry
;
2561 PPARTENTRY PartEntry
;
2566 CHAR PartTypeString
[32];
2567 FORMATMACHINESTATE PreviousFormatState
;
2569 DPRINT("SelectFileSystemPage()\n");
2571 if (PartitionList
== NULL
||
2572 PartitionList
->CurrentDisk
== NULL
||
2573 PartitionList
->CurrentPartition
== NULL
)
2575 /* FIXME: show an error dialog */
2579 /* Find or set the active system partition */
2580 CheckActiveSystemPartition(PartitionList
);
2581 if (PartitionList
->SystemPartition
== NULL
)
2583 /* FIXME: show an error dialog */
2585 // Error dialog should say that we cannot find a suitable
2586 // system partition and create one on the system. At this point,
2587 // it may be nice to ask the user whether he wants to continue,
2588 // or use an external drive as the system drive/partition
2589 // (e.g. floppy, USB drive, etc...)
2594 PreviousFormatState
= FormatState
;
2595 switch (FormatState
)
2599 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2601 TempPartition
= PartitionList
->SystemPartition
;
2602 TempPartition
->NeedsCheck
= TRUE
;
2604 FormatState
= FormatSystemPartition
;
2605 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2609 TempPartition
= PartitionList
->CurrentPartition
;
2610 TempPartition
->NeedsCheck
= TRUE
;
2612 FormatState
= FormatInstallPartition
;
2613 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2618 case FormatSystemPartition
:
2620 TempPartition
= PartitionList
->CurrentPartition
;
2621 TempPartition
->NeedsCheck
= TRUE
;
2623 FormatState
= FormatInstallPartition
;
2624 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2628 case FormatInstallPartition
:
2630 if (GetNextUnformattedPartition(PartitionList
,
2634 FormatState
= FormatOtherPartition
;
2635 TempPartition
->NeedsCheck
= TRUE
;
2636 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2640 FormatState
= FormatDone
;
2641 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2642 return CHECK_FILE_SYSTEM_PAGE
;
2647 case FormatOtherPartition
:
2649 if (GetNextUnformattedPartition(PartitionList
,
2653 FormatState
= FormatOtherPartition
;
2654 TempPartition
->NeedsCheck
= TRUE
;
2655 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2659 FormatState
= FormatDone
;
2660 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2661 return CHECK_FILE_SYSTEM_PAGE
;
2668 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2669 /* FIXME: show an error dialog */
2674 PartEntry
= TempPartition
;
2675 DiskEntry
= PartEntry
->DiskEntry
;
2677 /* Adjust disk size */
2678 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2679 if (DiskSize
>= 10 * GB
) /* 10 GB */
2681 DiskSize
= DiskSize
/ GB
;
2682 DiskUnit
= MUIGetString(STRING_GB
);
2686 DiskSize
= DiskSize
/ MB
;
2687 DiskUnit
= MUIGetString(STRING_MB
);
2690 /* Adjust partition size */
2691 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2692 if (PartSize
>= 10 * GB
) /* 10 GB */
2694 PartSize
= PartSize
/ GB
;
2695 PartUnit
= MUIGetString(STRING_GB
);
2699 PartSize
= PartSize
/ MB
;
2700 PartUnit
= MUIGetString(STRING_MB
);
2703 /* Adjust partition type */
2704 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2706 ARRAYSIZE(PartTypeString
));
2708 if (PartEntry
->AutoCreate
)
2710 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2713 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2714 PartEntry
->PartitionNumber
,
2720 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2721 DiskEntry
->DiskNumber
,
2727 &DiskEntry
->DriverName
,
2728 DiskEntry
->NoMbr
? "GPT" : "MBR");
2730 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2732 PartEntry
->AutoCreate
= FALSE
;
2734 else if (PartEntry
->New
)
2736 switch (FormatState
)
2738 case FormatSystemPartition
:
2739 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2742 case FormatInstallPartition
:
2743 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2746 case FormatOtherPartition
:
2747 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2754 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2758 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2760 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2762 CONSOLE_PrintTextXY(8, 10,
2763 MUIGetString(STRING_HDDINFOUNK4
),
2764 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2765 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2766 PartEntry
->PartitionType
,
2772 CONSOLE_PrintTextXY(8, 10,
2774 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2775 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2781 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
2782 DiskEntry
->DiskNumber
,
2788 &DiskEntry
->DriverName
,
2789 DiskEntry
->NoMbr
? "GPT" : "MBR");
2792 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2794 if (FileSystemList
== NULL
)
2796 /* Create the file system list, and by default select the "FAT" file system */
2797 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2798 if (FileSystemList
== NULL
)
2800 /* FIXME: show an error dialog */
2805 if (RepairUpdateFlag
)
2807 return CHECK_FILE_SYSTEM_PAGE
;
2808 //return SELECT_PARTITION_PAGE;
2811 if (IsUnattendedSetup
)
2813 if (USetupData
.FormatPartition
)
2816 * We use whatever currently selected file system we have
2817 * (by default, this is "FAT", as per the initialization
2818 * performed above). Note that it may be interesting to specify
2819 * which file system to use in unattended installations, in the
2820 * txtsetup.sif file.
2822 return FORMAT_PARTITION_PAGE
;
2825 return CHECK_FILE_SYSTEM_PAGE
;
2828 DrawFileSystemList(FileSystemList
);
2832 CONSOLE_ConInKey(Ir
);
2834 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2835 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2837 if (ConfirmQuit(Ir
))
2842 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2843 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2845 FormatState
= Start
;
2846 return SELECT_PARTITION_PAGE
;
2848 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2849 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2851 ScrollDownFileSystemList(FileSystemList
);
2853 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2854 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2856 ScrollUpFileSystemList(FileSystemList
);
2858 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2860 if (!FileSystemList
->Selected
->FileSystem
)
2861 return SELECT_FILE_SYSTEM_PAGE
;
2863 return FORMAT_PARTITION_PAGE
;
2867 FormatState
= PreviousFormatState
;
2869 return SELECT_FILE_SYSTEM_PAGE
;
2874 * Displays the FormatPartitionPage.
2877 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2878 * SelectPartitionPage (At once)
2882 * Sets PartitionList->CurrentPartition->FormatState
2883 * Sets USetupData.DestinationRootPath
2886 * Number of the next page.
2889 FormatPartitionPage(PINPUT_RECORD Ir
)
2891 UNICODE_STRING PartitionRootPath
;
2892 WCHAR PathBuffer
[MAX_PATH
];
2893 PDISKENTRY DiskEntry
;
2894 PPARTENTRY PartEntry
;
2895 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2901 PPARTITION_INFORMATION PartitionInfo
;
2904 DPRINT("FormatPartitionPage()\n");
2906 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2908 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2910 /* FIXME: show an error dialog */
2914 PartEntry
= TempPartition
;
2915 DiskEntry
= PartEntry
->DiskEntry
;
2917 SelectedFileSystem
= FileSystemList
->Selected
;
2921 if (!IsUnattendedSetup
)
2923 CONSOLE_ConInKey(Ir
);
2926 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2927 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2929 if (ConfirmQuit(Ir
))
2934 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2936 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2938 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2940 /* FIXME: show an error dialog */
2945 CONSOLE_PrintTextXY(6, 12,
2946 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
2947 DiskEntry
->Cylinders
,
2948 DiskEntry
->TracksPerCylinder
,
2949 DiskEntry
->SectorsPerTrack
,
2950 DiskEntry
->BytesPerSector
,
2951 DiskEntry
->Dirty
? '*' : ' ');
2955 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
2957 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
2959 CONSOLE_PrintTextXY(6, Line
,
2960 "%2u: %2lu %c %12I64u %12I64u %02x",
2962 PartitionInfo
->PartitionNumber
,
2963 PartitionInfo
->BootIndicator
? 'A' : '-',
2964 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
2965 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
2966 PartitionInfo
->PartitionType
);
2971 /* Commit the partition changes to the disk */
2972 if (!WritePartitionsToDisk(PartitionList
))
2974 DPRINT("WritePartitionsToDisk() failed\n");
2975 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
2979 /* Set PartitionRootPath */
2980 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
2981 L
"\\Device\\Harddisk%lu\\Partition%lu",
2982 DiskEntry
->DiskNumber
,
2983 PartEntry
->PartitionNumber
);
2984 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
2985 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
2987 /* Format the partition */
2988 if (SelectedFileSystem
->FileSystem
)
2990 Status
= FormatPartition(&PartitionRootPath
,
2991 SelectedFileSystem
);
2992 if (!NT_SUCCESS(Status
))
2994 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
2995 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
2999 PartEntry
->FormatState
= Formatted
;
3000 // PartEntry->FileSystem = FileSystem;
3001 PartEntry
->New
= FALSE
;
3005 CONSOLE_SetStatusText(" Done. Press any key ...");
3006 CONSOLE_ConInKey(Ir
);
3009 return SELECT_FILE_SYSTEM_PAGE
;
3013 return FORMAT_PARTITION_PAGE
;
3018 * Displays the CheckFileSystemPage.
3021 * InstallDirectoryPage (At once)
3025 * Inits or reloads FileSystemList
3028 * Number of the next page.
3031 CheckFileSystemPage(PINPUT_RECORD Ir
)
3033 PFILE_SYSTEM CurrentFileSystem
;
3034 UNICODE_STRING PartitionRootPath
;
3035 WCHAR PathBuffer
[MAX_PATH
];
3036 CHAR Buffer
[MAX_PATH
];
3037 PDISKENTRY DiskEntry
;
3038 PPARTENTRY PartEntry
;
3041 if (PartitionList
== NULL
)
3043 /* FIXME: show an error dialog */
3047 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3049 return INSTALL_DIRECTORY_PAGE
;
3052 /* Set PartitionRootPath */
3053 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3054 L
"\\Device\\Harddisk%lu\\Partition%lu",
3055 DiskEntry
->DiskNumber
,
3056 PartEntry
->PartitionNumber
);
3057 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3058 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3060 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3062 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3064 CurrentFileSystem
= PartEntry
->FileSystem
;
3065 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3066 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3068 /* HACK: Do not try to check a partition with an unknown filesystem */
3069 if (CurrentFileSystem
== NULL
)
3071 PartEntry
->NeedsCheck
= FALSE
;
3072 return CHECK_FILE_SYSTEM_PAGE
;
3075 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3078 "Setup is currently unable to check a partition formatted in %S.\n"
3080 " \x07 Press ENTER to continue Setup.\n"
3081 " \x07 Press F3 to quit Setup.",
3082 CurrentFileSystem
->FileSystemName
);
3085 MUIGetString(STRING_QUITCONTINUE
),
3086 NULL
, POPUP_WAIT_NONE
);
3090 CONSOLE_ConInKey(Ir
);
3092 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3093 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3095 if (ConfirmQuit(Ir
))
3098 return CHECK_FILE_SYSTEM_PAGE
;
3100 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3102 PartEntry
->NeedsCheck
= FALSE
;
3103 return CHECK_FILE_SYSTEM_PAGE
;
3109 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3110 if (!NT_SUCCESS(Status
))
3112 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3113 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3114 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3115 "(Status 0x%08lx).\n", Status
);
3117 // MUIGetString(STRING_REBOOTCOMPUTER),
3118 MUIGetString(STRING_CONTINUE
),
3119 Ir
, POPUP_WAIT_ENTER
);
3121 // return QUIT_PAGE;
3124 PartEntry
->NeedsCheck
= FALSE
;
3125 return CHECK_FILE_SYSTEM_PAGE
;
3131 BuildInstallPaths(PWSTR InstallDir
,
3132 PDISKENTRY DiskEntry
,
3133 PPARTENTRY PartEntry
)
3135 WCHAR PathBuffer
[MAX_PATH
];
3137 /** Equivalent of 'NTOS_INSTALLATION::PathComponent' **/
3138 /* Create 'InstallPath' string */
3139 RtlFreeUnicodeString(&InstallPath
);
3140 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3142 /* Create 'USetupData.DestinationRootPath' string */
3143 RtlFreeUnicodeString(&USetupData
.DestinationRootPath
);
3144 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3145 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
3146 DiskEntry
->DiskNumber
,
3147 PartEntry
->PartitionNumber
);
3148 RtlCreateUnicodeString(&USetupData
.DestinationRootPath
, PathBuffer
);
3149 DPRINT("DestinationRootPath: %wZ\n", &USetupData
.DestinationRootPath
);
3151 /** Equivalent of 'NTOS_INSTALLATION::SystemNtPath' **/
3152 /* Create 'USetupData.DestinationPath' string */
3153 RtlFreeUnicodeString(&USetupData
.DestinationPath
);
3154 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3155 USetupData
.DestinationRootPath
.Buffer
, InstallDir
);
3156 RtlCreateUnicodeString(&USetupData
.DestinationPath
, PathBuffer
);
3158 /** Equivalent of 'NTOS_INSTALLATION::SystemArcPath' **/
3159 /* Create 'USetupData.DestinationArcPath' */
3160 RtlFreeUnicodeString(&USetupData
.DestinationArcPath
);
3161 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3162 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
3163 DiskEntry
->BiosDiskNumber
,
3164 PartEntry
->PartitionNumber
);
3165 ConcatPaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 1, InstallDir
);
3166 RtlCreateUnicodeString(&USetupData
.DestinationArcPath
, PathBuffer
);
3168 /* Initialize DestinationDriveLetter */
3169 DestinationDriveLetter
= (WCHAR
)PartEntry
->DriveLetter
;
3174 * Displays the InstallDirectoryPage.
3181 * Number of the next page.
3184 InstallDirectoryPage(PINPUT_RECORD Ir
)
3186 PDISKENTRY DiskEntry
;
3187 PPARTENTRY PartEntry
;
3188 WCHAR InstallDir
[MAX_PATH
];
3192 /* We do not need the filesystem list anymore */
3193 if (FileSystemList
!= NULL
)
3195 DestroyFileSystemList(FileSystemList
);
3196 FileSystemList
= NULL
;
3199 if (PartitionList
== NULL
||
3200 PartitionList
->CurrentDisk
== NULL
||
3201 PartitionList
->CurrentPartition
== NULL
)
3203 /* FIXME: show an error dialog */
3207 DiskEntry
= PartitionList
->CurrentDisk
;
3208 PartEntry
= PartitionList
->CurrentPartition
;
3210 // if (IsUnattendedSetup)
3211 if (RepairUpdateFlag
)
3212 wcscpy(InstallDir
, CurrentInstallation
->PathComponent
); // SystemNtPath
3213 else if (USetupData
.InstallationDirectory
[0])
3214 wcscpy(InstallDir
, USetupData
.InstallationDirectory
);
3216 wcscpy(InstallDir
, L
"\\ReactOS");
3219 * Check the validity of the predefined 'InstallDir'. If we are either
3220 * in unattended setup or in update/repair mode, and the installation path
3221 * is valid, just perform the installation. Otherwise (either in the case
3222 * of an invalid path, or we are in regular setup), display the UI and allow
3223 * the user to specify a new installation path.
3225 if ((RepairUpdateFlag
|| IsUnattendedSetup
) && IsValidPath(InstallDir
))
3227 BuildInstallPaths(InstallDir
,
3231 return PREPARE_COPY_PAGE
;
3234 Length
= wcslen(InstallDir
);
3237 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3238 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3239 CONSOLE_SetCursorXY(8 + Pos
, 11);
3240 CONSOLE_SetCursorType(TRUE
, TRUE
);
3244 CONSOLE_ConInKey(Ir
);
3246 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3247 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3249 CONSOLE_SetCursorType(TRUE
, FALSE
);
3251 if (ConfirmQuit(Ir
))
3254 CONSOLE_SetCursorType(TRUE
, TRUE
);
3257 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3258 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3262 memmove(&InstallDir
[Pos
],
3263 &InstallDir
[Pos
+ 1],
3264 (Length
- Pos
- 1) * sizeof(WCHAR
));
3265 InstallDir
[Length
- 1] = UNICODE_NULL
;
3268 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3269 CONSOLE_SetCursorXY(8 + Pos
, 11);
3272 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3273 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3276 CONSOLE_SetCursorXY(8 + Pos
, 11);
3278 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3279 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3282 CONSOLE_SetCursorXY(8 + Pos
, 11);
3284 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3285 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3290 CONSOLE_SetCursorXY(8 + Pos
, 11);
3293 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3294 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3299 CONSOLE_SetCursorXY(8 + Pos
, 11);
3302 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3304 CONSOLE_SetCursorType(TRUE
, FALSE
);
3307 * Check for the validity of the installation directory and pop up
3308 * an error if it is not the case. Then the user can fix its input.
3310 if (!IsValidPath(InstallDir
))
3312 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3313 return INSTALL_DIRECTORY_PAGE
;
3316 BuildInstallPaths(InstallDir
,
3320 return PREPARE_COPY_PAGE
;
3322 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3327 memmove(&InstallDir
[Pos
- 1],
3329 (Length
- Pos
) * sizeof(WCHAR
));
3330 InstallDir
[Length
- 1] = UNICODE_NULL
;
3334 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3335 CONSOLE_SetCursorXY(8 + Pos
, 11);
3338 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3342 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3343 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3346 memmove(&InstallDir
[Pos
+ 1],
3348 (Length
- Pos
) * sizeof(WCHAR
));
3349 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3350 InstallDir
[Pos
] = c
;
3354 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3355 CONSOLE_SetCursorXY(8 + Pos
, 11);
3361 return INSTALL_DIRECTORY_PAGE
;
3366 AddSectionToCopyQueueCab(HINF InfFile
,
3368 PWCHAR SourceCabinet
,
3369 PCUNICODE_STRING DestinationPath
,
3372 INFCONTEXT FilesContext
;
3373 INFCONTEXT DirContext
;
3375 PWCHAR FileKeyValue
;
3377 PWCHAR TargetFileName
;
3380 * This code enumerates the list of files in reactos.dff / reactos.inf
3381 * that need to be extracted from reactos.cab and be installed in their
3382 * respective directories.
3385 /* Search for the SectionName section */
3386 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3389 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3390 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3395 * Enumerate the files in the section and add them to the file queue.
3399 /* Get source file name and target directory id */
3400 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3402 /* FIXME: Handle error! */
3403 DPRINT1("INF_GetData() failed\n");
3407 /* Get optional target file name */
3408 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3409 TargetFileName
= NULL
;
3411 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3413 /* Lookup target directory */
3414 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3416 /* FIXME: Handle error! */
3417 DPRINT1("SetupFindFirstLine() failed\n");
3418 INF_FreeData(FileKeyName
);
3419 INF_FreeData(FileKeyValue
);
3420 INF_FreeData(TargetFileName
);
3424 INF_FreeData(FileKeyValue
);
3426 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3428 /* FIXME: Handle error! */
3429 DPRINT1("INF_GetData() failed\n");
3430 INF_FreeData(FileKeyName
);
3431 INF_FreeData(TargetFileName
);
3435 if (!SetupQueueCopy(SetupFileQueue
,
3437 USetupData
.SourceRootPath
.Buffer
,
3438 USetupData
.SourceRootDir
.Buffer
,
3443 /* FIXME: Handle error! */
3444 DPRINT1("SetupQueueCopy() failed\n");
3447 INF_FreeData(FileKeyName
);
3448 INF_FreeData(TargetFileName
);
3449 INF_FreeData(DirKeyValue
);
3450 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3457 AddSectionToCopyQueue(HINF InfFile
,
3459 PWCHAR SourceCabinet
,
3460 PCUNICODE_STRING DestinationPath
,
3463 INFCONTEXT FilesContext
;
3464 INFCONTEXT DirContext
;
3466 PWCHAR FileKeyValue
;
3468 PWCHAR TargetFileName
;
3469 WCHAR CompleteOrigDirName
[512]; // FIXME: MAX_PATH is not enough?
3472 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3475 * This code enumerates the list of files in txtsetup.sif
3476 * that need to be installed in their respective directories.
3479 /* Search for the SectionName section */
3480 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3483 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3484 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3489 * Enumerate the files in the section and add them to the file queue.
3493 /* Get source file name */
3494 if (!INF_GetDataField(&FilesContext
, 0, &FileKeyName
))
3496 /* FIXME: Handle error! */
3497 DPRINT1("INF_GetData() failed\n");
3501 /* Get target directory id */
3502 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3504 /* FIXME: Handle error! */
3505 DPRINT1("INF_GetData() failed\n");
3506 INF_FreeData(FileKeyName
);
3510 /* Get optional target file name */
3511 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3512 TargetFileName
= NULL
;
3513 else if (!*TargetFileName
)
3514 TargetFileName
= NULL
;
3516 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3518 /* Lookup target directory */
3519 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3521 /* FIXME: Handle error! */
3522 DPRINT1("SetupFindFirstLine() failed\n");
3523 INF_FreeData(FileKeyName
);
3524 INF_FreeData(FileKeyValue
);
3525 INF_FreeData(TargetFileName
);
3529 INF_FreeData(FileKeyValue
);
3531 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3533 /* FIXME: Handle error! */
3534 DPRINT1("INF_GetData() failed\n");
3535 INF_FreeData(FileKeyName
);
3536 INF_FreeData(TargetFileName
);
3540 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3542 /* Installation path */
3543 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3545 StringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3546 USetupData
.SourceRootDir
.Buffer
);
3548 DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName
);
3550 else if (DirKeyValue
[0] == L
'\\')
3553 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3555 StringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3558 DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName
);
3560 else // if (DirKeyValue[0] != L'\\')
3562 /* Path relative to the installation path */
3563 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3565 CombinePaths(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
), 2,
3566 USetupData
.SourceRootDir
.Buffer
, DirKeyValue
);
3568 DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName
);
3571 if (!SetupQueueCopy(SetupFileQueue
,
3573 USetupData
.SourceRootPath
.Buffer
,
3574 CompleteOrigDirName
,
3579 /* FIXME: Handle error! */
3580 DPRINT1("SetupQueueCopy() failed\n");
3583 INF_FreeData(FileKeyName
);
3584 INF_FreeData(TargetFileName
);
3585 INF_FreeData(DirKeyValue
);
3586 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3593 PrepareCopyPageInfFile(HINF InfFile
,
3594 PWCHAR SourceCabinet
,
3598 INFCONTEXT DirContext
;
3599 PWCHAR AdditionalSectionName
= NULL
;
3601 WCHAR PathBuffer
[MAX_PATH
];
3603 /* Add common files */
3604 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &USetupData
.DestinationPath
, Ir
))
3607 /* Add specific files depending of computer type */
3608 if (SourceCabinet
== NULL
)
3610 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3613 if (AdditionalSectionName
)
3615 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &USetupData
.DestinationPath
, Ir
))
3620 /* Create directories */
3624 * Copying files to USetupData.DestinationRootPath should be done from within
3625 * the SystemPartitionFiles section.
3626 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3627 * For installing to USetupData.DestinationPath specify just '\' .
3630 /* Get destination path */
3631 StringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
), USetupData
.DestinationPath
.Buffer
);
3633 DPRINT("FullPath(1): '%S'\n", PathBuffer
);
3635 /* Create the install directory */
3636 Status
= SetupCreateDirectory(PathBuffer
);
3637 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3639 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer
, Status
);
3640 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3644 /* Search for the 'Directories' section */
3645 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3649 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3653 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3659 /* Enumerate the directory values and create the subdirectories */
3662 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3668 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3670 /* Installation path */
3671 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3673 StringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3674 USetupData
.DestinationPath
.Buffer
);
3676 DPRINT("InstallationPath(2): '%S'\n", PathBuffer
);
3678 else if (DirKeyValue
[0] == L
'\\')
3681 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3683 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3684 USetupData
.DestinationRootPath
.Buffer
, DirKeyValue
);
3686 DPRINT("AbsolutePath(2): '%S'\n", PathBuffer
);
3688 Status
= SetupCreateDirectory(PathBuffer
);
3689 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3691 INF_FreeData(DirKeyValue
);
3692 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3693 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3697 else // if (DirKeyValue[0] != L'\\')
3699 /* Path relative to the installation path */
3700 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3702 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3703 USetupData
.DestinationPath
.Buffer
, DirKeyValue
);
3705 DPRINT("RelativePath(2): '%S'\n", PathBuffer
);
3707 Status
= SetupCreateDirectory(PathBuffer
);
3708 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3710 INF_FreeData(DirKeyValue
);
3711 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3712 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3717 INF_FreeData(DirKeyValue
);
3718 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3725 * Displays the PrepareCopyPage.
3728 * FileCopyPage(At once)
3732 * Inits SetupFileQueue
3733 * Calls PrepareCopyPageInfFile
3736 * Number of the next page.
3739 PrepareCopyPage(PINPUT_RECORD Ir
)
3742 WCHAR PathBuffer
[MAX_PATH
];
3743 INFCONTEXT CabinetsContext
;
3749 MUIDisplayPage(PREPARE_COPY_PAGE
);
3751 /* Create the file queue */
3752 SetupFileQueue
= SetupOpenFileQueue();
3753 if (SetupFileQueue
== NULL
)
3755 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3759 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3761 /* FIXME: show an error dialog */
3765 /* Search for the 'Cabinets' section */
3766 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3768 return FILE_COPY_PAGE
;
3772 * Enumerate the directory values in the 'Cabinets'
3773 * section and parse their inf files.
3777 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3780 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3781 USetupData
.SourcePath
.Buffer
, KeyValue
);
3783 CabinetInitialize();
3784 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3785 CabinetSetCabinetName(PathBuffer
);
3787 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3789 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3791 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3792 if (InfFileData
== NULL
)
3794 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3800 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3801 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3805 InfHandle
= INF_OpenBufferedFileA((PSTR
)InfFileData
,
3809 USetupData
.LanguageId
,
3812 if (InfHandle
== INVALID_HANDLE_VALUE
)
3814 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3820 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3822 /* FIXME: show an error dialog */
3825 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3827 return FILE_COPY_PAGE
;
3833 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3836 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3838 /* Get the memory information from the system */
3839 NtQuerySystemInformation(SystemPerformanceInformation
,
3844 /* Check if this is initial setup */
3847 /* Set maximum limits to be total RAM pages */
3848 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3849 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3850 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3853 /* Set current values */
3854 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3855 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3856 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3862 FileCopyCallback(PVOID Context
,
3867 PCOPYCONTEXT CopyContext
;
3869 CopyContext
= (PCOPYCONTEXT
)Context
;
3871 switch (Notification
)
3873 case SPFILENOTIFY_STARTSUBQUEUE
:
3874 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3875 ProgressSetStepCount(CopyContext
->ProgressBar
,
3876 CopyContext
->TotalOperations
);
3877 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3880 case SPFILENOTIFY_STARTCOPY
:
3881 /* Display copy message */
3882 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3883 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3886 case SPFILENOTIFY_ENDCOPY
:
3887 CopyContext
->CompletedOperations
++;
3889 /* SYSREG checkpoint */
3890 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3891 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3893 ProgressNextStep(CopyContext
->ProgressBar
);
3894 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3903 * Displays the FileCopyPage.
3906 * RegistryPage(At once)
3909 * Calls SetupCommitFileQueueW
3910 * Calls SetupCloseFileQueue
3913 * Number of the next page.
3916 FileCopyPage(PINPUT_RECORD Ir
)
3918 COPYCONTEXT CopyContext
;
3919 unsigned int mem_bar_width
;
3921 MUIDisplayPage(FILE_COPY_PAGE
);
3923 /* Create context for the copy process */
3924 CopyContext
.DestinationRootPath
= USetupData
.DestinationRootPath
.Buffer
;
3925 CopyContext
.InstallPath
= InstallPath
.Buffer
;
3926 CopyContext
.TotalOperations
= 0;
3927 CopyContext
.CompletedOperations
= 0;
3929 /* Create the progress bar as well */
3930 CopyContext
.ProgressBar
= CreateProgressBar(13,
3937 MUIGetString(STRING_SETUPCOPYINGFILES
));
3939 // fit memory bars to screen width, distribute them uniform
3940 mem_bar_width
= (xScreen
- 26) / 5;
3941 mem_bar_width
-= mem_bar_width
% 2; // make even
3942 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3943 /* Create the paged pool progress bar */
3944 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3953 /* Create the non paged pool progress bar */
3954 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
3956 (xScreen
/ 2) + (mem_bar_width
/ 2),
3958 (xScreen
/ 2)- (mem_bar_width
/ 2),
3963 /* Create the global memory progress bar */
3964 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
3968 xScreen
- 13 - mem_bar_width
,
3973 /* Do the file copying */
3974 SetupCommitFileQueueW(NULL
,
3979 /* If we get here, we're done, so cleanup the queue and progress bar */
3980 SetupCloseFileQueue(SetupFileQueue
);
3981 DestroyProgressBar(CopyContext
.ProgressBar
);
3982 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
3983 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
3984 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
3986 /* Create the $winnt$.inf file */
3987 InstallSetupInfFile(&USetupData
);
3989 /* Go display the next page */
3990 return REGISTRY_PAGE
;
3995 * Displays the RegistryPage.
3998 * SuccessPage (if RepairUpdate)
3999 * BootLoaderPage (default)
4003 * Calls RegInitializeRegistry
4004 * Calls ImportRegistryFile
4005 * Calls SetDefaultPagefile
4006 * Calls SetMountedDeviceValues
4009 * Number of the next page.
4012 RegistryPage(PINPUT_RECORD Ir
)
4015 INFCONTEXT InfContext
;
4020 BOOLEAN ShouldRepairRegistry
= FALSE
;
4023 MUIDisplayPage(REGISTRY_PAGE
);
4025 if (RepairUpdateFlag
)
4027 DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n");
4029 /* Verify the registry hives and check whether we need to update or repair any of them */
4030 Status
= VerifyRegistryHives(&USetupData
.DestinationPath
, &ShouldRepairRegistry
);
4031 if (!NT_SUCCESS(Status
))
4033 DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status
);
4034 ShouldRepairRegistry
= FALSE
;
4036 if (!ShouldRepairRegistry
)
4037 DPRINT1("No need to repair the registry\n");
4041 /* Update the registry */
4042 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4044 /* Initialize the registry and setup the registry hives */
4045 Status
= RegInitializeRegistry(&USetupData
.DestinationPath
);
4046 if (!NT_SUCCESS(Status
))
4048 DPRINT1("RegInitializeRegistry() failed\n");
4049 /********** HACK!!!!!!!!!!! **********/
4050 if (Status
== STATUS_NOT_IMPLEMENTED
)
4052 /* The hack was called, display its corresponding error */
4053 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4056 /*************************************/
4058 /* Something else failed */
4059 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4064 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4067 * We fully setup the hives, in case we are doing a fresh installation
4068 * (RepairUpdateFlag == FALSE), or in case we are doing an update
4069 * (RepairUpdateFlag == TRUE) BUT we have some registry hives to
4070 * "repair" (aka. recreate: ShouldRepairRegistry == TRUE).
4073 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Fresh", NULL
, &InfContext
); // Windows-compatible
4075 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
); // ReactOS-specific
4079 DPRINT1("SetupFindFirstLine() failed\n");
4080 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4084 else // if (RepairUpdateFlag && !ShouldRepairRegistry)
4087 * In case we are doing an update (RepairUpdateFlag == TRUE) and
4088 * NO registry hives need a repair (ShouldRepairRegistry == FALSE),
4089 * we only update the hives.
4092 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Upgrade", NULL
, &InfContext
);
4095 /* Nothing to do for update! */
4096 DPRINT1("No update needed for the registry!\n");
4103 INF_GetDataField(&InfContext
, 0, &Action
);
4104 INF_GetDataField(&InfContext
, 1, &File
);
4105 INF_GetDataField(&InfContext
, 2, &Section
);
4107 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4111 INF_FreeData(Action
);
4113 INF_FreeData(Section
);
4117 if (!_wcsicmp(Action
, L
"AddReg"))
4119 else if (!_wcsicmp(Action
, L
"DelReg"))
4123 DPRINT1("Unrecognized registry INF action '%S'\n", Action
);
4124 INF_FreeData(Action
);
4126 INF_FreeData(Section
);
4130 INF_FreeData(Action
);
4132 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4134 if (!ImportRegistryFile(USetupData
.SourcePath
.Buffer
, File
, Section
, USetupData
.LanguageId
, Delete
))
4136 DPRINT1("Importing %S failed\n", File
);
4138 INF_FreeData(Section
);
4139 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4142 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4144 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4146 /* See the explanation for this test above */
4148 /* Update display registry settings */
4149 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4150 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4152 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4156 /* Set the locale */
4157 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4158 if (!ProcessLocaleRegistry(LanguageList
))
4160 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4164 /* Add keyboard layouts */
4165 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4166 if (!AddKeyboardLayouts())
4168 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4173 if (!SetGeoID(MUIGetGeoID()))
4175 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4179 if (!IsUnattendedSetup
)
4181 /* Update keyboard layout settings */
4182 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4183 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4185 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4190 /* Add codepage information to registry */
4191 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4194 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4198 /* Set the default pagefile entry */
4199 SetDefaultPagefile(DestinationDriveLetter
);
4201 /* Update the mounted devices list */
4202 // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
4203 SetMountedDeviceValues(PartitionList
);
4208 // TODO: Unload all the registry stuff, perform cleanup,
4209 // and copy the created hive files into .sav files.
4211 RegCleanupRegistry(&USetupData
.DestinationPath
);
4214 * Check whether we were in update/repair mode but we were actually
4215 * repairing the registry hives. If so, we have finished repairing them,
4216 * and we now reset the flag and run the proper registry update.
4217 * Otherwise we have finished the registry update!
4219 if (RepairUpdateFlag
&& ShouldRepairRegistry
)
4221 ShouldRepairRegistry
= FALSE
;
4225 if (NT_SUCCESS(Status
))
4227 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4228 return BOOT_LOADER_PAGE
;
4238 * Displays the BootLoaderPage.
4241 * SuccessPage (if RepairUpdate)
4242 * BootLoaderHarddiskMbrPage
4243 * BootLoaderHarddiskVbrPage
4244 * BootLoaderFloppyPage
4249 * Calls RegInitializeRegistry
4250 * Calls ImportRegistryFile
4251 * Calls SetDefaultPagefile
4252 * Calls SetMountedDeviceValues
4255 * Number of the next page.
4258 BootLoaderPage(PINPUT_RECORD Ir
)
4260 UCHAR PartitionType
;
4261 BOOLEAN InstallOnFloppy
;
4263 WCHAR PathBuffer
[MAX_PATH
];
4265 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4267 RtlFreeUnicodeString(&USetupData
.SystemRootPath
);
4268 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
4269 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
4270 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4271 PartitionList
->SystemPartition
->PartitionNumber
);
4272 RtlCreateUnicodeString(&USetupData
.SystemRootPath
, PathBuffer
);
4273 DPRINT1("SystemRootPath: %wZ\n", &USetupData
.SystemRootPath
);
4275 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4277 /* For unattended setup, skip MBR installation or install on floppy if needed */
4278 if (IsUnattendedSetup
)
4280 if ((USetupData
.MBRInstallType
== 0) ||
4281 (USetupData
.MBRInstallType
== 1))
4288 * We may install an MBR or VBR, but before that, check whether
4289 * we need to actually install the VBR on floppy.
4291 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4293 DPRINT("Error: system partition invalid (unused)\n");
4294 InstallOnFloppy
= TRUE
;
4296 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4298 /* OS/2 boot manager partition */
4299 DPRINT("Found OS/2 boot manager partition\n");
4300 InstallOnFloppy
= TRUE
;
4302 else if (PartitionType
== PARTITION_EXT2
)
4304 /* Linux EXT2 partition */
4305 DPRINT("Found Linux EXT2 partition\n");
4306 InstallOnFloppy
= FALSE
;
4308 else if (PartitionType
== PARTITION_IFS
)
4310 /* NTFS partition */
4311 DPRINT("Found NTFS partition\n");
4313 // FIXME: Make it FALSE when we'll support NTFS installation!
4314 InstallOnFloppy
= TRUE
;
4316 else if ((PartitionType
== PARTITION_FAT_12
) ||
4317 (PartitionType
== PARTITION_FAT_16
) ||
4318 (PartitionType
== PARTITION_HUGE
) ||
4319 (PartitionType
== PARTITION_XINT13
) ||
4320 (PartitionType
== PARTITION_FAT32
) ||
4321 (PartitionType
== PARTITION_FAT32_XINT13
))
4323 DPRINT("Found FAT partition\n");
4324 InstallOnFloppy
= FALSE
;
4328 /* Unknown partition */
4329 DPRINT("Unknown partition found\n");
4330 InstallOnFloppy
= TRUE
;
4333 /* We should install on floppy */
4334 if (InstallOnFloppy
)
4336 USetupData
.MBRInstallType
= 1;
4340 /* Is it an unattended install on hdd? */
4341 if (IsUnattendedSetup
)
4343 if ((USetupData
.MBRInstallType
== 2) ||
4344 (USetupData
.MBRInstallType
== 3))
4350 MUIDisplayPage(BOOT_LOADER_PAGE
);
4351 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4355 CONSOLE_ConInKey(Ir
);
4357 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4358 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4360 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4369 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4371 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4372 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4374 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4383 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4385 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4386 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4388 if (ConfirmQuit(Ir
))
4393 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4397 /* Install on both MBR and VBR */
4398 USetupData
.MBRInstallType
= 2;
4401 else if (Line
== 13)
4403 /* Install on VBR only */
4404 USetupData
.MBRInstallType
= 3;
4407 else if (Line
== 14)
4409 /* Install on floppy */
4410 USetupData
.MBRInstallType
= 1;
4413 else if (Line
== 15)
4415 /* Skip MBR installation */
4416 USetupData
.MBRInstallType
= 0;
4420 return BOOT_LOADER_PAGE
;
4425 switch (USetupData
.MBRInstallType
)
4427 /* Skip MBR installation */
4429 return SUCCESS_PAGE
;
4431 /* Install on floppy */
4433 return BOOT_LOADER_FLOPPY_PAGE
;
4435 /* Install on both MBR and VBR */
4437 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4439 /* Install on VBR only */
4441 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4444 return BOOT_LOADER_PAGE
;
4449 * Displays the BootLoaderFloppyPage.
4452 * SuccessPage (At once)
4456 * Calls InstallFatBootcodeToFloppy()
4459 * Number of the next page.
4462 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4466 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4468 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4472 CONSOLE_ConInKey(Ir
);
4474 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4475 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4477 if (ConfirmQuit(Ir
))
4482 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4484 if (DoesPathExist(NULL
, L
"\\Device\\Floppy0\\") == FALSE
)
4486 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4487 return BOOT_LOADER_FLOPPY_PAGE
;
4490 Status
= InstallFatBootcodeToFloppy(&USetupData
.SourceRootPath
, &USetupData
.DestinationArcPath
);
4491 if (!NT_SUCCESS(Status
))
4493 /* Print error message */
4494 return BOOT_LOADER_FLOPPY_PAGE
;
4497 return SUCCESS_PAGE
;
4501 return BOOT_LOADER_FLOPPY_PAGE
;
4506 * Displays the BootLoaderHarddiskVbrPage.
4509 * SuccessPage (At once)
4513 * Calls InstallVBRToPartition()
4516 * Number of the next page.
4519 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4523 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4524 &USetupData
.SourceRootPath
,
4525 &USetupData
.DestinationArcPath
,
4526 PartitionList
->SystemPartition
->PartitionType
);
4527 if (!NT_SUCCESS(Status
))
4529 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4533 return SUCCESS_PAGE
;
4538 * Displays the BootLoaderHarddiskMbrPage.
4541 * SuccessPage (At once)
4545 * Calls InstallVBRToPartition()
4546 * Calls InstallMbrBootCodeToDisk()
4549 * Number of the next page.
4552 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4555 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4556 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4557 WCHAR DstPath
[MAX_PATH
];
4559 /* Step 1: Write the VBR */
4560 Status
= InstallVBRToPartition(&USetupData
.SystemRootPath
,
4561 &USetupData
.SourceRootPath
,
4562 &USetupData
.DestinationArcPath
,
4563 PartitionList
->SystemPartition
->PartitionType
);
4564 if (!NT_SUCCESS(Status
))
4566 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4570 /* Step 2: Write the MBR */
4571 StringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4572 L
"\\Device\\Harddisk%d\\Partition0",
4573 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4575 CombinePaths(SourceMbrPathBuffer
, ARRAYSIZE(SourceMbrPathBuffer
), 2, USetupData
.SourceRootPath
.Buffer
, L
"\\loader\\dosmbr.bin");
4577 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4579 /* Save current MBR */
4580 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, USetupData
.SystemRootPath
.Buffer
, L
"mbr.old");
4582 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4583 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4584 if (!NT_SUCCESS(Status
))
4586 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4587 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4591 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4592 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4593 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4594 DestinationDevicePathBuffer
);
4595 if (!NT_SUCCESS(Status
))
4597 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4599 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4603 return SUCCESS_PAGE
;
4608 * @name ProgressTimeOutStringHandler
4610 * Handles the generation (displaying) of the timeout
4611 * countdown to the screen dynamically.
4614 * A pointer to a progress bar.
4616 * @param AlwaysUpdate
4617 * Constantly update the progress bar (boolean type).
4620 * A pointer to a string buffer.
4622 * @param cchBufferSize
4623 * The buffer's size in number of characters.
4626 * TRUE or FALSE on function termination.
4631 ProgressTimeOutStringHandler(
4632 IN PPROGRESSBAR Bar
,
4633 IN BOOLEAN AlwaysUpdate
,
4635 IN SIZE_T cchBufferSize
)
4637 ULONG OldProgress
= Bar
->Progress
;
4639 if (Bar
->StepCount
== 0)
4645 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4648 /* Build the progress string if it has changed */
4649 if (Bar
->ProgressFormatText
&&
4650 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4652 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4653 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4662 * @name ProgressCountdown
4664 * Displays and draws a red-coloured progress bar with a countdown.
4665 * When the timeout is reached, the flush page is displayed for reboot.
4668 * A pointer to an input keyboard record.
4671 * Initial countdown value in seconds.
4679 IN PINPUT_RECORD Ir
,
4683 ULONG StartTime
, BarWidth
, TimerDiv
;
4685 LONG TimerValue
, OldTimerValue
;
4686 LARGE_INTEGER Timeout
;
4687 PPROGRESSBAR ProgressBar
;
4688 BOOLEAN RefreshProgress
= TRUE
;
4690 /* Bail out if the timeout is already zero */
4694 /* Create the timeout progress bar and set it up */
4695 ProgressBar
= CreateProgressBarEx(13,
4702 FOREGROUND_RED
| BACKGROUND_BLUE
,
4705 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4706 ProgressTimeOutStringHandler
);
4708 BarWidth
= max(1, ProgressBar
->Width
);
4709 TimerValue
= TimeOut
* BarWidth
;
4710 ProgressSetStepCount(ProgressBar
, TimerValue
);
4712 StartTime
= NtGetTickCount();
4715 TimerDiv
= 1000 / BarWidth
;
4716 TimerDiv
= max(1, TimerDiv
);
4717 OldTimerValue
= TimerValue
;
4720 /* Decrease the timer */
4723 * Compute how much time the previous operations took.
4724 * This allows us in particular to take account for any time
4725 * elapsed if something slowed down.
4727 TimeElapsed
= NtGetTickCount() - StartTime
;
4728 if (TimeElapsed
>= TimerDiv
)
4730 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4731 TimeElapsed
/= TimerDiv
;
4732 StartTime
+= (TimerDiv
* TimeElapsed
);
4734 if (TimeElapsed
<= TimerValue
)
4735 TimerValue
-= TimeElapsed
;
4739 RefreshProgress
= TRUE
;
4742 if (RefreshProgress
)
4744 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4745 RefreshProgress
= FALSE
;
4748 /* Stop when the timer reaches zero */
4749 if (TimerValue
<= 0)
4752 /* Check for user key presses */
4755 * If the timer is used, use a passive wait of maximum 1 second
4756 * while monitoring for incoming console input events, so that
4757 * we are still able to display the timing count.
4760 /* Wait a maximum of 1 second for input events */
4761 TimeElapsed
= NtGetTickCount() - StartTime
;
4762 if (TimeElapsed
< TimerDiv
)
4764 /* Convert the time to NT Format */
4765 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4766 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4770 Status
= STATUS_TIMEOUT
;
4773 /* Check whether the input event has been signaled, or a timeout happened */
4774 if (Status
== STATUS_TIMEOUT
)
4778 if (Status
!= STATUS_WAIT_0
)
4780 /* An error happened, bail out */
4781 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4785 /* Check for an ENTER key press */
4786 while (CONSOLE_ConInKeyPeek(Ir
))
4788 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4790 /* Found it, stop waiting */
4797 /* Destroy the progress bar and quit */
4798 DestroyProgressBar(ProgressBar
);
4803 * Displays the QuitPage.
4806 * FlushPage (At once)
4812 * Number of the next page.
4815 QuitPage(PINPUT_RECORD Ir
)
4817 MUIDisplayPage(QUIT_PAGE
);
4819 /* Destroy the NTOS installations list */
4820 if (NtOsInstallsList
!= NULL
)
4822 DestroyGenericList(NtOsInstallsList
, TRUE
);
4823 NtOsInstallsList
= NULL
;
4826 /* Destroy the partition list */
4827 if (PartitionList
!= NULL
)
4829 DestroyPartitionList(PartitionList
);
4830 PartitionList
= NULL
;
4832 TempPartition
= NULL
;
4833 FormatState
= Start
;
4835 /* Destroy the filesystem list */
4836 if (FileSystemList
!= NULL
)
4838 DestroyFileSystemList(FileSystemList
);
4839 FileSystemList
= NULL
;
4842 /* Destroy the computer settings list */
4843 if (ComputerList
!= NULL
)
4845 DestroyGenericList(ComputerList
, TRUE
);
4846 ComputerList
= NULL
;
4849 /* Destroy the display settings list */
4850 if (DisplayList
!= NULL
)
4852 DestroyGenericList(DisplayList
, TRUE
);
4856 /* Destroy the keyboard settings list */
4857 if (KeyboardList
!= NULL
)
4859 DestroyGenericList(KeyboardList
, TRUE
);
4860 KeyboardList
= NULL
;
4863 /* Destroy the keyboard layout list */
4864 if (LayoutList
!= NULL
)
4866 DestroyGenericList(LayoutList
, TRUE
);
4870 /* Destroy the languages list */
4871 if (LanguageList
!= NULL
)
4873 DestroyGenericList(LanguageList
, FALSE
);
4874 LanguageList
= NULL
;
4877 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4879 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4880 ProgressCountdown(Ir
, 15);
4886 * Displays the SuccessPage.
4889 * FlushPage (At once)
4895 * Number of the next page.
4898 SuccessPage(PINPUT_RECORD Ir
)
4900 MUIDisplayPage(SUCCESS_PAGE
);
4902 if (IsUnattendedSetup
)
4905 /* Wait for maximum 15 seconds or an ENTER key before quitting */
4906 ProgressCountdown(Ir
, 15);
4912 * Displays the FlushPage.
4915 * RebootPage (At once)
4918 * Number of the next page.
4921 FlushPage(PINPUT_RECORD Ir
)
4923 MUIDisplayPage(FLUSH_PAGE
);
4929 PnpEventThread(IN LPVOID lpParameter
);
4933 * The start routine and page management
4943 InfSetHeap(ProcessHeap
);
4945 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
4946 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4947 if (!NT_SUCCESS(Status
))
4948 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
4950 /* Create the PnP thread in suspended state */
4951 Status
= RtlCreateUserThread(NtCurrentProcess(),
4961 if (!NT_SUCCESS(Status
))
4964 if (!CONSOLE_Init())
4966 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4967 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4968 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4970 /* We failed to initialize the video, just quit the installer */
4971 return STATUS_APP_INIT_FAILURE
;
4974 /* Initialize global unicode strings */
4975 RtlInitUnicodeString(&USetupData
.SourcePath
, NULL
);
4976 RtlInitUnicodeString(&USetupData
.SourceRootPath
, NULL
);
4977 RtlInitUnicodeString(&USetupData
.SourceRootDir
, NULL
);
4978 RtlInitUnicodeString(&InstallPath
, NULL
);
4979 RtlInitUnicodeString(&USetupData
.DestinationPath
, NULL
);
4980 RtlInitUnicodeString(&USetupData
.DestinationArcPath
, NULL
);
4981 RtlInitUnicodeString(&USetupData
.DestinationRootPath
, NULL
);
4982 RtlInitUnicodeString(&USetupData
.SystemRootPath
, NULL
);
4984 /* Hide the cursor */
4985 CONSOLE_SetCursorType(TRUE
, FALSE
);
4987 /* Global Initialization page */
4988 CONSOLE_ClearScreen();
4990 Page
= SetupStartPage(&Ir
);
4992 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4994 CONSOLE_ClearScreen();
4997 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
5004 Page
= LanguagePage(&Ir
);
5009 Page
= WelcomePage(&Ir
);
5014 Page
= LicensePage(&Ir
);
5018 case INSTALL_INTRO_PAGE
:
5019 Page
= InstallIntroPage(&Ir
);
5023 case SCSI_CONTROLLER_PAGE
:
5024 Page
= ScsiControllerPage(&Ir
);
5027 case OEM_DRIVER_PAGE
:
5028 Page
= OemDriverPage(&Ir
);
5032 case DEVICE_SETTINGS_PAGE
:
5033 Page
= DeviceSettingsPage(&Ir
);
5036 case COMPUTER_SETTINGS_PAGE
:
5037 Page
= ComputerSettingsPage(&Ir
);
5040 case DISPLAY_SETTINGS_PAGE
:
5041 Page
= DisplaySettingsPage(&Ir
);
5044 case KEYBOARD_SETTINGS_PAGE
:
5045 Page
= KeyboardSettingsPage(&Ir
);
5048 case LAYOUT_SETTINGS_PAGE
:
5049 Page
= LayoutSettingsPage(&Ir
);
5052 case SELECT_PARTITION_PAGE
:
5053 Page
= SelectPartitionPage(&Ir
);
5056 case CREATE_PRIMARY_PARTITION_PAGE
:
5057 Page
= CreatePrimaryPartitionPage(&Ir
);
5060 case CREATE_EXTENDED_PARTITION_PAGE
:
5061 Page
= CreateExtendedPartitionPage(&Ir
);
5064 case CREATE_LOGICAL_PARTITION_PAGE
:
5065 Page
= CreateLogicalPartitionPage(&Ir
);
5068 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
5069 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
5072 case DELETE_PARTITION_PAGE
:
5073 Page
= DeletePartitionPage(&Ir
);
5076 case SELECT_FILE_SYSTEM_PAGE
:
5077 Page
= SelectFileSystemPage(&Ir
);
5080 case FORMAT_PARTITION_PAGE
:
5081 Page
= FormatPartitionPage(&Ir
);
5084 case CHECK_FILE_SYSTEM_PAGE
:
5085 Page
= CheckFileSystemPage(&Ir
);
5088 case INSTALL_DIRECTORY_PAGE
:
5089 Page
= InstallDirectoryPage(&Ir
);
5092 case PREPARE_COPY_PAGE
:
5093 Page
= PrepareCopyPage(&Ir
);
5096 case FILE_COPY_PAGE
:
5097 Page
= FileCopyPage(&Ir
);
5101 Page
= RegistryPage(&Ir
);
5104 case BOOT_LOADER_PAGE
:
5105 Page
= BootLoaderPage(&Ir
);
5108 case BOOT_LOADER_FLOPPY_PAGE
:
5109 Page
= BootLoaderFloppyPage(&Ir
);
5112 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
5113 Page
= BootLoaderHarddiskMbrPage(&Ir
);
5116 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
5117 Page
= BootLoaderHarddiskVbrPage(&Ir
);
5121 case REPAIR_INTRO_PAGE
:
5122 Page
= RepairIntroPage(&Ir
);
5125 case UPGRADE_REPAIR_PAGE
:
5126 Page
= UpgradeRepairPage(&Ir
);
5130 Page
= SuccessPage(&Ir
);
5134 Page
= FlushPage(&Ir
);
5138 Page
= QuitPage(&Ir
);
5147 SetupCloseInfFile(SetupInf
);
5149 if (Page
== RECOVERY_PAGE
)
5155 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
5156 NtShutdownSystem(ShutdownReboot
);
5157 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
5159 return STATUS_SUCCESS
;
5164 NtProcessStartup(PPEB Peb
)
5169 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
5171 ProcessHeap
= Peb
->ProcessHeap
;
5173 NtQuerySystemTime(&Time
);
5175 Status
= RunUSetup();
5177 if (NT_SUCCESS(Status
))
5180 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
5181 * a protective waiting.
5182 * This wait is needed because, since we are started as SMSS.EXE,
5183 * the NT kernel explicitly waits 5 seconds for the initial process
5184 * SMSS.EXE to initialize (as a protective measure), and otherwise
5185 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
5187 Time
.QuadPart
+= 50000000;
5188 NtDelayExecution(FALSE
, &Time
);
5192 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
5193 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
5194 0, 0, NULL
, 0, NULL
);
5197 NtTerminateProcess(NtCurrentProcess(), Status
);