3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hervé Poussineau (hpoussin@reactos.org)
42 /* GLOBALS ******************************************************************/
45 UNICODE_STRING SourceRootPath
;
46 UNICODE_STRING SourceRootDir
;
47 UNICODE_STRING SourcePath
;
48 BOOLEAN IsUnattendedSetup
= FALSE
;
49 LONG UnattendDestinationDiskNumber
;
50 LONG UnattendDestinationPartitionNumber
;
51 LONG UnattendMBRInstallType
= -1;
52 LONG UnattendFormatPartition
= 0;
53 LONG AutoPartition
= 0;
54 WCHAR UnattendInstallationDirectory
[MAX_PATH
];
55 PWCHAR SelectedLanguageId
;
57 WCHAR DefaultLanguage
[20];
58 WCHAR DefaultKBLayout
[20];
59 BOOLEAN RepairUpdateFlag
= FALSE
;
60 HANDLE hPnpThread
= INVALID_HANDLE_VALUE
;
62 PPARTLIST PartitionList
= NULL
;
63 PPARTENTRY TempPartition
= NULL
;
64 FORMATMACHINESTATE FormatState
= Start
;
67 /* LOCALS *******************************************************************/
69 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
71 static UNICODE_STRING InstallPath
;
74 * Path to the system partition, where the boot manager resides.
75 * On x86 PCs, this is usually the active partition.
76 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
78 * For more information, see:
79 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
80 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
81 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
82 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
83 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
84 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
86 static UNICODE_STRING SystemRootPath
;
88 /* Path to the install directory inside the ReactOS boot partition */
89 static UNICODE_STRING DestinationPath
;
90 static UNICODE_STRING DestinationArcPath
;
91 static UNICODE_STRING DestinationRootPath
;
93 static WCHAR DestinationDriveLetter
; // FIXME: Is it really useful??
97 static HSPFILEQ SetupFileQueue
= NULL
;
99 static PGENERIC_LIST ComputerList
= NULL
;
100 static PGENERIC_LIST DisplayList
= NULL
;
101 static PGENERIC_LIST KeyboardList
= NULL
;
102 static PGENERIC_LIST LayoutList
= NULL
;
103 static PGENERIC_LIST LanguageList
= NULL
;
105 static LANGID LanguageId
= 0;
107 static ULONG RequiredPartitionDiskSpace
= ~0;
109 /* FUNCTIONS ****************************************************************/
112 PrintString(char* fmt
,...)
116 UNICODE_STRING UnicodeString
;
117 ANSI_STRING AnsiString
;
120 vsprintf(buffer
, fmt
, ap
);
123 RtlInitAnsiString(&AnsiString
, buffer
);
124 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
125 NtDisplayString(&UnicodeString
);
126 RtlFreeUnicodeString(&UnicodeString
);
131 DrawBox(IN SHORT xLeft
,
139 /* draw upper left corner */
142 FillConsoleOutputCharacterA(StdOutput
,
148 /* draw upper edge */
151 FillConsoleOutputCharacterA(StdOutput
,
157 /* draw upper right corner */
158 coPos
.X
= xLeft
+ Width
- 1;
160 FillConsoleOutputCharacterA(StdOutput
,
166 /* Draw right edge, inner space and left edge */
167 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
170 FillConsoleOutputCharacterA(StdOutput
,
177 FillConsoleOutputCharacterA(StdOutput
,
183 coPos
.X
= xLeft
+ Width
- 1;
184 FillConsoleOutputCharacterA(StdOutput
,
191 /* draw lower left corner */
193 coPos
.Y
= yTop
+ Height
- 1;
194 FillConsoleOutputCharacterA(StdOutput
,
200 /* draw lower edge */
202 coPos
.Y
= yTop
+ Height
- 1;
203 FillConsoleOutputCharacterA(StdOutput
,
209 /* draw lower right corner */
210 coPos
.X
= xLeft
+ Width
- 1;
211 coPos
.Y
= yTop
+ Height
- 1;
212 FillConsoleOutputCharacterA(StdOutput
,
221 PopupError(PCCH Text
,
239 /* Count text lines and longest line */
246 p
= strchr(pnext
, '\n');
250 Length
= strlen(pnext
);
255 Length
= (ULONG
)(p
- pnext
);
261 if (Length
> MaxLength
)
264 if (LastLine
!= FALSE
)
270 /* Check length of status line */
273 Length
= strlen(Status
);
275 if (Length
> MaxLength
)
279 Width
= MaxLength
+ 4;
285 yTop
= (yScreen
- Height
) / 2;
286 xLeft
= (xScreen
- Width
) / 2;
289 /* Set screen attributes */
291 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
293 FillConsoleOutputAttribute(StdOutput
,
294 FOREGROUND_RED
| BACKGROUND_WHITE
,
300 DrawBox(xLeft
, yTop
, Width
, Height
);
302 /* Print message text */
307 p
= strchr(pnext
, '\n');
311 Length
= strlen(pnext
);
316 Length
= (ULONG
)(p
- pnext
);
323 WriteConsoleOutputCharacterA(StdOutput
,
330 if (LastLine
!= FALSE
)
337 /* Print separator line and status text */
340 coPos
.Y
= yTop
+ Height
- 3;
342 FillConsoleOutputCharacterA(StdOutput
,
349 FillConsoleOutputCharacterA(StdOutput
,
355 coPos
.X
= xLeft
+ Width
- 1;
356 FillConsoleOutputCharacterA(StdOutput
,
364 WriteConsoleOutputCharacterA(StdOutput
,
366 min(strlen(Status
), (SIZE_T
)Width
- 4),
371 if (WaitEvent
== POPUP_WAIT_NONE
)
376 CONSOLE_ConInKey(Ir
);
378 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
379 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
391 * FALSE: Don't quit setup.
394 ConfirmQuit(PINPUT_RECORD Ir
)
397 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
401 CONSOLE_ConInKey(Ir
);
403 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
404 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
409 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
421 CheckUnattendedSetup(VOID
)
423 WCHAR UnattendInfPath
[MAX_PATH
];
430 if (DoesFileExist(NULL
, SourcePath
.Buffer
, L
"unattend.inf") == FALSE
)
432 DPRINT("Does not exist: %S\\%S\n", SourcePath
.Buffer
, L
"unattend.inf");
436 wcscpy(UnattendInfPath
, SourcePath
.Buffer
);
437 wcscat(UnattendInfPath
, L
"\\unattend.inf");
439 /* Load 'unattend.inf' from install media. */
440 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
446 if (UnattendInf
== INVALID_HANDLE_VALUE
)
448 DPRINT("SetupOpenInfFileW() failed\n");
452 /* Open 'Unattend' section */
453 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
455 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
456 SetupCloseInfFile(UnattendInf
);
460 /* Get pointer 'Signature' key */
461 if (!INF_GetData(&Context
, NULL
, &Value
))
463 DPRINT("INF_GetData() failed for key 'Signature'\n");
464 SetupCloseInfFile(UnattendInf
);
468 /* Check 'Signature' string */
469 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
471 DPRINT("Signature not $ReactOS$\n");
472 SetupCloseInfFile(UnattendInf
);
476 /* Check if Unattend setup is enabled */
477 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
479 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
480 SetupCloseInfFile(UnattendInf
);
484 if (!INF_GetData(&Context
, NULL
, &Value
))
486 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
487 SetupCloseInfFile(UnattendInf
);
491 if (_wcsicmp(Value
, L
"yes") != 0)
493 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
494 SetupCloseInfFile(UnattendInf
);
498 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
499 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
501 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
502 SetupCloseInfFile(UnattendInf
);
506 if (!SetupGetIntField(&Context
, 1, &IntValue
))
508 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
509 SetupCloseInfFile(UnattendInf
);
513 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
515 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
516 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
518 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
519 SetupCloseInfFile(UnattendInf
);
523 if (!SetupGetIntField(&Context
, 1, &IntValue
))
525 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
526 SetupCloseInfFile(UnattendInf
);
530 UnattendDestinationPartitionNumber
= IntValue
;
532 /* Search for 'InstallationDirectory' in the 'Unattend' section */
533 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
535 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
536 SetupCloseInfFile(UnattendInf
);
540 /* Get pointer 'InstallationDirectory' key */
541 if (!INF_GetData(&Context
, NULL
, &Value
))
543 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
544 SetupCloseInfFile(UnattendInf
);
548 wcscpy(UnattendInstallationDirectory
, Value
);
550 IsUnattendedSetup
= TRUE
;
552 /* Search for 'MBRInstallType' in the 'Unattend' section */
553 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
555 if (SetupGetIntField(&Context
, 1, &IntValue
))
557 UnattendMBRInstallType
= IntValue
;
561 /* Search for 'FormatPartition' in the 'Unattend' section */
562 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
564 if (SetupGetIntField(&Context
, 1, &IntValue
))
566 UnattendFormatPartition
= IntValue
;
570 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
572 if (SetupGetIntField(&Context
, 1, &IntValue
))
574 AutoPartition
= IntValue
;
578 /* search for LocaleID in the 'Unattend' section*/
579 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
581 if (INF_GetData(&Context
, NULL
, &Value
))
583 LONG Id
= wcstol(Value
, NULL
, 16);
584 swprintf(LocaleID
,L
"%08lx", Id
);
588 SetupCloseInfFile(UnattendInf
);
590 DPRINT("Running unattended setup\n");
597 PGENERIC_LIST_ENTRY ListEntry
;
598 LPCWSTR pszNewLayout
;
600 pszNewLayout
= MUIDefaultKeyboardLayout();
602 if (LayoutList
== NULL
)
604 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
605 if (LayoutList
== NULL
)
607 /* FIXME: Handle error! */
612 ListEntry
= GetFirstListEntry(LayoutList
);
614 /* Search for default layout (if provided) */
615 if (pszNewLayout
!= NULL
)
617 while (ListEntry
!= NULL
)
619 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
621 SetCurrentListEntry(LayoutList
, ListEntry
);
625 ListEntry
= GetNextListEntry(ListEntry
);
632 * Displays the LanguagePage.
634 * Next pages: IntroPage, QuitPage
637 * Init SelectedLanguageId
641 * Number of the next page.
644 LanguagePage(PINPUT_RECORD Ir
)
646 GENERIC_LIST_UI ListUi
;
647 PWCHAR NewLanguageId
;
648 BOOL RefreshPage
= FALSE
;
650 /* Initialize the computer settings list */
651 if (LanguageList
== NULL
)
653 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
654 if (LanguageList
== NULL
)
656 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
662 SelectedLanguageId
= DefaultLanguage
;
663 SetConsoleCodePage();
666 /* If there's just a single language in the list skip
667 * the language selection process altogether! */
668 if (GenericListHasSingleEntry(LanguageList
))
670 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
674 InitGenericListUi(&ListUi
, LanguageList
);
675 DrawGenericList(&ListUi
,
681 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
683 MUIDisplayPage(LANGUAGE_PAGE
);
687 CONSOLE_ConInKey(Ir
);
689 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
690 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
692 ScrollDownGenericList(&ListUi
);
695 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
696 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
698 ScrollUpGenericList(&ListUi
);
701 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
702 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
704 ScrollPageDownGenericList(&ListUi
);
707 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
708 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
710 ScrollPageUpGenericList(&ListUi
);
713 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
714 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
716 if (ConfirmQuit(Ir
) != FALSE
)
719 RedrawGenericList(&ListUi
);
721 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
723 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
725 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
727 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
733 SetConsoleCodePage();
737 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
740 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
746 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
748 if (SelectedLanguageId
!= NewLanguageId
)
750 /* Clear the language page */
751 MUIClearPage(LANGUAGE_PAGE
);
753 SelectedLanguageId
= NewLanguageId
;
756 SetConsoleCodePage();
758 /* Redraw language selection page in native language */
759 MUIDisplayPage(LANGUAGE_PAGE
);
774 * LanguagePage (at once, default)
775 * InstallIntroPage (at once, if unattended)
781 * Init SourceRootPath
784 * Init RequiredPartitionDiskSpace
785 * Init IsUnattendedSetup
786 * If unattended, init *List and sets the Codepage
787 * If unattended, init SelectedLanguageId
788 * If unattended, init LanguageId
791 * Number of the next page.
794 SetupStartPage(PINPUT_RECORD Ir
)
797 WCHAR FileNameBuffer
[MAX_PATH
];
801 PGENERIC_LIST_ENTRY ListEntry
;
804 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
806 /* Get the source path and source root path */
807 Status
= GetSourcePaths(&SourcePath
,
811 if (!NT_SUCCESS(Status
))
813 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
814 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
820 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
821 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
822 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir
);
826 /* Load txtsetup.sif from install media. */
827 wcscpy(FileNameBuffer
, SourcePath
.Buffer
);
828 wcscat(FileNameBuffer
, L
"\\txtsetup.sif");
830 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
836 if (SetupInf
== INVALID_HANDLE_VALUE
)
838 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
842 /* Open 'Version' section */
843 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
845 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
849 /* Get pointer 'Signature' key */
850 if (!INF_GetData(&Context
, NULL
, &Value
))
852 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
856 /* Check 'Signature' string */
857 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
859 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
863 /* Open 'DiskSpaceRequirements' section */
864 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
866 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
870 /* Get the 'FreeSysPartDiskSpace' value */
871 if (!SetupGetIntField(&Context
, 1, &IntValue
))
873 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
877 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
879 /* Start the PnP thread */
880 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
882 NtResumeThread(hPnpThread
, NULL
);
883 hPnpThread
= INVALID_HANDLE_VALUE
;
886 CheckUnattendedSetup();
888 if (IsUnattendedSetup
)
890 // TODO: Read options from inf
891 ComputerList
= CreateComputerTypeList(SetupInf
);
892 DisplayList
= CreateDisplayDriverList(SetupInf
);
893 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
894 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
895 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
898 wcscpy(SelectedLanguageId
, LocaleID
);
899 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
901 /* first we hack LanguageList */
902 ListEntry
= GetFirstListEntry(LanguageList
);
903 while (ListEntry
!= NULL
)
905 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
907 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
908 SetCurrentListEntry(LanguageList
, ListEntry
);
912 ListEntry
= GetNextListEntry(ListEntry
);
916 ListEntry
= GetFirstListEntry(LayoutList
);
917 while (ListEntry
!= NULL
)
919 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
921 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
922 SetCurrentListEntry(LayoutList
, ListEntry
);
926 ListEntry
= GetNextListEntry(ListEntry
);
929 SetConsoleCodePage();
931 return INSTALL_INTRO_PAGE
;
934 return LANGUAGE_PAGE
;
939 * Displays the IntroPage.
942 * InstallIntroPage (default)
948 * Number of the next page.
951 IntroPage(PINPUT_RECORD Ir
)
953 MUIDisplayPage(START_PAGE
);
957 CONSOLE_ConInKey(Ir
);
959 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
960 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
962 if (ConfirmQuit(Ir
) != FALSE
)
967 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
969 return INSTALL_INTRO_PAGE
;
971 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
973 return REPAIR_INTRO_PAGE
;
975 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
986 * Displays the License page.
989 * IntroPage (default)
992 * Number of the next page.
995 LicensePage(PINPUT_RECORD Ir
)
997 MUIDisplayPage(LICENSE_PAGE
);
1001 CONSOLE_ConInKey(Ir
);
1003 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1009 return LICENSE_PAGE
;
1014 * Displays the RepairIntroPage.
1017 * RebootPage (default)
1023 * Number of the next page.
1026 RepairIntroPage(PINPUT_RECORD Ir
)
1028 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1032 CONSOLE_ConInKey(Ir
);
1034 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1038 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1040 RepairUpdateFlag
= TRUE
;
1041 return INSTALL_INTRO_PAGE
;
1043 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1045 return RECOVERY_PAGE
;
1047 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1048 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1054 return REPAIR_INTRO_PAGE
;
1058 * Displays the InstallIntroPage.
1061 * DeviceSettingsPage (At once if repair or update is selected)
1062 * SelectPartitionPage (At once if unattended setup)
1063 * DeviceSettingsPage (default)
1067 * Number of the next page.
1070 InstallIntroPage(PINPUT_RECORD Ir
)
1072 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1074 if (RepairUpdateFlag
)
1076 //return SELECT_PARTITION_PAGE;
1077 return DEVICE_SETTINGS_PAGE
;
1080 if (IsUnattendedSetup
)
1082 return SELECT_PARTITION_PAGE
;
1087 CONSOLE_ConInKey(Ir
);
1089 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1090 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1092 if (ConfirmQuit(Ir
) != FALSE
)
1097 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1099 return DEVICE_SETTINGS_PAGE
;
1100 // return SCSI_CONTROLLER_PAGE;
1104 return INSTALL_INTRO_PAGE
;
1110 ScsiControllerPage(PINPUT_RECORD Ir
)
1112 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1114 /* FIXME: print loaded mass storage driver descriptions */
1116 SetTextXY(8, 10, "TEST device");
1120 SetStatusText(" ENTER = Continue F3 = Quit");
1126 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1127 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1129 if (ConfirmQuit(Ir
) != FALSE
)
1134 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1136 return DEVICE_SETTINGS_PAGE
;
1140 return SCSI_CONTROLLER_PAGE
;
1146 * Displays the DeviceSettingsPage.
1149 * SelectPartitionPage (At once if repair or update is selected)
1150 * ComputerSettingsPage
1151 * DisplaySettingsPage
1152 * KeyboardSettingsPage
1153 * LayoutsettingsPage
1154 * SelectPartitionPage
1164 * Number of the next page.
1167 DeviceSettingsPage(PINPUT_RECORD Ir
)
1169 static ULONG Line
= 16;
1170 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1172 /* Initialize the computer settings list */
1173 if (ComputerList
== NULL
)
1175 ComputerList
= CreateComputerTypeList(SetupInf
);
1176 if (ComputerList
== NULL
)
1178 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1183 /* Initialize the display settings list */
1184 if (DisplayList
== NULL
)
1186 DisplayList
= CreateDisplayDriverList(SetupInf
);
1187 if (DisplayList
== NULL
)
1189 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1194 /* Initialize the keyboard settings list */
1195 if (KeyboardList
== NULL
)
1197 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1198 if (KeyboardList
== NULL
)
1200 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1205 /* Initialize the keyboard layout list */
1206 if (LayoutList
== NULL
)
1208 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1209 if (LayoutList
== NULL
)
1211 /* FIXME: report error */
1212 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1217 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1220 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList
))));
1221 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList
))));
1222 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList
))));
1223 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList
))));
1225 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1227 if (RepairUpdateFlag
)
1229 return SELECT_PARTITION_PAGE
;
1234 CONSOLE_ConInKey(Ir
);
1236 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1237 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1239 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1243 else if (Line
== 16)
1248 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1250 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1251 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1253 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1257 else if (Line
== 16)
1262 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1264 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1265 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1267 if (ConfirmQuit(Ir
) != FALSE
)
1272 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1275 return COMPUTER_SETTINGS_PAGE
;
1276 else if (Line
== 12)
1277 return DISPLAY_SETTINGS_PAGE
;
1278 else if (Line
== 13)
1279 return KEYBOARD_SETTINGS_PAGE
;
1280 else if (Line
== 14)
1281 return LAYOUT_SETTINGS_PAGE
;
1282 else if (Line
== 16)
1283 return SELECT_PARTITION_PAGE
;
1287 return DEVICE_SETTINGS_PAGE
;
1292 * Handles generic selection lists.
1295 * GenericList: The list to handle.
1296 * nextPage: The page it needs to jump to after this page.
1297 * Ir: The PINPUT_RECORD
1300 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1301 PAGE_NUMBER nextPage
,
1306 CONSOLE_ConInKey(Ir
);
1308 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1309 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1311 ScrollDownGenericList(ListUi
);
1313 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1314 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1316 ScrollUpGenericList(ListUi
);
1318 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1319 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1321 ScrollPageDownGenericList(ListUi
);
1323 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1324 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1326 ScrollPageUpGenericList(ListUi
);
1328 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1329 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1331 if (ConfirmQuit(Ir
) != FALSE
)
1334 RedrawGenericList(ListUi
);
1336 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1337 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1339 RestoreGenericListState(ListUi
->List
);
1340 return nextPage
; // Use some "prevPage;" instead?
1342 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1346 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1349 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1356 * Displays the ComputerSettingsPage.
1359 * DeviceSettingsPage
1363 * Number of the next page.
1366 ComputerSettingsPage(PINPUT_RECORD Ir
)
1368 GENERIC_LIST_UI ListUi
;
1369 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1371 InitGenericListUi(&ListUi
, ComputerList
);
1372 DrawGenericList(&ListUi
,
1378 SaveGenericListState(ComputerList
);
1380 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1385 * Displays the DisplaySettingsPage.
1388 * DeviceSettingsPage
1392 * Number of the next page.
1395 DisplaySettingsPage(PINPUT_RECORD Ir
)
1397 GENERIC_LIST_UI ListUi
;
1398 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1400 InitGenericListUi(&ListUi
, DisplayList
);
1401 DrawGenericList(&ListUi
,
1407 SaveGenericListState(DisplayList
);
1409 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1414 * Displays the KeyboardSettingsPage.
1417 * DeviceSettingsPage
1421 * Number of the next page.
1424 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1426 GENERIC_LIST_UI ListUi
;
1427 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1429 InitGenericListUi(&ListUi
, KeyboardList
);
1430 DrawGenericList(&ListUi
,
1436 SaveGenericListState(KeyboardList
);
1438 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1443 * Displays the LayoutSettingsPage.
1446 * DeviceSettingsPage
1450 * Number of the next page.
1453 LayoutSettingsPage(PINPUT_RECORD Ir
)
1455 GENERIC_LIST_UI ListUi
;
1456 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1458 InitGenericListUi(&ListUi
, LayoutList
);
1459 DrawGenericList(&ListUi
,
1465 SaveGenericListState(LayoutList
);
1467 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1472 IsDiskSizeValid(PPARTENTRY PartEntry
)
1476 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1477 size
= (size
+ 524288) / 1048576; /* in MBytes */
1479 if (size
< RequiredPartitionDiskSpace
)
1481 /* partition is too small so ask for another partition */
1482 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1493 * Displays the SelectPartitionPage.
1496 * SelectFileSystemPage (At once if unattended)
1497 * SelectFileSystemPage (Default if free space is selected)
1498 * CreatePrimaryPartitionPage
1499 * CreateExtendedPartitionPage
1500 * CreateLogicalPartitionPage
1501 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1502 * DeletePartitionPage
1506 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1507 * Set InstallShortcut (only if not unattended + free space is selected)
1510 * Number of the next page.
1513 SelectPartitionPage(PINPUT_RECORD Ir
)
1518 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1520 if (PartitionList
== NULL
)
1522 PartitionList
= CreatePartitionList();
1523 if (PartitionList
== NULL
)
1525 /* FIXME: show an error dialog */
1526 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1529 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1531 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1535 TempPartition
= NULL
;
1536 FormatState
= Start
;
1539 InitPartitionListUi(&ListUi
, PartitionList
,
1544 DrawPartitionList(&ListUi
);
1546 if (IsUnattendedSetup
)
1548 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1552 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1554 CreateLogicalPartition(PartitionList
,
1555 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1560 CreatePrimaryPartition(PartitionList
,
1561 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1565 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1566 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1568 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1569 RequiredPartitionDiskSpace
);
1570 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1573 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1575 return SELECT_FILE_SYSTEM_PAGE
;
1580 DrawPartitionList(&ListUi
);
1582 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1583 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1585 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1586 RequiredPartitionDiskSpace
);
1587 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1590 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1592 return SELECT_FILE_SYSTEM_PAGE
;
1598 /* Update status text */
1599 if (PartitionList
->CurrentPartition
== NULL
)
1601 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1603 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1605 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1607 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1611 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1616 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1618 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1620 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1624 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1629 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1633 CONSOLE_ConInKey(Ir
);
1635 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1636 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1638 if (ConfirmQuit(Ir
) != FALSE
)
1640 DestroyPartitionList(PartitionList
);
1641 PartitionList
= NULL
;
1647 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1648 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1650 ScrollDownPartitionList(&ListUi
);
1652 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1653 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1655 ScrollUpPartitionList(&ListUi
);
1657 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1659 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1660 continue; // return SELECT_PARTITION_PAGE;
1662 if (PartitionList
->CurrentPartition
== NULL
||
1663 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1665 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1667 CreateLogicalPartition(PartitionList
,
1673 CreatePrimaryPartition(PartitionList
,
1679 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1681 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1682 RequiredPartitionDiskSpace
);
1683 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1686 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1688 return SELECT_FILE_SYSTEM_PAGE
;
1690 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1692 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1694 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1695 if (Error
!= NOT_AN_ERROR
)
1697 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1698 return SELECT_PARTITION_PAGE
;
1701 return CREATE_PRIMARY_PARTITION_PAGE
;
1704 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1706 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1708 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1709 if (Error
!= NOT_AN_ERROR
)
1711 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1712 return SELECT_PARTITION_PAGE
;
1715 return CREATE_EXTENDED_PARTITION_PAGE
;
1718 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1720 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1722 Error
= LogicalPartitionCreationChecks(PartitionList
);
1723 if (Error
!= NOT_AN_ERROR
)
1725 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1726 return SELECT_PARTITION_PAGE
;
1729 return CREATE_LOGICAL_PARTITION_PAGE
;
1732 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1734 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1736 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1737 return SELECT_PARTITION_PAGE
;
1740 if (PartitionList
->CurrentPartition
->BootIndicator
||
1741 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1743 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1746 return DELETE_PARTITION_PAGE
;
1750 return SELECT_PARTITION_PAGE
;
1754 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1755 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1756 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1759 ShowPartitionSizeInputBox(SHORT Left
,
1783 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1788 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1789 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1792 WriteConsoleOutputCharacterA(StdOutput
,
1798 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1799 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1801 WriteConsoleOutputCharacterA(StdOutput
,
1807 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1808 Length
= wcslen(InputBuffer
);
1810 CONSOLE_SetInputTextXY(iLeft
,
1812 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1814 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1815 CONSOLE_SetCursorType(TRUE
, TRUE
);
1819 CONSOLE_ConInKey(&Ir
);
1821 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1822 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1827 InputBuffer
[0] = UNICODE_NULL
;
1828 CONSOLE_SetCursorType(TRUE
, FALSE
);
1831 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1833 CONSOLE_SetCursorType(TRUE
, FALSE
);
1836 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1841 InputBuffer
[0] = UNICODE_NULL
;
1842 CONSOLE_SetCursorType(TRUE
, FALSE
);
1845 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1846 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1849 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1851 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1852 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1855 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1857 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1858 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1863 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1866 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1867 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1872 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1875 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1876 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1880 memmove(&InputBuffer
[Pos
],
1881 &InputBuffer
[Pos
+ 1],
1882 (Length
- Pos
- 1) * sizeof(WCHAR
));
1883 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1886 CONSOLE_SetInputTextXY(iLeft
,
1888 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1890 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1893 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1898 memmove(&InputBuffer
[Pos
- 1],
1900 (Length
- Pos
) * sizeof(WCHAR
));
1901 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1905 CONSOLE_SetInputTextXY(iLeft
,
1907 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1909 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1912 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1914 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1916 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1918 if ((ch
>= L
'0') && (ch
<= L
'9'))
1921 memmove(&InputBuffer
[Pos
+ 1],
1923 (Length
- Pos
) * sizeof(WCHAR
));
1924 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1925 InputBuffer
[Pos
] = ch
;
1929 CONSOLE_SetInputTextXY(iLeft
,
1931 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1933 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1942 * Displays the CreatePrimaryPartitionPage.
1945 * SelectPartitionPage
1946 * SelectFileSystemPage (default)
1950 * Number of the next page.
1953 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1955 PDISKENTRY DiskEntry
;
1956 PPARTENTRY PartEntry
;
1959 WCHAR InputBuffer
[50];
1963 ULONGLONG SectorCount
;
1966 if (PartitionList
== NULL
||
1967 PartitionList
->CurrentDisk
== NULL
||
1968 PartitionList
->CurrentPartition
== NULL
)
1970 /* FIXME: show an error dialog */
1974 DiskEntry
= PartitionList
->CurrentDisk
;
1975 PartEntry
= PartitionList
->CurrentPartition
;
1977 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1979 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1981 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1983 if (DiskSize
>= 10737418240) /* 10 GB */
1985 DiskSize
= DiskSize
/ 1073741824;
1986 Unit
= MUIGetString(STRING_GB
);
1991 DiskSize
= DiskSize
/ 1048576;
1995 Unit
= MUIGetString(STRING_MB
);
1998 if (DiskEntry
->DriverName
.Length
> 0)
2000 CONSOLE_PrintTextXY(6, 10,
2001 MUIGetString(STRING_HDINFOPARTCREATE
),
2004 DiskEntry
->DiskNumber
,
2008 &DiskEntry
->DriverName
);
2012 CONSOLE_PrintTextXY(6, 10,
2013 MUIGetString(STRING_HDDINFOUNK1
),
2016 DiskEntry
->DiskNumber
,
2022 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2025 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2026 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2029 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2031 PartEntry
= PartitionList
->CurrentPartition
;
2034 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2036 if (MaxSize
> PARTITION_MAXSIZE
)
2037 MaxSize
= PARTITION_MAXSIZE
;
2039 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2040 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2044 if (ConfirmQuit(Ir
) != FALSE
)
2049 else if (Cancel
!= FALSE
)
2051 return SELECT_PARTITION_PAGE
;
2055 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2063 if (PartSize
> MaxSize
)
2069 /* Convert to bytes */
2070 if (PartSize
== MaxSize
)
2072 /* Use all of the unpartitioned disk space */
2073 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2077 /* Calculate the sector count from the size in MB */
2078 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2080 /* But never get larger than the unpartitioned disk space */
2081 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2082 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2085 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2087 CreatePrimaryPartition(PartitionList
,
2091 return SELECT_PARTITION_PAGE
;
2095 return CREATE_PRIMARY_PARTITION_PAGE
;
2100 * Displays the CreateExtendedPartitionPage.
2103 * SelectPartitionPage (default)
2107 * Number of the next page.
2110 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2112 PDISKENTRY DiskEntry
;
2113 PPARTENTRY PartEntry
;
2116 WCHAR InputBuffer
[50];
2120 ULONGLONG SectorCount
;
2123 if (PartitionList
== NULL
||
2124 PartitionList
->CurrentDisk
== NULL
||
2125 PartitionList
->CurrentPartition
== NULL
)
2127 /* FIXME: show an error dialog */
2131 DiskEntry
= PartitionList
->CurrentDisk
;
2132 PartEntry
= PartitionList
->CurrentPartition
;
2134 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2136 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2138 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2140 if (DiskSize
>= 10737418240) /* 10 GB */
2142 DiskSize
= DiskSize
/ 1073741824;
2143 Unit
= MUIGetString(STRING_GB
);
2148 DiskSize
= DiskSize
/ 1048576;
2152 Unit
= MUIGetString(STRING_MB
);
2155 if (DiskEntry
->DriverName
.Length
> 0)
2157 CONSOLE_PrintTextXY(6, 10,
2158 MUIGetString(STRING_HDINFOPARTCREATE
),
2161 DiskEntry
->DiskNumber
,
2165 &DiskEntry
->DriverName
);
2169 CONSOLE_PrintTextXY(6, 10,
2170 MUIGetString(STRING_HDDINFOUNK1
),
2173 DiskEntry
->DiskNumber
,
2179 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2182 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2183 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2186 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2188 PartEntry
= PartitionList
->CurrentPartition
;
2191 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2193 if (MaxSize
> PARTITION_MAXSIZE
)
2194 MaxSize
= PARTITION_MAXSIZE
;
2196 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2197 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2201 if (ConfirmQuit(Ir
) != FALSE
)
2206 else if (Cancel
!= FALSE
)
2208 return SELECT_PARTITION_PAGE
;
2212 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2220 if (PartSize
> MaxSize
)
2226 /* Convert to bytes */
2227 if (PartSize
== MaxSize
)
2229 /* Use all of the unpartitioned disk space */
2230 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2234 /* Calculate the sector count from the size in MB */
2235 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2237 /* But never get larger than the unpartitioned disk space */
2238 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2239 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2242 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2244 CreateExtendedPartition(PartitionList
,
2247 return SELECT_PARTITION_PAGE
;
2251 return CREATE_EXTENDED_PARTITION_PAGE
;
2256 * Displays the CreateLogicalPartitionPage.
2259 * SelectFileSystemPage (default)
2263 * Number of the next page.
2266 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2268 PDISKENTRY DiskEntry
;
2269 PPARTENTRY PartEntry
;
2272 WCHAR InputBuffer
[50];
2276 ULONGLONG SectorCount
;
2279 if (PartitionList
== NULL
||
2280 PartitionList
->CurrentDisk
== NULL
||
2281 PartitionList
->CurrentPartition
== NULL
)
2283 /* FIXME: show an error dialog */
2287 DiskEntry
= PartitionList
->CurrentDisk
;
2288 PartEntry
= PartitionList
->CurrentPartition
;
2290 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2292 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2294 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2296 if (DiskSize
>= 10737418240) /* 10 GB */
2298 DiskSize
= DiskSize
/ 1073741824;
2299 Unit
= MUIGetString(STRING_GB
);
2304 DiskSize
= DiskSize
/ 1048576;
2308 Unit
= MUIGetString(STRING_MB
);
2311 if (DiskEntry
->DriverName
.Length
> 0)
2313 CONSOLE_PrintTextXY(6, 10,
2314 MUIGetString(STRING_HDINFOPARTCREATE
),
2317 DiskEntry
->DiskNumber
,
2321 &DiskEntry
->DriverName
);
2325 CONSOLE_PrintTextXY(6, 10,
2326 MUIGetString(STRING_HDDINFOUNK1
),
2329 DiskEntry
->DiskNumber
,
2335 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2338 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2339 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2342 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2344 PartEntry
= PartitionList
->CurrentPartition
;
2347 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2349 if (MaxSize
> PARTITION_MAXSIZE
)
2350 MaxSize
= PARTITION_MAXSIZE
;
2352 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2353 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2357 if (ConfirmQuit(Ir
) != FALSE
)
2362 else if (Cancel
!= FALSE
)
2364 return SELECT_PARTITION_PAGE
;
2368 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2376 if (PartSize
> MaxSize
)
2382 /* Convert to bytes */
2383 if (PartSize
== MaxSize
)
2385 /* Use all of the unpartitioned disk space */
2386 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2390 /* Calculate the sector count from the size in MB */
2391 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2393 /* But never get larger than the unpartitioned disk space */
2394 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2395 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2398 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2400 CreateLogicalPartition(PartitionList
,
2404 return SELECT_PARTITION_PAGE
;
2408 return CREATE_LOGICAL_PARTITION_PAGE
;
2413 * Displays the ConfirmDeleteSystemPartitionPage.
2416 * DeletePartitionPage (default)
2417 * SelectPartitionPage
2420 * Number of the next page.
2423 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2425 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2429 CONSOLE_ConInKey(Ir
);
2431 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2432 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2434 if (ConfirmQuit(Ir
) == TRUE
)
2439 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2441 return DELETE_PARTITION_PAGE
;
2443 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2445 return SELECT_PARTITION_PAGE
;
2449 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2454 * Displays the DeletePartitionPage.
2457 * SelectPartitionPage (default)
2461 * Number of the next page.
2464 DeletePartitionPage(PINPUT_RECORD Ir
)
2466 PDISKENTRY DiskEntry
;
2467 PPARTENTRY PartEntry
;
2471 CHAR PartTypeString
[32];
2473 if (PartitionList
== NULL
||
2474 PartitionList
->CurrentDisk
== NULL
||
2475 PartitionList
->CurrentPartition
== NULL
)
2477 /* FIXME: show an error dialog */
2481 DiskEntry
= PartitionList
->CurrentDisk
;
2482 PartEntry
= PartitionList
->CurrentPartition
;
2484 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2486 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2488 ARRAYSIZE(PartTypeString
));
2490 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2492 if (PartSize
>= 10737418240) /* 10 GB */
2494 PartSize
= PartSize
/ 1073741824;
2495 Unit
= MUIGetString(STRING_GB
);
2499 if (PartSize
>= 10485760) /* 10 MB */
2501 PartSize
= PartSize
/ 1048576;
2502 Unit
= MUIGetString(STRING_MB
);
2506 PartSize
= PartSize
/ 1024;
2507 Unit
= MUIGetString(STRING_KB
);
2510 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2512 CONSOLE_PrintTextXY(6, 10,
2513 MUIGetString(STRING_HDDINFOUNK2
),
2514 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2515 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2516 PartEntry
->PartitionType
,
2522 CONSOLE_PrintTextXY(6, 10,
2523 " %c%c %s %I64u %s",
2524 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2525 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2531 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2533 if (DiskSize
>= 10737418240) /* 10 GB */
2535 DiskSize
= DiskSize
/ 1073741824;
2536 Unit
= MUIGetString(STRING_GB
);
2541 DiskSize
= DiskSize
/ 1048576;
2545 Unit
= MUIGetString(STRING_MB
);
2548 if (DiskEntry
->DriverName
.Length
> 0)
2550 CONSOLE_PrintTextXY(6, 12,
2551 MUIGetString(STRING_HDINFOPARTDELETE
),
2554 DiskEntry
->DiskNumber
,
2558 &DiskEntry
->DriverName
);
2562 CONSOLE_PrintTextXY(6, 12,
2563 MUIGetString(STRING_HDDINFOUNK3
),
2566 DiskEntry
->DiskNumber
,
2574 CONSOLE_ConInKey(Ir
);
2576 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2577 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2579 if (ConfirmQuit(Ir
) != FALSE
)
2584 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2586 return SELECT_PARTITION_PAGE
;
2588 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2590 DeleteCurrentPartition(PartitionList
);
2592 return SELECT_PARTITION_PAGE
;
2596 return DELETE_PARTITION_PAGE
;
2601 * Displays the SelectFileSystemPage.
2604 * CheckFileSystemPage (At once if RepairUpdate is selected)
2605 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2606 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2607 * SelectPartitionPage (If the user aborts)
2608 * FormatPartitionPage (Default)
2612 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2613 * Calls CheckActiveSystemPartition()
2616 * Number of the next page.
2619 SelectFileSystemPage(PINPUT_RECORD Ir
)
2621 PDISKENTRY DiskEntry
;
2622 PPARTENTRY PartEntry
;
2627 CHAR PartTypeString
[32];
2628 FORMATMACHINESTATE PreviousFormatState
;
2630 DPRINT("SelectFileSystemPage()\n");
2632 if (PartitionList
== NULL
||
2633 PartitionList
->CurrentDisk
== NULL
||
2634 PartitionList
->CurrentPartition
== NULL
)
2636 /* FIXME: show an error dialog */
2640 /* Find or set the active system partition */
2641 CheckActiveSystemPartition(PartitionList
);
2642 if (PartitionList
->SystemPartition
== NULL
)
2644 /* FIXME: show an error dialog */
2648 PreviousFormatState
= FormatState
;
2649 switch (FormatState
)
2653 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2655 TempPartition
= PartitionList
->SystemPartition
;
2656 TempPartition
->NeedsCheck
= TRUE
;
2658 FormatState
= FormatSystemPartition
;
2659 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2663 TempPartition
= PartitionList
->CurrentPartition
;
2664 TempPartition
->NeedsCheck
= TRUE
;
2666 FormatState
= FormatInstallPartition
;
2667 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2672 case FormatSystemPartition
:
2674 TempPartition
= PartitionList
->CurrentPartition
;
2675 TempPartition
->NeedsCheck
= TRUE
;
2677 FormatState
= FormatInstallPartition
;
2678 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2682 case FormatInstallPartition
:
2684 if (GetNextUnformattedPartition(PartitionList
,
2688 FormatState
= FormatOtherPartition
;
2689 TempPartition
->NeedsCheck
= TRUE
;
2690 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2694 FormatState
= FormatDone
;
2695 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2696 return CHECK_FILE_SYSTEM_PAGE
;
2701 case FormatOtherPartition
:
2703 if (GetNextUnformattedPartition(PartitionList
,
2707 FormatState
= FormatOtherPartition
;
2708 TempPartition
->NeedsCheck
= TRUE
;
2709 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2713 FormatState
= FormatDone
;
2714 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2715 return CHECK_FILE_SYSTEM_PAGE
;
2722 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2723 /* FIXME: show an error dialog */
2728 PartEntry
= TempPartition
;
2729 DiskEntry
= PartEntry
->DiskEntry
;
2731 /* Adjust disk size */
2732 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2733 if (DiskSize
>= 10737418240) /* 10 GB */
2735 DiskSize
= DiskSize
/ 1073741824;
2736 DiskUnit
= MUIGetString(STRING_GB
);
2740 DiskSize
= DiskSize
/ 1048576;
2741 DiskUnit
= MUIGetString(STRING_MB
);
2744 /* Adjust partition size */
2745 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2746 if (PartSize
>= 10737418240) /* 10 GB */
2748 PartSize
= PartSize
/ 1073741824;
2749 PartUnit
= MUIGetString(STRING_GB
);
2753 PartSize
= PartSize
/ 1048576;
2754 PartUnit
= MUIGetString(STRING_MB
);
2757 /* Adjust partition type */
2758 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2760 ARRAYSIZE(PartTypeString
));
2762 if (PartEntry
->AutoCreate
!= FALSE
)
2764 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2767 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2768 PartEntry
->PartitionNumber
,
2774 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED
),
2775 DiskEntry
->DiskNumber
,
2781 &DiskEntry
->DriverName
);
2783 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2785 PartEntry
->AutoCreate
= FALSE
;
2787 else if (PartEntry
->New
!= FALSE
)
2789 switch (FormatState
)
2791 case FormatSystemPartition
:
2792 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2795 case FormatInstallPartition
:
2796 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2799 case FormatOtherPartition
:
2800 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2807 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2811 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2813 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2815 CONSOLE_PrintTextXY(8, 10,
2816 MUIGetString(STRING_HDDINFOUNK4
),
2817 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2818 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2819 PartEntry
->PartitionType
,
2825 CONSOLE_PrintTextXY(8, 10,
2827 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2828 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2834 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS
),
2835 DiskEntry
->DiskNumber
,
2841 &DiskEntry
->DriverName
);
2844 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2846 if (FileSystemList
== NULL
)
2848 /* Create the file system list, and by default select the "FAT" file system */
2849 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2850 if (FileSystemList
== NULL
)
2852 /* FIXME: show an error dialog */
2857 DrawFileSystemList(FileSystemList
);
2859 if (RepairUpdateFlag
)
2861 return CHECK_FILE_SYSTEM_PAGE
;
2862 //return SELECT_PARTITION_PAGE;
2865 if (IsUnattendedSetup
)
2867 if (UnattendFormatPartition
)
2870 * We use whatever currently selected file system we have
2871 * (by default, this is "FAT", as per the initialization
2872 * performed above). Note that it may be interesting to specify
2873 * which file system to use in unattended installations, in the
2874 * txtsetup.sif file.
2876 return FORMAT_PARTITION_PAGE
;
2879 return CHECK_FILE_SYSTEM_PAGE
;
2884 CONSOLE_ConInKey(Ir
);
2886 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2887 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2889 if (ConfirmQuit(Ir
) != FALSE
)
2894 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2895 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2897 FormatState
= Start
;
2898 return SELECT_PARTITION_PAGE
;
2900 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2901 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2903 ScrollDownFileSystemList(FileSystemList
);
2905 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2906 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2908 ScrollUpFileSystemList(FileSystemList
);
2910 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2912 if (!FileSystemList
->Selected
->FileSystem
)
2913 return SELECT_FILE_SYSTEM_PAGE
;
2915 return FORMAT_PARTITION_PAGE
;
2919 FormatState
= PreviousFormatState
;
2921 return SELECT_FILE_SYSTEM_PAGE
;
2926 * Displays the FormatPartitionPage.
2929 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2930 * SelectPartitionPage (At once)
2934 * Sets PartitionList->CurrentPartition->FormatState
2935 * Sets DestinationRootPath
2938 * Number of the next page.
2941 FormatPartitionPage(PINPUT_RECORD Ir
)
2943 UNICODE_STRING PartitionRootPath
;
2944 WCHAR PathBuffer
[MAX_PATH
];
2945 PDISKENTRY DiskEntry
;
2946 PPARTENTRY PartEntry
;
2947 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2953 PPARTITION_INFORMATION PartitionInfo
;
2956 DPRINT("FormatPartitionPage()\n");
2958 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2960 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2962 /* FIXME: show an error dialog */
2966 PartEntry
= TempPartition
;
2967 DiskEntry
= PartEntry
->DiskEntry
;
2969 SelectedFileSystem
= FileSystemList
->Selected
;
2973 if (!IsUnattendedSetup
)
2975 CONSOLE_ConInKey(Ir
);
2978 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2979 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2981 if (ConfirmQuit(Ir
) != FALSE
)
2986 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2988 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2990 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2992 /* FIXME: show an error dialog */
2997 CONSOLE_PrintTextXY(6, 12,
2998 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
2999 DiskEntry
->Cylinders
,
3000 DiskEntry
->TracksPerCylinder
,
3001 DiskEntry
->SectorsPerTrack
,
3002 DiskEntry
->BytesPerSector
,
3003 DiskEntry
->Dirty
? '*' : ' ');
3007 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3009 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3011 CONSOLE_PrintTextXY(6, Line
,
3012 "%2u: %2lu %c %12I64u %12I64u %02x",
3014 PartitionInfo
->PartitionNumber
,
3015 PartitionInfo
->BootIndicator
? 'A' : '-',
3016 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3017 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3018 PartitionInfo
->PartitionType
);
3023 /* Commit the partition changes to the disk */
3024 if (!WritePartitionsToDisk(PartitionList
))
3026 DPRINT("WritePartitionsToDisk() failed\n");
3027 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3031 /* Set PartitionRootPath */
3032 swprintf(PathBuffer
,
3033 L
"\\Device\\Harddisk%lu\\Partition%lu",
3034 DiskEntry
->DiskNumber
,
3035 PartEntry
->PartitionNumber
);
3036 RtlInitUnicodeString(&PartitionRootPath
,
3038 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3040 /* Format the partition */
3041 if (SelectedFileSystem
->FileSystem
)
3043 Status
= FormatPartition(&PartitionRootPath
,
3044 SelectedFileSystem
);
3045 if (!NT_SUCCESS(Status
))
3047 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3048 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3052 PartEntry
->FormatState
= Formatted
;
3053 // PartEntry->FileSystem = FileSystem;
3054 PartEntry
->New
= FALSE
;
3058 CONSOLE_SetStatusText(" Done. Press any key ...");
3059 CONSOLE_ConInKey(Ir
);
3062 return SELECT_FILE_SYSTEM_PAGE
;
3066 return FORMAT_PARTITION_PAGE
;
3071 * Displays the CheckFileSystemPage.
3074 * InstallDirectoryPage (At once)
3078 * Inits or reloads FileSystemList
3081 * Number of the next page.
3084 CheckFileSystemPage(PINPUT_RECORD Ir
)
3086 PFILE_SYSTEM CurrentFileSystem
;
3087 UNICODE_STRING PartitionRootPath
;
3088 WCHAR PathBuffer
[MAX_PATH
];
3089 CHAR Buffer
[MAX_PATH
];
3090 PDISKENTRY DiskEntry
;
3091 PPARTENTRY PartEntry
;
3094 if (PartitionList
== NULL
)
3096 /* FIXME: show an error dialog */
3100 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3102 return INSTALL_DIRECTORY_PAGE
;
3105 /* Set PartitionRootPath */
3106 swprintf(PathBuffer
,
3107 L
"\\Device\\Harddisk%lu\\Partition%lu",
3108 DiskEntry
->DiskNumber
,
3109 PartEntry
->PartitionNumber
);
3110 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3111 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3113 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3115 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3117 CurrentFileSystem
= PartEntry
->FileSystem
;
3118 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3119 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3121 /* HACK: Do not try to check a partition with an unknown filesystem */
3122 if (CurrentFileSystem
== NULL
)
3124 PartEntry
->NeedsCheck
= FALSE
;
3125 return CHECK_FILE_SYSTEM_PAGE
;
3128 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3131 "Setup is currently unable to check a partition formatted in %S.\n"
3133 " \x07 Press ENTER to continue Setup.\n"
3134 " \x07 Press F3 to quit Setup.",
3135 CurrentFileSystem
->FileSystemName
);
3138 MUIGetString(STRING_QUITCONTINUE
),
3139 NULL
, POPUP_WAIT_NONE
);
3143 CONSOLE_ConInKey(Ir
);
3145 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3146 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3148 if (ConfirmQuit(Ir
))
3151 return CHECK_FILE_SYSTEM_PAGE
;
3153 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3155 PartEntry
->NeedsCheck
= FALSE
;
3156 return CHECK_FILE_SYSTEM_PAGE
;
3162 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3163 if (!NT_SUCCESS(Status
))
3165 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3166 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3167 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3168 "(Status 0x%08lx).\n", Status
);
3170 // MUIGetString(STRING_REBOOTCOMPUTER),
3171 MUIGetString(STRING_CONTINUE
),
3172 Ir
, POPUP_WAIT_ENTER
);
3174 // return QUIT_PAGE;
3177 PartEntry
->NeedsCheck
= FALSE
;
3178 return CHECK_FILE_SYSTEM_PAGE
;
3185 BuildInstallPaths(PWCHAR InstallDir
,
3186 PDISKENTRY DiskEntry
,
3187 PPARTENTRY PartEntry
)
3189 WCHAR PathBuffer
[MAX_PATH
];
3191 /* Create 'InstallPath' string */
3192 RtlFreeUnicodeString(&InstallPath
);
3193 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3195 /* Create 'DestinationRootPath' string */
3196 RtlFreeUnicodeString(&DestinationRootPath
);
3197 swprintf(PathBuffer
,
3198 L
"\\Device\\Harddisk%lu\\Partition%lu",
3199 DiskEntry
->DiskNumber
,
3200 PartEntry
->PartitionNumber
);
3201 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3202 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3204 /* Create 'DestinationPath' string */
3205 RtlFreeUnicodeString(&DestinationPath
);
3206 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3208 if (InstallDir
[0] != L
'\\')
3209 wcscat(PathBuffer
, L
"\\");
3211 wcscat(PathBuffer
, InstallDir
);
3212 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3214 /* Create 'DestinationArcPath' */
3215 RtlFreeUnicodeString(&DestinationArcPath
);
3216 swprintf(PathBuffer
,
3217 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3218 DiskEntry
->BiosDiskNumber
,
3219 PartEntry
->PartitionNumber
);
3221 if (InstallDir
[0] != L
'\\')
3222 wcscat(PathBuffer
, L
"\\");
3224 wcscat(PathBuffer
, InstallDir
);
3225 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3230 * Displays the InstallDirectoryPage.
3233 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3237 * Number of the next page.
3240 InstallDirectoryPage(PINPUT_RECORD Ir
)
3242 PDISKENTRY DiskEntry
;
3243 PPARTENTRY PartEntry
;
3244 WCHAR InstallDir
[51];
3248 /* We do not need the filesystem list any more */
3249 if (FileSystemList
!= NULL
)
3251 DestroyFileSystemList(FileSystemList
);
3252 FileSystemList
= NULL
;
3255 if (PartitionList
== NULL
||
3256 PartitionList
->CurrentDisk
== NULL
||
3257 PartitionList
->CurrentPartition
== NULL
)
3259 /* FIXME: show an error dialog */
3263 DiskEntry
= PartitionList
->CurrentDisk
;
3264 PartEntry
= PartitionList
->CurrentPartition
;
3266 if (IsUnattendedSetup
)
3268 if (!IsValidPath(UnattendInstallationDirectory
))
3270 /* FIXME: Log the error? */
3274 BuildInstallPaths(UnattendInstallationDirectory
,
3278 return PREPARE_COPY_PAGE
;
3281 wcscpy(InstallDir
, L
"\\ReactOS");
3283 Length
= wcslen(InstallDir
);
3285 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3286 CONSOLE_SetCursorXY(8 + Pos
, 11);
3287 CONSOLE_SetCursorType(TRUE
, TRUE
);
3288 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3292 CONSOLE_ConInKey(Ir
);
3294 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3295 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3297 CONSOLE_SetCursorType(TRUE
, FALSE
);
3299 if (ConfirmQuit(Ir
) != FALSE
)
3302 CONSOLE_SetCursorType(TRUE
, TRUE
);
3305 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3306 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3310 memmove(&InstallDir
[Pos
],
3311 &InstallDir
[Pos
+ 1],
3312 (Length
- Pos
- 1) * sizeof(WCHAR
));
3313 InstallDir
[Length
- 1] = UNICODE_NULL
;
3316 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3317 CONSOLE_SetCursorXY(8 + Pos
, 11);
3320 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3321 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3324 CONSOLE_SetCursorXY(8 + Pos
, 11);
3326 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3327 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3330 CONSOLE_SetCursorXY(8 + Pos
, 11);
3332 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3333 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3338 CONSOLE_SetCursorXY(8 + Pos
, 11);
3341 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3342 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3347 CONSOLE_SetCursorXY(8 + Pos
, 11);
3350 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3352 CONSOLE_SetCursorType(TRUE
, FALSE
);
3355 * Check for the validity of the installation directory and pop up
3356 * an error if it is not the case. Then the user can fix its input.
3358 if (!IsValidPath(InstallDir
))
3360 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3361 return INSTALL_DIRECTORY_PAGE
;
3364 BuildInstallPaths(InstallDir
,
3368 return PREPARE_COPY_PAGE
;
3370 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3375 memmove(&InstallDir
[Pos
- 1],
3377 (Length
- Pos
) * sizeof(WCHAR
));
3378 InstallDir
[Length
- 1] = UNICODE_NULL
;
3382 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3383 CONSOLE_SetCursorXY(8 + Pos
, 11);
3386 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3390 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3391 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3394 memmove(&InstallDir
[Pos
+ 1],
3396 (Length
- Pos
) * sizeof(WCHAR
));
3397 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3398 InstallDir
[Pos
] = c
;
3402 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3403 CONSOLE_SetCursorXY(8 + Pos
, 11);
3409 return INSTALL_DIRECTORY_PAGE
;
3414 AddSectionToCopyQueueCab(HINF InfFile
,
3416 PWCHAR SourceCabinet
,
3417 PCUNICODE_STRING DestinationPath
,
3420 INFCONTEXT FilesContext
;
3421 INFCONTEXT DirContext
;
3423 PWCHAR FileKeyValue
;
3425 PWCHAR TargetFileName
;
3427 /* Search for the SectionName section */
3428 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3431 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3432 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3437 * Enumerate the files in the section
3438 * and add them to the file queue.
3442 /* Get source file name and target directory id */
3443 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3445 /* FIXME: Handle error! */
3446 DPRINT1("INF_GetData() failed\n");
3450 /* Get optional target file name */
3451 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3452 TargetFileName
= NULL
;
3454 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3456 /* Lookup target directory */
3457 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3459 /* FIXME: Handle error! */
3460 DPRINT1("SetupFindFirstLine() failed\n");
3464 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3466 /* FIXME: Handle error! */
3467 DPRINT1("INF_GetData() failed\n");
3471 if (!SetupQueueCopy(SetupFileQueue
,
3473 SourceRootPath
.Buffer
,
3474 SourceRootDir
.Buffer
,
3479 /* FIXME: Handle error! */
3480 DPRINT1("SetupQueueCopy() failed\n");
3482 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3489 AddSectionToCopyQueue(HINF InfFile
,
3491 PWCHAR SourceCabinet
,
3492 PCUNICODE_STRING DestinationPath
,
3495 INFCONTEXT FilesContext
;
3496 INFCONTEXT DirContext
;
3498 PWCHAR FileKeyValue
;
3500 PWCHAR TargetFileName
;
3502 WCHAR CompleteOrigDirName
[512];
3505 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3507 /* Search for the SectionName section */
3508 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3511 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3512 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3517 * Enumerate the files in the section
3518 * and add them to the file queue.
3522 /* Get source file name and target directory id */
3523 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3525 /* FIXME: Handle error! */
3526 DPRINT1("INF_GetData() failed\n");
3530 /* Get target directory id */
3531 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3533 /* FIXME: Handle error! */
3534 DPRINT1("INF_GetData() failed\n");
3538 /* Get optional target file name */
3539 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3540 TargetFileName
= NULL
;
3541 else if (!*TargetFileName
)
3542 TargetFileName
= NULL
;
3544 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3546 /* Lookup target directory */
3547 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3549 /* FIXME: Handle error! */
3550 DPRINT1("SetupFindFirstLine() failed\n");
3554 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3556 /* FIXME: Handle error! */
3557 DPRINT1("INF_GetData() failed\n");
3561 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3563 /* Installation path */
3564 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3566 else if (DirKeyValue
[0] == L
'\\')
3569 wcscpy(CompleteOrigDirName
, DirKeyValue
);
3571 else // if (DirKeyValue[0] != L'\\')
3573 /* Path relative to the installation path */
3574 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3575 wcscat(CompleteOrigDirName
, L
"\\");
3576 wcscat(CompleteOrigDirName
, DirKeyValue
);
3579 /* Remove trailing backslash */
3580 Length
= wcslen(CompleteOrigDirName
);
3581 if ((Length
> 0) && (CompleteOrigDirName
[Length
- 1] == L
'\\'))
3583 CompleteOrigDirName
[Length
- 1] = 0;
3586 if (!SetupQueueCopy(SetupFileQueue
,
3588 SourceRootPath
.Buffer
,
3589 CompleteOrigDirName
,
3594 /* FIXME: Handle error! */
3595 DPRINT1("SetupQueueCopy() failed\n");
3597 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3604 PrepareCopyPageInfFile(HINF InfFile
,
3605 PWCHAR SourceCabinet
,
3608 WCHAR PathBuffer
[MAX_PATH
];
3609 INFCONTEXT DirContext
;
3610 PWCHAR AdditionalSectionName
= NULL
;
3615 /* Add common files */
3616 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &DestinationPath
, Ir
))
3619 /* Add specific files depending of computer type */
3620 if (SourceCabinet
== NULL
)
3622 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3625 if (AdditionalSectionName
)
3627 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &DestinationPath
, Ir
))
3632 /* Create directories */
3636 * - Install directories like '\reactos\test' are not handled yet.
3637 * - Copying files to DestinationRootPath should be done from within
3638 * the SystemPartitionFiles section.
3639 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3640 * For installing to DestinationPath specify just '\' .
3643 /* Get destination path */
3644 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3646 /* Remove trailing backslash */
3647 Length
= wcslen(PathBuffer
);
3648 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3650 PathBuffer
[Length
- 1] = 0;
3653 /* Create the install directory */
3654 Status
= SetupCreateDirectory(PathBuffer
);
3655 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3657 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3658 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3662 /* Search for the 'Directories' section */
3663 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3667 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3671 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3677 /* Enumerate the directory values and create the subdirectories */
3680 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3686 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3688 /* Installation path */
3689 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3691 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3693 DPRINT("FullPath: '%S'\n", PathBuffer
);
3695 else if (DirKeyValue
[0] == L
'\\')
3698 DPRINT("Absolute Path: '%S'\n", DirKeyValue
);
3700 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3701 wcscat(PathBuffer
, DirKeyValue
);
3703 /* Remove trailing backslash */
3704 Length
= wcslen(PathBuffer
);
3705 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3707 PathBuffer
[Length
- 1] = 0;
3710 DPRINT("FullPath: '%S'\n", PathBuffer
);
3712 Status
= SetupCreateDirectory(PathBuffer
);
3713 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3715 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3716 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3720 else // if (DirKeyValue[0] != L'\\')
3722 /* Path relative to the installation path */
3723 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3725 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3726 wcscat(PathBuffer
, L
"\\");
3727 wcscat(PathBuffer
, DirKeyValue
);
3729 /* Remove trailing backslash */
3730 Length
= wcslen(PathBuffer
);
3731 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3733 PathBuffer
[Length
- 1] = 0;
3736 DPRINT("FullPath: '%S'\n", PathBuffer
);
3738 Status
= SetupCreateDirectory(PathBuffer
);
3739 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3741 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3742 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3746 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3753 * Displays the PrepareCopyPage.
3756 * FileCopyPage(At once)
3760 * Inits SetupFileQueue
3761 * Calls PrepareCopyPageInfFile
3764 * Number of the next page.
3767 PrepareCopyPage(PINPUT_RECORD Ir
)
3770 WCHAR PathBuffer
[MAX_PATH
];
3771 INFCONTEXT CabinetsContext
;
3777 MUIDisplayPage(PREPARE_COPY_PAGE
);
3779 /* Create the file queue */
3780 SetupFileQueue
= SetupOpenFileQueue();
3781 if (SetupFileQueue
== NULL
)
3783 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3787 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3789 /* FIXME: show an error dialog */
3793 /* Search for the 'Cabinets' section */
3794 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3796 return FILE_COPY_PAGE
;
3800 * Enumerate the directory values in the 'Cabinets'
3801 * section and parse their inf files.
3805 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3808 wcscpy(PathBuffer
, SourcePath
.Buffer
);
3809 wcscat(PathBuffer
, L
"\\");
3810 wcscat(PathBuffer
, KeyValue
);
3812 CabinetInitialize();
3813 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3814 CabinetSetCabinetName(PathBuffer
);
3816 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3818 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3820 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3821 if (InfFileData
== NULL
)
3823 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3829 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3830 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3834 InfHandle
= INF_OpenBufferedFileA((CHAR
*) InfFileData
,
3841 if (InfHandle
== INVALID_HANDLE_VALUE
)
3843 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3849 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3851 /* FIXME: show an error dialog */
3854 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3856 return FILE_COPY_PAGE
;
3862 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3865 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3867 /* Get the memory information from the system */
3868 NtQuerySystemInformation(SystemPerformanceInformation
,
3873 /* Check if this is initial setup */
3876 /* Set maximum limits to be total RAM pages */
3877 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3878 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3879 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3882 /* Set current values */
3883 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3884 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3885 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3891 FileCopyCallback(PVOID Context
,
3896 PCOPYCONTEXT CopyContext
;
3898 CopyContext
= (PCOPYCONTEXT
)Context
;
3900 switch (Notification
)
3902 case SPFILENOTIFY_STARTSUBQUEUE
:
3903 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3904 ProgressSetStepCount(CopyContext
->ProgressBar
,
3905 CopyContext
->TotalOperations
);
3906 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3909 case SPFILENOTIFY_STARTCOPY
:
3910 /* Display copy message */
3911 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3912 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3915 case SPFILENOTIFY_ENDCOPY
:
3916 CopyContext
->CompletedOperations
++;
3918 /* SYSREG checkpoint */
3919 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3920 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3922 ProgressNextStep(CopyContext
->ProgressBar
);
3923 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3932 * Displays the FileCopyPage.
3935 * RegistryPage(At once)
3938 * Calls SetupCommitFileQueueW
3939 * Calls SetupCloseFileQueue
3942 * Number of the next page.
3945 FileCopyPage(PINPUT_RECORD Ir
)
3947 COPYCONTEXT CopyContext
;
3948 unsigned int mem_bar_width
;
3950 MUIDisplayPage(FILE_COPY_PAGE
);
3952 /* Create context for the copy process */
3953 CopyContext
.DestinationRootPath
= DestinationRootPath
.Buffer
;
3954 CopyContext
.InstallPath
= InstallPath
.Buffer
;
3955 CopyContext
.TotalOperations
= 0;
3956 CopyContext
.CompletedOperations
= 0;
3958 /* Create the progress bar as well */
3959 CopyContext
.ProgressBar
= CreateProgressBar(13,
3966 MUIGetString(STRING_SETUPCOPYINGFILES
));
3968 // fit memory bars to screen width, distribute them uniform
3969 mem_bar_width
= (xScreen
- 26) / 5;
3970 mem_bar_width
-= mem_bar_width
% 2; // make even
3971 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3972 /* Create the paged pool progress bar */
3973 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3982 /* Create the non paged pool progress bar */
3983 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
3985 (xScreen
/ 2) + (mem_bar_width
/ 2),
3987 (xScreen
/ 2)- (mem_bar_width
/ 2),
3992 /* Create the global memory progress bar */
3993 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
3997 xScreen
- 13 - mem_bar_width
,
4002 /* Do the file copying */
4003 SetupCommitFileQueueW(NULL
,
4008 /* If we get here, we're done, so cleanup the queue and progress bar */
4009 SetupCloseFileQueue(SetupFileQueue
);
4010 DestroyProgressBar(CopyContext
.ProgressBar
);
4011 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4012 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4013 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4015 /* Go display the next page */
4016 return REGISTRY_PAGE
;
4021 * Displays the RegistryPage.
4024 * SuccessPage (if RepairUpdate)
4025 * BootLoaderPage (default)
4029 * Calls SetInstallPathValue
4030 * Calls NtInitializeRegistry
4031 * Calls ImportRegistryFile
4032 * Calls SetDefaultPagefile
4033 * Calls SetMountedDeviceValues
4036 * Number of the next page.
4039 RegistryPage(PINPUT_RECORD Ir
)
4041 INFCONTEXT InfContext
;
4048 MUIDisplayPage(REGISTRY_PAGE
);
4050 if (RepairUpdateFlag
)
4052 return SUCCESS_PAGE
;
4055 if (!SetInstallPathValue(&DestinationPath
))
4057 DPRINT1("SetInstallPathValue() failed\n");
4058 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4062 /* Create the default hives */
4063 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4064 if (!NT_SUCCESS(Status
))
4066 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
4067 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4071 /* Update registry */
4072 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4074 if (!SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
))
4076 DPRINT1("SetupFindFirstLine() failed\n");
4077 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4083 INF_GetDataField(&InfContext
, 0, &Action
);
4084 INF_GetDataField(&InfContext
, 1, &File
);
4085 INF_GetDataField(&InfContext
, 2, &Section
);
4087 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4092 if (!_wcsicmp(Action
, L
"AddReg"))
4096 else if (!_wcsicmp(Action
, L
"DelReg"))
4105 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4107 if (!ImportRegistryFile(File
, Section
, LanguageId
, Delete
))
4109 DPRINT1("Importing %S failed\n", File
);
4111 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4114 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4116 /* Update display registry settings */
4117 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4118 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4120 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4124 /* Set the locale */
4125 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4126 if (!ProcessLocaleRegistry(LanguageList
))
4128 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4132 /* Add keyboard layouts */
4133 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4134 if (!AddKeyboardLayouts())
4136 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4141 if (!SetGeoID(MUIGetGeoID()))
4143 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4147 if (!IsUnattendedSetup
)
4149 /* Update keyboard layout settings */
4150 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4151 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4153 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4158 /* Add codepage information to registry */
4159 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4162 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4166 /* Set the default pagefile entry */
4167 SetDefaultPagefile(DestinationDriveLetter
);
4169 /* Update the mounted devices list */
4170 SetMountedDeviceValues(PartitionList
);
4172 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4174 return BOOT_LOADER_PAGE
;
4179 * Displays the BootLoaderPage.
4182 * SuccessPage (if RepairUpdate)
4183 * BootLoaderHarddiskMbrPage
4184 * BootLoaderHarddiskVbrPage
4185 * BootLoaderFloppyPage
4190 * Calls SetInstallPathValue
4191 * Calls NtInitializeRegistry
4192 * Calls ImportRegistryFile
4193 * Calls SetDefaultPagefile
4194 * Calls SetMountedDeviceValues
4197 * Number of the next page.
4200 BootLoaderPage(PINPUT_RECORD Ir
)
4202 UCHAR PartitionType
;
4203 BOOLEAN InstallOnFloppy
;
4205 WCHAR PathBuffer
[MAX_PATH
];
4207 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4209 RtlFreeUnicodeString(&SystemRootPath
);
4210 swprintf(PathBuffer
,
4211 L
"\\Device\\Harddisk%lu\\Partition%lu",
4212 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4213 PartitionList
->SystemPartition
->PartitionNumber
);
4214 RtlCreateUnicodeString(&SystemRootPath
, PathBuffer
);
4215 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath
);
4217 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4219 if (IsUnattendedSetup
)
4221 if (UnattendMBRInstallType
== 0) /* skip MBR installation */
4223 return SUCCESS_PAGE
;
4225 else if (UnattendMBRInstallType
== 1) /* install on floppy */
4227 return BOOT_LOADER_FLOPPY_PAGE
;
4231 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4233 DPRINT("Error: system partition invalid (unused)\n");
4234 InstallOnFloppy
= TRUE
;
4236 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4238 /* OS/2 boot manager partition */
4239 DPRINT("Found OS/2 boot manager partition\n");
4240 InstallOnFloppy
= TRUE
;
4242 else if (PartitionType
== PARTITION_EXT2
)
4244 /* Linux EXT2 partition */
4245 DPRINT("Found Linux EXT2 partition\n");
4246 InstallOnFloppy
= FALSE
;
4248 else if (PartitionType
== PARTITION_IFS
)
4250 /* NTFS partition */
4251 DPRINT("Found NTFS partition\n");
4253 // FIXME: Make it FALSE when we'll support NTFS installation!
4254 InstallOnFloppy
= TRUE
;
4256 else if ((PartitionType
== PARTITION_FAT_12
) ||
4257 (PartitionType
== PARTITION_FAT_16
) ||
4258 (PartitionType
== PARTITION_HUGE
) ||
4259 (PartitionType
== PARTITION_XINT13
) ||
4260 (PartitionType
== PARTITION_FAT32
) ||
4261 (PartitionType
== PARTITION_FAT32_XINT13
))
4263 DPRINT("Found FAT partition\n");
4264 InstallOnFloppy
= FALSE
;
4268 /* Unknown partition */
4269 DPRINT("Unknown partition found\n");
4270 InstallOnFloppy
= TRUE
;
4273 if (InstallOnFloppy
!= FALSE
)
4275 return BOOT_LOADER_FLOPPY_PAGE
;
4278 /* Unattended install on hdd? */
4279 if (IsUnattendedSetup
&& UnattendMBRInstallType
== 2)
4281 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4284 MUIDisplayPage(BOOT_LOADER_PAGE
);
4285 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4289 CONSOLE_ConInKey(Ir
);
4291 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4292 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4294 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4303 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4305 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4306 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4308 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4317 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4319 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4320 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4322 if (ConfirmQuit(Ir
) != FALSE
)
4327 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4331 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4333 else if (Line
== 13)
4335 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4337 else if (Line
== 14)
4339 return BOOT_LOADER_FLOPPY_PAGE
;
4341 else if (Line
== 15)
4343 return SUCCESS_PAGE
;
4346 return BOOT_LOADER_PAGE
;
4350 return BOOT_LOADER_PAGE
;
4355 * Displays the BootLoaderFloppyPage.
4358 * SuccessPage (At once)
4362 * Calls InstallFatBootcodeToFloppy()
4365 * Number of the next page.
4368 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4372 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4374 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4378 CONSOLE_ConInKey(Ir
);
4380 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4381 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4383 if (ConfirmQuit(Ir
) != FALSE
)
4388 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4390 if (DoesFileExist(NULL
, L
"\\Device\\Floppy0", L
"\\") == FALSE
)
4392 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4393 return BOOT_LOADER_FLOPPY_PAGE
;
4396 Status
= InstallFatBootcodeToFloppy(&SourceRootPath
, &DestinationArcPath
);
4397 if (!NT_SUCCESS(Status
))
4399 /* Print error message */
4400 return BOOT_LOADER_FLOPPY_PAGE
;
4403 return SUCCESS_PAGE
;
4407 return BOOT_LOADER_FLOPPY_PAGE
;
4412 * Displays the BootLoaderHarddiskVbrPage.
4415 * SuccessPage (At once)
4419 * Calls InstallVBRToPartition()
4422 * Number of the next page.
4425 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4427 UCHAR PartitionType
;
4430 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4432 Status
= InstallVBRToPartition(&SystemRootPath
,
4434 &DestinationArcPath
,
4436 if (!NT_SUCCESS(Status
))
4438 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4442 return SUCCESS_PAGE
;
4447 * Displays the BootLoaderHarddiskMbrPage.
4450 * SuccessPage (At once)
4454 * Calls InstallVBRToPartition()
4455 * CallsInstallMbrBootCodeToDisk()
4458 * Number of the next page.
4461 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4463 UCHAR PartitionType
;
4465 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4466 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4467 WCHAR DstPath
[MAX_PATH
];
4469 /* Step 1: Write the VBR */
4470 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4472 Status
= InstallVBRToPartition(&SystemRootPath
,
4474 &DestinationArcPath
,
4476 if (!NT_SUCCESS(Status
))
4478 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4482 /* Step 2: Write the MBR */
4483 swprintf(DestinationDevicePathBuffer
,
4484 L
"\\Device\\Harddisk%d\\Partition0",
4485 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4487 wcscpy(SourceMbrPathBuffer
, SourceRootPath
.Buffer
);
4488 wcscat(SourceMbrPathBuffer
, L
"\\loader\\dosmbr.bin");
4490 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4492 /* Save current MBR */
4493 wcscpy(DstPath
, SystemRootPath
.Buffer
);
4494 wcscat(DstPath
, L
"\\mbr.old");
4496 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4497 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4498 if (!NT_SUCCESS(Status
))
4500 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4501 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4505 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4506 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4507 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4508 DestinationDevicePathBuffer
);
4509 if (!NT_SUCCESS(Status
))
4511 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4513 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4517 return SUCCESS_PAGE
;
4522 * Displays the QuitPage.
4525 * FlushPage (At once)
4531 * Number of the next page.
4534 QuitPage(PINPUT_RECORD Ir
)
4536 MUIDisplayPage(QUIT_PAGE
);
4538 /* Destroy the partition list */
4539 if (PartitionList
!= NULL
)
4541 DestroyPartitionList(PartitionList
);
4542 PartitionList
= NULL
;
4544 TempPartition
= NULL
;
4545 FormatState
= Start
;
4547 /* Destroy the filesystem list */
4548 if (FileSystemList
!= NULL
)
4550 DestroyFileSystemList(FileSystemList
);
4551 FileSystemList
= NULL
;
4554 /* Destroy the computer settings list */
4555 if (ComputerList
!= NULL
)
4557 DestroyGenericList(ComputerList
, TRUE
);
4558 ComputerList
= NULL
;
4561 /* Destroy the display settings list */
4562 if (DisplayList
!= NULL
)
4564 DestroyGenericList(DisplayList
, TRUE
);
4568 /* Destroy the keyboard settings list */
4569 if (KeyboardList
!= NULL
)
4571 DestroyGenericList(KeyboardList
, TRUE
);
4572 KeyboardList
= NULL
;
4575 /* Destroy the keyboard layout list */
4576 if (LayoutList
!= NULL
)
4578 DestroyGenericList(LayoutList
, TRUE
);
4582 /* Destroy the languages list */
4583 if (LanguageList
!= NULL
)
4585 DestroyGenericList(LanguageList
, FALSE
);
4586 LanguageList
= NULL
;
4589 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4593 CONSOLE_ConInKey(Ir
);
4595 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4604 * Displays the SuccessPage.
4607 * FlushPage (At once)
4613 * Number of the next page.
4616 SuccessPage(PINPUT_RECORD Ir
)
4618 MUIDisplayPage(SUCCESS_PAGE
);
4620 if (IsUnattendedSetup
)
4627 CONSOLE_ConInKey(Ir
);
4629 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4638 * Displays the FlushPage.
4641 * RebootPage (At once)
4644 * Number of the next page.
4647 FlushPage(PINPUT_RECORD Ir
)
4649 MUIDisplayPage(FLUSH_PAGE
);
4655 PnpEventThread(IN LPVOID lpParameter
);
4659 * The start routine and page management
4670 NtQuerySystemTime(&Time
);
4672 /* Create the PnP thread in suspended state */
4673 Status
= RtlCreateUserThread(NtCurrentProcess(),
4683 if (!NT_SUCCESS(Status
))
4684 hPnpThread
= INVALID_HANDLE_VALUE
;
4686 if (!CONSOLE_Init())
4688 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4689 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4690 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4692 /* Raise a hard error (crash the system/BSOD) */
4693 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4697 /* Initialize global unicode strings */
4698 RtlInitUnicodeString(&SourcePath
, NULL
);
4699 RtlInitUnicodeString(&SourceRootPath
, NULL
);
4700 RtlInitUnicodeString(&SourceRootDir
, NULL
);
4701 RtlInitUnicodeString(&InstallPath
, NULL
);
4702 RtlInitUnicodeString(&DestinationPath
, NULL
);
4703 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
4704 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
4705 RtlInitUnicodeString(&SystemRootPath
, NULL
);
4707 /* Hide the cursor */
4708 CONSOLE_SetCursorType(TRUE
, FALSE
);
4711 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4713 CONSOLE_ClearScreen();
4716 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4723 Page
= SetupStartPage(&Ir
);
4728 Page
= LanguagePage(&Ir
);
4733 Page
= LicensePage(&Ir
);
4738 Page
= IntroPage(&Ir
);
4742 case INSTALL_INTRO_PAGE
:
4743 Page
= InstallIntroPage(&Ir
);
4747 case SCSI_CONTROLLER_PAGE
:
4748 Page
= ScsiControllerPage(&Ir
);
4751 case OEM_DRIVER_PAGE
:
4752 Page
= OemDriverPage(&Ir
);
4756 case DEVICE_SETTINGS_PAGE
:
4757 Page
= DeviceSettingsPage(&Ir
);
4760 case COMPUTER_SETTINGS_PAGE
:
4761 Page
= ComputerSettingsPage(&Ir
);
4764 case DISPLAY_SETTINGS_PAGE
:
4765 Page
= DisplaySettingsPage(&Ir
);
4768 case KEYBOARD_SETTINGS_PAGE
:
4769 Page
= KeyboardSettingsPage(&Ir
);
4772 case LAYOUT_SETTINGS_PAGE
:
4773 Page
= LayoutSettingsPage(&Ir
);
4776 case SELECT_PARTITION_PAGE
:
4777 Page
= SelectPartitionPage(&Ir
);
4780 case CREATE_PRIMARY_PARTITION_PAGE
:
4781 Page
= CreatePrimaryPartitionPage(&Ir
);
4784 case CREATE_EXTENDED_PARTITION_PAGE
:
4785 Page
= CreateExtendedPartitionPage(&Ir
);
4788 case CREATE_LOGICAL_PARTITION_PAGE
:
4789 Page
= CreateLogicalPartitionPage(&Ir
);
4792 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4793 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4796 case DELETE_PARTITION_PAGE
:
4797 Page
= DeletePartitionPage(&Ir
);
4800 case SELECT_FILE_SYSTEM_PAGE
:
4801 Page
= SelectFileSystemPage(&Ir
);
4804 case FORMAT_PARTITION_PAGE
:
4805 Page
= FormatPartitionPage(&Ir
);
4808 case CHECK_FILE_SYSTEM_PAGE
:
4809 Page
= CheckFileSystemPage(&Ir
);
4812 case INSTALL_DIRECTORY_PAGE
:
4813 Page
= InstallDirectoryPage(&Ir
);
4816 case PREPARE_COPY_PAGE
:
4817 Page
= PrepareCopyPage(&Ir
);
4820 case FILE_COPY_PAGE
:
4821 Page
= FileCopyPage(&Ir
);
4825 Page
= RegistryPage(&Ir
);
4828 case BOOT_LOADER_PAGE
:
4829 Page
= BootLoaderPage(&Ir
);
4832 case BOOT_LOADER_FLOPPY_PAGE
:
4833 Page
= BootLoaderFloppyPage(&Ir
);
4836 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4837 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4840 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4841 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4845 case REPAIR_INTRO_PAGE
:
4846 Page
= RepairIntroPage(&Ir
);
4850 Page
= SuccessPage(&Ir
);
4854 Page
= FlushPage(&Ir
);
4858 Page
= QuitPage(&Ir
);
4867 if (Page
== RECOVERY_PAGE
)
4872 /* Avoid bugcheck */
4873 Time
.QuadPart
+= 50000000;
4874 NtDelayExecution(FALSE
, &Time
);
4877 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4878 NtShutdownSystem(ShutdownReboot
);
4879 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4880 NtTerminateProcess(NtCurrentProcess(), 0);
4885 NtProcessStartup(PPEB Peb
)
4887 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4889 ProcessHeap
= Peb
->ProcessHeap
;
4890 InfSetHeap(ProcessHeap
);