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 CombinePaths(UnattendInfPath
, ARRAYSIZE(UnattendInfPath
), 2, SourcePath
.Buffer
, L
"\\unattend.inf");
432 if (DoesFileExist(NULL
, NULL
, UnattendInfPath
) == FALSE
)
434 DPRINT("Does not exist: %S\n", UnattendInfPath
);
438 /* Load 'unattend.inf' from install media. */
439 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
445 if (UnattendInf
== INVALID_HANDLE_VALUE
)
447 DPRINT("SetupOpenInfFileW() failed\n");
451 /* Open 'Unattend' section */
452 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
454 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
455 SetupCloseInfFile(UnattendInf
);
459 /* Get pointer 'Signature' key */
460 if (!INF_GetData(&Context
, NULL
, &Value
))
462 DPRINT("INF_GetData() failed for key 'Signature'\n");
463 SetupCloseInfFile(UnattendInf
);
467 /* Check 'Signature' string */
468 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
470 DPRINT("Signature not $ReactOS$\n");
471 SetupCloseInfFile(UnattendInf
);
475 /* Check if Unattend setup is enabled */
476 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
478 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
479 SetupCloseInfFile(UnattendInf
);
483 if (!INF_GetData(&Context
, NULL
, &Value
))
485 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
486 SetupCloseInfFile(UnattendInf
);
490 if (_wcsicmp(Value
, L
"yes") != 0)
492 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
493 SetupCloseInfFile(UnattendInf
);
497 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
498 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
500 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
501 SetupCloseInfFile(UnattendInf
);
505 if (!SetupGetIntField(&Context
, 1, &IntValue
))
507 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
508 SetupCloseInfFile(UnattendInf
);
512 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
514 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
515 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
517 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
518 SetupCloseInfFile(UnattendInf
);
522 if (!SetupGetIntField(&Context
, 1, &IntValue
))
524 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
525 SetupCloseInfFile(UnattendInf
);
529 UnattendDestinationPartitionNumber
= (LONG
)IntValue
;
531 /* Search for 'InstallationDirectory' in the 'Unattend' section */
532 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
534 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
535 SetupCloseInfFile(UnattendInf
);
539 /* Get pointer 'InstallationDirectory' key */
540 if (!INF_GetData(&Context
, NULL
, &Value
))
542 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
543 SetupCloseInfFile(UnattendInf
);
547 wcscpy(UnattendInstallationDirectory
, Value
);
549 IsUnattendedSetup
= TRUE
;
551 /* Search for 'MBRInstallType' in the 'Unattend' section */
552 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
554 if (SetupGetIntField(&Context
, 1, &IntValue
))
556 UnattendMBRInstallType
= IntValue
;
560 /* Search for 'FormatPartition' in the 'Unattend' section */
561 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
563 if (SetupGetIntField(&Context
, 1, &IntValue
))
565 UnattendFormatPartition
= IntValue
;
569 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
571 if (SetupGetIntField(&Context
, 1, &IntValue
))
573 AutoPartition
= IntValue
;
577 /* search for LocaleID in the 'Unattend' section*/
578 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
580 if (INF_GetData(&Context
, NULL
, &Value
))
582 LONG Id
= wcstol(Value
, NULL
, 16);
583 swprintf(LocaleID
,L
"%08lx", Id
);
587 SetupCloseInfFile(UnattendInf
);
589 DPRINT("Running unattended setup\n");
596 PGENERIC_LIST_ENTRY ListEntry
;
597 LPCWSTR pszNewLayout
;
599 pszNewLayout
= MUIDefaultKeyboardLayout();
601 if (LayoutList
== NULL
)
603 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
604 if (LayoutList
== NULL
)
606 /* FIXME: Handle error! */
611 ListEntry
= GetFirstListEntry(LayoutList
);
613 /* Search for default layout (if provided) */
614 if (pszNewLayout
!= NULL
)
616 while (ListEntry
!= NULL
)
618 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
620 SetCurrentListEntry(LayoutList
, ListEntry
);
624 ListEntry
= GetNextListEntry(ListEntry
);
631 * Displays the LanguagePage.
633 * Next pages: IntroPage, QuitPage
636 * Init SelectedLanguageId
640 * Number of the next page.
643 LanguagePage(PINPUT_RECORD Ir
)
645 GENERIC_LIST_UI ListUi
;
646 PWCHAR NewLanguageId
;
647 BOOL RefreshPage
= FALSE
;
649 /* Initialize the computer settings list */
650 if (LanguageList
== NULL
)
652 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
653 if (LanguageList
== NULL
)
655 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
661 SelectedLanguageId
= DefaultLanguage
;
662 SetConsoleCodePage();
665 /* If there's just a single language in the list skip
666 * the language selection process altogether! */
667 if (GenericListHasSingleEntry(LanguageList
))
669 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
673 InitGenericListUi(&ListUi
, LanguageList
);
674 DrawGenericList(&ListUi
,
680 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
682 MUIDisplayPage(LANGUAGE_PAGE
);
686 CONSOLE_ConInKey(Ir
);
688 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
689 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
691 ScrollDownGenericList(&ListUi
);
694 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
695 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
697 ScrollUpGenericList(&ListUi
);
700 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
701 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
703 ScrollPageDownGenericList(&ListUi
);
706 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
707 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
709 ScrollPageUpGenericList(&ListUi
);
712 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
713 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
715 if (ConfirmQuit(Ir
) != FALSE
)
718 RedrawGenericList(&ListUi
);
720 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
722 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
724 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
726 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
732 SetConsoleCodePage();
736 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
739 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
745 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
747 if (SelectedLanguageId
!= NewLanguageId
)
749 /* Clear the language page */
750 MUIClearPage(LANGUAGE_PAGE
);
752 SelectedLanguageId
= NewLanguageId
;
755 SetConsoleCodePage();
757 /* Redraw language selection page in native language */
758 MUIDisplayPage(LANGUAGE_PAGE
);
773 * LanguagePage (at once, default)
774 * InstallIntroPage (at once, if unattended)
780 * Init SourceRootPath
783 * Init RequiredPartitionDiskSpace
784 * Init IsUnattendedSetup
785 * If unattended, init *List and sets the Codepage
786 * If unattended, init SelectedLanguageId
787 * If unattended, init LanguageId
790 * Number of the next page.
793 SetupStartPage(PINPUT_RECORD Ir
)
796 WCHAR FileNameBuffer
[MAX_PATH
];
800 PGENERIC_LIST_ENTRY ListEntry
;
803 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
805 /* Get the source path and source root path */
806 Status
= GetSourcePaths(&SourcePath
,
810 if (!NT_SUCCESS(Status
))
812 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
813 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
819 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
820 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
821 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir
);
825 /* Load txtsetup.sif from install media. */
826 CombinePaths(FileNameBuffer
, ARRAYSIZE(FileNameBuffer
), 2, SourcePath
.Buffer
, L
"\\txtsetup.sif");
827 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
833 if (SetupInf
== INVALID_HANDLE_VALUE
)
835 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
839 /* Open 'Version' section */
840 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
842 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
846 /* Get pointer 'Signature' key */
847 if (!INF_GetData(&Context
, NULL
, &Value
))
849 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
853 /* Check 'Signature' string */
854 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
856 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
860 /* Open 'DiskSpaceRequirements' section */
861 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
863 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
867 /* Get the 'FreeSysPartDiskSpace' value */
868 if (!SetupGetIntField(&Context
, 1, &IntValue
))
870 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
874 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
876 /* Start the PnP thread */
877 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
879 NtResumeThread(hPnpThread
, NULL
);
880 hPnpThread
= INVALID_HANDLE_VALUE
;
883 CheckUnattendedSetup();
885 if (IsUnattendedSetup
)
887 // TODO: Read options from inf
888 ComputerList
= CreateComputerTypeList(SetupInf
);
889 DisplayList
= CreateDisplayDriverList(SetupInf
);
890 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
891 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
892 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
895 wcscpy(SelectedLanguageId
, LocaleID
);
896 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
898 /* first we hack LanguageList */
899 ListEntry
= GetFirstListEntry(LanguageList
);
900 while (ListEntry
!= NULL
)
902 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
904 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
905 SetCurrentListEntry(LanguageList
, ListEntry
);
909 ListEntry
= GetNextListEntry(ListEntry
);
913 ListEntry
= GetFirstListEntry(LayoutList
);
914 while (ListEntry
!= NULL
)
916 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
918 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
919 SetCurrentListEntry(LayoutList
, ListEntry
);
923 ListEntry
= GetNextListEntry(ListEntry
);
926 SetConsoleCodePage();
928 return INSTALL_INTRO_PAGE
;
931 return LANGUAGE_PAGE
;
936 * Displays the IntroPage.
939 * InstallIntroPage (default)
945 * Number of the next page.
948 IntroPage(PINPUT_RECORD Ir
)
950 MUIDisplayPage(START_PAGE
);
954 CONSOLE_ConInKey(Ir
);
956 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
957 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
959 if (ConfirmQuit(Ir
) != FALSE
)
964 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
966 return INSTALL_INTRO_PAGE
;
968 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
970 return REPAIR_INTRO_PAGE
;
972 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
983 * Displays the License page.
986 * IntroPage (default)
989 * Number of the next page.
992 LicensePage(PINPUT_RECORD Ir
)
994 MUIDisplayPage(LICENSE_PAGE
);
998 CONSOLE_ConInKey(Ir
);
1000 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1006 return LICENSE_PAGE
;
1011 * Displays the RepairIntroPage.
1014 * RebootPage (default)
1020 * Number of the next page.
1023 RepairIntroPage(PINPUT_RECORD Ir
)
1025 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1029 CONSOLE_ConInKey(Ir
);
1031 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1035 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1037 RepairUpdateFlag
= TRUE
;
1038 return INSTALL_INTRO_PAGE
;
1040 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1042 return RECOVERY_PAGE
;
1044 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1045 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1051 return REPAIR_INTRO_PAGE
;
1055 * Displays the InstallIntroPage.
1058 * DeviceSettingsPage (At once if repair or update is selected)
1059 * SelectPartitionPage (At once if unattended setup)
1060 * DeviceSettingsPage (default)
1064 * Number of the next page.
1067 InstallIntroPage(PINPUT_RECORD Ir
)
1069 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1071 if (RepairUpdateFlag
)
1073 //return SELECT_PARTITION_PAGE;
1074 return DEVICE_SETTINGS_PAGE
;
1077 if (IsUnattendedSetup
)
1079 return SELECT_PARTITION_PAGE
;
1084 CONSOLE_ConInKey(Ir
);
1086 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1087 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1089 if (ConfirmQuit(Ir
) != FALSE
)
1094 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1096 return DEVICE_SETTINGS_PAGE
;
1097 // return SCSI_CONTROLLER_PAGE;
1101 return INSTALL_INTRO_PAGE
;
1107 ScsiControllerPage(PINPUT_RECORD Ir
)
1109 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1111 /* FIXME: print loaded mass storage driver descriptions */
1113 SetTextXY(8, 10, "TEST device");
1117 SetStatusText(" ENTER = Continue F3 = Quit");
1123 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1124 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1126 if (ConfirmQuit(Ir
) != FALSE
)
1131 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1133 return DEVICE_SETTINGS_PAGE
;
1137 return SCSI_CONTROLLER_PAGE
;
1143 * Displays the DeviceSettingsPage.
1146 * SelectPartitionPage (At once if repair or update is selected)
1147 * ComputerSettingsPage
1148 * DisplaySettingsPage
1149 * KeyboardSettingsPage
1150 * LayoutsettingsPage
1151 * SelectPartitionPage
1161 * Number of the next page.
1164 DeviceSettingsPage(PINPUT_RECORD Ir
)
1166 static ULONG Line
= 16;
1167 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1169 /* Initialize the computer settings list */
1170 if (ComputerList
== NULL
)
1172 ComputerList
= CreateComputerTypeList(SetupInf
);
1173 if (ComputerList
== NULL
)
1175 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1180 /* Initialize the display settings list */
1181 if (DisplayList
== NULL
)
1183 DisplayList
= CreateDisplayDriverList(SetupInf
);
1184 if (DisplayList
== NULL
)
1186 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1191 /* Initialize the keyboard settings list */
1192 if (KeyboardList
== NULL
)
1194 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1195 if (KeyboardList
== NULL
)
1197 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1202 /* Initialize the keyboard layout list */
1203 if (LayoutList
== NULL
)
1205 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1206 if (LayoutList
== NULL
)
1208 /* FIXME: report error */
1209 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1214 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1217 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList
))));
1218 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList
))));
1219 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList
))));
1220 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList
))));
1222 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1224 if (RepairUpdateFlag
)
1226 return SELECT_PARTITION_PAGE
;
1231 CONSOLE_ConInKey(Ir
);
1233 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1234 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1236 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1240 else if (Line
== 16)
1245 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1247 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1248 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1250 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1254 else if (Line
== 16)
1259 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1261 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1262 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1264 if (ConfirmQuit(Ir
) != FALSE
)
1269 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1272 return COMPUTER_SETTINGS_PAGE
;
1273 else if (Line
== 12)
1274 return DISPLAY_SETTINGS_PAGE
;
1275 else if (Line
== 13)
1276 return KEYBOARD_SETTINGS_PAGE
;
1277 else if (Line
== 14)
1278 return LAYOUT_SETTINGS_PAGE
;
1279 else if (Line
== 16)
1280 return SELECT_PARTITION_PAGE
;
1284 return DEVICE_SETTINGS_PAGE
;
1289 * Handles generic selection lists.
1292 * GenericList: The list to handle.
1293 * nextPage: The page it needs to jump to after this page.
1294 * Ir: The PINPUT_RECORD
1297 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1298 PAGE_NUMBER nextPage
,
1303 CONSOLE_ConInKey(Ir
);
1305 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1306 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1308 ScrollDownGenericList(ListUi
);
1310 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1311 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1313 ScrollUpGenericList(ListUi
);
1315 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1316 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1318 ScrollPageDownGenericList(ListUi
);
1320 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1321 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1323 ScrollPageUpGenericList(ListUi
);
1325 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1326 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1328 if (ConfirmQuit(Ir
) != FALSE
)
1331 RedrawGenericList(ListUi
);
1333 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1334 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1336 RestoreGenericListState(ListUi
->List
);
1337 return nextPage
; // Use some "prevPage;" instead?
1339 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1343 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1346 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1353 * Displays the ComputerSettingsPage.
1356 * DeviceSettingsPage
1360 * Number of the next page.
1363 ComputerSettingsPage(PINPUT_RECORD Ir
)
1365 GENERIC_LIST_UI ListUi
;
1366 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1368 InitGenericListUi(&ListUi
, ComputerList
);
1369 DrawGenericList(&ListUi
,
1375 SaveGenericListState(ComputerList
);
1377 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1382 * Displays the DisplaySettingsPage.
1385 * DeviceSettingsPage
1389 * Number of the next page.
1392 DisplaySettingsPage(PINPUT_RECORD Ir
)
1394 GENERIC_LIST_UI ListUi
;
1395 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1397 InitGenericListUi(&ListUi
, DisplayList
);
1398 DrawGenericList(&ListUi
,
1404 SaveGenericListState(DisplayList
);
1406 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1411 * Displays the KeyboardSettingsPage.
1414 * DeviceSettingsPage
1418 * Number of the next page.
1421 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1423 GENERIC_LIST_UI ListUi
;
1424 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1426 InitGenericListUi(&ListUi
, KeyboardList
);
1427 DrawGenericList(&ListUi
,
1433 SaveGenericListState(KeyboardList
);
1435 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1440 * Displays the LayoutSettingsPage.
1443 * DeviceSettingsPage
1447 * Number of the next page.
1450 LayoutSettingsPage(PINPUT_RECORD Ir
)
1452 GENERIC_LIST_UI ListUi
;
1453 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1455 InitGenericListUi(&ListUi
, LayoutList
);
1456 DrawGenericList(&ListUi
,
1462 SaveGenericListState(LayoutList
);
1464 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1469 IsDiskSizeValid(PPARTENTRY PartEntry
)
1473 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1474 size
= (size
+ 524288) / 1048576; /* in MBytes */
1476 if (size
< RequiredPartitionDiskSpace
)
1478 /* partition is too small so ask for another partition */
1479 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1490 * Displays the SelectPartitionPage.
1493 * SelectFileSystemPage (At once if unattended)
1494 * SelectFileSystemPage (Default if free space is selected)
1495 * CreatePrimaryPartitionPage
1496 * CreateExtendedPartitionPage
1497 * CreateLogicalPartitionPage
1498 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1499 * DeletePartitionPage
1503 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1504 * Set InstallShortcut (only if not unattended + free space is selected)
1507 * Number of the next page.
1510 SelectPartitionPage(PINPUT_RECORD Ir
)
1515 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1517 if (PartitionList
== NULL
)
1519 PartitionList
= CreatePartitionList();
1520 if (PartitionList
== NULL
)
1522 /* FIXME: show an error dialog */
1523 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1526 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1528 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1532 TempPartition
= NULL
;
1533 FormatState
= Start
;
1536 InitPartitionListUi(&ListUi
, PartitionList
,
1541 DrawPartitionList(&ListUi
);
1543 if (IsUnattendedSetup
)
1545 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1549 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1551 CreateLogicalPartition(PartitionList
,
1552 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1557 CreatePrimaryPartition(PartitionList
,
1558 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1562 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1563 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1565 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1566 RequiredPartitionDiskSpace
);
1567 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1570 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1572 return SELECT_FILE_SYSTEM_PAGE
;
1577 DrawPartitionList(&ListUi
);
1579 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1580 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1582 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1583 RequiredPartitionDiskSpace
);
1584 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1587 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1589 return SELECT_FILE_SYSTEM_PAGE
;
1595 /* Update status text */
1596 if (PartitionList
->CurrentPartition
== NULL
)
1598 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1600 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1602 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1604 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1608 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1613 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1615 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1617 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1621 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1626 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1630 CONSOLE_ConInKey(Ir
);
1632 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1633 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1635 if (ConfirmQuit(Ir
) != FALSE
)
1637 DestroyPartitionList(PartitionList
);
1638 PartitionList
= NULL
;
1644 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1645 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1647 ScrollDownPartitionList(&ListUi
);
1649 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1650 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1652 ScrollUpPartitionList(&ListUi
);
1654 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1656 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1657 continue; // return SELECT_PARTITION_PAGE;
1659 if (PartitionList
->CurrentPartition
== NULL
||
1660 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1662 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1664 CreateLogicalPartition(PartitionList
,
1670 CreatePrimaryPartition(PartitionList
,
1676 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1678 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1679 RequiredPartitionDiskSpace
);
1680 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1683 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1685 return SELECT_FILE_SYSTEM_PAGE
;
1687 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1689 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1691 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1692 if (Error
!= NOT_AN_ERROR
)
1694 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1695 return SELECT_PARTITION_PAGE
;
1698 return CREATE_PRIMARY_PARTITION_PAGE
;
1701 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1703 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1705 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1706 if (Error
!= NOT_AN_ERROR
)
1708 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1709 return SELECT_PARTITION_PAGE
;
1712 return CREATE_EXTENDED_PARTITION_PAGE
;
1715 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1717 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1719 Error
= LogicalPartitionCreationChecks(PartitionList
);
1720 if (Error
!= NOT_AN_ERROR
)
1722 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1723 return SELECT_PARTITION_PAGE
;
1726 return CREATE_LOGICAL_PARTITION_PAGE
;
1729 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1731 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1733 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1734 return SELECT_PARTITION_PAGE
;
1737 if (PartitionList
->CurrentPartition
->BootIndicator
||
1738 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1740 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1743 return DELETE_PARTITION_PAGE
;
1747 return SELECT_PARTITION_PAGE
;
1751 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1752 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1753 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1756 ShowPartitionSizeInputBox(SHORT Left
,
1780 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1785 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1786 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1789 WriteConsoleOutputCharacterA(StdOutput
,
1795 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1796 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1798 WriteConsoleOutputCharacterA(StdOutput
,
1804 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1805 Length
= wcslen(InputBuffer
);
1807 CONSOLE_SetInputTextXY(iLeft
,
1809 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1811 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1812 CONSOLE_SetCursorType(TRUE
, TRUE
);
1816 CONSOLE_ConInKey(&Ir
);
1818 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1819 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1824 InputBuffer
[0] = UNICODE_NULL
;
1825 CONSOLE_SetCursorType(TRUE
, FALSE
);
1828 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1830 CONSOLE_SetCursorType(TRUE
, FALSE
);
1833 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1838 InputBuffer
[0] = UNICODE_NULL
;
1839 CONSOLE_SetCursorType(TRUE
, FALSE
);
1842 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1843 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1846 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1848 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1849 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1852 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1854 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1855 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1860 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1863 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1864 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1869 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1872 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1873 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1877 memmove(&InputBuffer
[Pos
],
1878 &InputBuffer
[Pos
+ 1],
1879 (Length
- Pos
- 1) * sizeof(WCHAR
));
1880 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1883 CONSOLE_SetInputTextXY(iLeft
,
1885 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1887 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1890 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1895 memmove(&InputBuffer
[Pos
- 1],
1897 (Length
- Pos
) * sizeof(WCHAR
));
1898 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1902 CONSOLE_SetInputTextXY(iLeft
,
1904 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1906 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1909 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1911 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1913 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1915 if ((ch
>= L
'0') && (ch
<= L
'9'))
1918 memmove(&InputBuffer
[Pos
+ 1],
1920 (Length
- Pos
) * sizeof(WCHAR
));
1921 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1922 InputBuffer
[Pos
] = ch
;
1926 CONSOLE_SetInputTextXY(iLeft
,
1928 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1930 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1939 * Displays the CreatePrimaryPartitionPage.
1942 * SelectPartitionPage
1943 * SelectFileSystemPage (default)
1947 * Number of the next page.
1950 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1952 PDISKENTRY DiskEntry
;
1953 PPARTENTRY PartEntry
;
1956 WCHAR InputBuffer
[50];
1960 ULONGLONG SectorCount
;
1963 if (PartitionList
== NULL
||
1964 PartitionList
->CurrentDisk
== NULL
||
1965 PartitionList
->CurrentPartition
== NULL
)
1967 /* FIXME: show an error dialog */
1971 DiskEntry
= PartitionList
->CurrentDisk
;
1972 PartEntry
= PartitionList
->CurrentPartition
;
1974 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1976 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1978 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1980 if (DiskSize
>= 10737418240) /* 10 GB */
1982 DiskSize
= DiskSize
/ 1073741824;
1983 Unit
= MUIGetString(STRING_GB
);
1988 DiskSize
= DiskSize
/ 1048576;
1992 Unit
= MUIGetString(STRING_MB
);
1995 if (DiskEntry
->DriverName
.Length
> 0)
1997 CONSOLE_PrintTextXY(6, 10,
1998 MUIGetString(STRING_HDINFOPARTCREATE
),
2001 DiskEntry
->DiskNumber
,
2005 &DiskEntry
->DriverName
);
2009 CONSOLE_PrintTextXY(6, 10,
2010 MUIGetString(STRING_HDDINFOUNK1
),
2013 DiskEntry
->DiskNumber
,
2019 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2022 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2023 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2026 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2028 PartEntry
= PartitionList
->CurrentPartition
;
2031 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2033 if (MaxSize
> PARTITION_MAXSIZE
)
2034 MaxSize
= PARTITION_MAXSIZE
;
2036 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2037 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2041 if (ConfirmQuit(Ir
) != FALSE
)
2046 else if (Cancel
!= FALSE
)
2048 return SELECT_PARTITION_PAGE
;
2052 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2060 if (PartSize
> MaxSize
)
2066 /* Convert to bytes */
2067 if (PartSize
== MaxSize
)
2069 /* Use all of the unpartitioned disk space */
2070 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2074 /* Calculate the sector count from the size in MB */
2075 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2077 /* But never get larger than the unpartitioned disk space */
2078 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2079 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2082 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2084 CreatePrimaryPartition(PartitionList
,
2088 return SELECT_PARTITION_PAGE
;
2092 return CREATE_PRIMARY_PARTITION_PAGE
;
2097 * Displays the CreateExtendedPartitionPage.
2100 * SelectPartitionPage (default)
2104 * Number of the next page.
2107 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2109 PDISKENTRY DiskEntry
;
2110 PPARTENTRY PartEntry
;
2113 WCHAR InputBuffer
[50];
2117 ULONGLONG SectorCount
;
2120 if (PartitionList
== NULL
||
2121 PartitionList
->CurrentDisk
== NULL
||
2122 PartitionList
->CurrentPartition
== NULL
)
2124 /* FIXME: show an error dialog */
2128 DiskEntry
= PartitionList
->CurrentDisk
;
2129 PartEntry
= PartitionList
->CurrentPartition
;
2131 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2133 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2135 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2137 if (DiskSize
>= 10737418240) /* 10 GB */
2139 DiskSize
= DiskSize
/ 1073741824;
2140 Unit
= MUIGetString(STRING_GB
);
2145 DiskSize
= DiskSize
/ 1048576;
2149 Unit
= MUIGetString(STRING_MB
);
2152 if (DiskEntry
->DriverName
.Length
> 0)
2154 CONSOLE_PrintTextXY(6, 10,
2155 MUIGetString(STRING_HDINFOPARTCREATE
),
2158 DiskEntry
->DiskNumber
,
2162 &DiskEntry
->DriverName
);
2166 CONSOLE_PrintTextXY(6, 10,
2167 MUIGetString(STRING_HDDINFOUNK1
),
2170 DiskEntry
->DiskNumber
,
2176 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2179 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2180 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2183 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2185 PartEntry
= PartitionList
->CurrentPartition
;
2188 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2190 if (MaxSize
> PARTITION_MAXSIZE
)
2191 MaxSize
= PARTITION_MAXSIZE
;
2193 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2194 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2198 if (ConfirmQuit(Ir
) != FALSE
)
2203 else if (Cancel
!= FALSE
)
2205 return SELECT_PARTITION_PAGE
;
2209 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2217 if (PartSize
> MaxSize
)
2223 /* Convert to bytes */
2224 if (PartSize
== MaxSize
)
2226 /* Use all of the unpartitioned disk space */
2227 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2231 /* Calculate the sector count from the size in MB */
2232 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2234 /* But never get larger than the unpartitioned disk space */
2235 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2236 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2239 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2241 CreateExtendedPartition(PartitionList
,
2244 return SELECT_PARTITION_PAGE
;
2248 return CREATE_EXTENDED_PARTITION_PAGE
;
2253 * Displays the CreateLogicalPartitionPage.
2256 * SelectFileSystemPage (default)
2260 * Number of the next page.
2263 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2265 PDISKENTRY DiskEntry
;
2266 PPARTENTRY PartEntry
;
2269 WCHAR InputBuffer
[50];
2273 ULONGLONG SectorCount
;
2276 if (PartitionList
== NULL
||
2277 PartitionList
->CurrentDisk
== NULL
||
2278 PartitionList
->CurrentPartition
== NULL
)
2280 /* FIXME: show an error dialog */
2284 DiskEntry
= PartitionList
->CurrentDisk
;
2285 PartEntry
= PartitionList
->CurrentPartition
;
2287 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2289 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2291 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2293 if (DiskSize
>= 10737418240) /* 10 GB */
2295 DiskSize
= DiskSize
/ 1073741824;
2296 Unit
= MUIGetString(STRING_GB
);
2301 DiskSize
= DiskSize
/ 1048576;
2305 Unit
= MUIGetString(STRING_MB
);
2308 if (DiskEntry
->DriverName
.Length
> 0)
2310 CONSOLE_PrintTextXY(6, 10,
2311 MUIGetString(STRING_HDINFOPARTCREATE
),
2314 DiskEntry
->DiskNumber
,
2318 &DiskEntry
->DriverName
);
2322 CONSOLE_PrintTextXY(6, 10,
2323 MUIGetString(STRING_HDDINFOUNK1
),
2326 DiskEntry
->DiskNumber
,
2332 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2335 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2336 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2339 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2341 PartEntry
= PartitionList
->CurrentPartition
;
2344 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2346 if (MaxSize
> PARTITION_MAXSIZE
)
2347 MaxSize
= PARTITION_MAXSIZE
;
2349 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2350 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2354 if (ConfirmQuit(Ir
) != FALSE
)
2359 else if (Cancel
!= FALSE
)
2361 return SELECT_PARTITION_PAGE
;
2365 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2373 if (PartSize
> MaxSize
)
2379 /* Convert to bytes */
2380 if (PartSize
== MaxSize
)
2382 /* Use all of the unpartitioned disk space */
2383 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2387 /* Calculate the sector count from the size in MB */
2388 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2390 /* But never get larger than the unpartitioned disk space */
2391 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2392 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2395 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2397 CreateLogicalPartition(PartitionList
,
2401 return SELECT_PARTITION_PAGE
;
2405 return CREATE_LOGICAL_PARTITION_PAGE
;
2410 * Displays the ConfirmDeleteSystemPartitionPage.
2413 * DeletePartitionPage (default)
2414 * SelectPartitionPage
2417 * Number of the next page.
2420 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2422 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2426 CONSOLE_ConInKey(Ir
);
2428 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2429 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2431 if (ConfirmQuit(Ir
) == TRUE
)
2436 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2438 return DELETE_PARTITION_PAGE
;
2440 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2442 return SELECT_PARTITION_PAGE
;
2446 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2451 * Displays the DeletePartitionPage.
2454 * SelectPartitionPage (default)
2458 * Number of the next page.
2461 DeletePartitionPage(PINPUT_RECORD Ir
)
2463 PDISKENTRY DiskEntry
;
2464 PPARTENTRY PartEntry
;
2468 CHAR PartTypeString
[32];
2470 if (PartitionList
== NULL
||
2471 PartitionList
->CurrentDisk
== NULL
||
2472 PartitionList
->CurrentPartition
== NULL
)
2474 /* FIXME: show an error dialog */
2478 DiskEntry
= PartitionList
->CurrentDisk
;
2479 PartEntry
= PartitionList
->CurrentPartition
;
2481 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2483 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2485 ARRAYSIZE(PartTypeString
));
2487 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2489 if (PartSize
>= 10737418240) /* 10 GB */
2491 PartSize
= PartSize
/ 1073741824;
2492 Unit
= MUIGetString(STRING_GB
);
2496 if (PartSize
>= 10485760) /* 10 MB */
2498 PartSize
= PartSize
/ 1048576;
2499 Unit
= MUIGetString(STRING_MB
);
2503 PartSize
= PartSize
/ 1024;
2504 Unit
= MUIGetString(STRING_KB
);
2507 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2509 CONSOLE_PrintTextXY(6, 10,
2510 MUIGetString(STRING_HDDINFOUNK2
),
2511 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2512 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2513 PartEntry
->PartitionType
,
2519 CONSOLE_PrintTextXY(6, 10,
2520 " %c%c %s %I64u %s",
2521 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2522 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2528 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2530 if (DiskSize
>= 10737418240) /* 10 GB */
2532 DiskSize
= DiskSize
/ 1073741824;
2533 Unit
= MUIGetString(STRING_GB
);
2538 DiskSize
= DiskSize
/ 1048576;
2542 Unit
= MUIGetString(STRING_MB
);
2545 if (DiskEntry
->DriverName
.Length
> 0)
2547 CONSOLE_PrintTextXY(6, 12,
2548 MUIGetString(STRING_HDINFOPARTDELETE
),
2551 DiskEntry
->DiskNumber
,
2555 &DiskEntry
->DriverName
);
2559 CONSOLE_PrintTextXY(6, 12,
2560 MUIGetString(STRING_HDDINFOUNK3
),
2563 DiskEntry
->DiskNumber
,
2571 CONSOLE_ConInKey(Ir
);
2573 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2574 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2576 if (ConfirmQuit(Ir
) != FALSE
)
2581 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2583 return SELECT_PARTITION_PAGE
;
2585 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2587 DeleteCurrentPartition(PartitionList
);
2589 return SELECT_PARTITION_PAGE
;
2593 return DELETE_PARTITION_PAGE
;
2598 * Displays the SelectFileSystemPage.
2601 * CheckFileSystemPage (At once if RepairUpdate is selected)
2602 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2603 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2604 * SelectPartitionPage (If the user aborts)
2605 * FormatPartitionPage (Default)
2609 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2610 * Calls CheckActiveSystemPartition()
2613 * Number of the next page.
2616 SelectFileSystemPage(PINPUT_RECORD Ir
)
2618 PDISKENTRY DiskEntry
;
2619 PPARTENTRY PartEntry
;
2624 CHAR PartTypeString
[32];
2625 FORMATMACHINESTATE PreviousFormatState
;
2627 DPRINT("SelectFileSystemPage()\n");
2629 if (PartitionList
== NULL
||
2630 PartitionList
->CurrentDisk
== NULL
||
2631 PartitionList
->CurrentPartition
== NULL
)
2633 /* FIXME: show an error dialog */
2637 /* Find or set the active system partition */
2638 CheckActiveSystemPartition(PartitionList
);
2639 if (PartitionList
->SystemPartition
== NULL
)
2641 /* FIXME: show an error dialog */
2645 PreviousFormatState
= FormatState
;
2646 switch (FormatState
)
2650 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2652 TempPartition
= PartitionList
->SystemPartition
;
2653 TempPartition
->NeedsCheck
= TRUE
;
2655 FormatState
= FormatSystemPartition
;
2656 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2660 TempPartition
= PartitionList
->CurrentPartition
;
2661 TempPartition
->NeedsCheck
= TRUE
;
2663 FormatState
= FormatInstallPartition
;
2664 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2669 case FormatSystemPartition
:
2671 TempPartition
= PartitionList
->CurrentPartition
;
2672 TempPartition
->NeedsCheck
= TRUE
;
2674 FormatState
= FormatInstallPartition
;
2675 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2679 case FormatInstallPartition
:
2681 if (GetNextUnformattedPartition(PartitionList
,
2685 FormatState
= FormatOtherPartition
;
2686 TempPartition
->NeedsCheck
= TRUE
;
2687 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2691 FormatState
= FormatDone
;
2692 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2693 return CHECK_FILE_SYSTEM_PAGE
;
2698 case FormatOtherPartition
:
2700 if (GetNextUnformattedPartition(PartitionList
,
2704 FormatState
= FormatOtherPartition
;
2705 TempPartition
->NeedsCheck
= TRUE
;
2706 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2710 FormatState
= FormatDone
;
2711 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2712 return CHECK_FILE_SYSTEM_PAGE
;
2719 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2720 /* FIXME: show an error dialog */
2725 PartEntry
= TempPartition
;
2726 DiskEntry
= PartEntry
->DiskEntry
;
2728 /* Adjust disk size */
2729 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2730 if (DiskSize
>= 10737418240) /* 10 GB */
2732 DiskSize
= DiskSize
/ 1073741824;
2733 DiskUnit
= MUIGetString(STRING_GB
);
2737 DiskSize
= DiskSize
/ 1048576;
2738 DiskUnit
= MUIGetString(STRING_MB
);
2741 /* Adjust partition size */
2742 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2743 if (PartSize
>= 10737418240) /* 10 GB */
2745 PartSize
= PartSize
/ 1073741824;
2746 PartUnit
= MUIGetString(STRING_GB
);
2750 PartSize
= PartSize
/ 1048576;
2751 PartUnit
= MUIGetString(STRING_MB
);
2754 /* Adjust partition type */
2755 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2757 ARRAYSIZE(PartTypeString
));
2759 if (PartEntry
->AutoCreate
!= FALSE
)
2761 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2764 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2765 PartEntry
->PartitionNumber
,
2771 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED
),
2772 DiskEntry
->DiskNumber
,
2778 &DiskEntry
->DriverName
);
2780 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2782 PartEntry
->AutoCreate
= FALSE
;
2784 else if (PartEntry
->New
!= FALSE
)
2786 switch (FormatState
)
2788 case FormatSystemPartition
:
2789 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2792 case FormatInstallPartition
:
2793 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2796 case FormatOtherPartition
:
2797 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2804 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2808 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2810 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2812 CONSOLE_PrintTextXY(8, 10,
2813 MUIGetString(STRING_HDDINFOUNK4
),
2814 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2815 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2816 PartEntry
->PartitionType
,
2822 CONSOLE_PrintTextXY(8, 10,
2824 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2825 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2831 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS
),
2832 DiskEntry
->DiskNumber
,
2838 &DiskEntry
->DriverName
);
2841 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2843 if (FileSystemList
== NULL
)
2845 /* Create the file system list, and by default select the "FAT" file system */
2846 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2847 if (FileSystemList
== NULL
)
2849 /* FIXME: show an error dialog */
2854 DrawFileSystemList(FileSystemList
);
2856 if (RepairUpdateFlag
)
2858 return CHECK_FILE_SYSTEM_PAGE
;
2859 //return SELECT_PARTITION_PAGE;
2862 if (IsUnattendedSetup
)
2864 if (UnattendFormatPartition
)
2867 * We use whatever currently selected file system we have
2868 * (by default, this is "FAT", as per the initialization
2869 * performed above). Note that it may be interesting to specify
2870 * which file system to use in unattended installations, in the
2871 * txtsetup.sif file.
2873 return FORMAT_PARTITION_PAGE
;
2876 return CHECK_FILE_SYSTEM_PAGE
;
2881 CONSOLE_ConInKey(Ir
);
2883 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2884 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2886 if (ConfirmQuit(Ir
) != FALSE
)
2891 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2892 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2894 FormatState
= Start
;
2895 return SELECT_PARTITION_PAGE
;
2897 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2898 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2900 ScrollDownFileSystemList(FileSystemList
);
2902 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2903 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2905 ScrollUpFileSystemList(FileSystemList
);
2907 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2909 if (!FileSystemList
->Selected
->FileSystem
)
2910 return SELECT_FILE_SYSTEM_PAGE
;
2912 return FORMAT_PARTITION_PAGE
;
2916 FormatState
= PreviousFormatState
;
2918 return SELECT_FILE_SYSTEM_PAGE
;
2923 * Displays the FormatPartitionPage.
2926 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2927 * SelectPartitionPage (At once)
2931 * Sets PartitionList->CurrentPartition->FormatState
2932 * Sets DestinationRootPath
2935 * Number of the next page.
2938 FormatPartitionPage(PINPUT_RECORD Ir
)
2940 UNICODE_STRING PartitionRootPath
;
2941 WCHAR PathBuffer
[MAX_PATH
];
2942 PDISKENTRY DiskEntry
;
2943 PPARTENTRY PartEntry
;
2944 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2950 PPARTITION_INFORMATION PartitionInfo
;
2953 DPRINT("FormatPartitionPage()\n");
2955 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2957 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2959 /* FIXME: show an error dialog */
2963 PartEntry
= TempPartition
;
2964 DiskEntry
= PartEntry
->DiskEntry
;
2966 SelectedFileSystem
= FileSystemList
->Selected
;
2970 if (!IsUnattendedSetup
)
2972 CONSOLE_ConInKey(Ir
);
2975 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2976 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2978 if (ConfirmQuit(Ir
) != FALSE
)
2983 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2985 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2987 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2989 /* FIXME: show an error dialog */
2994 CONSOLE_PrintTextXY(6, 12,
2995 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
2996 DiskEntry
->Cylinders
,
2997 DiskEntry
->TracksPerCylinder
,
2998 DiskEntry
->SectorsPerTrack
,
2999 DiskEntry
->BytesPerSector
,
3000 DiskEntry
->Dirty
? '*' : ' ');
3004 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3006 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3008 CONSOLE_PrintTextXY(6, Line
,
3009 "%2u: %2lu %c %12I64u %12I64u %02x",
3011 PartitionInfo
->PartitionNumber
,
3012 PartitionInfo
->BootIndicator
? 'A' : '-',
3013 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3014 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3015 PartitionInfo
->PartitionType
);
3020 /* Commit the partition changes to the disk */
3021 if (!WritePartitionsToDisk(PartitionList
))
3023 DPRINT("WritePartitionsToDisk() failed\n");
3024 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3028 /* Set PartitionRootPath */
3029 swprintf(PathBuffer
,
3030 L
"\\Device\\Harddisk%lu\\Partition%lu",
3031 DiskEntry
->DiskNumber
,
3032 PartEntry
->PartitionNumber
);
3033 RtlInitUnicodeString(&PartitionRootPath
,
3035 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3037 /* Format the partition */
3038 if (SelectedFileSystem
->FileSystem
)
3040 Status
= FormatPartition(&PartitionRootPath
,
3041 SelectedFileSystem
);
3042 if (!NT_SUCCESS(Status
))
3044 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3045 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3049 PartEntry
->FormatState
= Formatted
;
3050 // PartEntry->FileSystem = FileSystem;
3051 PartEntry
->New
= FALSE
;
3055 CONSOLE_SetStatusText(" Done. Press any key ...");
3056 CONSOLE_ConInKey(Ir
);
3059 return SELECT_FILE_SYSTEM_PAGE
;
3063 return FORMAT_PARTITION_PAGE
;
3068 * Displays the CheckFileSystemPage.
3071 * InstallDirectoryPage (At once)
3075 * Inits or reloads FileSystemList
3078 * Number of the next page.
3081 CheckFileSystemPage(PINPUT_RECORD Ir
)
3083 PFILE_SYSTEM CurrentFileSystem
;
3084 UNICODE_STRING PartitionRootPath
;
3085 WCHAR PathBuffer
[MAX_PATH
];
3086 CHAR Buffer
[MAX_PATH
];
3087 PDISKENTRY DiskEntry
;
3088 PPARTENTRY PartEntry
;
3091 if (PartitionList
== NULL
)
3093 /* FIXME: show an error dialog */
3097 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3099 return INSTALL_DIRECTORY_PAGE
;
3102 /* Set PartitionRootPath */
3103 swprintf(PathBuffer
,
3104 L
"\\Device\\Harddisk%lu\\Partition%lu",
3105 DiskEntry
->DiskNumber
,
3106 PartEntry
->PartitionNumber
);
3107 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3108 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3110 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3112 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3114 CurrentFileSystem
= PartEntry
->FileSystem
;
3115 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3116 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3118 /* HACK: Do not try to check a partition with an unknown filesystem */
3119 if (CurrentFileSystem
== NULL
)
3121 PartEntry
->NeedsCheck
= FALSE
;
3122 return CHECK_FILE_SYSTEM_PAGE
;
3125 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3128 "Setup is currently unable to check a partition formatted in %S.\n"
3130 " \x07 Press ENTER to continue Setup.\n"
3131 " \x07 Press F3 to quit Setup.",
3132 CurrentFileSystem
->FileSystemName
);
3135 MUIGetString(STRING_QUITCONTINUE
),
3136 NULL
, POPUP_WAIT_NONE
);
3140 CONSOLE_ConInKey(Ir
);
3142 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3143 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3145 if (ConfirmQuit(Ir
))
3148 return CHECK_FILE_SYSTEM_PAGE
;
3150 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3152 PartEntry
->NeedsCheck
= FALSE
;
3153 return CHECK_FILE_SYSTEM_PAGE
;
3159 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3160 if (!NT_SUCCESS(Status
))
3162 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3163 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3164 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3165 "(Status 0x%08lx).\n", Status
);
3167 // MUIGetString(STRING_REBOOTCOMPUTER),
3168 MUIGetString(STRING_CONTINUE
),
3169 Ir
, POPUP_WAIT_ENTER
);
3171 // return QUIT_PAGE;
3174 PartEntry
->NeedsCheck
= FALSE
;
3175 return CHECK_FILE_SYSTEM_PAGE
;
3182 BuildInstallPaths(PWCHAR InstallDir
,
3183 PDISKENTRY DiskEntry
,
3184 PPARTENTRY PartEntry
)
3186 WCHAR PathBuffer
[MAX_PATH
];
3188 /* Create 'InstallPath' string */
3189 RtlFreeUnicodeString(&InstallPath
);
3190 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3192 /* Create 'DestinationRootPath' string */
3193 RtlFreeUnicodeString(&DestinationRootPath
);
3194 swprintf(PathBuffer
,
3195 L
"\\Device\\Harddisk%lu\\Partition%lu",
3196 DiskEntry
->DiskNumber
,
3197 PartEntry
->PartitionNumber
);
3198 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3199 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3201 /* Create 'DestinationPath' string */
3202 RtlFreeUnicodeString(&DestinationPath
);
3203 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 2,
3204 DestinationRootPath
.Buffer
, InstallDir
);
3205 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3207 /* Create 'DestinationArcPath' */
3208 RtlFreeUnicodeString(&DestinationArcPath
);
3209 swprintf(PathBuffer
,
3210 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3211 DiskEntry
->BiosDiskNumber
,
3212 PartEntry
->PartitionNumber
);
3213 ConcatPaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 1, InstallDir
);
3214 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3219 * Displays the InstallDirectoryPage.
3222 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3226 * Number of the next page.
3229 InstallDirectoryPage(PINPUT_RECORD Ir
)
3231 PDISKENTRY DiskEntry
;
3232 PPARTENTRY PartEntry
;
3233 WCHAR InstallDir
[51];
3237 /* We do not need the filesystem list any more */
3238 if (FileSystemList
!= NULL
)
3240 DestroyFileSystemList(FileSystemList
);
3241 FileSystemList
= NULL
;
3244 if (PartitionList
== NULL
||
3245 PartitionList
->CurrentDisk
== NULL
||
3246 PartitionList
->CurrentPartition
== NULL
)
3248 /* FIXME: show an error dialog */
3252 DiskEntry
= PartitionList
->CurrentDisk
;
3253 PartEntry
= PartitionList
->CurrentPartition
;
3255 if (IsUnattendedSetup
)
3257 if (!IsValidPath(UnattendInstallationDirectory
))
3259 /* FIXME: Log the error? */
3263 BuildInstallPaths(UnattendInstallationDirectory
,
3267 return PREPARE_COPY_PAGE
;
3270 wcscpy(InstallDir
, L
"\\ReactOS");
3272 Length
= wcslen(InstallDir
);
3274 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3275 CONSOLE_SetCursorXY(8 + Pos
, 11);
3276 CONSOLE_SetCursorType(TRUE
, TRUE
);
3277 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3281 CONSOLE_ConInKey(Ir
);
3283 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3284 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3286 CONSOLE_SetCursorType(TRUE
, FALSE
);
3288 if (ConfirmQuit(Ir
) != FALSE
)
3291 CONSOLE_SetCursorType(TRUE
, TRUE
);
3294 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3295 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3299 memmove(&InstallDir
[Pos
],
3300 &InstallDir
[Pos
+ 1],
3301 (Length
- Pos
- 1) * sizeof(WCHAR
));
3302 InstallDir
[Length
- 1] = UNICODE_NULL
;
3305 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3306 CONSOLE_SetCursorXY(8 + Pos
, 11);
3309 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3310 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3313 CONSOLE_SetCursorXY(8 + Pos
, 11);
3315 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3316 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3319 CONSOLE_SetCursorXY(8 + Pos
, 11);
3321 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3322 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3327 CONSOLE_SetCursorXY(8 + Pos
, 11);
3330 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3331 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3336 CONSOLE_SetCursorXY(8 + Pos
, 11);
3339 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3341 CONSOLE_SetCursorType(TRUE
, FALSE
);
3344 * Check for the validity of the installation directory and pop up
3345 * an error if it is not the case. Then the user can fix its input.
3347 if (!IsValidPath(InstallDir
))
3349 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3350 return INSTALL_DIRECTORY_PAGE
;
3353 BuildInstallPaths(InstallDir
,
3357 return PREPARE_COPY_PAGE
;
3359 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3364 memmove(&InstallDir
[Pos
- 1],
3366 (Length
- Pos
) * sizeof(WCHAR
));
3367 InstallDir
[Length
- 1] = UNICODE_NULL
;
3371 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3372 CONSOLE_SetCursorXY(8 + Pos
, 11);
3375 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3379 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3380 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3383 memmove(&InstallDir
[Pos
+ 1],
3385 (Length
- Pos
) * sizeof(WCHAR
));
3386 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3387 InstallDir
[Pos
] = c
;
3391 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3392 CONSOLE_SetCursorXY(8 + Pos
, 11);
3398 return INSTALL_DIRECTORY_PAGE
;
3403 AddSectionToCopyQueueCab(HINF InfFile
,
3405 PWCHAR SourceCabinet
,
3406 PCUNICODE_STRING DestinationPath
,
3409 INFCONTEXT FilesContext
;