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: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
43 /* GLOBALS ******************************************************************/
46 UNICODE_STRING SourceRootPath
;
47 UNICODE_STRING SourceRootDir
;
48 UNICODE_STRING SourcePath
;
49 BOOLEAN IsUnattendedSetup
= FALSE
;
50 LONG UnattendDestinationDiskNumber
;
51 LONG UnattendDestinationPartitionNumber
;
52 LONG UnattendMBRInstallType
= -1;
53 LONG UnattendFormatPartition
= 0;
54 LONG AutoPartition
= 0;
55 WCHAR UnattendInstallationDirectory
[MAX_PATH
];
56 PWCHAR SelectedLanguageId
;
58 WCHAR DefaultLanguage
[20];
59 WCHAR DefaultKBLayout
[20];
60 BOOLEAN RepairUpdateFlag
= FALSE
;
61 HANDLE hPnpThread
= INVALID_HANDLE_VALUE
;
62 PPARTLIST PartitionList
= NULL
;
64 /* LOCALS *******************************************************************/
66 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
68 static UNICODE_STRING InstallPath
;
71 * Path to the system partition, where the boot manager resides.
72 * On x86 PCs, this is usually the active partition.
73 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
75 * For more information, see:
76 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
77 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
78 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
79 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
80 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
81 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
83 static UNICODE_STRING SystemRootPath
;
85 /* Path to the install directory inside the ReactOS boot partition */
86 static UNICODE_STRING DestinationPath
;
87 static UNICODE_STRING DestinationArcPath
;
88 static UNICODE_STRING DestinationRootPath
;
90 static WCHAR DestinationDriveLetter
;
94 static HSPFILEQ SetupFileQueue
= NULL
;
96 static PGENERIC_LIST ComputerList
= NULL
;
97 static PGENERIC_LIST DisplayList
= NULL
;
98 static PGENERIC_LIST KeyboardList
= NULL
;
99 static PGENERIC_LIST LayoutList
= NULL
;
100 static PGENERIC_LIST LanguageList
= NULL
;
102 static LANGID LanguageId
= 0;
104 static ULONG RequiredPartitionDiskSpace
= ~0;
106 /* FUNCTIONS ****************************************************************/
109 PrintString(char* fmt
,...)
113 UNICODE_STRING UnicodeString
;
114 ANSI_STRING AnsiString
;
117 vsprintf(buffer
, fmt
, ap
);
120 RtlInitAnsiString(&AnsiString
, buffer
);
121 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
122 NtDisplayString(&UnicodeString
);
123 RtlFreeUnicodeString(&UnicodeString
);
128 DrawBox(IN SHORT xLeft
,
136 /* draw upper left corner */
139 FillConsoleOutputCharacterA(StdOutput
,
145 /* draw upper edge */
148 FillConsoleOutputCharacterA(StdOutput
,
154 /* draw upper right corner */
155 coPos
.X
= xLeft
+ Width
- 1;
157 FillConsoleOutputCharacterA(StdOutput
,
163 /* Draw right edge, inner space and left edge */
164 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
167 FillConsoleOutputCharacterA(StdOutput
,
174 FillConsoleOutputCharacterA(StdOutput
,
180 coPos
.X
= xLeft
+ Width
- 1;
181 FillConsoleOutputCharacterA(StdOutput
,
188 /* draw lower left corner */
190 coPos
.Y
= yTop
+ Height
- 1;
191 FillConsoleOutputCharacterA(StdOutput
,
197 /* draw lower edge */
199 coPos
.Y
= yTop
+ Height
- 1;
200 FillConsoleOutputCharacterA(StdOutput
,
206 /* draw lower right corner */
207 coPos
.X
= xLeft
+ Width
- 1;
208 coPos
.Y
= yTop
+ Height
- 1;
209 FillConsoleOutputCharacterA(StdOutput
,
218 PopupError(PCCH Text
,
236 /* Count text lines and longest line */
243 p
= strchr(pnext
, '\n');
247 Length
= strlen(pnext
);
252 Length
= (ULONG
)(p
- pnext
);
258 if (Length
> MaxLength
)
261 if (LastLine
!= FALSE
)
267 /* Check length of status line */
270 Length
= strlen(Status
);
272 if (Length
> MaxLength
)
276 Width
= MaxLength
+ 4;
282 yTop
= (yScreen
- Height
) / 2;
283 xLeft
= (xScreen
- Width
) / 2;
286 /* Set screen attributes */
288 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
290 FillConsoleOutputAttribute(StdOutput
,
291 FOREGROUND_RED
| BACKGROUND_WHITE
,
297 DrawBox(xLeft
, yTop
, Width
, Height
);
299 /* Print message text */
304 p
= strchr(pnext
, '\n');
308 Length
= strlen(pnext
);
313 Length
= (ULONG
)(p
- pnext
);
320 WriteConsoleOutputCharacterA(StdOutput
,
327 if (LastLine
!= FALSE
)
334 /* Print separator line and status text */
337 coPos
.Y
= yTop
+ Height
- 3;
339 FillConsoleOutputCharacterA(StdOutput
,
346 FillConsoleOutputCharacterA(StdOutput
,
352 coPos
.X
= xLeft
+ Width
- 1;
353 FillConsoleOutputCharacterA(StdOutput
,
361 WriteConsoleOutputCharacterA(StdOutput
,
363 min(strlen(Status
), (SIZE_T
)Width
- 4),
368 if (WaitEvent
== POPUP_WAIT_NONE
)
373 CONSOLE_ConInKey(Ir
);
375 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
376 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
388 * FALSE: Don't quit setup.
391 ConfirmQuit(PINPUT_RECORD Ir
)
394 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
398 CONSOLE_ConInKey(Ir
);
400 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
401 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
406 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
418 CheckUnattendedSetup(VOID
)
420 WCHAR UnattendInfPath
[MAX_PATH
];
427 if (DoesFileExist(SourcePath
.Buffer
, L
"unattend.inf") == FALSE
)
429 DPRINT("Does not exist: %S\\%S\n", SourcePath
.Buffer
, L
"unattend.inf");
433 wcscpy(UnattendInfPath
, SourcePath
.Buffer
);
434 wcscat(UnattendInfPath
, L
"\\unattend.inf");
436 /* Load 'unattend.inf' from install media. */
437 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
443 if (UnattendInf
== INVALID_HANDLE_VALUE
)
445 DPRINT("SetupOpenInfFileW() failed\n");
449 /* Open 'Unattend' section */
450 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
452 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
453 SetupCloseInfFile(UnattendInf
);
457 /* Get pointer 'Signature' key */
458 if (!INF_GetData(&Context
, NULL
, &Value
))
460 DPRINT("INF_GetData() failed for key 'Signature'\n");
461 SetupCloseInfFile(UnattendInf
);
465 /* Check 'Signature' string */
466 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
468 DPRINT("Signature not $ReactOS$\n");
469 SetupCloseInfFile(UnattendInf
);
473 /* Check if Unattend setup is enabled */
474 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
476 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
477 SetupCloseInfFile(UnattendInf
);
481 if (!INF_GetData(&Context
, NULL
, &Value
))
483 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
484 SetupCloseInfFile(UnattendInf
);
488 if (_wcsicmp(Value
, L
"yes") != 0)
490 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
491 SetupCloseInfFile(UnattendInf
);
495 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
496 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
498 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
499 SetupCloseInfFile(UnattendInf
);
503 if (!SetupGetIntField(&Context
, 1, &IntValue
))
505 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
506 SetupCloseInfFile(UnattendInf
);
510 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
512 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
513 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
515 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
516 SetupCloseInfFile(UnattendInf
);
520 if (!SetupGetIntField(&Context
, 1, &IntValue
))
522 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
523 SetupCloseInfFile(UnattendInf
);
527 UnattendDestinationPartitionNumber
= IntValue
;
529 /* Search for 'InstallationDirectory' in the 'Unattend' section */
530 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
532 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
533 SetupCloseInfFile(UnattendInf
);
537 /* Get pointer 'InstallationDirectory' key */
538 if (!INF_GetData(&Context
, NULL
, &Value
))
540 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
541 SetupCloseInfFile(UnattendInf
);
545 wcscpy(UnattendInstallationDirectory
, Value
);
547 IsUnattendedSetup
= TRUE
;
549 /* Search for 'MBRInstallType' in the 'Unattend' section */
550 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
552 if (SetupGetIntField(&Context
, 1, &IntValue
))
554 UnattendMBRInstallType
= IntValue
;
558 /* Search for 'FormatPartition' in the 'Unattend' section */
559 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
561 if (SetupGetIntField(&Context
, 1, &IntValue
))
563 UnattendFormatPartition
= IntValue
;
567 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
569 if (SetupGetIntField(&Context
, 1, &IntValue
))
571 AutoPartition
= IntValue
;
575 /* search for LocaleID in the 'Unattend' section*/
576 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
578 if (INF_GetData(&Context
, NULL
, &Value
))
580 LONG Id
= wcstol(Value
, NULL
, 16);
581 swprintf(LocaleID
,L
"%08lx", Id
);
585 SetupCloseInfFile(UnattendInf
);
587 DPRINT("Running unattended setup\n");
594 PGENERIC_LIST_ENTRY ListEntry
;
595 LPCWSTR pszNewLayout
;
597 pszNewLayout
= MUIDefaultKeyboardLayout();
599 if (LayoutList
== NULL
)
601 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
602 if (LayoutList
== NULL
)
604 /* FIXME: Handle error! */
609 ListEntry
= GetFirstListEntry(LayoutList
);
611 /* Search for default layout (if provided) */
612 if (pszNewLayout
!= NULL
)
614 while (ListEntry
!= NULL
)
616 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
618 SetCurrentListEntry(LayoutList
, ListEntry
);
622 ListEntry
= GetNextListEntry(ListEntry
);
629 * Displays the LanguagePage.
631 * Next pages: IntroPage, QuitPage
634 * Init SelectedLanguageId
638 * Number of the next page.
641 LanguagePage(PINPUT_RECORD Ir
)
643 PWCHAR NewLanguageId
;
644 BOOL RefreshPage
= FALSE
;
646 /* Initialize the computer settings list */
647 if (LanguageList
== NULL
)
649 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
651 if (LanguageList
== NULL
)
653 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
659 SelectedLanguageId
= DefaultLanguage
;
660 SetConsoleCodePage();
663 /* If there's just a single language in the list skip
664 * the language selection process altogether! */
665 if (GenericListHasSingleEntry(LanguageList
))
667 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
671 DrawGenericList(LanguageList
,
677 ScrollToPositionGenericList(LanguageList
, GetDefaultLanguageIndex());
679 MUIDisplayPage(LANGUAGE_PAGE
);
683 CONSOLE_ConInKey(Ir
);
685 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
686 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
688 ScrollDownGenericList(LanguageList
);
691 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
692 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
694 ScrollUpGenericList(LanguageList
);
697 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
698 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
700 ScrollPageDownGenericList(LanguageList
);
703 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
704 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
706 ScrollPageUpGenericList(LanguageList
);
709 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
710 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
712 if (ConfirmQuit(Ir
) != FALSE
)
715 RedrawGenericList(LanguageList
);
717 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
719 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
721 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
723 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
729 SetConsoleCodePage();
733 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
736 GenericListKeyPress(LanguageList
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
742 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
744 if (SelectedLanguageId
!= NewLanguageId
)
746 /* Clear the language page */
747 MUIClearPage(LANGUAGE_PAGE
);
749 SelectedLanguageId
= NewLanguageId
;
752 SetConsoleCodePage();
754 /* Redraw language selection page in native language */
755 MUIDisplayPage(LANGUAGE_PAGE
);
770 * LanguagePage (at once, default)
771 * InstallIntroPage (at once, if unattended)
777 * Init SourceRootPath
780 * Init RequiredPartitionDiskSpace
781 * Init IsUnattendedSetup
782 * If unattended, init *List and sets the Codepage
783 * If unattended, init SelectedLanguageId
784 * If unattended, init LanguageId
787 * Number of the next page.
790 SetupStartPage(PINPUT_RECORD Ir
)
792 //SYSTEM_DEVICE_INFORMATION Sdi;
794 WCHAR FileNameBuffer
[MAX_PATH
];
799 PGENERIC_LIST_ENTRY ListEntry
;
802 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
805 /* Check whether a harddisk is available */
806 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
808 sizeof(SYSTEM_DEVICE_INFORMATION
),
811 if (!NT_SUCCESS(Status
))
813 CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status
);
814 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
818 if (Sdi
.NumberOfDisks
== 0)
820 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
825 /* Get the source path and source root path */
826 Status
= GetSourcePaths(&SourcePath
,
830 if (!NT_SUCCESS(Status
))
832 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
833 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
839 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
840 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
841 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir
);
845 /* Load txtsetup.sif from install media. */
846 wcscpy(FileNameBuffer
, SourcePath
.Buffer
);
847 wcscat(FileNameBuffer
, L
"\\txtsetup.sif");
849 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
855 if (SetupInf
== INVALID_HANDLE_VALUE
)
857 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
861 /* Open 'Version' section */
862 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
864 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
868 /* Get pointer 'Signature' key */
869 if (!INF_GetData(&Context
, NULL
, &Value
))
871 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
875 /* Check 'Signature' string */
876 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
878 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
882 /* Open 'DiskSpaceRequirements' section */
883 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
885 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
889 /* Get the 'FreeSysPartDiskSpace' value */
890 if (!SetupGetIntField(&Context
, 1, &IntValue
))
892 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
896 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
898 /* Start PnP thread */
899 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
901 NtResumeThread(hPnpThread
, NULL
);
902 hPnpThread
= INVALID_HANDLE_VALUE
;
905 CheckUnattendedSetup();
907 if (IsUnattendedSetup
)
910 //read options from inf
911 ComputerList
= CreateComputerTypeList(SetupInf
);
912 DisplayList
= CreateDisplayDriverList(SetupInf
);
913 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
914 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
915 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
918 wcscpy(SelectedLanguageId
,LocaleID
);
919 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
921 /* first we hack LanguageList */
922 ListEntry
= GetFirstListEntry(LanguageList
);
924 while (ListEntry
!= NULL
)
926 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
928 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
929 SetCurrentListEntry(LanguageList
, ListEntry
);
933 ListEntry
= GetNextListEntry(ListEntry
);
937 ListEntry
= GetFirstListEntry(LayoutList
);
939 while (ListEntry
!= NULL
)
941 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
943 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
944 SetCurrentListEntry(LayoutList
, ListEntry
);
948 ListEntry
= GetNextListEntry(ListEntry
);
951 SetConsoleCodePage();
953 return INSTALL_INTRO_PAGE
;
956 return LANGUAGE_PAGE
;
961 * Displays the IntroPage.
964 * InstallIntroPage (default)
970 * Number of the next page.
973 IntroPage(PINPUT_RECORD Ir
)
975 MUIDisplayPage(START_PAGE
);
979 CONSOLE_ConInKey(Ir
);
981 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
982 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
984 if (ConfirmQuit(Ir
) != FALSE
)
989 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
991 return INSTALL_INTRO_PAGE
;
993 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
995 return REPAIR_INTRO_PAGE
;
997 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* R */
1008 * Displays the License page.
1011 * IntroPage (default)
1014 * Number of the next page.
1017 LicensePage(PINPUT_RECORD Ir
)
1019 MUIDisplayPage(LICENSE_PAGE
);
1023 CONSOLE_ConInKey(Ir
);
1025 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1031 return LICENSE_PAGE
;
1036 * Displays the RepairIntroPage.
1039 * RebootPage (default)
1045 * Number of the next page.
1048 RepairIntroPage(PINPUT_RECORD Ir
)
1050 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1054 CONSOLE_ConInKey(Ir
);
1056 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1060 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1062 RepairUpdateFlag
= TRUE
;
1063 return INSTALL_INTRO_PAGE
;
1065 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1067 return RECOVERY_PAGE
;
1069 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1070 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1076 return REPAIR_INTRO_PAGE
;
1080 * Displays the InstallIntroPage.
1083 * DeviceSettingsPage (At once if repair or update is selected)
1084 * SelectPartitionPage (At once if unattended setup)
1085 * DeviceSettingsPage (default)
1089 * Number of the next page.
1092 InstallIntroPage(PINPUT_RECORD Ir
)
1094 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1096 if (RepairUpdateFlag
)
1098 //return SELECT_PARTITION_PAGE;
1099 return DEVICE_SETTINGS_PAGE
;
1102 if (IsUnattendedSetup
)
1104 return SELECT_PARTITION_PAGE
;
1109 CONSOLE_ConInKey(Ir
);
1111 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1112 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1114 if (ConfirmQuit(Ir
) != FALSE
)
1119 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1121 return DEVICE_SETTINGS_PAGE
;
1122 // return SCSI_CONTROLLER_PAGE;
1126 return INSTALL_INTRO_PAGE
;
1132 ScsiControllerPage(PINPUT_RECORD Ir
)
1134 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1136 /* FIXME: print loaded mass storage driver descriptions */
1138 SetTextXY(8, 10, "TEST device");
1142 SetStatusText(" ENTER = Continue F3 = Quit");
1148 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1149 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1151 if (ConfirmQuit(Ir
) != FALSE
)
1156 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1158 return DEVICE_SETTINGS_PAGE
;
1162 return SCSI_CONTROLLER_PAGE
;
1168 * Displays the DeviceSettingsPage.
1171 * SelectPartitionPage (At once if repair or update is selected)
1172 * ComputerSettingsPage
1173 * DisplaySettingsPage
1174 * KeyboardSettingsPage
1175 * LayoutsettingsPage
1176 * SelectPartitionPage
1186 * Number of the next page.
1189 DeviceSettingsPage(PINPUT_RECORD Ir
)
1191 static ULONG Line
= 16;
1192 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1194 /* Initialize the computer settings list */
1195 if (ComputerList
== NULL
)
1197 ComputerList
= CreateComputerTypeList(SetupInf
);
1198 if (ComputerList
== NULL
)
1200 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1205 /* Initialize the display settings list */
1206 if (DisplayList
== NULL
)
1208 DisplayList
= CreateDisplayDriverList(SetupInf
);
1209 if (DisplayList
== NULL
)
1211 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1216 /* Initialize the keyboard settings list */
1217 if (KeyboardList
== NULL
)
1219 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1220 if (KeyboardList
== NULL
)
1222 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1227 /* Initialize the keyboard layout list */
1228 if (LayoutList
== NULL
)
1230 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1231 if (LayoutList
== NULL
)
1233 /* FIXME: report error */
1234 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1239 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1242 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList
))));
1243 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList
))));
1244 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList
))));
1245 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList
))));
1247 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1249 if (RepairUpdateFlag
)
1251 return SELECT_PARTITION_PAGE
;
1256 CONSOLE_ConInKey(Ir
);
1258 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1259 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1261 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1265 else if (Line
== 16)
1270 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1272 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1273 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1275 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1279 else if (Line
== 16)
1284 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1286 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1287 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1289 if (ConfirmQuit(Ir
) != FALSE
)
1294 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1297 return COMPUTER_SETTINGS_PAGE
;
1298 else if (Line
== 12)
1299 return DISPLAY_SETTINGS_PAGE
;
1300 else if (Line
== 13)
1301 return KEYBOARD_SETTINGS_PAGE
;
1302 else if (Line
== 14)
1303 return LAYOUT_SETTINGS_PAGE
;
1304 else if (Line
== 16)
1305 return SELECT_PARTITION_PAGE
;
1309 return DEVICE_SETTINGS_PAGE
;
1314 * Handles generic selection lists.
1317 * GenericList: The list to handle.
1318 * nextPage: The page it needs to jump to after this page.
1319 * Ir: The PINPUT_RECORD
1322 HandleGenericList(PGENERIC_LIST GenericList
,
1323 PAGE_NUMBER nextPage
,
1328 CONSOLE_ConInKey(Ir
);
1330 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1331 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1333 ScrollDownGenericList(GenericList
);
1335 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1336 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1338 ScrollUpGenericList(GenericList
);
1340 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1341 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1343 ScrollPageDownGenericList(GenericList
);
1345 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1346 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1348 ScrollPageUpGenericList(GenericList
);
1350 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1351 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1353 if (ConfirmQuit(Ir
) != FALSE
)
1358 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1359 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1361 RestoreGenericListState(GenericList
);
1364 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1368 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1371 GenericListKeyPress(GenericList
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1378 * Displays the ComputerSettingsPage.
1381 * DeviceSettingsPage
1385 * Number of the next page.
1388 ComputerSettingsPage(PINPUT_RECORD Ir
)
1390 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1392 DrawGenericList(ComputerList
,
1398 SaveGenericListState(ComputerList
);
1400 return HandleGenericList(ComputerList
, DEVICE_SETTINGS_PAGE
, Ir
);
1405 * Displays the DisplaySettingsPage.
1408 * DeviceSettingsPage
1412 * Number of the next page.
1415 DisplaySettingsPage(PINPUT_RECORD Ir
)
1417 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1419 DrawGenericList(DisplayList
,
1425 SaveGenericListState(DisplayList
);
1427 return HandleGenericList(DisplayList
, DEVICE_SETTINGS_PAGE
, Ir
);
1432 * Displays the KeyboardSettingsPage.
1435 * DeviceSettingsPage
1439 * Number of the next page.
1442 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1444 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1446 DrawGenericList(KeyboardList
,
1452 SaveGenericListState(KeyboardList
);
1454 return HandleGenericList(KeyboardList
, DEVICE_SETTINGS_PAGE
, Ir
);
1459 * Displays the LayoutSettingsPage.
1462 * DeviceSettingsPage
1466 * Number of the next page.
1469 LayoutSettingsPage(PINPUT_RECORD Ir
)
1471 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1473 DrawGenericList(LayoutList
,
1479 SaveGenericListState(LayoutList
);
1481 return HandleGenericList(LayoutList
, DEVICE_SETTINGS_PAGE
, Ir
);
1486 IsDiskSizeValid(PPARTENTRY PartEntry
)
1490 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1491 size
= (size
+ 524288) / 1048576; /* in MBytes */
1493 if (size
< RequiredPartitionDiskSpace
)
1495 /* partition is too small so ask for another partition */
1496 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1507 * Displays the SelectPartitionPage.
1510 * SelectFileSystemPage (At once if unattended)
1511 * SelectFileSystemPage (Default if free space is selected)
1512 * CreatePrimaryPartitionPage
1513 * CreateExtendedPartitionPage
1514 * CreateLogicalPartitionPage
1515 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1516 * DeletePartitionPage
1520 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1521 * Set InstallShortcut (only if not unattended + free space is selected)
1524 * Number of the next page.
1527 SelectPartitionPage(PINPUT_RECORD Ir
)
1531 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1533 if (PartitionList
== NULL
)
1535 PartitionList
= CreatePartitionList(2,
1539 if (PartitionList
== NULL
)
1541 /* FIXME: show an error dialog */
1544 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1546 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1551 DrawPartitionList(PartitionList
);
1553 if (IsUnattendedSetup
)
1555 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1559 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1561 CreateLogicalPartition(PartitionList
,
1562 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1567 CreatePrimaryPartition(PartitionList
,
1568 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1572 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1574 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1575 RequiredPartitionDiskSpace
);
1576 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1579 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1581 return SELECT_FILE_SYSTEM_PAGE
;
1586 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1588 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1589 RequiredPartitionDiskSpace
);
1590 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1593 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1595 return SELECT_FILE_SYSTEM_PAGE
;
1601 /* Update status text */
1602 if (PartitionList
->CurrentPartition
== NULL
)
1604 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1606 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1608 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1610 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1614 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1619 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1621 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1623 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1627 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1632 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1636 CONSOLE_ConInKey(Ir
);
1638 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1639 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1641 if (ConfirmQuit(Ir
) != FALSE
)
1643 DestroyPartitionList(PartitionList
);
1644 PartitionList
= NULL
;
1650 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1651 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1653 if (ScrollDownPartitionList(PartitionList
))
1654 DrawPartitionList(PartitionList
);
1656 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1657 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1659 if (ScrollUpPartitionList(PartitionList
))
1660 DrawPartitionList(PartitionList
);
1662 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1664 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1665 continue; //return SELECT_PARTITION_PAGE;
1667 if (PartitionList
->CurrentPartition
== NULL
||
1668 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1670 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1672 CreateLogicalPartition(PartitionList
,
1678 CreatePrimaryPartition(PartitionList
,
1684 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1686 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1687 RequiredPartitionDiskSpace
);
1688 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1691 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1693 return SELECT_FILE_SYSTEM_PAGE
;
1695 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1697 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1699 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1700 if (Error
!= NOT_AN_ERROR
)
1702 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1703 return SELECT_PARTITION_PAGE
;
1706 return CREATE_PRIMARY_PARTITION_PAGE
;
1709 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1711 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1713 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1714 if (Error
!= NOT_AN_ERROR
)
1716 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1717 return SELECT_PARTITION_PAGE
;
1720 return CREATE_EXTENDED_PARTITION_PAGE
;
1723 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1725 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1727 Error
= LogicalPartitionCreationChecks(PartitionList
);
1728 if (Error
!= NOT_AN_ERROR
)
1730 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1731 return SELECT_PARTITION_PAGE
;
1734 return CREATE_LOGICAL_PARTITION_PAGE
;
1737 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1739 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1741 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1742 return SELECT_PARTITION_PAGE
;
1745 if (PartitionList
->CurrentPartition
->BootIndicator
||
1746 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1748 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1751 return DELETE_PARTITION_PAGE
;
1755 return SELECT_PARTITION_PAGE
;
1759 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1760 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1761 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1764 ShowPartitionSizeInputBox(SHORT Left
,
1777 WCHAR PartitionSizeBuffer
[100];
1789 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1794 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1795 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1798 WriteConsoleOutputCharacterA(StdOutput
,
1804 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1805 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1807 WriteConsoleOutputCharacterA(StdOutput
,
1813 swprintf(PartitionSizeBuffer
, L
"%lu", MaxSize
);
1814 Length
= wcslen(PartitionSizeBuffer
);
1816 CONSOLE_SetInputTextXY(iLeft
,
1818 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1819 PartitionSizeBuffer
);
1820 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1821 CONSOLE_SetCursorType(TRUE
, TRUE
);
1825 CONSOLE_ConInKey(&Ir
);
1827 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1828 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1833 PartitionSizeBuffer
[0] = UNICODE_NULL
;
1834 CONSOLE_SetCursorType(TRUE
, FALSE
);
1837 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1839 CONSOLE_SetCursorType(TRUE
, FALSE
);
1842 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1847 PartitionSizeBuffer
[0] = UNICODE_NULL
;
1848 CONSOLE_SetCursorType(TRUE
, FALSE
);
1851 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1852 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1855 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1857 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1858 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1861 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1863 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1864 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1869 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1872 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1873 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1878 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1881 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1882 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1886 memmove(&PartitionSizeBuffer
[Pos
],
1887 &PartitionSizeBuffer
[Pos
+ 1],
1888 (Length
- Pos
- 1) * sizeof(WCHAR
));
1889 PartitionSizeBuffer
[Length
- 1] = UNICODE_NULL
;
1892 CONSOLE_SetInputTextXY(iLeft
,
1894 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1895 PartitionSizeBuffer
);
1896 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1899 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1904 memmove(&PartitionSizeBuffer
[Pos
- 1],
1905 &PartitionSizeBuffer
[Pos
],
1906 (Length
- Pos
) * sizeof(WCHAR
));
1907 PartitionSizeBuffer
[Length
- 1] = UNICODE_NULL
;
1911 CONSOLE_SetInputTextXY(iLeft
,
1913 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1914 PartitionSizeBuffer
);
1915 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1918 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1920 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1922 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1924 if ((ch
>= L
'0') && (ch
<= L
'9'))
1927 memmove(&PartitionSizeBuffer
[Pos
+ 1],
1928 &PartitionSizeBuffer
[Pos
],
1929 (Length
- Pos
) * sizeof(WCHAR
));
1930 PartitionSizeBuffer
[Length
+ 1] = UNICODE_NULL
;
1931 PartitionSizeBuffer
[Pos
] = ch
;
1935 CONSOLE_SetInputTextXY(iLeft
,
1937 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1938 PartitionSizeBuffer
);
1939 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1945 /* Convert UNICODE --> ANSI the poor man's way */
1946 sprintf(InputBuffer
, "%S", PartitionSizeBuffer
);
1951 * Displays the CreatePrimaryPartitionPage.
1954 * SelectPartitionPage
1955 * SelectFileSystemPage (default)
1959 * Number of the next page.
1962 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1964 PDISKENTRY DiskEntry
;
1965 PPARTENTRY PartEntry
;
1968 CHAR InputBuffer
[50];
1972 ULONGLONG SectorCount
;
1975 if (PartitionList
== NULL
||
1976 PartitionList
->CurrentDisk
== NULL
||
1977 PartitionList
->CurrentPartition
== NULL
)
1979 /* FIXME: show an error dialog */
1983 DiskEntry
= PartitionList
->CurrentDisk
;
1984 PartEntry
= PartitionList
->CurrentPartition
;
1986 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1988 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1990 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1992 if (DiskSize
>= 10737418240) /* 10 GB */
1994 DiskSize
= DiskSize
/ 1073741824;
1995 Unit
= MUIGetString(STRING_GB
);
2000 DiskSize
= DiskSize
/ 1048576;
2004 Unit
= MUIGetString(STRING_MB
);
2007 if (DiskEntry
->DriverName
.Length
> 0)
2009 CONSOLE_PrintTextXY(6, 10,
2010 MUIGetString(STRING_HDINFOPARTCREATE
),
2013 DiskEntry
->DiskNumber
,
2017 &DiskEntry
->DriverName
);
2021 CONSOLE_PrintTextXY(6, 10,
2022 MUIGetString(STRING_HDDINFOUNK1
),
2025 DiskEntry
->DiskNumber
,
2031 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2034 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2035 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2038 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2040 PartEntry
= PartitionList
->CurrentPartition
;
2043 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2045 if (MaxSize
> PARTITION_MAXSIZE
)
2046 MaxSize
= PARTITION_MAXSIZE
;
2048 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2049 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2053 if (ConfirmQuit(Ir
) != FALSE
)
2058 else if (Cancel
!= FALSE
)
2060 return SELECT_PARTITION_PAGE
;
2064 PartSize
= atoi(InputBuffer
);
2072 if (PartSize
> MaxSize
)
2078 /* Convert to bytes */
2079 if (PartSize
== MaxSize
)
2081 /* Use all of the unpartitioned disk space */
2082 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2086 /* Calculate the sector count from the size in MB */
2087 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2089 /* But never get larger than the unpartitioned disk space */
2090 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2091 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2094 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2096 CreatePrimaryPartition(PartitionList
,
2100 return SELECT_PARTITION_PAGE
;
2104 return CREATE_PRIMARY_PARTITION_PAGE
;
2109 * Displays the CreateExtendedPartitionPage.
2112 * SelectPartitionPage (default)
2116 * Number of the next page.
2119 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2121 PDISKENTRY DiskEntry
;
2122 PPARTENTRY PartEntry
;
2125 CHAR InputBuffer
[50];
2129 ULONGLONG SectorCount
;
2132 if (PartitionList
== NULL
||
2133 PartitionList
->CurrentDisk
== NULL
||
2134 PartitionList
->CurrentPartition
== NULL
)
2136 /* FIXME: show an error dialog */
2140 DiskEntry
= PartitionList
->CurrentDisk
;
2141 PartEntry
= PartitionList
->CurrentPartition
;
2143 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2145 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2147 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2149 if (DiskSize
>= 10737418240) /* 10 GB */
2151 DiskSize
= DiskSize
/ 1073741824;
2152 Unit
= MUIGetString(STRING_GB
);
2157 DiskSize
= DiskSize
/ 1048576;
2161 Unit
= MUIGetString(STRING_MB
);
2164 if (DiskEntry
->DriverName
.Length
> 0)
2166 CONSOLE_PrintTextXY(6, 10,
2167 MUIGetString(STRING_HDINFOPARTCREATE
),
2170 DiskEntry
->DiskNumber
,
2174 &DiskEntry
->DriverName
);
2178 CONSOLE_PrintTextXY(6, 10,
2179 MUIGetString(STRING_HDDINFOUNK1
),
2182 DiskEntry
->DiskNumber
,
2188 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2191 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2192 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2195 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2197 PartEntry
= PartitionList
->CurrentPartition
;
2200 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2202 if (MaxSize
> PARTITION_MAXSIZE
)
2203 MaxSize
= PARTITION_MAXSIZE
;
2205 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2206 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2210 if (ConfirmQuit(Ir
) != FALSE
)
2215 else if (Cancel
!= FALSE
)
2217 return SELECT_PARTITION_PAGE
;
2221 PartSize
= atoi(InputBuffer
);
2229 if (PartSize
> MaxSize
)
2235 /* Convert to bytes */
2236 if (PartSize
== MaxSize
)
2238 /* Use all of the unpartitioned disk space */
2239 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2243 /* Calculate the sector count from the size in MB */
2244 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2246 /* But never get larger than the unpartitioned disk space */
2247 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2248 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2251 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2253 CreateExtendedPartition(PartitionList
,
2256 return SELECT_PARTITION_PAGE
;
2260 return CREATE_EXTENDED_PARTITION_PAGE
;
2265 * Displays the CreateLogicalPartitionPage.
2268 * SelectFileSystemPage (default)
2272 * Number of the next page.
2275 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2277 PDISKENTRY DiskEntry
;
2278 PPARTENTRY PartEntry
;
2281 CHAR InputBuffer
[50];
2285 ULONGLONG SectorCount
;
2288 if (PartitionList
== NULL
||
2289 PartitionList
->CurrentDisk
== NULL
||
2290 PartitionList
->CurrentPartition
== NULL
)
2292 /* FIXME: show an error dialog */
2296 DiskEntry
= PartitionList
->CurrentDisk
;
2297 PartEntry
= PartitionList
->CurrentPartition
;
2299 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2301 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2303 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2305 if (DiskSize
>= 10737418240) /* 10 GB */
2307 DiskSize
= DiskSize
/ 1073741824;
2308 Unit
= MUIGetString(STRING_GB
);
2313 DiskSize
= DiskSize
/ 1048576;
2317 Unit
= MUIGetString(STRING_MB
);
2320 if (DiskEntry
->DriverName
.Length
> 0)
2322 CONSOLE_PrintTextXY(6, 10,
2323 MUIGetString(STRING_HDINFOPARTCREATE
),
2326 DiskEntry
->DiskNumber
,
2330 &DiskEntry
->DriverName
);
2334 CONSOLE_PrintTextXY(6, 10,
2335 MUIGetString(STRING_HDDINFOUNK1
),
2338 DiskEntry
->DiskNumber
,
2344 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2347 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2348 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2351 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2353 PartEntry
= PartitionList
->CurrentPartition
;
2356 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2358 if (MaxSize
> PARTITION_MAXSIZE
)
2359 MaxSize
= PARTITION_MAXSIZE
;
2361 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2362 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2366 if (ConfirmQuit(Ir
) != FALSE
)
2371 else if (Cancel
!= FALSE
)
2373 return SELECT_PARTITION_PAGE
;
2377 PartSize
= atoi(InputBuffer
);
2385 if (PartSize
> MaxSize
)
2391 /* Convert to bytes */
2392 if (PartSize
== MaxSize
)
2394 /* Use all of the unpartitioned disk space */
2395 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2399 /* Calculate the sector count from the size in MB */
2400 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2402 /* But never get larger than the unpartitioned disk space */
2403 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2404 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2407 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2409 CreateLogicalPartition(PartitionList
,
2413 return SELECT_PARTITION_PAGE
;
2417 return CREATE_LOGICAL_PARTITION_PAGE
;
2422 * Displays the ConfirmDeleteSystemPartitionPage.
2425 * DeletePartitionPage (default)
2426 * SelectPartitionPage
2429 * Number of the next page.
2432 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2434 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2438 CONSOLE_ConInKey(Ir
);
2440 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2441 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2443 if (ConfirmQuit(Ir
) == TRUE
)
2448 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2450 return DELETE_PARTITION_PAGE
;
2452 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2454 return SELECT_PARTITION_PAGE
;
2458 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2463 * Displays the DeletePartitionPage.
2466 * SelectPartitionPage (default)
2470 * Number of the next page.
2473 DeletePartitionPage(PINPUT_RECORD Ir
)
2475 PDISKENTRY DiskEntry
;
2476 PPARTENTRY PartEntry
;
2480 CHAR PartTypeString
[32];
2482 if (PartitionList
== NULL
||
2483 PartitionList
->CurrentDisk
== NULL
||
2484 PartitionList
->CurrentPartition
== NULL
)
2486 /* FIXME: show an error dialog */
2490 DiskEntry
= PartitionList
->CurrentDisk
;
2491 PartEntry
= PartitionList
->CurrentPartition
;
2493 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2495 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2497 ARRAYSIZE(PartTypeString
));
2499 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2501 if (PartSize
>= 10737418240) /* 10 GB */
2503 PartSize
= PartSize
/ 1073741824;
2504 Unit
= MUIGetString(STRING_GB
);
2508 if (PartSize
>= 10485760) /* 10 MB */
2510 PartSize
= PartSize
/ 1048576;
2511 Unit
= MUIGetString(STRING_MB
);
2515 PartSize
= PartSize
/ 1024;
2516 Unit
= MUIGetString(STRING_KB
);
2519 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2521 CONSOLE_PrintTextXY(6, 10,
2522 MUIGetString(STRING_HDDINFOUNK2
),
2523 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2524 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2525 PartEntry
->PartitionType
,
2531 CONSOLE_PrintTextXY(6, 10,
2532 " %c%c %s %I64u %s",
2533 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2534 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2540 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2542 if (DiskSize
>= 10737418240) /* 10 GB */
2544 DiskSize
= DiskSize
/ 1073741824;
2545 Unit
= MUIGetString(STRING_GB
);
2550 DiskSize
= DiskSize
/ 1048576;
2554 Unit
= MUIGetString(STRING_MB
);
2557 if (DiskEntry
->DriverName
.Length
> 0)
2559 CONSOLE_PrintTextXY(6, 12,
2560 MUIGetString(STRING_HDINFOPARTDELETE
),
2563 DiskEntry
->DiskNumber
,
2567 &DiskEntry
->DriverName
);
2571 CONSOLE_PrintTextXY(6, 12,
2572 MUIGetString(STRING_HDDINFOUNK3
),
2575 DiskEntry
->DiskNumber
,
2583 CONSOLE_ConInKey(Ir
);
2585 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2586 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2588 if (ConfirmQuit(Ir
) != FALSE
)
2593 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2595 return SELECT_PARTITION_PAGE
;
2597 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2599 DeleteCurrentPartition(PartitionList
);
2601 return SELECT_PARTITION_PAGE
;
2605 return DELETE_PARTITION_PAGE
;
2610 * Displays the SelectFileSystemPage.
2613 * CheckFileSystemPage (At once if RepairUpdate is selected)
2614 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2615 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2616 * SelectPartitionPage (If the user aborts)
2617 * FormatPartitionPage (Default)
2621 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2622 * Calls CheckActiveSystemPartition()
2625 * Number of the next page.
2628 SelectFileSystemPage(PINPUT_RECORD Ir
)
2630 PDISKENTRY DiskEntry
;
2631 PPARTENTRY PartEntry
;
2636 CHAR PartTypeString
[32];
2637 FORMATMACHINESTATE PreviousFormatState
;
2639 DPRINT("SelectFileSystemPage()\n");
2641 if (PartitionList
== NULL
||
2642 PartitionList
->CurrentDisk
== NULL
||
2643 PartitionList
->CurrentPartition
== NULL
)
2645 /* FIXME: show an error dialog */
2650 if (FileSystemList
== NULL
)
2652 FileSystemList
= CreateFileSystemList(6, 26, PartitionList
->CurrentPartition
->New
, L
"FAT");
2653 if (FileSystemList
== NULL
)
2655 /* FIXME: show an error dialog */
2659 /* FIXME: Add file systems to list */
2662 /* Find or set the active system partition */
2663 CheckActiveSystemPartition(PartitionList
, FileSystemList
);
2665 if (PartitionList
->SystemDisk
== NULL
||
2666 PartitionList
->SystemPartition
== NULL
)
2668 /* FIXME: show an error dialog */
2672 PreviousFormatState
= PartitionList
->FormatState
;
2673 switch (PartitionList
->FormatState
)
2676 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2678 PartitionList
->TempDisk
= PartitionList
->SystemDisk
;
2679 PartitionList
->TempPartition
= PartitionList
->SystemPartition
;
2680 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2682 PartitionList
->FormatState
= FormatSystemPartition
;
2683 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2687 PartitionList
->TempDisk
= PartitionList
->CurrentDisk
;
2688 PartitionList
->TempPartition
= PartitionList
->CurrentPartition
;
2689 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2691 PartitionList
->FormatState
= FormatInstallPartition
;
2692 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2696 case FormatSystemPartition
:
2697 PartitionList
->TempDisk
= PartitionList
->CurrentDisk
;
2698 PartitionList
->TempPartition
= PartitionList
->CurrentPartition
;
2699 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2701 PartitionList
->FormatState
= FormatInstallPartition
;
2702 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2705 case FormatInstallPartition
:
2706 if (GetNextUnformattedPartition(PartitionList
,
2707 &PartitionList
->TempDisk
,
2708 &PartitionList
->TempPartition
))
2710 PartitionList
->FormatState
= FormatOtherPartition
;
2711 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2712 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2716 PartitionList
->FormatState
= FormatDone
;
2717 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2718 return CHECK_FILE_SYSTEM_PAGE
;
2722 case FormatOtherPartition
:
2723 if (GetNextUnformattedPartition(PartitionList
,
2724 &PartitionList
->TempDisk
,
2725 &PartitionList
->TempPartition
))
2727 PartitionList
->FormatState
= FormatOtherPartition
;
2728 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2729 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2733 PartitionList
->FormatState
= FormatDone
;
2734 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2735 return CHECK_FILE_SYSTEM_PAGE
;
2740 DPRINT1("FormatState: Invalid value %ld\n", PartitionList
->FormatState
);
2741 /* FIXME: show an error dialog */
2745 DiskEntry
= PartitionList
->TempDisk
;
2746 PartEntry
= PartitionList
->TempPartition
;
2748 /* adjust disk size */
2749 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2750 if (DiskSize
>= 10737418240) /* 10 GB */
2752 DiskSize
= DiskSize
/ 1073741824;
2753 DiskUnit
= MUIGetString(STRING_GB
);
2757 DiskSize
= DiskSize
/ 1048576;
2758 DiskUnit
= MUIGetString(STRING_MB
);
2761 /* adjust partition size */
2762 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2763 if (PartSize
>= 10737418240) /* 10 GB */
2765 PartSize
= PartSize
/ 1073741824;
2766 PartUnit
= MUIGetString(STRING_GB
);
2770 PartSize
= PartSize
/ 1048576;
2771 PartUnit
= MUIGetString(STRING_MB
);
2774 /* adjust partition type */
2775 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2777 ARRAYSIZE(PartTypeString
));
2779 if (PartEntry
->AutoCreate
!= FALSE
)
2781 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2784 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2785 PartEntry
->PartitionNumber
,
2791 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED
),
2792 DiskEntry
->DiskNumber
,
2798 &DiskEntry
->DriverName
);
2800 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2803 PartEntry
->AutoCreate
= FALSE
;
2805 else if (PartEntry
->New
!= FALSE
)
2807 switch (PartitionList
->FormatState
)
2809 case FormatSystemPartition
:
2810 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2813 case FormatInstallPartition
:
2814 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2817 case FormatOtherPartition
:
2818 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2825 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2829 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2831 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2833 CONSOLE_PrintTextXY(8, 10,
2834 MUIGetString(STRING_HDDINFOUNK4
),
2835 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2836 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2837 PartEntry
->PartitionType
,
2843 CONSOLE_PrintTextXY(8, 10,
2845 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2846 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2852 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS
),
2853 DiskEntry
->DiskNumber
,
2859 &DiskEntry
->DriverName
);
2862 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2864 if (FileSystemList
== NULL
)
2866 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2867 if (FileSystemList
== NULL
)
2869 /* FIXME: show an error dialog */
2873 /* FIXME: Add file systems to list */
2876 DrawFileSystemList(FileSystemList
);
2878 if (RepairUpdateFlag
)
2880 return CHECK_FILE_SYSTEM_PAGE
;
2881 //return SELECT_PARTITION_PAGE;
2884 if (IsUnattendedSetup
)
2886 if (UnattendFormatPartition
)
2888 PartEntry
->FileSystem
= GetFileSystemByName(FileSystemList
, L
"FAT");
2889 return FORMAT_PARTITION_PAGE
;
2892 return CHECK_FILE_SYSTEM_PAGE
;
2897 CONSOLE_ConInKey(Ir
);
2899 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2900 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2902 if (ConfirmQuit(Ir
) != FALSE
)
2907 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2908 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2910 PartitionList
->FormatState
= Start
;
2911 return SELECT_PARTITION_PAGE
;
2913 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2914 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2916 ScrollDownFileSystemList(FileSystemList
);
2918 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2919 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2921 ScrollUpFileSystemList(FileSystemList
);
2923 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2925 if (!FileSystemList
->Selected
->FormatFunc
)
2927 return SELECT_FILE_SYSTEM_PAGE
;
2931 PartEntry
->FileSystem
= FileSystemList
->Selected
;
2932 return FORMAT_PARTITION_PAGE
;
2937 PartitionList
->FormatState
= PreviousFormatState
;
2939 return SELECT_FILE_SYSTEM_PAGE
;
2944 * Displays the FormatPartitionPage.
2947 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2948 * SelectPartitionPage (At once)
2952 * Sets PartitionList->CurrentPartition->FormatState
2953 * Sets DestinationRootPath
2956 * Number of the next page.
2959 FormatPartitionPage(PINPUT_RECORD Ir
)
2961 UNICODE_STRING PartitionRootPath
;
2962 WCHAR PathBuffer
[MAX_PATH
];
2963 PDISKENTRY DiskEntry
;
2964 PPARTENTRY PartEntry
;
2970 PPARTITION_INFORMATION PartitionInfo
;
2973 DPRINT("FormatPartitionPage()\n");
2975 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2977 if (PartitionList
== NULL
||
2978 PartitionList
->TempDisk
== NULL
||
2979 PartitionList
->TempPartition
== NULL
)
2981 /* FIXME: show an error dialog */
2985 DiskEntry
= PartitionList
->TempDisk
;
2986 PartEntry
= PartitionList
->TempPartition
;
2990 if (!IsUnattendedSetup
)
2992 CONSOLE_ConInKey(Ir
);
2995 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2996 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2998 if (ConfirmQuit(Ir
) != FALSE
)
3003 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
3005 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3007 if (wcscmp(PartEntry
->FileSystem
->FileSystemName
, L
"FAT") == 0)
3009 if (PartEntry
->SectorCount
.QuadPart
< 8192)
3011 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
3012 PartEntry
->PartitionType
= PARTITION_FAT_12
;
3014 else if (PartEntry
->StartSector
.QuadPart
< 1450560)
3016 /* Partition starts below the 8.4GB boundary ==> CHS partition */
3018 if (PartEntry
->SectorCount
.QuadPart
< 65536)
3020 /* FAT16 CHS partition (partition size < 32MB) */
3021 PartEntry
->PartitionType
= PARTITION_FAT_16
;
3023 else if (PartEntry
->SectorCount
.QuadPart
< 1048576)
3025 /* FAT16 CHS partition (partition size < 512MB) */
3026 PartEntry
->PartitionType
= PARTITION_HUGE
;
3030 /* FAT32 CHS partition (partition size >= 512MB) */
3031 PartEntry
->PartitionType
= PARTITION_FAT32
;
3036 /* Partition starts above the 8.4GB boundary ==> LBA partition */
3038 if (PartEntry
->SectorCount
.QuadPart
< 1048576)
3040 /* FAT16 LBA partition (partition size < 512MB) */
3041 PartEntry
->PartitionType
= PARTITION_XINT13
;
3045 /* FAT32 LBA partition (partition size >= 512MB) */
3046 PartEntry
->PartitionType
= PARTITION_FAT32_XINT13
;
3050 DiskEntry
->Dirty
= TRUE
;
3051 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].PartitionType
= PartEntry
->PartitionType
;
3052 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3055 else if (wcscmp(PartEntry
->FileSystem
->FileSystemName
, L
"EXT2") == 0)
3057 PartEntry
->PartitionType
= PARTITION_EXT2
;
3059 DiskEntry
->Dirty
= TRUE
;
3060 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].PartitionType
= PartEntry
->PartitionType
;
3061 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3063 else if (wcscmp(PartEntry
->FileSystem
->FileSystemName
, L
"NTFS") == 0)
3065 PartEntry
->PartitionType
= PARTITION_IFS
;
3067 DiskEntry
->Dirty
= TRUE
;
3068 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].PartitionType
= PartEntry
->PartitionType
;
3069 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3072 else if (!PartEntry
->FileSystem
->FormatFunc
)
3074 /* FIXME: show an error dialog */
3079 CONSOLE_PrintTextXY(6, 12,
3080 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3081 DiskEntry
->Cylinders
,
3082 DiskEntry
->TracksPerCylinder
,
3083 DiskEntry
->SectorsPerTrack
,
3084 DiskEntry
->BytesPerSector
,
3085 DiskEntry
->Dirty
? '*' : ' ');
3089 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3091 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3093 CONSOLE_PrintTextXY(6, Line
,
3094 "%2u: %2lu %c %12I64u %12I64u %02x",
3096 PartitionInfo
->PartitionNumber
,
3097 PartitionInfo
->BootIndicator
? 'A' : '-',
3098 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3099 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3100 PartitionInfo
->PartitionType
);
3105 if (WritePartitionsToDisk(PartitionList
) == FALSE
)
3107 DPRINT("WritePartitionsToDisk() failed\n");
3108 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3112 /* Set PartitionRootPath */
3113 swprintf(PathBuffer
,
3114 L
"\\Device\\Harddisk%lu\\Partition%lu",
3115 DiskEntry
->DiskNumber
,
3116 PartEntry
->PartitionNumber
);
3117 RtlInitUnicodeString(&PartitionRootPath
,
3119 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3121 if (PartEntry
->FileSystem
->FormatFunc
)
3123 Status
= FormatPartition(&PartitionRootPath
,
3124 PartEntry
->FileSystem
);
3125 if (!NT_SUCCESS(Status
))
3127 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3128 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3132 PartEntry
->New
= FALSE
;
3136 CONSOLE_SetStatusText(" Done. Press any key ...");
3137 CONSOLE_ConInKey(Ir
);
3140 return SELECT_FILE_SYSTEM_PAGE
;
3144 return FORMAT_PARTITION_PAGE
;
3149 * Displays the CheckFileSystemPage.
3152 * InstallDirectoryPage (At once)
3156 * Inits or reloads FileSystemList
3159 * Number of the next page.
3162 CheckFileSystemPage(PINPUT_RECORD Ir
)
3164 PFILE_SYSTEM_ITEM CurrentFileSystem
;
3165 UNICODE_STRING PartitionRootPath
;
3166 WCHAR PathBuffer
[MAX_PATH
];
3167 CHAR Buffer
[MAX_PATH
];
3168 PDISKENTRY DiskEntry
;
3169 PPARTENTRY PartEntry
;
3172 if (PartitionList
== NULL
)
3174 /* FIXME: show an error dialog */
3178 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3180 return INSTALL_DIRECTORY_PAGE
;
3183 /* Set PartitionRootPath */
3184 swprintf(PathBuffer
,
3185 L
"\\Device\\Harddisk%lu\\Partition%lu",
3186 DiskEntry
->DiskNumber
,
3187 PartEntry
->PartitionNumber
);
3188 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3189 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3191 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3193 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3195 CurrentFileSystem
= GetFileSystem(FileSystemList
, PartEntry
);
3196 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3197 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3199 /* HACK: Do not try to check a partition with an unknown filesystem */
3200 if (CurrentFileSystem
== NULL
)
3202 PartEntry
->NeedsCheck
= FALSE
;
3203 return CHECK_FILE_SYSTEM_PAGE
;
3206 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3209 "Setup is currently unable to check a partition formatted in %S.\n"
3211 " \x07 Press ENTER to continue Setup.\n"
3212 " \x07 Press F3 to quit Setup.",
3213 CurrentFileSystem
->FileSystemName
);
3216 MUIGetString(STRING_QUITCONTINUE
),
3217 NULL
, POPUP_WAIT_NONE
);
3221 CONSOLE_ConInKey(Ir
);
3223 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3224 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3226 if (ConfirmQuit(Ir
))
3229 return CHECK_FILE_SYSTEM_PAGE
;
3231 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3233 PartEntry
->NeedsCheck
= FALSE
;
3234 return CHECK_FILE_SYSTEM_PAGE
;
3240 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3241 if (!NT_SUCCESS(Status
))
3243 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3244 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3245 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3246 "(Status 0x%08lx).\n", Status
);
3248 // MUIGetString(STRING_REBOOTCOMPUTER),
3249 MUIGetString(STRING_CONTINUE
),
3250 Ir
, POPUP_WAIT_ENTER
);
3252 // return QUIT_PAGE;
3255 PartEntry
->NeedsCheck
= FALSE
;
3256 return CHECK_FILE_SYSTEM_PAGE
;
3263 BuildInstallPaths(PWCHAR InstallDir
,
3264 PDISKENTRY DiskEntry
,
3265 PPARTENTRY PartEntry
)
3267 WCHAR PathBuffer
[MAX_PATH
];
3269 /* Create 'InstallPath' string */
3270 RtlFreeUnicodeString(&InstallPath
);
3271 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3273 /* Create 'DestinationRootPath' string */
3274 RtlFreeUnicodeString(&DestinationRootPath
);
3275 swprintf(PathBuffer
,
3276 L
"\\Device\\Harddisk%lu\\Partition%lu",
3277 DiskEntry
->DiskNumber
,
3278 PartEntry
->PartitionNumber
);
3279 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3280 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3282 /* Create 'DestinationPath' string */
3283 RtlFreeUnicodeString(&DestinationPath
);
3284 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3286 if (InstallDir
[0] != L
'\\')
3287 wcscat(PathBuffer
, L
"\\");
3289 wcscat(PathBuffer
, InstallDir
);
3290 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3292 /* Create 'DestinationArcPath' */
3293 RtlFreeUnicodeString(&DestinationArcPath
);
3294 swprintf(PathBuffer
,
3295 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3296 DiskEntry
->BiosDiskNumber
,
3297 PartEntry
->PartitionNumber
);
3299 if (InstallDir
[0] != L
'\\')
3300 wcscat(PathBuffer
, L
"\\");
3302 wcscat(PathBuffer
, InstallDir
);
3303 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3308 * Displays the InstallDirectoryPage.
3311 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3315 * Number of the next page.
3318 InstallDirectoryPage(PINPUT_RECORD Ir
)
3320 PDISKENTRY DiskEntry
;
3321 PPARTENTRY PartEntry
;
3322 WCHAR InstallDir
[51];
3326 /* We do not need the filesystem list any more */
3327 if (FileSystemList
!= NULL
)
3329 DestroyFileSystemList(FileSystemList
);
3330 FileSystemList
= NULL
;
3333 if (PartitionList
== NULL
||
3334 PartitionList
->CurrentDisk
== NULL
||
3335 PartitionList
->CurrentPartition
== NULL
)
3337 /* FIXME: show an error dialog */
3341 DiskEntry
= PartitionList
->CurrentDisk
;
3342 PartEntry
= PartitionList
->CurrentPartition
;
3344 if (IsUnattendedSetup
)
3346 if (!IsValidPath(UnattendInstallationDirectory
))
3348 /* FIXME: Log the error? */
3352 BuildInstallPaths(UnattendInstallationDirectory
,
3356 return PREPARE_COPY_PAGE
;
3359 wcscpy(InstallDir
, L
"\\ReactOS");
3361 Length
= wcslen(InstallDir
);
3363 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3364 CONSOLE_SetCursorXY(8 + Pos
, 11);
3365 CONSOLE_SetCursorType(TRUE
, TRUE
);
3366 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3370 CONSOLE_ConInKey(Ir
);
3372 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3373 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3375 CONSOLE_SetCursorType(TRUE
, FALSE
);
3377 if (ConfirmQuit(Ir
) != FALSE
)
3380 CONSOLE_SetCursorType(TRUE
, TRUE
);
3383 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3384 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3388 memmove(&InstallDir
[Pos
],
3389 &InstallDir
[Pos
+ 1],
3390 (Length
- Pos
- 1) * sizeof(WCHAR
));
3391 InstallDir
[Length
- 1] = UNICODE_NULL
;
3394 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3395 CONSOLE_SetCursorXY(8 + Pos
, 11);
3398 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3399 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3402 CONSOLE_SetCursorXY(8 + Pos
, 11);
3404 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3405 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3408 CONSOLE_SetCursorXY(8 + Pos
, 11);
3410 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3411 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3416 CONSOLE_SetCursorXY(8 + Pos
, 11);
3419 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3420 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3425 CONSOLE_SetCursorXY(8 + Pos
, 11);
3428 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3430 CONSOLE_SetCursorType(TRUE
, FALSE
);
3433 * Check for the validity of the installation directory and pop up
3434 * an error if it is not the case. Then the user can fix its input.
3436 if (!IsValidPath(InstallDir
))
3438 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3439 return INSTALL_DIRECTORY_PAGE
;
3442 BuildInstallPaths(InstallDir
,
3446 return PREPARE_COPY_PAGE
;
3448 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3453 memmove(&InstallDir
[Pos
- 1],
3455 (Length
- Pos
) * sizeof(WCHAR
));
3456 InstallDir
[Length
- 1] = UNICODE_NULL
;
3460 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3461 CONSOLE_SetCursorXY(8 + Pos
, 11);
3464 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3468 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3469 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3472 memmove(&InstallDir
[Pos
+ 1],
3474 (Length
- Pos
) * sizeof(WCHAR
));
3475 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3476 InstallDir
[Pos
] = c
;
3480 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3481 CONSOLE_SetCursorXY(8 + Pos
, 11);
3487 return INSTALL_DIRECTORY_PAGE
;
3492 AddSectionToCopyQueueCab(HINF InfFile
,
3494 PWCHAR SourceCabinet
,
3495 PCUNICODE_STRING DestinationPath
,
3498 INFCONTEXT FilesContext
;
3499 INFCONTEXT DirContext
;
3501 PWCHAR FileKeyValue
;
3503 PWCHAR TargetFileName
;
3505 /* Search for the SectionName section */
3506 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3509 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3510 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3515 * Enumerate the files in the section
3516 * and add them to the file queue.
3520 /* Get source file name and target directory id */
3521 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3523 /* FIXME: Handle error! */
3524 DPRINT1("INF_GetData() failed\n");
3528 /* Get optional target file name */
3529 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3530 TargetFileName
= NULL
;
3532 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3534 /* Lookup target directory */
3535 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3537 /* FIXME: Handle error! */
3538 DPRINT1("SetupFindFirstLine() failed\n");
3542 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3544 /* FIXME: Handle error! */
3545 DPRINT1("INF_GetData() failed\n");
3549 if (!SetupQueueCopy(SetupFileQueue
,
3551 SourceRootPath
.Buffer
,
3552 SourceRootDir
.Buffer
,
3557 /* FIXME: Handle error! */
3558 DPRINT1("SetupQueueCopy() failed\n");
3560 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3567 AddSectionToCopyQueue(HINF InfFile
,
3569 PWCHAR SourceCabinet
,
3570 PCUNICODE_STRING DestinationPath
,
3573 INFCONTEXT FilesContext
;
3574 INFCONTEXT DirContext
;
3576 PWCHAR FileKeyValue
;
3578 PWCHAR TargetFileName
;
3580 WCHAR CompleteOrigDirName
[512];
3583 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3585 /* Search for the SectionName section */
3586 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3589 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3590 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3595 * Enumerate the files in the section
3596 * and add them to the file queue.
3600 /* Get source file name and target directory id */
3601 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3603 /* FIXME: Handle error! */
3604 DPRINT1("INF_GetData() failed\n");
3608 /* Get target directory id */
3609 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3611 /* FIXME: Handle error! */
3612 DPRINT1("INF_GetData() failed\n");
3616 /* Get optional target file name */
3617 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3618 TargetFileName
= NULL
;
3619 else if (!*TargetFileName
)
3620 TargetFileName
= NULL
;
3622 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3624 /* Lookup target directory */
3625 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3627 /* FIXME: Handle error! */
3628 DPRINT1("SetupFindFirstLine() failed\n");
3632 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3634 /* FIXME: Handle error! */
3635 DPRINT1("INF_GetData() failed\n");
3639 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3641 /* Installation path */
3642 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3644 else if (DirKeyValue
[0] == L
'\\')
3647 wcscpy(CompleteOrigDirName
, DirKeyValue
);
3649 else // if (DirKeyValue[0] != L'\\')
3651 /* Path relative to the installation path */
3652 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3653 wcscat(CompleteOrigDirName
, L
"\\");
3654 wcscat(CompleteOrigDirName
, DirKeyValue
);
3657 /* Remove trailing backslash */
3658 Length
= wcslen(CompleteOrigDirName
);
3659 if ((Length
> 0) && (CompleteOrigDirName
[Length
- 1] == L
'\\'))
3661 CompleteOrigDirName
[Length
- 1] = 0;
3664 if (!SetupQueueCopy(SetupFileQueue
,
3666 SourceRootPath
.Buffer
,
3667 CompleteOrigDirName
,
3672 /* FIXME: Handle error! */
3673 DPRINT1("SetupQueueCopy() failed\n");
3675 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3682 PrepareCopyPageInfFile(HINF InfFile
,
3683 PWCHAR SourceCabinet
,
3686 WCHAR PathBuffer
[MAX_PATH
];
3687 INFCONTEXT DirContext
;
3688 PWCHAR AdditionalSectionName
= NULL
;
3693 /* Add common files */
3694 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &DestinationPath
, Ir
))
3697 /* Add specific files depending of computer type */
3698 if (SourceCabinet
== NULL
)
3700 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3703 if (AdditionalSectionName
)
3705 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &DestinationPath
, Ir
))
3710 /* Create directories */
3714 * - Install directories like '\reactos\test' are not handled yet.
3715 * - Copying files to DestinationRootPath should be done from within
3716 * the SystemPartitionFiles section.
3717 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3718 * For installing to DestinationPath specify just '\' .
3721 /* Get destination path */
3722 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3724 /* Remove trailing backslash */
3725 Length
= wcslen(PathBuffer
);
3726 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3728 PathBuffer
[Length
- 1] = 0;
3731 /* Create the install directory */
3732 Status
= SetupCreateDirectory(PathBuffer
);
3733 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3735 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3736 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3740 /* Search for the 'Directories' section */
3741 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3745 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3749 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3755 /* Enumerate the directory values and create the subdirectories */
3758 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3764 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3766 /* Installation path */
3767 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3769 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3771 DPRINT("FullPath: '%S'\n", PathBuffer
);
3773 else if (DirKeyValue
[0] == L
'\\')
3776 DPRINT("Absolute Path: '%S'\n", DirKeyValue
);
3778 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3779 wcscat(PathBuffer
, DirKeyValue
);
3781 /* Remove trailing backslash */
3782 Length
= wcslen(PathBuffer
);
3783 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3785 PathBuffer
[Length
- 1] = 0;
3788 DPRINT("FullPath: '%S'\n", PathBuffer
);
3790 Status
= SetupCreateDirectory(PathBuffer
);
3791 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3793 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3794 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3798 else // if (DirKeyValue[0] != L'\\')
3800 /* Path relative to the installation path */
3801 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3803 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3804 wcscat(PathBuffer
, L
"\\");
3805 wcscat(PathBuffer
, DirKeyValue
);
3807 /* Remove trailing backslash */
3808 Length
= wcslen(PathBuffer
);
3809 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3811 PathBuffer
[Length
- 1] = 0;
3814 DPRINT("FullPath: '%S'\n", PathBuffer
);
3816 Status
= SetupCreateDirectory(PathBuffer
);
3817 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3819 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3820 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3824 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3831 * Displays the PrepareCopyPage.
3834 * FileCopyPage(At once)
3838 * Inits SetupFileQueue
3839 * Calls PrepareCopyPageInfFile
3842 * Number of the next page.
3845 PrepareCopyPage(PINPUT_RECORD Ir
)
3848 WCHAR PathBuffer
[MAX_PATH
];
3849 INFCONTEXT CabinetsContext
;
3855 MUIDisplayPage(PREPARE_COPY_PAGE
);
3857 /* Create the file queue */
3858 SetupFileQueue
= SetupOpenFileQueue();
3859 if (SetupFileQueue
== NULL
)
3861 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3865 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3867 /* FIXME: show an error dialog */
3871 /* Search for the 'Cabinets' section */
3872 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3874 return FILE_COPY_PAGE
;
3878 * Enumerate the directory values in the 'Cabinets'
3879 * section and parse their inf files.
3883 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3886 wcscpy(PathBuffer
, SourcePath
.Buffer
);
3887 wcscat(PathBuffer
, L
"\\");
3888 wcscat(PathBuffer
, KeyValue
);
3890 CabinetInitialize();
3891 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3892 CabinetSetCabinetName(PathBuffer
);
3894 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3896 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3898 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3899 if (InfFileData
== NULL
)
3901 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3907 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3908 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3912 InfHandle
= INF_OpenBufferedFileA((CHAR
*) InfFileData
,
3919 if (InfHandle
== INVALID_HANDLE_VALUE
)
3921 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3927 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3929 /* FIXME: show an error dialog */
3932 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3934 return FILE_COPY_PAGE
;
3940 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3943 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3945 /* Get the memory information from the system */
3946 NtQuerySystemInformation(SystemPerformanceInformation
,
3951 /* Check if this is initial setup */
3954 /* Set maximum limits to be total RAM pages */
3955 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3956 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3957 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3960 /* Set current values */
3961 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3962 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3963 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3969 FileCopyCallback(PVOID Context
,
3974 PCOPYCONTEXT CopyContext
;
3976 CopyContext
= (PCOPYCONTEXT
)Context
;
3978 switch (Notification
)
3980 case SPFILENOTIFY_STARTSUBQUEUE
:
3981 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3982 ProgressSetStepCount(CopyContext
->ProgressBar
,
3983 CopyContext
->TotalOperations
);
3984 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3987 case SPFILENOTIFY_STARTCOPY
:
3988 /* Display copy message */
3989 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3990 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3993 case SPFILENOTIFY_ENDCOPY
:
3994 CopyContext
->CompletedOperations
++;
3996 /* SYSREG checkpoint */
3997 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3998 DPRINT1("CHECKPOINT:HALF_COPIED\n");
4000 ProgressNextStep(CopyContext
->ProgressBar
);
4001 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
4010 * Displays the FileCopyPage.
4013 * RegistryPage(At once)
4016 * Calls SetupCommitFileQueueW
4017 * Calls SetupCloseFileQueue
4020 * Number of the next page.
4024 FileCopyPage(PINPUT_RECORD Ir
)
4026 COPYCONTEXT CopyContext
;
4027 unsigned int mem_bar_width
;
4029 MUIDisplayPage(FILE_COPY_PAGE
);
4031 /* Create context for the copy process */
4032 CopyContext
.DestinationRootPath
= DestinationRootPath
.Buffer
;
4033 CopyContext
.InstallPath
= InstallPath
.Buffer
;
4034 CopyContext
.TotalOperations
= 0;
4035 CopyContext
.CompletedOperations
= 0;
4037 /* Create the progress bar as well */
4038 CopyContext
.ProgressBar
= CreateProgressBar(13,
4045 MUIGetString(STRING_SETUPCOPYINGFILES
));
4047 // fit memory bars to screen width, distribute them uniform
4048 mem_bar_width
= (xScreen
- 26) / 5;
4049 mem_bar_width
-= mem_bar_width
% 2; // make even
4050 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4051 /* Create the paged pool progress bar */
4052 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
4061 /* Create the non paged pool progress bar */
4062 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
4064 (xScreen
/ 2) + (mem_bar_width
/ 2),
4066 (xScreen
/ 2)- (mem_bar_width
/ 2),
4071 /* Create the global memory progress bar */
4072 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
4076 xScreen
- 13 - mem_bar_width
,
4081 /* Do the file copying */
4082 SetupCommitFileQueueW(NULL
,
4087 /* If we get here, we're done, so cleanup the queue and progress bar */
4088 SetupCloseFileQueue(SetupFileQueue
);
4089 DestroyProgressBar(CopyContext
.ProgressBar
);
4090 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4091 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4092 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4094 /* Go display the next page */
4095 return REGISTRY_PAGE
;
4100 * Displays the RegistryPage.
4103 * SuccessPage (if RepairUpdate)
4104 * BootLoaderPage (default)
4108 * Calls SetInstallPathValue
4109 * Calls NtInitializeRegistry
4110 * Calls ImportRegistryFile
4111 * Calls SetDefaultPagefile
4112 * Calls SetMountedDeviceValues
4115 * Number of the next page.
4118 RegistryPage(PINPUT_RECORD Ir
)
4120 INFCONTEXT InfContext
;
4127 MUIDisplayPage(REGISTRY_PAGE
);
4129 if (RepairUpdateFlag
)
4131 return SUCCESS_PAGE
;
4134 if (!SetInstallPathValue(&DestinationPath
))
4136 DPRINT1("SetInstallPathValue() failed\n");
4137 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4141 /* Create the default hives */
4142 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4143 if (!NT_SUCCESS(Status
))
4145 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
4146 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4150 /* Update registry */
4151 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4153 if (!SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
))
4155 DPRINT1("SetupFindFirstLine() failed\n");
4156 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4162 INF_GetDataField(&InfContext
, 0, &Action
);
4163 INF_GetDataField(&InfContext
, 1, &File
);
4164 INF_GetDataField(&InfContext
, 2, &Section
);
4166 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4171 if (!_wcsicmp(Action
, L
"AddReg"))
4175 else if (!_wcsicmp(Action
, L
"DelReg"))
4184 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4186 if (!ImportRegistryFile(File
, Section
, LanguageId
, Delete
))
4188 DPRINT1("Importing %S failed\n", File
);
4190 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4193 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4195 /* Update display registry settings */
4196 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4197 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4199 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4203 /* Set the locale */
4204 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4205 if (!ProcessLocaleRegistry(LanguageList
))
4207 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4211 /* Add keyboard layouts */
4212 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4213 if (!AddKeyboardLayouts())
4215 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4221 if (!SetGeoID(MUIGetGeoID()))
4223 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4227 if (!IsUnattendedSetup
)
4229 /* Update keyboard layout settings */
4230 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4231 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4233 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4238 /* Add codepage information to registry */
4239 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4242 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4246 /* Set the default pagefile entry */
4247 SetDefaultPagefile(DestinationDriveLetter
);
4249 /* Update the mounted devices list */
4250 SetMountedDeviceValues(PartitionList
);
4252 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4254 return BOOT_LOADER_PAGE
;
4259 * Displays the BootLoaderPage.
4262 * SuccessPage (if RepairUpdate)
4263 * BootLoaderHarddiskMbrPage
4264 * BootLoaderHarddiskVbrPage
4265 * BootLoaderFloppyPage
4270 * Calls SetInstallPathValue
4271 * Calls NtInitializeRegistry
4272 * Calls ImportRegistryFile
4273 * Calls SetDefaultPagefile
4274 * Calls SetMountedDeviceValues
4277 * Number of the next page.
4280 BootLoaderPage(PINPUT_RECORD Ir
)
4282 UCHAR PartitionType
;
4283 BOOLEAN InstallOnFloppy
;
4285 WCHAR PathBuffer
[MAX_PATH
];
4287 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4289 RtlFreeUnicodeString(&SystemRootPath
);
4290 swprintf(PathBuffer
,
4291 L
"\\Device\\Harddisk%lu\\Partition%lu",
4292 PartitionList
->SystemDisk
->DiskNumber
,
4293 PartitionList
->SystemPartition
->PartitionNumber
);
4294 RtlCreateUnicodeString(&SystemRootPath
, PathBuffer
);
4295 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath
);
4297 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4299 if (IsUnattendedSetup
)
4301 if (UnattendMBRInstallType
== 0) /* skip MBR installation */
4303 return SUCCESS_PAGE
;
4305 else if (UnattendMBRInstallType
== 1) /* install on floppy */
4307 return BOOT_LOADER_FLOPPY_PAGE
;
4311 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4313 DPRINT("Error: system partition invalid (unused)\n");
4314 InstallOnFloppy
= TRUE
;
4316 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4318 /* OS/2 boot manager partition */
4319 DPRINT("Found OS/2 boot manager partition\n");
4320 InstallOnFloppy
= TRUE
;
4322 else if (PartitionType
== PARTITION_EXT2
)
4324 /* Linux EXT2 partition */
4325 DPRINT("Found Linux EXT2 partition\n");
4326 InstallOnFloppy
= FALSE
;
4328 else if (PartitionType
== PARTITION_IFS
)
4330 /* NTFS partition */
4331 DPRINT("Found NTFS partition\n");
4333 // FIXME: Make it FALSE when we'll support NTFS installation!
4334 InstallOnFloppy
= TRUE
;
4336 else if ((PartitionType
== PARTITION_FAT_12
) ||
4337 (PartitionType
== PARTITION_FAT_16
) ||
4338 (PartitionType
== PARTITION_HUGE
) ||
4339 (PartitionType
== PARTITION_XINT13
) ||
4340 (PartitionType
== PARTITION_FAT32
) ||
4341 (PartitionType
== PARTITION_FAT32_XINT13
))
4343 DPRINT("Found FAT partition\n");
4344 InstallOnFloppy
= FALSE
;
4348 /* Unknown partition */
4349 DPRINT("Unknown partition found\n");
4350 InstallOnFloppy
= TRUE
;
4353 if (InstallOnFloppy
!= FALSE
)
4355 return BOOT_LOADER_FLOPPY_PAGE
;
4358 /* Unattended install on hdd? */
4359 if (IsUnattendedSetup
&& UnattendMBRInstallType
== 2)
4361 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4364 MUIDisplayPage(BOOT_LOADER_PAGE
);
4365 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4369 CONSOLE_ConInKey(Ir
);
4371 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4372 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4374 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4383 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4385 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4386 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4388 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4397 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4399 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4400 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4402 if (ConfirmQuit(Ir
) != FALSE
)
4407 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4411 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4413 else if (Line
== 13)
4415 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4417 else if (Line
== 14)
4419 return BOOT_LOADER_FLOPPY_PAGE
;
4421 else if (Line
== 15)
4423 return SUCCESS_PAGE
;
4426 return BOOT_LOADER_PAGE
;
4430 return BOOT_LOADER_PAGE
;
4435 * Displays the BootLoaderFloppyPage.
4438 * SuccessPage (At once)
4442 * Calls InstallFatBootcodeToFloppy()
4445 * Number of the next page.
4448 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4452 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4454 // SetStatusText(" Please wait...");
4458 CONSOLE_ConInKey(Ir
);
4460 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4461 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4463 if (ConfirmQuit(Ir
) != FALSE
)
4468 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4470 if (DoesFileExist(L
"\\Device\\Floppy0", L
"\\") == FALSE
)
4472 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4473 return BOOT_LOADER_FLOPPY_PAGE
;
4476 Status
= InstallFatBootcodeToFloppy(&SourceRootPath
, &DestinationArcPath
);
4477 if (!NT_SUCCESS(Status
))
4479 /* Print error message */
4480 return BOOT_LOADER_FLOPPY_PAGE
;
4483 return SUCCESS_PAGE
;
4487 return BOOT_LOADER_FLOPPY_PAGE
;
4492 * Displays the BootLoaderHarddiskVbrPage.
4495 * SuccessPage (At once)
4499 * Calls InstallVBRToPartition()
4502 * Number of the next page.
4505 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4507 UCHAR PartitionType
;
4510 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4512 Status
= InstallVBRToPartition(&SystemRootPath
,
4514 &DestinationArcPath
,
4516 if (!NT_SUCCESS(Status
))
4518 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4522 return SUCCESS_PAGE
;
4527 * Displays the BootLoaderHarddiskMbrPage.
4530 * SuccessPage (At once)
4534 * Calls InstallVBRToPartition()
4535 * CallsInstallMbrBootCodeToDisk()
4538 * Number of the next page.
4541 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4543 UCHAR PartitionType
;
4545 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4546 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4547 WCHAR DstPath
[MAX_PATH
];
4549 /* Step 1: Write the VBR */
4550 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4552 Status
= InstallVBRToPartition(&SystemRootPath
,
4554 &DestinationArcPath
,
4556 if (!NT_SUCCESS(Status
))
4558 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4562 /* Step 2: Write the MBR */
4563 swprintf(DestinationDevicePathBuffer
,
4564 L
"\\Device\\Harddisk%d\\Partition0",
4565 PartitionList
->SystemDisk
->DiskNumber
);
4567 wcscpy(SourceMbrPathBuffer
, SourceRootPath
.Buffer
);
4568 wcscat(SourceMbrPathBuffer
, L
"\\loader\\dosmbr.bin");
4570 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4572 /* Save current MBR */
4573 wcscpy(DstPath
, SystemRootPath
.Buffer
);
4574 wcscat(DstPath
, L
"\\mbr.old");
4576 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4577 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4578 if (!NT_SUCCESS(Status
))
4580 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4581 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4585 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4586 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4587 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4588 DestinationDevicePathBuffer
);
4589 if (!NT_SUCCESS(Status
))
4591 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4593 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4597 return SUCCESS_PAGE
;
4602 * Displays the QuitPage.
4605 * FlushPage (At once)
4611 * Number of the next page.
4614 QuitPage(PINPUT_RECORD Ir
)
4616 MUIDisplayPage(QUIT_PAGE
);
4618 /* Destroy partition list */
4619 if (PartitionList
!= NULL
)
4621 DestroyPartitionList(PartitionList
);
4622 PartitionList
= NULL
;
4625 /* Destroy filesystem list */
4626 if (FileSystemList
!= NULL
)
4628 DestroyFileSystemList(FileSystemList
);
4629 FileSystemList
= NULL
;
4632 /* Destroy computer settings list */
4633 if (ComputerList
!= NULL
)
4635 DestroyGenericList(ComputerList
, TRUE
);
4636 ComputerList
= NULL
;
4639 /* Destroy display settings list */
4640 if (DisplayList
!= NULL
)
4642 DestroyGenericList(DisplayList
, TRUE
);
4646 /* Destroy keyboard settings list */
4647 if (KeyboardList
!= NULL
)
4649 DestroyGenericList(KeyboardList
, TRUE
);
4650 KeyboardList
= NULL
;
4653 /* Destroy keyboard layout list */
4654 if (LayoutList
!= NULL
)
4656 DestroyGenericList(LayoutList
, TRUE
);
4660 if (LanguageList
!= NULL
)
4662 DestroyGenericList(LanguageList
, FALSE
);
4663 LanguageList
= NULL
;
4666 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4670 CONSOLE_ConInKey(Ir
);
4672 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4681 * Displays the SuccessPage.
4684 * FlushPage (At once)
4690 * Number of the next page.
4693 SuccessPage(PINPUT_RECORD Ir
)
4695 MUIDisplayPage(SUCCESS_PAGE
);
4697 if (IsUnattendedSetup
)
4704 CONSOLE_ConInKey(Ir
);
4706 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4715 * Displays the FlushPage.
4718 * RebootPage (At once)
4721 * Number of the next page.
4724 FlushPage(PINPUT_RECORD Ir
)
4726 MUIDisplayPage(FLUSH_PAGE
);
4732 PnpEventThread(IN LPVOID lpParameter
);
4736 * The start routine and page management
4747 NtQuerySystemTime(&Time
);
4749 Status
= RtlCreateUserThread(NtCurrentProcess(),
4759 if (!NT_SUCCESS(Status
))
4760 hPnpThread
= INVALID_HANDLE_VALUE
;
4762 if (!CONSOLE_Init())
4764 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4765 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4766 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4768 /* Raise a hard error (crash the system/BSOD) */
4769 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4773 /* Initialize global unicode strings */
4774 RtlInitUnicodeString(&SourcePath
, NULL
);
4775 RtlInitUnicodeString(&SourceRootPath
, NULL
);
4776 RtlInitUnicodeString(&SourceRootDir
, NULL
);
4777 RtlInitUnicodeString(&InstallPath
, NULL
);
4778 RtlInitUnicodeString(&DestinationPath
, NULL
);
4779 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
4780 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
4781 RtlInitUnicodeString(&SystemRootPath
, NULL
);
4783 /* Hide the cursor */
4784 CONSOLE_SetCursorType(TRUE
, FALSE
);
4787 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4789 CONSOLE_ClearScreen();
4792 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4799 Page
= SetupStartPage(&Ir
);
4804 Page
= LanguagePage(&Ir
);
4809 Page
= LicensePage(&Ir
);
4814 Page
= IntroPage(&Ir
);
4818 case INSTALL_INTRO_PAGE
:
4819 Page
= InstallIntroPage(&Ir
);
4823 case SCSI_CONTROLLER_PAGE
:
4824 Page
= ScsiControllerPage(&Ir
);
4829 case OEM_DRIVER_PAGE
:
4830 Page
= OemDriverPage(&Ir
);
4834 case DEVICE_SETTINGS_PAGE
:
4835 Page
= DeviceSettingsPage(&Ir
);
4838 case COMPUTER_SETTINGS_PAGE
:
4839 Page
= ComputerSettingsPage(&Ir
);
4842 case DISPLAY_SETTINGS_PAGE
:
4843 Page
= DisplaySettingsPage(&Ir
);
4846 case KEYBOARD_SETTINGS_PAGE
:
4847 Page
= KeyboardSettingsPage(&Ir
);
4850 case LAYOUT_SETTINGS_PAGE
:
4851 Page
= LayoutSettingsPage(&Ir
);
4854 case SELECT_PARTITION_PAGE
:
4855 Page
= SelectPartitionPage(&Ir
);
4858 case CREATE_PRIMARY_PARTITION_PAGE
:
4859 Page
= CreatePrimaryPartitionPage(&Ir
);
4862 case CREATE_EXTENDED_PARTITION_PAGE
:
4863 Page
= CreateExtendedPartitionPage(&Ir
);
4866 case CREATE_LOGICAL_PARTITION_PAGE
:
4867 Page
= CreateLogicalPartitionPage(&Ir
);
4870 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4871 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4874 case DELETE_PARTITION_PAGE
:
4875 Page
= DeletePartitionPage(&Ir
);
4878 case SELECT_FILE_SYSTEM_PAGE
:
4879 Page
= SelectFileSystemPage(&Ir
);
4882 case FORMAT_PARTITION_PAGE
:
4883 Page
= (PAGE_NUMBER
) FormatPartitionPage(&Ir
);
4886 case CHECK_FILE_SYSTEM_PAGE
:
4887 Page
= (PAGE_NUMBER
) CheckFileSystemPage(&Ir
);
4890 case INSTALL_DIRECTORY_PAGE
:
4891 Page
= InstallDirectoryPage(&Ir
);
4894 case PREPARE_COPY_PAGE
:
4895 Page
= PrepareCopyPage(&Ir
);
4898 case FILE_COPY_PAGE
:
4899 Page
= FileCopyPage(&Ir
);
4903 Page
= RegistryPage(&Ir
);
4906 case BOOT_LOADER_PAGE
:
4907 Page
= BootLoaderPage(&Ir
);
4910 case BOOT_LOADER_FLOPPY_PAGE
:
4911 Page
= BootLoaderFloppyPage(&Ir
);
4914 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4915 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4918 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4919 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4923 case REPAIR_INTRO_PAGE
:
4924 Page
= RepairIntroPage(&Ir
);
4928 Page
= SuccessPage(&Ir
);
4932 Page
= FlushPage(&Ir
);
4936 Page
= QuitPage(&Ir
);
4945 if (Page
== RECOVERY_PAGE
)
4950 /* Avoid bugcheck */
4951 Time
.QuadPart
+= 50000000;
4952 NtDelayExecution(FALSE
, &Time
);
4955 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4956 NtShutdownSystem(ShutdownReboot
);
4957 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4958 NtTerminateProcess(NtCurrentProcess(), 0);
4963 NtProcessStartup(PPEB Peb
)
4965 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4967 ProcessHeap
= Peb
->ProcessHeap
;
4968 InfSetHeap(ProcessHeap
);