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)
45 /* GLOBALS ******************************************************************/
49 static UNICODE_STRING SourceRootPath
;
50 static UNICODE_STRING SourceRootDir
;
51 /* static */ UNICODE_STRING SourcePath
;
53 BOOLEAN IsUnattendedSetup
= FALSE
;
54 LONG UnattendDestinationDiskNumber
;
55 LONG UnattendDestinationPartitionNumber
;
56 LONG UnattendMBRInstallType
= -1;
57 LONG UnattendFormatPartition
= 0;
58 LONG AutoPartition
= 0;
59 WCHAR UnattendInstallationDirectory
[MAX_PATH
];
60 PWCHAR SelectedLanguageId
;
62 WCHAR DefaultLanguage
[20];
63 WCHAR DefaultKBLayout
[20];
64 static BOOLEAN RepairUpdateFlag
= FALSE
;
65 static HANDLE hPnpThread
= INVALID_HANDLE_VALUE
;
67 static PPARTLIST PartitionList
= NULL
;
68 static PPARTENTRY TempPartition
= NULL
;
69 static FORMATMACHINESTATE FormatState
= Start
;
72 /* LOCALS *******************************************************************/
74 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
76 static UNICODE_STRING InstallPath
;
79 * Path to the system partition, where the boot manager resides.
80 * On x86 PCs, this is usually the active partition.
81 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
83 * For more information, see:
84 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
85 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
86 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
87 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
88 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
89 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
91 static UNICODE_STRING SystemRootPath
;
93 /* Path to the install directory inside the ReactOS boot partition */
94 static UNICODE_STRING DestinationPath
;
95 static UNICODE_STRING DestinationArcPath
;
96 static UNICODE_STRING DestinationRootPath
;
98 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
99 static WCHAR DestinationDriveLetter
;
101 static HINF SetupInf
;
103 static HSPFILEQ SetupFileQueue
= NULL
;
105 static PNTOS_INSTALLATION CurrentInstallation
= NULL
;
106 static PGENERIC_LIST NtOsInstallsList
= NULL
;
108 static PGENERIC_LIST ComputerList
= NULL
;
109 static PGENERIC_LIST DisplayList
= NULL
;
110 static PGENERIC_LIST KeyboardList
= NULL
;
111 static PGENERIC_LIST LayoutList
= NULL
;
112 static PGENERIC_LIST LanguageList
= NULL
;
114 static LANGID LanguageId
= 0;
116 static ULONG RequiredPartitionDiskSpace
= ~0;
118 /* FUNCTIONS ****************************************************************/
121 PrintString(char* fmt
,...)
125 UNICODE_STRING UnicodeString
;
126 ANSI_STRING AnsiString
;
129 vsprintf(buffer
, fmt
, ap
);
132 RtlInitAnsiString(&AnsiString
, buffer
);
133 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
134 NtDisplayString(&UnicodeString
);
135 RtlFreeUnicodeString(&UnicodeString
);
140 DrawBox(IN SHORT xLeft
,
148 /* draw upper left corner */
151 FillConsoleOutputCharacterA(StdOutput
,
157 /* draw upper edge */
160 FillConsoleOutputCharacterA(StdOutput
,
166 /* draw upper right corner */
167 coPos
.X
= xLeft
+ Width
- 1;
169 FillConsoleOutputCharacterA(StdOutput
,
175 /* Draw right edge, inner space and left edge */
176 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
179 FillConsoleOutputCharacterA(StdOutput
,
186 FillConsoleOutputCharacterA(StdOutput
,
192 coPos
.X
= xLeft
+ Width
- 1;
193 FillConsoleOutputCharacterA(StdOutput
,
200 /* draw lower left corner */
202 coPos
.Y
= yTop
+ Height
- 1;
203 FillConsoleOutputCharacterA(StdOutput
,
209 /* draw lower edge */
211 coPos
.Y
= yTop
+ Height
- 1;
212 FillConsoleOutputCharacterA(StdOutput
,
218 /* draw lower right corner */
219 coPos
.X
= xLeft
+ Width
- 1;
220 coPos
.Y
= yTop
+ Height
- 1;
221 FillConsoleOutputCharacterA(StdOutput
,
230 PopupError(PCCH Text
,
248 /* Count text lines and longest line */
255 p
= strchr(pnext
, '\n');
259 Length
= strlen(pnext
);
264 Length
= (ULONG
)(p
- pnext
);
270 if (Length
> MaxLength
)
273 if (LastLine
!= FALSE
)
279 /* Check length of status line */
282 Length
= strlen(Status
);
284 if (Length
> MaxLength
)
288 Width
= MaxLength
+ 4;
294 yTop
= (yScreen
- Height
) / 2;
295 xLeft
= (xScreen
- Width
) / 2;
298 /* Set screen attributes */
300 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
302 FillConsoleOutputAttribute(StdOutput
,
303 FOREGROUND_RED
| BACKGROUND_WHITE
,
309 DrawBox(xLeft
, yTop
, Width
, Height
);
311 /* Print message text */
316 p
= strchr(pnext
, '\n');
320 Length
= strlen(pnext
);
325 Length
= (ULONG
)(p
- pnext
);
332 WriteConsoleOutputCharacterA(StdOutput
,
339 if (LastLine
!= FALSE
)
346 /* Print separator line and status text */
349 coPos
.Y
= yTop
+ Height
- 3;
351 FillConsoleOutputCharacterA(StdOutput
,
358 FillConsoleOutputCharacterA(StdOutput
,
364 coPos
.X
= xLeft
+ Width
- 1;
365 FillConsoleOutputCharacterA(StdOutput
,
373 WriteConsoleOutputCharacterA(StdOutput
,
375 min(strlen(Status
), (SIZE_T
)Width
- 4),
380 if (WaitEvent
== POPUP_WAIT_NONE
)
385 CONSOLE_ConInKey(Ir
);
387 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
388 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
400 * FALSE: Don't quit setup.
403 ConfirmQuit(PINPUT_RECORD Ir
)
406 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
410 CONSOLE_ConInKey(Ir
);
412 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
413 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
418 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
430 CheckUnattendedSetup(VOID
)
432 WCHAR UnattendInfPath
[MAX_PATH
];
439 CombinePaths(UnattendInfPath
, ARRAYSIZE(UnattendInfPath
), 2, SourcePath
.Buffer
, L
"unattend.inf");
441 if (DoesFileExist(NULL
, UnattendInfPath
) == FALSE
)
443 DPRINT("Does not exist: %S\n", UnattendInfPath
);
447 /* Load 'unattend.inf' from install media. */
448 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
454 if (UnattendInf
== INVALID_HANDLE_VALUE
)
456 DPRINT("SetupOpenInfFileW() failed\n");
460 /* Open 'Unattend' section */
461 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
463 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
464 SetupCloseInfFile(UnattendInf
);
468 /* Get pointer 'Signature' key */
469 if (!INF_GetData(&Context
, NULL
, &Value
))
471 DPRINT("INF_GetData() failed for key 'Signature'\n");
472 SetupCloseInfFile(UnattendInf
);
476 /* Check 'Signature' string */
477 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
479 DPRINT("Signature not $ReactOS$\n");
480 SetupCloseInfFile(UnattendInf
);
484 /* Check if Unattend setup is enabled */
485 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
487 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
488 SetupCloseInfFile(UnattendInf
);
492 if (!INF_GetData(&Context
, NULL
, &Value
))
494 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
495 SetupCloseInfFile(UnattendInf
);
499 if (_wcsicmp(Value
, L
"yes") != 0)
501 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
502 SetupCloseInfFile(UnattendInf
);
506 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
507 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
509 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
510 SetupCloseInfFile(UnattendInf
);
514 if (!SetupGetIntField(&Context
, 1, &IntValue
))
516 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
517 SetupCloseInfFile(UnattendInf
);
521 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
523 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
524 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
526 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
527 SetupCloseInfFile(UnattendInf
);
531 if (!SetupGetIntField(&Context
, 1, &IntValue
))
533 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
534 SetupCloseInfFile(UnattendInf
);
538 UnattendDestinationPartitionNumber
= (LONG
)IntValue
;
540 /* Search for 'InstallationDirectory' in the 'Unattend' section */
541 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
543 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
544 SetupCloseInfFile(UnattendInf
);
548 /* Get pointer 'InstallationDirectory' key */
549 if (!INF_GetData(&Context
, NULL
, &Value
))
551 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
552 SetupCloseInfFile(UnattendInf
);
556 wcscpy(UnattendInstallationDirectory
, Value
);
558 IsUnattendedSetup
= TRUE
;
559 DPRINT("Running unattended setup\n");
561 /* Search for 'MBRInstallType' in the 'Unattend' section */
562 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
564 if (SetupGetIntField(&Context
, 1, &IntValue
))
566 UnattendMBRInstallType
= IntValue
;
570 /* Search for 'FormatPartition' in the 'Unattend' section */
571 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
573 if (SetupGetIntField(&Context
, 1, &IntValue
))
575 UnattendFormatPartition
= IntValue
;
579 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
581 if (SetupGetIntField(&Context
, 1, &IntValue
))
583 AutoPartition
= IntValue
;
587 /* search for LocaleID in the 'Unattend' section*/
588 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
590 if (INF_GetData(&Context
, NULL
, &Value
))
592 LONG Id
= wcstol(Value
, NULL
, 16);
593 swprintf(LocaleID
, L
"%08lx", Id
);
597 SetupCloseInfFile(UnattendInf
);
604 PGENERIC_LIST_ENTRY ListEntry
;
605 LPCWSTR pszNewLayout
;
607 pszNewLayout
= MUIDefaultKeyboardLayout();
609 if (LayoutList
== NULL
)
611 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
612 if (LayoutList
== NULL
)
614 /* FIXME: Handle error! */
619 ListEntry
= GetFirstListEntry(LayoutList
);
621 /* Search for default layout (if provided) */
622 if (pszNewLayout
!= NULL
)
624 while (ListEntry
!= NULL
)
626 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
628 SetCurrentListEntry(LayoutList
, ListEntry
);
632 ListEntry
= GetNextListEntry(ListEntry
);
639 * Displays the LanguagePage.
641 * Next pages: WelcomePage, QuitPage
644 * Init SelectedLanguageId
648 * Number of the next page.
651 LanguagePage(PINPUT_RECORD Ir
)
653 GENERIC_LIST_UI ListUi
;
654 PWCHAR NewLanguageId
;
655 BOOL RefreshPage
= FALSE
;
657 /* Initialize the computer settings list */
658 if (LanguageList
== NULL
)
660 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
661 if (LanguageList
== NULL
)
663 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
669 SelectedLanguageId
= DefaultLanguage
;
670 SetConsoleCodePage();
673 /* If there's just a single language in the list skip
674 * the language selection process altogether! */
675 if (GenericListHasSingleEntry(LanguageList
))
677 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
681 InitGenericListUi(&ListUi
, LanguageList
);
682 DrawGenericList(&ListUi
,
688 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
690 MUIDisplayPage(LANGUAGE_PAGE
);
694 CONSOLE_ConInKey(Ir
);
696 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
697 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
699 ScrollDownGenericList(&ListUi
);
702 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
703 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
705 ScrollUpGenericList(&ListUi
);
708 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
709 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
711 ScrollPageDownGenericList(&ListUi
);
714 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
715 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
717 ScrollPageUpGenericList(&ListUi
);
720 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
721 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
723 if (ConfirmQuit(Ir
) != FALSE
)
726 RedrawGenericList(&ListUi
);
728 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
730 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
732 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
734 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
740 SetConsoleCodePage();
744 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
747 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
753 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
755 if (SelectedLanguageId
!= NewLanguageId
)
757 /* Clear the language page */
758 MUIClearPage(LANGUAGE_PAGE
);
760 SelectedLanguageId
= NewLanguageId
;
763 SetConsoleCodePage();
765 /* Redraw language selection page in native language */
766 MUIDisplayPage(LANGUAGE_PAGE
);
781 * LanguagePage (at once, default)
782 * InstallIntroPage (at once, if unattended)
788 * Init SourceRootPath
791 * Init RequiredPartitionDiskSpace
792 * Init IsUnattendedSetup
793 * If unattended, init *List and sets the Codepage
794 * If unattended, init SelectedLanguageId
795 * If unattended, init LanguageId
798 * Number of the next page.
801 SetupStartPage(PINPUT_RECORD Ir
)
804 WCHAR FileNameBuffer
[MAX_PATH
];
808 PGENERIC_LIST_ENTRY ListEntry
;
811 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
813 /* Get the source path and source root path */
814 Status
= GetSourcePaths(&SourcePath
,
817 if (!NT_SUCCESS(Status
))
819 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
820 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
823 DPRINT1("SourcePath: '%wZ'\n", &SourcePath
);
824 DPRINT1("SourceRootPath: '%wZ'\n", &SourceRootPath
);
825 DPRINT1("SourceRootDir: '%wZ'\n", &SourceRootDir
);
827 /* Load txtsetup.sif from install media. */
828 CombinePaths(FileNameBuffer
, ARRAYSIZE(FileNameBuffer
), 2, SourcePath
.Buffer
, L
"txtsetup.sif");
829 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
835 if (SetupInf
== INVALID_HANDLE_VALUE
)
837 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
841 /* Open 'Version' section */
842 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
844 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
848 /* Get pointer 'Signature' key */
849 if (!INF_GetData(&Context
, NULL
, &Value
))
851 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
855 /* Check 'Signature' string */
856 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
858 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
862 /* Open 'DiskSpaceRequirements' section */
863 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
865 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
869 /* Get the 'FreeSysPartDiskSpace' value */
870 if (!SetupGetIntField(&Context
, 1, &IntValue
))
872 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
876 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
878 /* Start the PnP thread */
879 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
881 NtResumeThread(hPnpThread
, NULL
);
882 hPnpThread
= INVALID_HANDLE_VALUE
;
885 CheckUnattendedSetup();
887 if (IsUnattendedSetup
)
889 // TODO: Read options from inf
890 ComputerList
= CreateComputerTypeList(SetupInf
);
891 DisplayList
= CreateDisplayDriverList(SetupInf
);
892 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
893 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
894 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
897 wcscpy(SelectedLanguageId
, LocaleID
);
898 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
900 /* first we hack LanguageList */
901 ListEntry
= GetFirstListEntry(LanguageList
);
902 while (ListEntry
!= NULL
)
904 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
906 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
907 SetCurrentListEntry(LanguageList
, ListEntry
);
911 ListEntry
= GetNextListEntry(ListEntry
);
915 ListEntry
= GetFirstListEntry(LayoutList
);
916 while (ListEntry
!= NULL
)
918 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
920 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
921 SetCurrentListEntry(LayoutList
, ListEntry
);
925 ListEntry
= GetNextListEntry(ListEntry
);
928 SetConsoleCodePage();
930 return INSTALL_INTRO_PAGE
;
933 return LANGUAGE_PAGE
;
938 * Displays the WelcomePage.
941 * InstallIntroPage (default)
948 * Number of the next page.
951 WelcomePage(PINPUT_RECORD Ir
)
953 MUIDisplayPage(WELCOME_PAGE
);
957 CONSOLE_ConInKey(Ir
);
959 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
960 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
962 if (ConfirmQuit(Ir
) != FALSE
)
967 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
969 return INSTALL_INTRO_PAGE
;
971 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
973 return RECOVERY_PAGE
; // REPAIR_INTRO_PAGE;
975 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
986 * Displays the License page.
989 * WelcomePage (default)
992 * Number of the next page.
995 LicensePage(PINPUT_RECORD Ir
)
997 MUIDisplayPage(LICENSE_PAGE
);
1001 CONSOLE_ConInKey(Ir
);
1003 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1005 return WELCOME_PAGE
;
1009 return LICENSE_PAGE
;
1014 * Displays the RepairIntroPage.
1017 * RebootPage (default)
1023 * Number of the next page.
1026 RepairIntroPage(PINPUT_RECORD Ir
)
1028 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1032 CONSOLE_ConInKey(Ir
);
1034 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1038 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1040 RepairUpdateFlag
= TRUE
;
1041 return INSTALL_INTRO_PAGE
;
1043 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1045 return RECOVERY_PAGE
;
1047 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1048 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1050 return WELCOME_PAGE
;
1054 return REPAIR_INTRO_PAGE
;
1058 * Displays the UpgradeRepairPage.
1061 * RebootPage (default)
1067 * Number of the next page.
1070 UpgradeRepairPage(PINPUT_RECORD Ir
)
1072 GENERIC_LIST_UI ListUi
;
1075 if (PartitionList
== NULL
)
1077 PartitionList
= CreatePartitionList();
1078 if (PartitionList
== NULL
)
1080 /* FIXME: show an error dialog */
1081 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1084 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1086 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1090 TempPartition
= NULL
;
1091 FormatState
= Start
;
1095 NtOsInstallsList
= CreateNTOSInstallationsList(PartitionList
);
1096 if (!NtOsInstallsList
)
1097 DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
1098 if (!NtOsInstallsList
|| GetNumberOfListEntries(NtOsInstallsList
) == 0)
1100 RepairUpdateFlag
= FALSE
;
1102 // return INSTALL_INTRO_PAGE;
1103 return DEVICE_SETTINGS_PAGE
;
1104 // return SCSI_CONTROLLER_PAGE;
1107 MUIDisplayPage(UPGRADE_REPAIR_PAGE
);
1109 InitGenericListUi(&ListUi
, NtOsInstallsList
);
1110 DrawGenericList(&ListUi
,
1115 SaveGenericListState(NtOsInstallsList
);
1117 // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
1120 CONSOLE_ConInKey(Ir
);
1122 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00)
1124 switch (Ir
->Event
.KeyEvent
.wVirtualKeyCode
)
1126 case VK_DOWN
: /* DOWN */
1127 ScrollDownGenericList(&ListUi
);
1129 case VK_UP
: /* UP */
1130 ScrollUpGenericList(&ListUi
);
1132 case VK_NEXT
: /* PAGE DOWN */
1133 ScrollPageDownGenericList(&ListUi
);
1135 case VK_PRIOR
: /* PAGE UP */
1136 ScrollPageUpGenericList(&ListUi
);
1138 case VK_F3
: /* F3 */
1140 if (ConfirmQuit(Ir
) == TRUE
)
1143 RedrawGenericList(&ListUi
);
1146 case VK_ESCAPE
: /* ESC */
1148 RestoreGenericListState(NtOsInstallsList
);
1149 // return nextPage; // prevPage;
1151 // return INSTALL_INTRO_PAGE;
1152 return DEVICE_SETTINGS_PAGE
;
1153 // return SCSI_CONTROLLER_PAGE;
1159 // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar))
1160 // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
1161 if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1163 /* Retrieve the current installation */
1164 CurrentInstallation
= (PNTOS_INSTALLATION
)GetListEntryUserData(GetCurrentListEntry(NtOsInstallsList
));
1165 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
1166 CurrentInstallation
->InstallationName
, CurrentInstallation
->DiskNumber
, CurrentInstallation
->PartitionNumber
);
1168 RepairUpdateFlag
= TRUE
;
1171 /***/return INSTALL_INTRO_PAGE
;/***/
1173 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) &&
1174 (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b)) /* a-z */
1176 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1181 return UPGRADE_REPAIR_PAGE
;
1186 * Displays the InstallIntroPage.
1189 * DeviceSettingsPage (At once if repair or update is selected)
1190 * SelectPartitionPage (At once if unattended setup)
1191 * DeviceSettingsPage (default)
1195 * Number of the next page.
1198 InstallIntroPage(PINPUT_RECORD Ir
)
1200 if (RepairUpdateFlag
)
1202 #if 1 /* Old code that looks good */
1204 // return SELECT_PARTITION_PAGE;
1205 return DEVICE_SETTINGS_PAGE
;
1207 #else /* Possible new code? */
1209 return DEVICE_SETTINGS_PAGE
;
1210 // return SCSI_CONTROLLER_PAGE;
1215 if (IsUnattendedSetup
)
1216 return SELECT_PARTITION_PAGE
;
1218 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1222 CONSOLE_ConInKey(Ir
);
1224 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1225 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1227 if (ConfirmQuit(Ir
) != FALSE
)
1232 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1234 return UPGRADE_REPAIR_PAGE
;
1238 return INSTALL_INTRO_PAGE
;
1244 ScsiControllerPage(PINPUT_RECORD Ir
)
1246 // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
1248 CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1250 /* FIXME: print loaded mass storage driver descriptions */
1252 CONSOLE_SetTextXY(8, 10, "TEST device");
1255 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1259 CONSOLE_ConInKey(Ir
);
1261 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1262 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1264 if (ConfirmQuit(Ir
) != FALSE
)
1269 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1271 return DEVICE_SETTINGS_PAGE
;
1275 return SCSI_CONTROLLER_PAGE
;
1279 OemDriverPage(PINPUT_RECORD Ir
)
1281 // MUIDisplayPage(OEM_DRIVER_PAGE);
1283 CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
1285 /* FIXME: Implement!! */
1287 CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit");
1291 CONSOLE_ConInKey(Ir
);
1293 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1294 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1296 if (ConfirmQuit(Ir
) == TRUE
)
1301 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1303 return DEVICE_SETTINGS_PAGE
;
1307 return OEM_DRIVER_PAGE
;
1313 * Displays the DeviceSettingsPage.
1316 * SelectPartitionPage (At once if repair or update is selected)
1317 * ComputerSettingsPage
1318 * DisplaySettingsPage
1319 * KeyboardSettingsPage
1320 * LayoutsettingsPage
1321 * SelectPartitionPage
1331 * Number of the next page.
1334 DeviceSettingsPage(PINPUT_RECORD Ir
)
1336 static ULONG Line
= 16;
1338 /* Initialize the computer settings list */
1339 if (ComputerList
== NULL
)
1341 ComputerList
= CreateComputerTypeList(SetupInf
);
1342 if (ComputerList
== NULL
)
1344 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1349 /* Initialize the display settings list */
1350 if (DisplayList
== NULL
)
1352 DisplayList
= CreateDisplayDriverList(SetupInf
);
1353 if (DisplayList
== NULL
)
1355 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1360 /* Initialize the keyboard settings list */
1361 if (KeyboardList
== NULL
)
1363 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1364 if (KeyboardList
== NULL
)
1366 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1371 /* Initialize the keyboard layout list */
1372 if (LayoutList
== NULL
)
1374 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1375 if (LayoutList
== NULL
)
1377 /* FIXME: report error */
1378 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1383 if (RepairUpdateFlag
)
1384 return SELECT_PARTITION_PAGE
;
1386 // if (IsUnattendedSetup)
1387 // return SELECT_PARTITION_PAGE;
1389 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1391 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry(ComputerList
)));
1392 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry(DisplayList
)));
1393 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry(KeyboardList
)));
1394 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry(LayoutList
)));
1396 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1400 CONSOLE_ConInKey(Ir
);
1402 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1403 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1405 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1409 else if (Line
== 16)
1414 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1416 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1417 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1419 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1423 else if (Line
== 16)
1428 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1430 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1431 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1433 if (ConfirmQuit(Ir
) != FALSE
)
1438 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1441 return COMPUTER_SETTINGS_PAGE
;
1442 else if (Line
== 12)
1443 return DISPLAY_SETTINGS_PAGE
;
1444 else if (Line
== 13)
1445 return KEYBOARD_SETTINGS_PAGE
;
1446 else if (Line
== 14)
1447 return LAYOUT_SETTINGS_PAGE
;
1448 else if (Line
== 16)
1449 return SELECT_PARTITION_PAGE
;
1453 return DEVICE_SETTINGS_PAGE
;
1458 * Handles generic selection lists.
1461 * GenericList: The list to handle.
1462 * nextPage: The page it needs to jump to after this page.
1463 * Ir: The PINPUT_RECORD
1466 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1467 PAGE_NUMBER nextPage
,
1472 CONSOLE_ConInKey(Ir
);
1474 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1475 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1477 ScrollDownGenericList(ListUi
);
1479 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1480 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1482 ScrollUpGenericList(ListUi
);
1484 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1485 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1487 ScrollPageDownGenericList(ListUi
);
1489 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1490 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1492 ScrollPageUpGenericList(ListUi
);
1494 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1495 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1497 if (ConfirmQuit(Ir
) != FALSE
)
1500 RedrawGenericList(ListUi
);
1502 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1503 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1505 RestoreGenericListState(ListUi
->List
);
1506 return nextPage
; // Use some "prevPage;" instead?
1508 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1512 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1515 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1522 * Displays the ComputerSettingsPage.
1525 * DeviceSettingsPage
1529 * Number of the next page.
1532 ComputerSettingsPage(PINPUT_RECORD Ir
)
1534 GENERIC_LIST_UI ListUi
;
1535 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1537 InitGenericListUi(&ListUi
, ComputerList
);
1538 DrawGenericList(&ListUi
,
1544 SaveGenericListState(ComputerList
);
1546 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1551 * Displays the DisplaySettingsPage.
1554 * DeviceSettingsPage
1558 * Number of the next page.
1561 DisplaySettingsPage(PINPUT_RECORD Ir
)
1563 GENERIC_LIST_UI ListUi
;
1564 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1566 InitGenericListUi(&ListUi
, DisplayList
);
1567 DrawGenericList(&ListUi
,
1573 SaveGenericListState(DisplayList
);
1575 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1580 * Displays the KeyboardSettingsPage.
1583 * DeviceSettingsPage
1587 * Number of the next page.
1590 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1592 GENERIC_LIST_UI ListUi
;
1593 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1595 InitGenericListUi(&ListUi
, KeyboardList
);
1596 DrawGenericList(&ListUi
,
1602 SaveGenericListState(KeyboardList
);
1604 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1609 * Displays the LayoutSettingsPage.
1612 * DeviceSettingsPage
1616 * Number of the next page.
1619 LayoutSettingsPage(PINPUT_RECORD Ir
)
1621 GENERIC_LIST_UI ListUi
;
1622 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1624 InitGenericListUi(&ListUi
, LayoutList
);
1625 DrawGenericList(&ListUi
,
1631 SaveGenericListState(LayoutList
);
1633 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1638 IsDiskSizeValid(PPARTENTRY PartEntry
)
1642 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1643 size
= (size
+ 524288) / 1048576; /* in MBytes */
1645 if (size
< RequiredPartitionDiskSpace
)
1647 /* Partition is too small so ask for another one */
1648 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1659 * Displays the SelectPartitionPage.
1662 * SelectFileSystemPage (At once if unattended)
1663 * SelectFileSystemPage (Default if free space is selected)
1664 * CreatePrimaryPartitionPage
1665 * CreateExtendedPartitionPage
1666 * CreateLogicalPartitionPage
1667 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1668 * DeletePartitionPage
1672 * Set InstallShortcut (only if not unattended + free space is selected)
1675 * Number of the next page.
1678 SelectPartitionPage(PINPUT_RECORD Ir
)
1683 if (PartitionList
== NULL
)
1685 PartitionList
= CreatePartitionList();
1686 if (PartitionList
== NULL
)
1688 /* FIXME: show an error dialog */
1689 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1692 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1694 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1698 TempPartition
= NULL
;
1699 FormatState
= Start
;
1702 if (RepairUpdateFlag
)
1704 /* Determine the selected installation disk & partition */
1705 if (!SelectPartition(PartitionList
,
1706 CurrentInstallation
->DiskNumber
,
1707 CurrentInstallation
->PartitionNumber
))
1709 DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
1713 return SELECT_FILE_SYSTEM_PAGE
;
1716 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1718 InitPartitionListUi(&ListUi
, PartitionList
,
1723 DrawPartitionList(&ListUi
);
1725 if (IsUnattendedSetup
)
1727 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1731 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1733 CreateLogicalPartition(PartitionList
,
1734 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1739 CreatePrimaryPartition(PartitionList
,
1740 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1744 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1745 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1747 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1748 RequiredPartitionDiskSpace
);
1749 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1752 return SELECT_FILE_SYSTEM_PAGE
;
1757 DrawPartitionList(&ListUi
);
1759 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1760 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1762 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1763 RequiredPartitionDiskSpace
);
1764 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1767 return SELECT_FILE_SYSTEM_PAGE
;
1773 /* Update status text */
1774 if (PartitionList
->CurrentPartition
== NULL
)
1776 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1778 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1780 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1782 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1786 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1791 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1793 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1795 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1799 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1804 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1808 CONSOLE_ConInKey(Ir
);
1810 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1811 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1813 if (ConfirmQuit(Ir
) != FALSE
)
1815 DestroyPartitionList(PartitionList
);
1816 PartitionList
= NULL
;
1822 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1823 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1825 ScrollDownPartitionList(&ListUi
);
1827 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1828 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1830 ScrollUpPartitionList(&ListUi
);
1832 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1834 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1835 continue; // return SELECT_PARTITION_PAGE;
1837 if (PartitionList
->CurrentPartition
== NULL
||
1838 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1840 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1842 CreateLogicalPartition(PartitionList
,
1848 CreatePrimaryPartition(PartitionList
,
1854 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1856 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1857 RequiredPartitionDiskSpace
);
1858 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1861 return SELECT_FILE_SYSTEM_PAGE
;
1863 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1865 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1867 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1868 if (Error
!= NOT_AN_ERROR
)
1870 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1871 return SELECT_PARTITION_PAGE
;
1874 return CREATE_PRIMARY_PARTITION_PAGE
;
1877 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1879 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1881 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1882 if (Error
!= NOT_AN_ERROR
)
1884 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1885 return SELECT_PARTITION_PAGE
;
1888 return CREATE_EXTENDED_PARTITION_PAGE
;
1891 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1893 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1895 Error
= LogicalPartitionCreationChecks(PartitionList
);
1896 if (Error
!= NOT_AN_ERROR
)
1898 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1899 return SELECT_PARTITION_PAGE
;
1902 return CREATE_LOGICAL_PARTITION_PAGE
;
1905 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1907 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1909 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1910 return SELECT_PARTITION_PAGE
;
1913 if (PartitionList
->CurrentPartition
->BootIndicator
||
1914 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1916 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1919 return DELETE_PARTITION_PAGE
;
1923 return SELECT_PARTITION_PAGE
;
1927 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1928 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1929 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1932 ShowPartitionSizeInputBox(SHORT Left
,
1956 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1961 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1962 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1965 WriteConsoleOutputCharacterA(StdOutput
,
1971 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1972 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1974 WriteConsoleOutputCharacterA(StdOutput
,
1980 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1981 Length
= wcslen(InputBuffer
);
1983 CONSOLE_SetInputTextXY(iLeft
,
1985 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1987 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1988 CONSOLE_SetCursorType(TRUE
, TRUE
);
1992 CONSOLE_ConInKey(&Ir
);
1994 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1995 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2000 InputBuffer
[0] = UNICODE_NULL
;
2001 CONSOLE_SetCursorType(TRUE
, FALSE
);
2004 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2006 CONSOLE_SetCursorType(TRUE
, FALSE
);
2009 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
2014 InputBuffer
[0] = UNICODE_NULL
;
2015 CONSOLE_SetCursorType(TRUE
, FALSE
);
2018 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2019 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
2022 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2024 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2025 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
2028 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2030 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2031 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
2036 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2039 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2040 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
2045 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2048 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2049 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
2053 memmove(&InputBuffer
[Pos
],
2054 &InputBuffer
[Pos
+ 1],
2055 (Length
- Pos
- 1) * sizeof(WCHAR
));
2056 InputBuffer
[Length
- 1] = UNICODE_NULL
;
2059 CONSOLE_SetInputTextXY(iLeft
,
2061 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2063 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2066 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
2071 memmove(&InputBuffer
[Pos
- 1],
2073 (Length
- Pos
) * sizeof(WCHAR
));
2074 InputBuffer
[Length
- 1] = UNICODE_NULL
;
2078 CONSOLE_SetInputTextXY(iLeft
,
2080 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2082 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2085 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
2087 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
2089 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
2091 if ((ch
>= L
'0') && (ch
<= L
'9'))
2094 memmove(&InputBuffer
[Pos
+ 1],
2096 (Length
- Pos
) * sizeof(WCHAR
));
2097 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
2098 InputBuffer
[Pos
] = ch
;
2102 CONSOLE_SetInputTextXY(iLeft
,
2104 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
2106 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
2115 * Displays the CreatePrimaryPartitionPage.
2118 * SelectPartitionPage
2119 * SelectFileSystemPage (default)
2123 * Number of the next page.
2126 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
2128 PDISKENTRY DiskEntry
;
2129 PPARTENTRY PartEntry
;
2132 WCHAR InputBuffer
[50];
2136 ULONGLONG SectorCount
;
2139 if (PartitionList
== NULL
||
2140 PartitionList
->CurrentDisk
== NULL
||
2141 PartitionList
->CurrentPartition
== NULL
)
2143 /* FIXME: show an error dialog */
2147 DiskEntry
= PartitionList
->CurrentDisk
;
2148 PartEntry
= PartitionList
->CurrentPartition
;
2150 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2152 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
2154 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2156 if (DiskSize
>= 10737418240) /* 10 GB */
2158 DiskSize
= DiskSize
/ 1073741824;
2159 Unit
= MUIGetString(STRING_GB
);
2164 DiskSize
= DiskSize
/ 1048576;
2168 Unit
= MUIGetString(STRING_MB
);
2171 if (DiskEntry
->DriverName
.Length
> 0)
2173 CONSOLE_PrintTextXY(6, 10,
2174 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2177 DiskEntry
->DiskNumber
,
2181 &DiskEntry
->DriverName
,
2182 DiskEntry
->NoMbr
? "GPT" : "MBR");
2186 CONSOLE_PrintTextXY(6, 10,
2187 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2190 DiskEntry
->DiskNumber
,
2194 DiskEntry
->NoMbr
? "GPT" : "MBR");
2197 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2200 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2201 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2204 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2206 PartEntry
= PartitionList
->CurrentPartition
;
2209 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2211 if (MaxSize
> PARTITION_MAXSIZE
)
2212 MaxSize
= PARTITION_MAXSIZE
;
2214 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2215 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2219 if (ConfirmQuit(Ir
) != FALSE
)
2224 else if (Cancel
!= FALSE
)
2226 return SELECT_PARTITION_PAGE
;
2230 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2238 if (PartSize
> MaxSize
)
2244 /* Convert to bytes */
2245 if (PartSize
== MaxSize
)
2247 /* Use all of the unpartitioned disk space */
2248 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2252 /* Calculate the sector count from the size in MB */
2253 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2255 /* But never get larger than the unpartitioned disk space */
2256 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2257 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2260 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2262 CreatePrimaryPartition(PartitionList
,
2266 return SELECT_PARTITION_PAGE
;
2270 return CREATE_PRIMARY_PARTITION_PAGE
;
2275 * Displays the CreateExtendedPartitionPage.
2278 * SelectPartitionPage (default)
2282 * Number of the next page.
2285 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2287 PDISKENTRY DiskEntry
;
2288 PPARTENTRY PartEntry
;
2291 WCHAR InputBuffer
[50];
2295 ULONGLONG SectorCount
;
2298 if (PartitionList
== NULL
||
2299 PartitionList
->CurrentDisk
== NULL
||
2300 PartitionList
->CurrentPartition
== NULL
)
2302 /* FIXME: show an error dialog */
2306 DiskEntry
= PartitionList
->CurrentDisk
;
2307 PartEntry
= PartitionList
->CurrentPartition
;
2309 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2311 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2313 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2315 if (DiskSize
>= 10737418240) /* 10 GB */
2317 DiskSize
= DiskSize
/ 1073741824;
2318 Unit
= MUIGetString(STRING_GB
);
2323 DiskSize
= DiskSize
/ 1048576;
2327 Unit
= MUIGetString(STRING_MB
);
2330 if (DiskEntry
->DriverName
.Length
> 0)
2332 CONSOLE_PrintTextXY(6, 10,
2333 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2336 DiskEntry
->DiskNumber
,
2340 &DiskEntry
->DriverName
,
2341 DiskEntry
->NoMbr
? "GPT" : "MBR");
2345 CONSOLE_PrintTextXY(6, 10,
2346 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2349 DiskEntry
->DiskNumber
,
2353 DiskEntry
->NoMbr
? "GPT" : "MBR");
2356 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2359 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2360 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2363 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2365 PartEntry
= PartitionList
->CurrentPartition
;
2368 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2370 if (MaxSize
> PARTITION_MAXSIZE
)
2371 MaxSize
= PARTITION_MAXSIZE
;
2373 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2374 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2378 if (ConfirmQuit(Ir
) != FALSE
)
2383 else if (Cancel
!= FALSE
)
2385 return SELECT_PARTITION_PAGE
;
2389 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2397 if (PartSize
> MaxSize
)
2403 /* Convert to bytes */
2404 if (PartSize
== MaxSize
)
2406 /* Use all of the unpartitioned disk space */
2407 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2411 /* Calculate the sector count from the size in MB */
2412 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2414 /* But never get larger than the unpartitioned disk space */
2415 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2416 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2419 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2421 CreateExtendedPartition(PartitionList
,
2424 return SELECT_PARTITION_PAGE
;
2428 return CREATE_EXTENDED_PARTITION_PAGE
;
2433 * Displays the CreateLogicalPartitionPage.
2436 * SelectFileSystemPage (default)
2440 * Number of the next page.
2443 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2445 PDISKENTRY DiskEntry
;
2446 PPARTENTRY PartEntry
;
2449 WCHAR InputBuffer
[50];
2453 ULONGLONG SectorCount
;
2456 if (PartitionList
== NULL
||
2457 PartitionList
->CurrentDisk
== NULL
||
2458 PartitionList
->CurrentPartition
== NULL
)
2460 /* FIXME: show an error dialog */
2464 DiskEntry
= PartitionList
->CurrentDisk
;
2465 PartEntry
= PartitionList
->CurrentPartition
;
2467 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2469 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2471 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2473 if (DiskSize
>= 10737418240) /* 10 GB */
2475 DiskSize
= DiskSize
/ 1073741824;
2476 Unit
= MUIGetString(STRING_GB
);
2481 DiskSize
= DiskSize
/ 1048576;
2485 Unit
= MUIGetString(STRING_MB
);
2488 if (DiskEntry
->DriverName
.Length
> 0)
2490 CONSOLE_PrintTextXY(6, 10,
2491 MUIGetString(STRING_HDINFOPARTCREATE_1
),
2494 DiskEntry
->DiskNumber
,
2498 &DiskEntry
->DriverName
,
2499 DiskEntry
->NoMbr
? "GPT" : "MBR");
2503 CONSOLE_PrintTextXY(6, 10,
2504 MUIGetString(STRING_HDINFOPARTCREATE_2
),
2507 DiskEntry
->DiskNumber
,
2511 DiskEntry
->NoMbr
? "GPT" : "MBR");
2514 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2517 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2518 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2521 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2523 PartEntry
= PartitionList
->CurrentPartition
;
2526 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2528 if (MaxSize
> PARTITION_MAXSIZE
)
2529 MaxSize
= PARTITION_MAXSIZE
;
2531 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2532 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2536 if (ConfirmQuit(Ir
) != FALSE
)
2541 else if (Cancel
!= FALSE
)
2543 return SELECT_PARTITION_PAGE
;
2547 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2555 if (PartSize
> MaxSize
)
2561 /* Convert to bytes */
2562 if (PartSize
== MaxSize
)
2564 /* Use all of the unpartitioned disk space */
2565 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2569 /* Calculate the sector count from the size in MB */
2570 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2572 /* But never get larger than the unpartitioned disk space */
2573 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2574 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2577 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2579 CreateLogicalPartition(PartitionList
,
2583 return SELECT_PARTITION_PAGE
;
2587 return CREATE_LOGICAL_PARTITION_PAGE
;
2592 * Displays the ConfirmDeleteSystemPartitionPage.
2595 * DeletePartitionPage (default)
2596 * SelectPartitionPage
2599 * Number of the next page.
2602 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2604 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2608 CONSOLE_ConInKey(Ir
);
2610 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2611 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2613 if (ConfirmQuit(Ir
) == TRUE
)
2618 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2620 return DELETE_PARTITION_PAGE
;
2622 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2624 return SELECT_PARTITION_PAGE
;
2628 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2633 * Displays the DeletePartitionPage.
2636 * SelectPartitionPage (default)
2640 * Number of the next page.
2643 DeletePartitionPage(PINPUT_RECORD Ir
)
2645 PDISKENTRY DiskEntry
;
2646 PPARTENTRY PartEntry
;
2650 CHAR PartTypeString
[32];
2652 if (PartitionList
== NULL
||
2653 PartitionList
->CurrentDisk
== NULL
||
2654 PartitionList
->CurrentPartition
== NULL
)
2656 /* FIXME: show an error dialog */
2660 DiskEntry
= PartitionList
->CurrentDisk
;
2661 PartEntry
= PartitionList
->CurrentPartition
;
2663 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2665 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2667 ARRAYSIZE(PartTypeString
));
2669 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2671 if (PartSize
>= 10737418240) /* 10 GB */
2673 PartSize
= PartSize
/ 1073741824;
2674 Unit
= MUIGetString(STRING_GB
);
2678 if (PartSize
>= 10485760) /* 10 MB */
2680 PartSize
= PartSize
/ 1048576;
2681 Unit
= MUIGetString(STRING_MB
);
2685 PartSize
= PartSize
/ 1024;
2686 Unit
= MUIGetString(STRING_KB
);
2689 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2691 CONSOLE_PrintTextXY(6, 10,
2692 MUIGetString(STRING_HDDINFOUNK2
),
2693 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2694 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2695 PartEntry
->PartitionType
,
2701 CONSOLE_PrintTextXY(6, 10,
2702 " %c%c %s %I64u %s",
2703 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2704 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2710 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2712 if (DiskSize
>= 10737418240) /* 10 GB */
2714 DiskSize
= DiskSize
/ 1073741824;
2715 Unit
= MUIGetString(STRING_GB
);
2720 DiskSize
= DiskSize
/ 1048576;
2724 Unit
= MUIGetString(STRING_MB
);
2727 if (DiskEntry
->DriverName
.Length
> 0)
2729 CONSOLE_PrintTextXY(6, 12,
2730 MUIGetString(STRING_HDINFOPARTDELETE_1
),
2733 DiskEntry
->DiskNumber
,
2737 &DiskEntry
->DriverName
,
2738 DiskEntry
->NoMbr
? "GPT" : "MBR");
2742 CONSOLE_PrintTextXY(6, 12,
2743 MUIGetString(STRING_HDINFOPARTDELETE_2
),
2746 DiskEntry
->DiskNumber
,
2750 DiskEntry
->NoMbr
? "GPT" : "MBR");
2755 CONSOLE_ConInKey(Ir
);
2757 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2758 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2760 if (ConfirmQuit(Ir
) != FALSE
)
2765 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2767 return SELECT_PARTITION_PAGE
;
2769 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2771 DeleteCurrentPartition(PartitionList
);
2773 return SELECT_PARTITION_PAGE
;
2777 return DELETE_PARTITION_PAGE
;
2782 * Displays the SelectFileSystemPage.
2785 * CheckFileSystemPage (At once if RepairUpdate is selected)
2786 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2787 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2788 * SelectPartitionPage (If the user aborts)
2789 * FormatPartitionPage (Default)
2793 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2794 * Calls CheckActiveSystemPartition()
2797 * Number of the next page.
2800 SelectFileSystemPage(PINPUT_RECORD Ir
)
2802 PDISKENTRY DiskEntry
;
2803 PPARTENTRY PartEntry
;
2808 CHAR PartTypeString
[32];
2809 FORMATMACHINESTATE PreviousFormatState
;
2811 DPRINT("SelectFileSystemPage()\n");
2813 if (PartitionList
== NULL
||
2814 PartitionList
->CurrentDisk
== NULL
||
2815 PartitionList
->CurrentPartition
== NULL
)
2817 /* FIXME: show an error dialog */
2821 /* Find or set the active system partition */
2822 CheckActiveSystemPartition(PartitionList
);
2823 if (PartitionList
->SystemPartition
== NULL
)
2825 /* FIXME: show an error dialog */
2827 // Error dialog should say that we cannot find a suitable
2828 // system partition and create one on the system. At this point,
2829 // it may be nice to ask the user whether he wants to continue,
2830 // or use an external drive as the system drive/partition
2831 // (e.g. floppy, USB drive, etc...)
2836 PreviousFormatState
= FormatState
;
2837 switch (FormatState
)
2841 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2843 TempPartition
= PartitionList
->SystemPartition
;
2844 TempPartition
->NeedsCheck
= TRUE
;
2846 FormatState
= FormatSystemPartition
;
2847 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2851 TempPartition
= PartitionList
->CurrentPartition
;
2852 TempPartition
->NeedsCheck
= TRUE
;
2854 FormatState
= FormatInstallPartition
;
2855 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2860 case FormatSystemPartition
:
2862 TempPartition
= PartitionList
->CurrentPartition
;
2863 TempPartition
->NeedsCheck
= TRUE
;
2865 FormatState
= FormatInstallPartition
;
2866 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2870 case FormatInstallPartition
:
2872 if (GetNextUnformattedPartition(PartitionList
,
2876 FormatState
= FormatOtherPartition
;
2877 TempPartition
->NeedsCheck
= TRUE
;
2878 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2882 FormatState
= FormatDone
;
2883 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2884 return CHECK_FILE_SYSTEM_PAGE
;
2889 case FormatOtherPartition
:
2891 if (GetNextUnformattedPartition(PartitionList
,
2895 FormatState
= FormatOtherPartition
;
2896 TempPartition
->NeedsCheck
= TRUE
;
2897 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2901 FormatState
= FormatDone
;
2902 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2903 return CHECK_FILE_SYSTEM_PAGE
;
2910 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2911 /* FIXME: show an error dialog */
2916 PartEntry
= TempPartition
;
2917 DiskEntry
= PartEntry
->DiskEntry
;
2919 /* Adjust disk size */
2920 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2921 if (DiskSize
>= 10737418240) /* 10 GB */
2923 DiskSize
= DiskSize
/ 1073741824;
2924 DiskUnit
= MUIGetString(STRING_GB
);
2928 DiskSize
= DiskSize
/ 1048576;
2929 DiskUnit
= MUIGetString(STRING_MB
);
2932 /* Adjust partition size */
2933 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2934 if (PartSize
>= 10737418240) /* 10 GB */
2936 PartSize
= PartSize
/ 1073741824;
2937 PartUnit
= MUIGetString(STRING_GB
);
2941 PartSize
= PartSize
/ 1048576;
2942 PartUnit
= MUIGetString(STRING_MB
);
2945 /* Adjust partition type */
2946 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2948 ARRAYSIZE(PartTypeString
));
2950 if (PartEntry
->AutoCreate
!= FALSE
)
2952 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2955 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2956 PartEntry
->PartitionNumber
,
2962 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1
),
2963 DiskEntry
->DiskNumber
,
2969 &DiskEntry
->DriverName
,
2970 DiskEntry
->NoMbr
? "GPT" : "MBR");
2972 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2974 PartEntry
->AutoCreate
= FALSE
;
2976 else if (PartEntry
->New
!= FALSE
)
2978 switch (FormatState
)
2980 case FormatSystemPartition
:
2981 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2984 case FormatInstallPartition
:
2985 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2988 case FormatOtherPartition
:
2989 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2996 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
3000 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
3002 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
3004 CONSOLE_PrintTextXY(8, 10,
3005 MUIGetString(STRING_HDDINFOUNK4
),
3006 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
3007 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
3008 PartEntry
->PartitionType
,
3014 CONSOLE_PrintTextXY(8, 10,
3016 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
3017 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
3023 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1
),
3024 DiskEntry
->DiskNumber
,
3030 &DiskEntry
->DriverName
,
3031 DiskEntry
->NoMbr
? "GPT" : "MBR");
3034 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
3036 if (FileSystemList
== NULL
)
3038 /* Create the file system list, and by default select the "FAT" file system */
3039 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
3040 if (FileSystemList
== NULL
)
3042 /* FIXME: show an error dialog */
3047 if (RepairUpdateFlag
)
3049 return CHECK_FILE_SYSTEM_PAGE
;
3050 //return SELECT_PARTITION_PAGE;
3053 if (IsUnattendedSetup
)
3055 if (UnattendFormatPartition
)
3058 * We use whatever currently selected file system we have
3059 * (by default, this is "FAT", as per the initialization
3060 * performed above). Note that it may be interesting to specify
3061 * which file system to use in unattended installations, in the
3062 * txtsetup.sif file.
3064 return FORMAT_PARTITION_PAGE
;
3067 return CHECK_FILE_SYSTEM_PAGE
;
3070 DrawFileSystemList(FileSystemList
);
3074 CONSOLE_ConInKey(Ir
);
3076 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3077 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3079 if (ConfirmQuit(Ir
) != FALSE
)
3084 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3085 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
3087 FormatState
= Start
;
3088 return SELECT_PARTITION_PAGE
;
3090 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3091 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
3093 ScrollDownFileSystemList(FileSystemList
);
3095 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3096 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
3098 ScrollUpFileSystemList(FileSystemList
);
3100 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
3102 if (!FileSystemList
->Selected
->FileSystem
)
3103 return SELECT_FILE_SYSTEM_PAGE
;
3105 return FORMAT_PARTITION_PAGE
;
3109 FormatState
= PreviousFormatState
;
3111 return SELECT_FILE_SYSTEM_PAGE
;
3116 * Displays the FormatPartitionPage.
3119 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
3120 * SelectPartitionPage (At once)
3124 * Sets PartitionList->CurrentPartition->FormatState
3125 * Sets DestinationRootPath
3128 * Number of the next page.
3131 FormatPartitionPage(PINPUT_RECORD Ir
)
3133 UNICODE_STRING PartitionRootPath
;
3134 WCHAR PathBuffer
[MAX_PATH
];
3135 PDISKENTRY DiskEntry
;
3136 PPARTENTRY PartEntry
;
3137 PFILE_SYSTEM_ITEM SelectedFileSystem
;
3143 PPARTITION_INFORMATION PartitionInfo
;
3146 DPRINT("FormatPartitionPage()\n");
3148 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
3150 if (PartitionList
== NULL
|| TempPartition
== NULL
)
3152 /* FIXME: show an error dialog */
3156 PartEntry
= TempPartition
;
3157 DiskEntry
= PartEntry
->DiskEntry
;
3159 SelectedFileSystem
= FileSystemList
->Selected
;
3163 if (!IsUnattendedSetup
)
3165 CONSOLE_ConInKey(Ir
);
3168 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3169 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3171 if (ConfirmQuit(Ir
) != FALSE
)
3176 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3178 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3180 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
3182 /* FIXME: show an error dialog */
3187 CONSOLE_PrintTextXY(6, 12,
3188 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3189 DiskEntry
->Cylinders
,
3190 DiskEntry
->TracksPerCylinder
,
3191 DiskEntry
->SectorsPerTrack
,
3192 DiskEntry
->BytesPerSector
,
3193 DiskEntry
->Dirty
? '*' : ' ');
3197 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3199 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3201 CONSOLE_PrintTextXY(6, Line
,
3202 "%2u: %2lu %c %12I64u %12I64u %02x",
3204 PartitionInfo
->PartitionNumber
,
3205 PartitionInfo
->BootIndicator
? 'A' : '-',
3206 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3207 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3208 PartitionInfo
->PartitionType
);
3213 /* Commit the partition changes to the disk */
3214 if (!WritePartitionsToDisk(PartitionList
))
3216 DPRINT("WritePartitionsToDisk() failed\n");
3217 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3221 /* Set PartitionRootPath */
3222 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3223 L
"\\Device\\Harddisk%lu\\Partition%lu",
3224 DiskEntry
->DiskNumber
,
3225 PartEntry
->PartitionNumber
);
3226 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3227 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3229 /* Format the partition */
3230 if (SelectedFileSystem
->FileSystem
)
3232 Status
= FormatPartition(&PartitionRootPath
,
3233 SelectedFileSystem
);
3234 if (!NT_SUCCESS(Status
))
3236 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3237 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3241 PartEntry
->FormatState
= Formatted
;
3242 // PartEntry->FileSystem = FileSystem;
3243 PartEntry
->New
= FALSE
;
3247 CONSOLE_SetStatusText(" Done. Press any key ...");
3248 CONSOLE_ConInKey(Ir
);
3251 return SELECT_FILE_SYSTEM_PAGE
;
3255 return FORMAT_PARTITION_PAGE
;
3260 * Displays the CheckFileSystemPage.
3263 * InstallDirectoryPage (At once)
3267 * Inits or reloads FileSystemList
3270 * Number of the next page.
3273 CheckFileSystemPage(PINPUT_RECORD Ir
)
3275 PFILE_SYSTEM CurrentFileSystem
;
3276 UNICODE_STRING PartitionRootPath
;
3277 WCHAR PathBuffer
[MAX_PATH
];
3278 CHAR Buffer
[MAX_PATH
];
3279 PDISKENTRY DiskEntry
;
3280 PPARTENTRY PartEntry
;
3283 if (PartitionList
== NULL
)
3285 /* FIXME: show an error dialog */
3289 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3291 return INSTALL_DIRECTORY_PAGE
;
3294 /* Set PartitionRootPath */
3295 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3296 L
"\\Device\\Harddisk%lu\\Partition%lu",
3297 DiskEntry
->DiskNumber
,
3298 PartEntry
->PartitionNumber
);
3299 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3300 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3302 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3304 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3306 CurrentFileSystem
= PartEntry
->FileSystem
;
3307 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3308 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3310 /* HACK: Do not try to check a partition with an unknown filesystem */
3311 if (CurrentFileSystem
== NULL
)
3313 PartEntry
->NeedsCheck
= FALSE
;
3314 return CHECK_FILE_SYSTEM_PAGE
;
3317 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3320 "Setup is currently unable to check a partition formatted in %S.\n"
3322 " \x07 Press ENTER to continue Setup.\n"
3323 " \x07 Press F3 to quit Setup.",
3324 CurrentFileSystem
->FileSystemName
);
3327 MUIGetString(STRING_QUITCONTINUE
),
3328 NULL
, POPUP_WAIT_NONE
);
3332 CONSOLE_ConInKey(Ir
);
3334 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3335 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3337 if (ConfirmQuit(Ir
))
3340 return CHECK_FILE_SYSTEM_PAGE
;
3342 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3344 PartEntry
->NeedsCheck
= FALSE
;
3345 return CHECK_FILE_SYSTEM_PAGE
;
3351 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3352 if (!NT_SUCCESS(Status
))
3354 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3355 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3356 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3357 "(Status 0x%08lx).\n", Status
);
3359 // MUIGetString(STRING_REBOOTCOMPUTER),
3360 MUIGetString(STRING_CONTINUE
),
3361 Ir
, POPUP_WAIT_ENTER
);
3363 // return QUIT_PAGE;
3366 PartEntry
->NeedsCheck
= FALSE
;
3367 return CHECK_FILE_SYSTEM_PAGE
;
3373 BuildInstallPaths(PWSTR InstallDir
,
3374 PDISKENTRY DiskEntry
,
3375 PPARTENTRY PartEntry
)
3377 WCHAR PathBuffer
[MAX_PATH
];
3379 /* Create 'InstallPath' string */
3380 RtlFreeUnicodeString(&InstallPath
);
3381 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3383 /* Create 'DestinationRootPath' string */
3384 RtlFreeUnicodeString(&DestinationRootPath
);
3385 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3386 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
3387 DiskEntry
->DiskNumber
,
3388 PartEntry
->PartitionNumber
);
3389 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3390 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3392 /* Create 'DestinationPath' string */
3393 RtlFreeUnicodeString(&DestinationPath
);
3394 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3395 DestinationRootPath
.Buffer
, InstallDir
);
3396 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3398 /* Create 'DestinationArcPath' */
3399 RtlFreeUnicodeString(&DestinationArcPath
);
3400 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3401 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
3402 DiskEntry
->BiosDiskNumber
,
3403 PartEntry
->PartitionNumber
);
3404 ConcatPaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 1, InstallDir
);
3405 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3407 /* Initialize DestinationDriveLetter */
3408 DestinationDriveLetter
= (WCHAR
)PartEntry
->DriveLetter
;
3413 * Displays the InstallDirectoryPage.
3420 * Number of the next page.
3423 InstallDirectoryPage(PINPUT_RECORD Ir
)
3425 PDISKENTRY DiskEntry
;
3426 PPARTENTRY PartEntry
;
3427 WCHAR InstallDir
[51];
3431 /* We do not need the filesystem list any more */
3432 if (FileSystemList
!= NULL
)
3434 DestroyFileSystemList(FileSystemList
);
3435 FileSystemList
= NULL
;
3438 if (PartitionList
== NULL
||
3439 PartitionList
->CurrentDisk
== NULL
||
3440 PartitionList
->CurrentPartition
== NULL
)
3442 /* FIXME: show an error dialog */
3446 DiskEntry
= PartitionList
->CurrentDisk
;
3447 PartEntry
= PartitionList
->CurrentPartition
;
3449 if (RepairUpdateFlag
)
3451 if (!IsValidPath(CurrentInstallation
->PathComponent
)) // SystemNtPath
3453 /* FIXME: Log the error? */
3457 BuildInstallPaths(CurrentInstallation
->PathComponent
, // SystemNtPath
3461 return PREPARE_COPY_PAGE
;
3463 if (IsUnattendedSetup
)
3465 if (!IsValidPath(UnattendInstallationDirectory
))
3467 /* FIXME: Log the error? */
3471 BuildInstallPaths(UnattendInstallationDirectory
,
3475 return PREPARE_COPY_PAGE
;
3478 wcscpy(InstallDir
, L
"\\ReactOS");
3480 Length
= wcslen(InstallDir
);
3482 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3483 CONSOLE_SetCursorXY(8 + Pos
, 11);
3484 CONSOLE_SetCursorType(TRUE
, TRUE
);
3485 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3489 CONSOLE_ConInKey(Ir
);
3491 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3492 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3494 CONSOLE_SetCursorType(TRUE
, FALSE
);
3496 if (ConfirmQuit(Ir
) != FALSE
)
3499 CONSOLE_SetCursorType(TRUE
, TRUE
);
3502 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3503 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3507 memmove(&InstallDir
[Pos
],
3508 &InstallDir
[Pos
+ 1],
3509 (Length
- Pos
- 1) * sizeof(WCHAR
));
3510 InstallDir
[Length
- 1] = UNICODE_NULL
;
3513 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3514 CONSOLE_SetCursorXY(8 + Pos
, 11);
3517 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3518 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3521 CONSOLE_SetCursorXY(8 + Pos
, 11);
3523 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3524 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3527 CONSOLE_SetCursorXY(8 + Pos
, 11);
3529 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3530 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3535 CONSOLE_SetCursorXY(8 + Pos
, 11);
3538 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3539 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3544 CONSOLE_SetCursorXY(8 + Pos
, 11);
3547 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3549 CONSOLE_SetCursorType(TRUE
, FALSE
);
3552 * Check for the validity of the installation directory and pop up
3553 * an error if it is not the case. Then the user can fix its input.
3555 if (!IsValidPath(InstallDir
))
3557 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3558 return INSTALL_DIRECTORY_PAGE
;
3561 BuildInstallPaths(InstallDir
,
3565 return PREPARE_COPY_PAGE
;
3567 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3572 memmove(&InstallDir
[Pos
- 1],
3574 (Length
- Pos
) * sizeof(WCHAR
));
3575 InstallDir
[Length
- 1] = UNICODE_NULL
;
3579 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3580 CONSOLE_SetCursorXY(8 + Pos
, 11);
3583 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3587 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3588 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3591 memmove(&InstallDir
[Pos
+ 1],
3593 (Length
- Pos
) * sizeof(WCHAR
));
3594 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3595 InstallDir
[Pos
] = c
;
3599 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3600 CONSOLE_SetCursorXY(8 + Pos
, 11);
3606 return INSTALL_DIRECTORY_PAGE
;
3611 AddSectionToCopyQueueCab(HINF InfFile
,
3613 PWCHAR SourceCabinet
,
3614 PCUNICODE_STRING DestinationPath
,
3617 INFCONTEXT FilesContext
;
3618 INFCONTEXT DirContext
;
3620 PWCHAR FileKeyValue
;
3622 PWCHAR TargetFileName
;
3625 * This code enumerates the list of files in reactos.dff / reactos.inf
3626 * that need to be extracted from reactos.cab and be installed in their
3627 * respective directories.
3630 /* Search for the SectionName section */
3631 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3634 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3635 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3640 * Enumerate the files in the section and add them to the file queue.
3644 /* Get source file name and target directory id */
3645 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3647 /* FIXME: Handle error! */
3648 DPRINT1("INF_GetData() failed\n");
3652 /* Get optional target file name */
3653 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3654 TargetFileName
= NULL
;
3656 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3658 /* Lookup target directory */
3659 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3661 /* FIXME: Handle error! */
3662 DPRINT1("SetupFindFirstLine() failed\n");
3666 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3668 /* FIXME: Handle error! */
3669 DPRINT1("INF_GetData() failed\n");
3673 if (!SetupQueueCopy(SetupFileQueue
,
3675 SourceRootPath
.Buffer
,
3676 SourceRootDir
.Buffer
,
3681 /* FIXME: Handle error! */
3682 DPRINT1("SetupQueueCopy() failed\n");
3684 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3691 AddSectionToCopyQueue(HINF InfFile
,
3693 PWCHAR SourceCabinet
,
3694 PCUNICODE_STRING DestinationPath
,
3697 INFCONTEXT FilesContext
;
3698 INFCONTEXT DirContext
;
3700 PWCHAR FileKeyValue
;
3702 PWCHAR TargetFileName
;
3703 WCHAR CompleteOrigDirName
[512]; // FIXME: MAX_PATH is not enough?
3706 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3709 * This code enumerates the list of files in txtsetup.sif
3710 * that need to be installed in their respective directories.
3713 /* Search for the SectionName section */
3714 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3717 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3718 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3723 * Enumerate the files in the section and add them to the file queue.
3727 /* Get source file name and target directory id */
3728 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3730 /* FIXME: Handle error! */
3731 DPRINT1("INF_GetData() failed\n");
3735 /* Get target directory id */
3736 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3738 /* FIXME: Handle error! */
3739 DPRINT1("INF_GetData() failed\n");
3743 /* Get optional target file name */
3744 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3745 TargetFileName
= NULL
;
3746 else if (!*TargetFileName
)
3747 TargetFileName
= NULL
;
3749 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3751 /* Lookup target directory */
3752 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3754 /* FIXME: Handle error! */
3755 DPRINT1("SetupFindFirstLine() failed\n");
3759 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3761 /* FIXME: Handle error! */
3762 DPRINT1("INF_GetData() failed\n");
3766 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3768 /* Installation path */
3769 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3771 StringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3772 SourceRootDir
.Buffer
);
3774 DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName
);
3776 else if (DirKeyValue
[0] == L
'\\')
3779 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3781 StringCchCopyW(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
),
3784 DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName
);
3786 else // if (DirKeyValue[0] != L'\\')
3788 /* Path relative to the installation path */
3789 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3791 CombinePaths(CompleteOrigDirName
, ARRAYSIZE(CompleteOrigDirName
), 2,
3792 SourceRootDir
.Buffer
, DirKeyValue
);
3794 DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName
);
3797 if (!SetupQueueCopy(SetupFileQueue
,
3799 SourceRootPath
.Buffer
,
3800 CompleteOrigDirName
,
3805 /* FIXME: Handle error! */
3806 DPRINT1("SetupQueueCopy() failed\n");
3808 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3815 PrepareCopyPageInfFile(HINF InfFile
,
3816 PWCHAR SourceCabinet
,
3820 INFCONTEXT DirContext
;
3821 PWCHAR AdditionalSectionName
= NULL
;
3823 WCHAR PathBuffer
[MAX_PATH
];
3825 /* Add common files */
3826 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &DestinationPath
, Ir
))
3829 /* Add specific files depending of computer type */
3830 if (SourceCabinet
== NULL
)
3832 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3835 if (AdditionalSectionName
)
3837 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &DestinationPath
, Ir
))
3842 /* Create directories */
3846 * Copying files to DestinationRootPath should be done from within
3847 * the SystemPartitionFiles section.
3848 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3849 * For installing to DestinationPath specify just '\' .
3852 /* Get destination path */
3853 StringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
), DestinationPath
.Buffer
);
3855 DPRINT("FullPath(1): '%S'\n", PathBuffer
);
3857 /* Create the install directory */
3858 Status
= SetupCreateDirectory(PathBuffer
);
3859 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3861 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer
, Status
);
3862 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3866 /* Search for the 'Directories' section */
3867 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3871 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3875 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3881 /* Enumerate the directory values and create the subdirectories */
3884 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3890 if ((DirKeyValue
[0] == UNICODE_NULL
) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == UNICODE_NULL
))
3892 /* Installation path */
3893 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3895 StringCchCopyW(PathBuffer
, ARRAYSIZE(PathBuffer
),
3896 DestinationPath
.Buffer
);
3898 DPRINT("InstallationPath(2): '%S'\n", PathBuffer
);
3900 else if (DirKeyValue
[0] == L
'\\')
3903 DPRINT("AbsolutePath: '%S'\n", DirKeyValue
);
3905 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3906 DestinationRootPath
.Buffer
, DirKeyValue
);
3908 DPRINT("AbsolutePath(2): '%S'\n", PathBuffer
);
3910 Status
= SetupCreateDirectory(PathBuffer
);
3911 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3913 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3914 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3918 else // if (DirKeyValue[0] != L'\\')
3920 /* Path relative to the installation path */
3921 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3923 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3924 DestinationPath
.Buffer
, DirKeyValue
);
3926 DPRINT("RelativePath(2): '%S'\n", PathBuffer
);
3928 Status
= SetupCreateDirectory(PathBuffer
);
3929 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3931 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3932 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3936 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3943 * Displays the PrepareCopyPage.
3946 * FileCopyPage(At once)
3950 * Inits SetupFileQueue
3951 * Calls PrepareCopyPageInfFile
3954 * Number of the next page.
3957 PrepareCopyPage(PINPUT_RECORD Ir
)
3960 WCHAR PathBuffer
[MAX_PATH
];
3961 INFCONTEXT CabinetsContext
;
3967 MUIDisplayPage(PREPARE_COPY_PAGE
);
3969 /* Create the file queue */
3970 SetupFileQueue
= SetupOpenFileQueue();
3971 if (SetupFileQueue
== NULL
)
3973 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3977 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3979 /* FIXME: show an error dialog */
3983 /* Search for the 'Cabinets' section */
3984 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3986 return FILE_COPY_PAGE
;
3990 * Enumerate the directory values in the 'Cabinets'
3991 * section and parse their inf files.
3995 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3998 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3999 SourcePath
.Buffer
, KeyValue
);
4001 CabinetInitialize();
4002 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
4003 CabinetSetCabinetName(PathBuffer
);
4005 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
4007 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
4009 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
4010 if (InfFileData
== NULL
)
4012 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
4018 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
4019 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
4023 InfHandle
= INF_OpenBufferedFileA((CHAR
*) InfFileData
,
4030 if (InfHandle
== INVALID_HANDLE_VALUE
)
4032 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
4038 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
4040 /* FIXME: show an error dialog */
4043 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
4045 return FILE_COPY_PAGE
;
4051 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
4054 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
4056 /* Get the memory information from the system */
4057 NtQuerySystemInformation(SystemPerformanceInformation
,
4062 /* Check if this is initial setup */
4065 /* Set maximum limits to be total RAM pages */
4066 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
4067 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
4068 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
4071 /* Set current values */
4072 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
4073 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
4074 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
4080 FileCopyCallback(PVOID Context
,
4085 PCOPYCONTEXT CopyContext
;
4087 CopyContext
= (PCOPYCONTEXT
)Context
;
4089 switch (Notification
)
4091 case SPFILENOTIFY_STARTSUBQUEUE
:
4092 CopyContext
->TotalOperations
= (ULONG
)Param2
;
4093 ProgressSetStepCount(CopyContext
->ProgressBar
,
4094 CopyContext
->TotalOperations
);
4095 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
4098 case SPFILENOTIFY_STARTCOPY
:
4099 /* Display copy message */
4100 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
4101 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
4104 case SPFILENOTIFY_ENDCOPY
:
4105 CopyContext
->CompletedOperations
++;
4107 /* SYSREG checkpoint */
4108 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
4109 DPRINT1("CHECKPOINT:HALF_COPIED\n");
4111 ProgressNextStep(CopyContext
->ProgressBar
);
4112 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
4121 * Displays the FileCopyPage.
4124 * RegistryPage(At once)
4127 * Calls SetupCommitFileQueueW
4128 * Calls SetupCloseFileQueue
4131 * Number of the next page.
4134 FileCopyPage(PINPUT_RECORD Ir
)
4136 COPYCONTEXT CopyContext
;
4137 unsigned int mem_bar_width
;
4139 MUIDisplayPage(FILE_COPY_PAGE
);
4141 /* Create context for the copy process */
4142 CopyContext
.DestinationRootPath
= DestinationRootPath
.Buffer
;
4143 CopyContext
.InstallPath
= InstallPath
.Buffer
;
4144 CopyContext
.TotalOperations
= 0;
4145 CopyContext
.CompletedOperations
= 0;
4147 /* Create the progress bar as well */
4148 CopyContext
.ProgressBar
= CreateProgressBar(13,
4155 MUIGetString(STRING_SETUPCOPYINGFILES
));
4157 // fit memory bars to screen width, distribute them uniform
4158 mem_bar_width
= (xScreen
- 26) / 5;
4159 mem_bar_width
-= mem_bar_width
% 2; // make even
4160 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4161 /* Create the paged pool progress bar */
4162 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
4171 /* Create the non paged pool progress bar */
4172 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
4174 (xScreen
/ 2) + (mem_bar_width
/ 2),
4176 (xScreen
/ 2)- (mem_bar_width
/ 2),
4181 /* Create the global memory progress bar */
4182 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
4186 xScreen
- 13 - mem_bar_width
,
4191 /* Do the file copying */
4192 SetupCommitFileQueueW(NULL
,
4197 /* If we get here, we're done, so cleanup the queue and progress bar */
4198 SetupCloseFileQueue(SetupFileQueue
);
4199 DestroyProgressBar(CopyContext
.ProgressBar
);
4200 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4201 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4202 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4204 /* Go display the next page */
4205 return REGISTRY_PAGE
;
4210 * Displays the RegistryPage.
4213 * SuccessPage (if RepairUpdate)
4214 * BootLoaderPage (default)
4218 * Calls RegInitializeRegistry
4219 * Calls ImportRegistryFile
4220 * Calls SetDefaultPagefile
4221 * Calls SetMountedDeviceValues
4224 * Number of the next page.
4227 RegistryPage(PINPUT_RECORD Ir
)
4230 INFCONTEXT InfContext
;
4235 BOOLEAN ShouldRepairRegistry
= FALSE
;
4238 MUIDisplayPage(REGISTRY_PAGE
);
4240 if (RepairUpdateFlag
)
4242 DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n");
4244 /* Verify the registry hives and check whether we need to update or repair any of them */
4245 Status
= VerifyRegistryHives(&DestinationPath
, &ShouldRepairRegistry
);
4246 if (!NT_SUCCESS(Status
))
4248 DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status
);
4249 ShouldRepairRegistry
= FALSE
;
4251 if (!ShouldRepairRegistry
)
4252 DPRINT1("No need to repair the registry\n");
4256 /* Update the registry */
4257 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4259 /* Initialize the registry and setup the registry hives */
4260 Status
= RegInitializeRegistry(&DestinationPath
);
4261 if (!NT_SUCCESS(Status
))
4263 DPRINT1("RegInitializeRegistry() failed\n");
4264 /********** HACK!!!!!!!!!!! **********/
4265 if (Status
== STATUS_NOT_IMPLEMENTED
)
4267 /* The hack was called, display its corresponding error */
4268 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4271 /*************************************/
4273 /* Something else failed */
4274 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4279 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4282 * We fully setup the hives, in case we are doing a fresh installation
4283 * (RepairUpdateFlag == FALSE), or in case we are doing an update
4284 * (RepairUpdateFlag == TRUE) BUT we have some registry hives to
4285 * "repair" (aka. recreate: ShouldRepairRegistry == TRUE).
4288 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Fresh", NULL
, &InfContext
); // Windows-compatible
4290 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
); // ReactOS-specific
4294 DPRINT1("SetupFindFirstLine() failed\n");
4295 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4299 else // if (RepairUpdateFlag && !ShouldRepairRegistry)
4302 * In case we are doing an update (RepairUpdateFlag == TRUE) and
4303 * NO registry hives need a repair (ShouldRepairRegistry == FALSE),
4304 * we only update the hives.
4307 Success
= SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Upgrade", NULL
, &InfContext
);
4310 /* Nothing to do for update! */
4311 DPRINT1("No update needed for the registry!\n");
4318 INF_GetDataField(&InfContext
, 0, &Action
);
4319 INF_GetDataField(&InfContext
, 1, &File
);
4320 INF_GetDataField(&InfContext
, 2, &Section
);
4322 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4327 if (!_wcsicmp(Action
, L
"AddReg"))
4329 else if (!_wcsicmp(Action
, L
"DelReg"))
4333 DPRINT1("Unrecognized registry INF action '%S'\n", Action
);
4337 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4339 if (!ImportRegistryFile(File
, Section
, LanguageId
, Delete
))
4341 DPRINT1("Importing %S failed\n", File
);
4342 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4345 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4347 if (!RepairUpdateFlag
|| ShouldRepairRegistry
)
4349 /* See the explanation for this test above */
4351 /* Update display registry settings */
4352 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4353 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4355 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4359 /* Set the locale */
4360 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4361 if (!ProcessLocaleRegistry(LanguageList
))
4363 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4367 /* Add keyboard layouts */
4368 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4369 if (!AddKeyboardLayouts())
4371 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4376 if (!SetGeoID(MUIGetGeoID()))
4378 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4382 if (!IsUnattendedSetup
)
4384 /* Update keyboard layout settings */
4385 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4386 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4388 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4393 /* Add codepage information to registry */
4394 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4397 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4401 /* Set the default pagefile entry */
4402 SetDefaultPagefile(DestinationDriveLetter
);
4404 /* Update the mounted devices list */
4405 // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
4406 SetMountedDeviceValues(PartitionList
);
4411 // TODO: Unload all the registry stuff, perform cleanup,
4412 // and copy the created hive files into .sav files.
4414 RegCleanupRegistry(&DestinationPath
);
4417 * Check whether we were in update/repair mode but we were actually
4418 * repairing the registry hives. If so, we have finished repairing them,
4419 * and we now reset the flag and run the proper registry update.
4420 * Otherwise we have finished the registry update!
4422 if (RepairUpdateFlag
&& ShouldRepairRegistry
)
4424 ShouldRepairRegistry
= FALSE
;
4428 if (NT_SUCCESS(Status
))
4430 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4431 return BOOT_LOADER_PAGE
;
4441 * Displays the BootLoaderPage.
4444 * SuccessPage (if RepairUpdate)
4445 * BootLoaderHarddiskMbrPage
4446 * BootLoaderHarddiskVbrPage
4447 * BootLoaderFloppyPage
4452 * Calls RegInitializeRegistry
4453 * Calls ImportRegistryFile
4454 * Calls SetDefaultPagefile
4455 * Calls SetMountedDeviceValues
4458 * Number of the next page.
4461 BootLoaderPage(PINPUT_RECORD Ir
)
4463 UCHAR PartitionType
;
4464 BOOLEAN InstallOnFloppy
;
4466 WCHAR PathBuffer
[MAX_PATH
];
4468 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4470 RtlFreeUnicodeString(&SystemRootPath
);
4471 StringCchPrintfW(PathBuffer
, ARRAYSIZE(PathBuffer
),
4472 L
"\\Device\\Harddisk%lu\\Partition%lu\\",
4473 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4474 PartitionList
->SystemPartition
->PartitionNumber
);
4475 RtlCreateUnicodeString(&SystemRootPath
, PathBuffer
);
4476 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath
);
4478 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4480 if (IsUnattendedSetup
)
4482 if (UnattendMBRInstallType
== 0) /* skip MBR installation */
4484 return SUCCESS_PAGE
;
4486 else if (UnattendMBRInstallType
== 1) /* install on floppy */
4488 return BOOT_LOADER_FLOPPY_PAGE
;
4492 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4494 DPRINT("Error: system partition invalid (unused)\n");
4495 InstallOnFloppy
= TRUE
;
4497 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4499 /* OS/2 boot manager partition */
4500 DPRINT("Found OS/2 boot manager partition\n");
4501 InstallOnFloppy
= TRUE
;
4503 else if (PartitionType
== PARTITION_EXT2
)
4505 /* Linux EXT2 partition */
4506 DPRINT("Found Linux EXT2 partition\n");
4507 InstallOnFloppy
= FALSE
;
4509 else if (PartitionType
== PARTITION_IFS
)
4511 /* NTFS partition */
4512 DPRINT("Found NTFS partition\n");
4514 // FIXME: Make it FALSE when we'll support NTFS installation!
4515 InstallOnFloppy
= TRUE
;
4517 else if ((PartitionType
== PARTITION_FAT_12
) ||
4518 (PartitionType
== PARTITION_FAT_16
) ||
4519 (PartitionType
== PARTITION_HUGE
) ||
4520 (PartitionType
== PARTITION_XINT13
) ||
4521 (PartitionType
== PARTITION_FAT32
) ||
4522 (PartitionType
== PARTITION_FAT32_XINT13
))
4524 DPRINT("Found FAT partition\n");
4525 InstallOnFloppy
= FALSE
;
4529 /* Unknown partition */
4530 DPRINT("Unknown partition found\n");
4531 InstallOnFloppy
= TRUE
;
4534 if (InstallOnFloppy
!= FALSE
)
4536 return BOOT_LOADER_FLOPPY_PAGE
;
4539 /* Unattended install on hdd? */
4540 if (IsUnattendedSetup
&& UnattendMBRInstallType
== 2)
4542 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4545 MUIDisplayPage(BOOT_LOADER_PAGE
);
4546 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4550 CONSOLE_ConInKey(Ir
);
4552 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4553 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4555 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4564 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4566 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4567 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4569 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4578 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4580 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4581 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4583 if (ConfirmQuit(Ir
) != FALSE
)
4588 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4592 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4594 else if (Line
== 13)
4596 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4598 else if (Line
== 14)
4600 return BOOT_LOADER_FLOPPY_PAGE
;
4602 else if (Line
== 15)
4604 return SUCCESS_PAGE
;
4607 return BOOT_LOADER_PAGE
;
4611 return BOOT_LOADER_PAGE
;
4616 * Displays the BootLoaderFloppyPage.
4619 * SuccessPage (At once)
4623 * Calls InstallFatBootcodeToFloppy()
4626 * Number of the next page.
4629 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4633 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4635 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4639 CONSOLE_ConInKey(Ir
);
4641 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4642 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4644 if (ConfirmQuit(Ir
) != FALSE
)
4649 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4651 if (DoesPathExist(NULL
, L
"\\Device\\Floppy0\\") == FALSE
)
4653 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4654 return BOOT_LOADER_FLOPPY_PAGE
;
4657 Status
= InstallFatBootcodeToFloppy(&SourceRootPath
, &DestinationArcPath
);
4658 if (!NT_SUCCESS(Status
))
4660 /* Print error message */
4661 return BOOT_LOADER_FLOPPY_PAGE
;
4664 return SUCCESS_PAGE
;
4668 return BOOT_LOADER_FLOPPY_PAGE
;
4673 * Displays the BootLoaderHarddiskVbrPage.
4676 * SuccessPage (At once)
4680 * Calls InstallVBRToPartition()
4683 * Number of the next page.
4686 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4690 Status
= InstallVBRToPartition(&SystemRootPath
,
4692 &DestinationArcPath
,
4693 PartitionList
->SystemPartition
->PartitionType
);
4694 if (!NT_SUCCESS(Status
))
4696 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4700 return SUCCESS_PAGE
;
4705 * Displays the BootLoaderHarddiskMbrPage.
4708 * SuccessPage (At once)
4712 * Calls InstallVBRToPartition()
4713 * Calls InstallMbrBootCodeToDisk()
4716 * Number of the next page.
4719 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4722 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4723 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4724 WCHAR DstPath
[MAX_PATH
];
4726 /* Step 1: Write the VBR */
4727 Status
= InstallVBRToPartition(&SystemRootPath
,
4729 &DestinationArcPath
,
4730 PartitionList
->SystemPartition
->PartitionType
);
4731 if (!NT_SUCCESS(Status
))
4733 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4737 /* Step 2: Write the MBR */
4738 StringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
4739 L
"\\Device\\Harddisk%d\\Partition0",
4740 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4742 CombinePaths(SourceMbrPathBuffer
, ARRAYSIZE(SourceMbrPathBuffer
), 2, SourceRootPath
.Buffer
, L
"\\loader\\dosmbr.bin");
4744 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4746 /* Save current MBR */
4747 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
.Buffer
, L
"mbr.old");
4749 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4750 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4751 if (!NT_SUCCESS(Status
))
4753 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4754 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4758 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4759 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4760 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4761 DestinationDevicePathBuffer
);
4762 if (!NT_SUCCESS(Status
))
4764 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4766 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4770 return SUCCESS_PAGE
;
4775 * @name ProgressTimeOutStringHandler
4777 * Handles the generation (displaying) of the timeout
4778 * countdown to the screen dynamically.
4781 * A pointer to a progress bar.
4783 * @param AlwaysUpdate
4784 * Constantly update the progress bar (boolean type).
4787 * A pointer to a string buffer.
4789 * @param cchBufferSize
4790 * The buffer's size in number of characters.
4793 * TRUE or FALSE on function termination.
4798 ProgressTimeOutStringHandler(
4799 IN PPROGRESSBAR Bar
,
4800 IN BOOLEAN AlwaysUpdate
,
4802 IN SIZE_T cchBufferSize
)
4804 ULONG OldProgress
= Bar
->Progress
;
4806 if (Bar
->StepCount
== 0)
4812 Bar
->Progress
= Bar
->StepCount
- Bar
->CurrentStep
;
4815 /* Build the progress string if it has changed */
4816 if (Bar
->ProgressFormatText
&&
4817 (AlwaysUpdate
|| (Bar
->Progress
!= OldProgress
)))
4819 RtlStringCchPrintfA(Buffer
, cchBufferSize
,
4820 Bar
->ProgressFormatText
, Bar
->Progress
/ max(1, Bar
->Width
) + 1);
4829 * @name ProgressCountdown
4831 * Displays and draws a red-coloured progress bar with a countdown.
4832 * When the timeout is reached, the flush page is displayed for reboot.
4835 * A pointer to an input keyboard record.
4838 * Initial countdown value in seconds.
4846 IN PINPUT_RECORD Ir
,
4850 ULONG StartTime
, BarWidth
, TimerDiv
;
4852 LONG TimerValue
, OldTimerValue
;
4853 LARGE_INTEGER Timeout
;
4854 PPROGRESSBAR ProgressBar
;
4855 BOOLEAN RefreshProgress
= TRUE
;
4857 /* Bail out if the timeout is already zero */
4861 /* Create the timeout progress bar and set it up */
4862 ProgressBar
= CreateProgressBarEx(13,
4869 FOREGROUND_RED
| BACKGROUND_BLUE
,
4872 MUIGetString(STRING_REBOOTPROGRESSBAR
),
4873 ProgressTimeOutStringHandler
);
4875 BarWidth
= max(1, ProgressBar
->Width
);
4876 TimerValue
= TimeOut
* BarWidth
;
4877 ProgressSetStepCount(ProgressBar
, TimerValue
);
4879 StartTime
= NtGetTickCount();
4882 TimerDiv
= 1000 / BarWidth
;
4883 TimerDiv
= max(1, TimerDiv
);
4884 OldTimerValue
= TimerValue
;
4887 /* Decrease the timer */
4890 * Compute how much time the previous operations took.
4891 * This allows us in particular to take account for any time
4892 * elapsed if something slowed down.
4894 TimeElapsed
= NtGetTickCount() - StartTime
;
4895 if (TimeElapsed
>= TimerDiv
)
4897 /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
4898 TimeElapsed
/= TimerDiv
;
4899 StartTime
+= (TimerDiv
* TimeElapsed
);
4901 if (TimeElapsed
<= TimerValue
)
4902 TimerValue
-= TimeElapsed
;
4906 RefreshProgress
= TRUE
;
4909 if (RefreshProgress
)
4911 ProgressSetStep(ProgressBar
, OldTimerValue
- TimerValue
);
4912 RefreshProgress
= FALSE
;
4915 /* Stop when the timer reaches zero */
4916 if (TimerValue
<= 0)
4919 /* Check for user key presses */
4922 * If the timer is used, use a passive wait of maximum 1 second
4923 * while monitoring for incoming console input events, so that
4924 * we are still able to display the timing count.
4927 /* Wait a maximum of 1 second for input events */
4928 TimeElapsed
= NtGetTickCount() - StartTime
;
4929 if (TimeElapsed
< TimerDiv
)
4931 /* Convert the time to NT Format */
4932 Timeout
.QuadPart
= (TimerDiv
- TimeElapsed
) * -10000LL;
4933 Status
= NtWaitForSingleObject(StdInput
, FALSE
, &Timeout
);
4937 Status
= STATUS_TIMEOUT
;
4940 /* Check whether the input event has been signaled, or a timeout happened */
4941 if (Status
== STATUS_TIMEOUT
)
4945 if (Status
!= STATUS_WAIT_0
)
4947 /* An error happened, bail out */
4948 DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status
);
4952 /* Check for an ENTER key press */
4953 while (CONSOLE_ConInKeyPeek(Ir
))
4955 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4957 /* Found it, stop waiting */
4964 /* Destroy the progress bar and quit */
4965 DestroyProgressBar(ProgressBar
);
4970 * Displays the QuitPage.
4973 * FlushPage (At once)
4979 * Number of the next page.
4982 QuitPage(PINPUT_RECORD Ir
)
4984 MUIDisplayPage(QUIT_PAGE
);
4986 /* Destroy the NTOS installations list */
4987 if (NtOsInstallsList
!= NULL
)
4989 DestroyGenericList(NtOsInstallsList
, TRUE
);
4990 NtOsInstallsList
= NULL
;
4993 /* Destroy the partition list */
4994 if (PartitionList
!= NULL
)
4996 DestroyPartitionList(PartitionList
);
4997 PartitionList
= NULL
;
4999 TempPartition
= NULL
;
5000 FormatState
= Start
;
5002 /* Destroy the filesystem list */
5003 if (FileSystemList
!= NULL
)
5005 DestroyFileSystemList(FileSystemList
);
5006 FileSystemList
= NULL
;
5009 /* Destroy the computer settings list */
5010 if (ComputerList
!= NULL
)
5012 DestroyGenericList(ComputerList
, TRUE
);
5013 ComputerList
= NULL
;
5016 /* Destroy the display settings list */
5017 if (DisplayList
!= NULL
)
5019 DestroyGenericList(DisplayList
, TRUE
);
5023 /* Destroy the keyboard settings list */
5024 if (KeyboardList
!= NULL
)
5026 DestroyGenericList(KeyboardList
, TRUE
);
5027 KeyboardList
= NULL
;
5030 /* Destroy the keyboard layout list */
5031 if (LayoutList
!= NULL
)
5033 DestroyGenericList(LayoutList
, TRUE
);
5037 /* Destroy the languages list */
5038 if (LanguageList
!= NULL
)
5040 DestroyGenericList(LanguageList
, FALSE
);
5041 LanguageList
= NULL
;
5044 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
5046 /* Wait for maximum 15 seconds or an ENTER key before quitting */
5047 ProgressCountdown(Ir
, 15);
5053 * Displays the SuccessPage.
5056 * FlushPage (At once)
5062 * Number of the next page.
5065 SuccessPage(PINPUT_RECORD Ir
)
5067 MUIDisplayPage(SUCCESS_PAGE
);
5069 if (IsUnattendedSetup
)
5072 /* Wait for maximum 15 seconds or an ENTER key before quitting */
5073 ProgressCountdown(Ir
, 15);
5079 * Displays the FlushPage.
5082 * RebootPage (At once)
5085 * Number of the next page.
5088 FlushPage(PINPUT_RECORD Ir
)
5090 MUIDisplayPage(FLUSH_PAGE
);
5096 PnpEventThread(IN LPVOID lpParameter
);
5100 * The start routine and page management
5110 InfSetHeap(ProcessHeap
);
5112 /* Tell the Cm this is a setup boot, and it has to behave accordingly */
5113 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
5114 if (!NT_SUCCESS(Status
))
5115 DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status
);
5117 /* Create the PnP thread in suspended state */
5118 Status
= RtlCreateUserThread(NtCurrentProcess(),
5128 if (!NT_SUCCESS(Status
))
5129 hPnpThread
= INVALID_HANDLE_VALUE
;
5131 if (!CONSOLE_Init())
5133 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
5134 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
5135 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
5137 /* We failed to initialize the video, just quit the installer */
5138 return STATUS_APP_INIT_FAILURE
;
5141 /* Initialize global unicode strings */
5142 RtlInitUnicodeString(&SourcePath
, NULL
);
5143 RtlInitUnicodeString(&SourceRootPath
, NULL
);
5144 RtlInitUnicodeString(&SourceRootDir
, NULL
);
5145 RtlInitUnicodeString(&InstallPath
, NULL
);
5146 RtlInitUnicodeString(&DestinationPath
, NULL
);
5147 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
5148 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
5149 RtlInitUnicodeString(&SystemRootPath
, NULL
);
5151 /* Hide the cursor */
5152 CONSOLE_SetCursorType(TRUE
, FALSE
);
5154 /* Global Initialization page */
5155 CONSOLE_ClearScreen();
5157 Page
= SetupStartPage(&Ir
);
5159 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
5161 CONSOLE_ClearScreen();
5164 // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
5171 Page
= LanguagePage(&Ir
);
5176 Page
= WelcomePage(&Ir
);
5181 Page
= LicensePage(&Ir
);
5185 case INSTALL_INTRO_PAGE
:
5186 Page
= InstallIntroPage(&Ir
);
5190 case SCSI_CONTROLLER_PAGE
:
5191 Page
= ScsiControllerPage(&Ir
);
5194 case OEM_DRIVER_PAGE
:
5195 Page
= OemDriverPage(&Ir
);
5199 case DEVICE_SETTINGS_PAGE
:
5200 Page
= DeviceSettingsPage(&Ir
);
5203 case COMPUTER_SETTINGS_PAGE
:
5204 Page
= ComputerSettingsPage(&Ir
);
5207 case DISPLAY_SETTINGS_PAGE
:
5208 Page
= DisplaySettingsPage(&Ir
);
5211 case KEYBOARD_SETTINGS_PAGE
:
5212 Page
= KeyboardSettingsPage(&Ir
);
5215 case LAYOUT_SETTINGS_PAGE
:
5216 Page
= LayoutSettingsPage(&Ir
);
5219 case SELECT_PARTITION_PAGE
:
5220 Page
= SelectPartitionPage(&Ir
);
5223 case CREATE_PRIMARY_PARTITION_PAGE
:
5224 Page
= CreatePrimaryPartitionPage(&Ir
);
5227 case CREATE_EXTENDED_PARTITION_PAGE
:
5228 Page
= CreateExtendedPartitionPage(&Ir
);
5231 case CREATE_LOGICAL_PARTITION_PAGE
:
5232 Page
= CreateLogicalPartitionPage(&Ir
);
5235 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
5236 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
5239 case DELETE_PARTITION_PAGE
:
5240 Page
= DeletePartitionPage(&Ir
);
5243 case SELECT_FILE_SYSTEM_PAGE
:
5244 Page
= SelectFileSystemPage(&Ir
);
5247 case FORMAT_PARTITION_PAGE
:
5248 Page
= FormatPartitionPage(&Ir
);
5251 case CHECK_FILE_SYSTEM_PAGE
:
5252 Page
= CheckFileSystemPage(&Ir
);
5255 case INSTALL_DIRECTORY_PAGE
:
5256 Page
= InstallDirectoryPage(&Ir
);
5259 case PREPARE_COPY_PAGE
:
5260 Page
= PrepareCopyPage(&Ir
);
5263 case FILE_COPY_PAGE
:
5264 Page
= FileCopyPage(&Ir
);
5268 Page
= RegistryPage(&Ir
);
5271 case BOOT_LOADER_PAGE
:
5272 Page
= BootLoaderPage(&Ir
);
5275 case BOOT_LOADER_FLOPPY_PAGE
:
5276 Page
= BootLoaderFloppyPage(&Ir
);
5279 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
5280 Page
= BootLoaderHarddiskMbrPage(&Ir
);
5283 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
5284 Page
= BootLoaderHarddiskVbrPage(&Ir
);
5288 case REPAIR_INTRO_PAGE
:
5289 Page
= RepairIntroPage(&Ir
);
5292 case UPGRADE_REPAIR_PAGE
:
5293 Page
= UpgradeRepairPage(&Ir
);
5297 Page
= SuccessPage(&Ir
);
5301 Page
= FlushPage(&Ir
);
5305 Page
= QuitPage(&Ir
);
5314 if (Page
== RECOVERY_PAGE
)
5320 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
5321 NtShutdownSystem(ShutdownReboot
);
5322 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
5324 return STATUS_SUCCESS
;
5329 NtProcessStartup(PPEB Peb
)
5334 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
5336 ProcessHeap
= Peb
->ProcessHeap
;
5338 NtQuerySystemTime(&Time
);
5340 Status
= RunUSetup();
5342 if (NT_SUCCESS(Status
))
5345 * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
5346 * a protective waiting.
5347 * This wait is needed because, since we are started as SMSS.EXE,
5348 * the NT kernel explicitly waits 5 seconds for the initial process
5349 * SMSS.EXE to initialize (as a protective measure), and otherwise
5350 * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
5352 Time
.QuadPart
+= 50000000;
5353 NtDelayExecution(FALSE
, &Time
);
5357 /* The installer failed to start: raise a hard error (crash the system/BSOD) */
5358 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
5359 0, 0, NULL
, 0, NULL
);
5362 NtTerminateProcess(NtCurrentProcess(), Status
);