3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
43 /* GLOBALS ******************************************************************/
46 UNICODE_STRING SourceRootPath
;
47 UNICODE_STRING SourceRootDir
;
48 UNICODE_STRING SourcePath
;
49 BOOLEAN IsUnattendedSetup
= FALSE
;
50 LONG UnattendDestinationDiskNumber
;
51 LONG UnattendDestinationPartitionNumber
;
52 LONG UnattendMBRInstallType
= -1;
53 LONG UnattendFormatPartition
= 0;
54 LONG AutoPartition
= 0;
55 WCHAR UnattendInstallationDirectory
[MAX_PATH
];
56 PWCHAR SelectedLanguageId
;
58 WCHAR DefaultLanguage
[20];
59 WCHAR DefaultKBLayout
[20];
60 BOOLEAN RepairUpdateFlag
= FALSE
;
61 HANDLE hPnpThread
= INVALID_HANDLE_VALUE
;
63 PPARTLIST PartitionList
= NULL
;
64 PPARTENTRY TempPartition
= NULL
;
65 FORMATMACHINESTATE FormatState
= Start
;
68 /* LOCALS *******************************************************************/
70 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
72 static UNICODE_STRING InstallPath
;
75 * Path to the system partition, where the boot manager resides.
76 * On x86 PCs, this is usually the active partition.
77 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
79 * For more information, see:
80 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
81 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
82 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
83 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
84 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
85 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
87 static UNICODE_STRING SystemRootPath
;
89 /* Path to the install directory inside the ReactOS boot partition */
90 static UNICODE_STRING DestinationPath
;
91 static UNICODE_STRING DestinationArcPath
;
92 static UNICODE_STRING DestinationRootPath
;
94 static WCHAR DestinationDriveLetter
; // FIXME: Is it really useful??
98 static HSPFILEQ SetupFileQueue
= NULL
;
100 static PGENERIC_LIST ComputerList
= NULL
;
101 static PGENERIC_LIST DisplayList
= NULL
;
102 static PGENERIC_LIST KeyboardList
= NULL
;
103 static PGENERIC_LIST LayoutList
= NULL
;
104 static PGENERIC_LIST LanguageList
= NULL
;
106 static LANGID LanguageId
= 0;
108 static ULONG RequiredPartitionDiskSpace
= ~0;
110 /* FUNCTIONS ****************************************************************/
113 PrintString(char* fmt
,...)
117 UNICODE_STRING UnicodeString
;
118 ANSI_STRING AnsiString
;
121 vsprintf(buffer
, fmt
, ap
);
124 RtlInitAnsiString(&AnsiString
, buffer
);
125 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
126 NtDisplayString(&UnicodeString
);
127 RtlFreeUnicodeString(&UnicodeString
);
132 DrawBox(IN SHORT xLeft
,
140 /* draw upper left corner */
143 FillConsoleOutputCharacterA(StdOutput
,
149 /* draw upper edge */
152 FillConsoleOutputCharacterA(StdOutput
,
158 /* draw upper right corner */
159 coPos
.X
= xLeft
+ Width
- 1;
161 FillConsoleOutputCharacterA(StdOutput
,
167 /* Draw right edge, inner space and left edge */
168 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
171 FillConsoleOutputCharacterA(StdOutput
,
178 FillConsoleOutputCharacterA(StdOutput
,
184 coPos
.X
= xLeft
+ Width
- 1;
185 FillConsoleOutputCharacterA(StdOutput
,
192 /* draw lower left corner */
194 coPos
.Y
= yTop
+ Height
- 1;
195 FillConsoleOutputCharacterA(StdOutput
,
201 /* draw lower edge */
203 coPos
.Y
= yTop
+ Height
- 1;
204 FillConsoleOutputCharacterA(StdOutput
,
210 /* draw lower right corner */
211 coPos
.X
= xLeft
+ Width
- 1;
212 coPos
.Y
= yTop
+ Height
- 1;
213 FillConsoleOutputCharacterA(StdOutput
,
222 PopupError(PCCH Text
,
240 /* Count text lines and longest line */
247 p
= strchr(pnext
, '\n');
251 Length
= strlen(pnext
);
256 Length
= (ULONG
)(p
- pnext
);
262 if (Length
> MaxLength
)
265 if (LastLine
!= FALSE
)
271 /* Check length of status line */
274 Length
= strlen(Status
);
276 if (Length
> MaxLength
)
280 Width
= MaxLength
+ 4;
286 yTop
= (yScreen
- Height
) / 2;
287 xLeft
= (xScreen
- Width
) / 2;
290 /* Set screen attributes */
292 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
294 FillConsoleOutputAttribute(StdOutput
,
295 FOREGROUND_RED
| BACKGROUND_WHITE
,
301 DrawBox(xLeft
, yTop
, Width
, Height
);
303 /* Print message text */
308 p
= strchr(pnext
, '\n');
312 Length
= strlen(pnext
);
317 Length
= (ULONG
)(p
- pnext
);
324 WriteConsoleOutputCharacterA(StdOutput
,
331 if (LastLine
!= FALSE
)
338 /* Print separator line and status text */
341 coPos
.Y
= yTop
+ Height
- 3;
343 FillConsoleOutputCharacterA(StdOutput
,
350 FillConsoleOutputCharacterA(StdOutput
,
356 coPos
.X
= xLeft
+ Width
- 1;
357 FillConsoleOutputCharacterA(StdOutput
,
365 WriteConsoleOutputCharacterA(StdOutput
,
367 min(strlen(Status
), (SIZE_T
)Width
- 4),
372 if (WaitEvent
== POPUP_WAIT_NONE
)
377 CONSOLE_ConInKey(Ir
);
379 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
380 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
392 * FALSE: Don't quit setup.
395 ConfirmQuit(PINPUT_RECORD Ir
)
398 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
402 CONSOLE_ConInKey(Ir
);
404 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
405 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
410 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
422 CheckUnattendedSetup(VOID
)
424 WCHAR UnattendInfPath
[MAX_PATH
];
431 if (DoesFileExist(NULL
, SourcePath
.Buffer
, L
"unattend.inf") == FALSE
)
433 DPRINT("Does not exist: %S\\%S\n", SourcePath
.Buffer
, L
"unattend.inf");
437 wcscpy(UnattendInfPath
, SourcePath
.Buffer
);
438 wcscat(UnattendInfPath
, L
"\\unattend.inf");
440 /* Load 'unattend.inf' from install media. */
441 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
447 if (UnattendInf
== INVALID_HANDLE_VALUE
)
449 DPRINT("SetupOpenInfFileW() failed\n");
453 /* Open 'Unattend' section */
454 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
456 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
457 SetupCloseInfFile(UnattendInf
);
461 /* Get pointer 'Signature' key */
462 if (!INF_GetData(&Context
, NULL
, &Value
))
464 DPRINT("INF_GetData() failed for key 'Signature'\n");
465 SetupCloseInfFile(UnattendInf
);
469 /* Check 'Signature' string */
470 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
472 DPRINT("Signature not $ReactOS$\n");
473 SetupCloseInfFile(UnattendInf
);
477 /* Check if Unattend setup is enabled */
478 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
480 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
481 SetupCloseInfFile(UnattendInf
);
485 if (!INF_GetData(&Context
, NULL
, &Value
))
487 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
488 SetupCloseInfFile(UnattendInf
);
492 if (_wcsicmp(Value
, L
"yes") != 0)
494 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
495 SetupCloseInfFile(UnattendInf
);
499 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
500 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
502 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
503 SetupCloseInfFile(UnattendInf
);
507 if (!SetupGetIntField(&Context
, 1, &IntValue
))
509 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
510 SetupCloseInfFile(UnattendInf
);
514 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
516 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
517 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
519 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
520 SetupCloseInfFile(UnattendInf
);
524 if (!SetupGetIntField(&Context
, 1, &IntValue
))
526 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
527 SetupCloseInfFile(UnattendInf
);
531 UnattendDestinationPartitionNumber
= IntValue
;
533 /* Search for 'InstallationDirectory' in the 'Unattend' section */
534 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
536 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
537 SetupCloseInfFile(UnattendInf
);
541 /* Get pointer 'InstallationDirectory' key */
542 if (!INF_GetData(&Context
, NULL
, &Value
))
544 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
545 SetupCloseInfFile(UnattendInf
);
549 wcscpy(UnattendInstallationDirectory
, Value
);
551 IsUnattendedSetup
= TRUE
;
553 /* Search for 'MBRInstallType' in the 'Unattend' section */
554 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
556 if (SetupGetIntField(&Context
, 1, &IntValue
))
558 UnattendMBRInstallType
= IntValue
;
562 /* Search for 'FormatPartition' in the 'Unattend' section */
563 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
565 if (SetupGetIntField(&Context
, 1, &IntValue
))
567 UnattendFormatPartition
= IntValue
;
571 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
573 if (SetupGetIntField(&Context
, 1, &IntValue
))
575 AutoPartition
= IntValue
;
579 /* search for LocaleID in the 'Unattend' section*/
580 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
582 if (INF_GetData(&Context
, NULL
, &Value
))
584 LONG Id
= wcstol(Value
, NULL
, 16);
585 swprintf(LocaleID
,L
"%08lx", Id
);
589 SetupCloseInfFile(UnattendInf
);
591 DPRINT("Running unattended setup\n");
598 PGENERIC_LIST_ENTRY ListEntry
;
599 LPCWSTR pszNewLayout
;
601 pszNewLayout
= MUIDefaultKeyboardLayout();
603 if (LayoutList
== NULL
)
605 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
606 if (LayoutList
== NULL
)
608 /* FIXME: Handle error! */
613 ListEntry
= GetFirstListEntry(LayoutList
);
615 /* Search for default layout (if provided) */
616 if (pszNewLayout
!= NULL
)
618 while (ListEntry
!= NULL
)
620 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
622 SetCurrentListEntry(LayoutList
, ListEntry
);
626 ListEntry
= GetNextListEntry(ListEntry
);
633 * Displays the LanguagePage.
635 * Next pages: IntroPage, QuitPage
638 * Init SelectedLanguageId
642 * Number of the next page.
645 LanguagePage(PINPUT_RECORD Ir
)
647 GENERIC_LIST_UI ListUi
;
648 PWCHAR NewLanguageId
;
649 BOOL RefreshPage
= FALSE
;
651 /* Initialize the computer settings list */
652 if (LanguageList
== NULL
)
654 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
655 if (LanguageList
== NULL
)
657 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
663 SelectedLanguageId
= DefaultLanguage
;
664 SetConsoleCodePage();
667 /* If there's just a single language in the list skip
668 * the language selection process altogether! */
669 if (GenericListHasSingleEntry(LanguageList
))
671 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
675 InitGenericListUi(&ListUi
, LanguageList
);
676 DrawGenericList(&ListUi
,
682 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
684 MUIDisplayPage(LANGUAGE_PAGE
);
688 CONSOLE_ConInKey(Ir
);
690 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
691 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
693 ScrollDownGenericList(&ListUi
);
696 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
697 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
699 ScrollUpGenericList(&ListUi
);
702 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
703 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
705 ScrollPageDownGenericList(&ListUi
);
708 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
709 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
711 ScrollPageUpGenericList(&ListUi
);
714 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
715 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
717 if (ConfirmQuit(Ir
) != FALSE
)
720 RedrawGenericList(&ListUi
);
722 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
724 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
726 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
728 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
734 SetConsoleCodePage();
738 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
741 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
747 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
749 if (SelectedLanguageId
!= NewLanguageId
)
751 /* Clear the language page */
752 MUIClearPage(LANGUAGE_PAGE
);
754 SelectedLanguageId
= NewLanguageId
;
757 SetConsoleCodePage();
759 /* Redraw language selection page in native language */
760 MUIDisplayPage(LANGUAGE_PAGE
);
775 * LanguagePage (at once, default)
776 * InstallIntroPage (at once, if unattended)
782 * Init SourceRootPath
785 * Init RequiredPartitionDiskSpace
786 * Init IsUnattendedSetup
787 * If unattended, init *List and sets the Codepage
788 * If unattended, init SelectedLanguageId
789 * If unattended, init LanguageId
792 * Number of the next page.
795 SetupStartPage(PINPUT_RECORD Ir
)
798 WCHAR FileNameBuffer
[MAX_PATH
];
802 PGENERIC_LIST_ENTRY ListEntry
;
805 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
807 /* Get the source path and source root path */
808 Status
= GetSourcePaths(&SourcePath
,
812 if (!NT_SUCCESS(Status
))
814 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
815 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
821 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
822 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
823 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir
);
827 /* Load txtsetup.sif from install media. */
828 wcscpy(FileNameBuffer
, SourcePath
.Buffer
);
829 wcscat(FileNameBuffer
, L
"\\txtsetup.sif");
831 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
837 if (SetupInf
== INVALID_HANDLE_VALUE
)
839 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
843 /* Open 'Version' section */
844 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
846 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
850 /* Get pointer 'Signature' key */
851 if (!INF_GetData(&Context
, NULL
, &Value
))
853 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
857 /* Check 'Signature' string */
858 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
860 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
864 /* Open 'DiskSpaceRequirements' section */
865 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
867 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
871 /* Get the 'FreeSysPartDiskSpace' value */
872 if (!SetupGetIntField(&Context
, 1, &IntValue
))
874 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
878 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
880 /* Start the PnP thread */
881 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
883 NtResumeThread(hPnpThread
, NULL
);
884 hPnpThread
= INVALID_HANDLE_VALUE
;
887 CheckUnattendedSetup();
889 if (IsUnattendedSetup
)
891 // TODO: Read options from inf
892 ComputerList
= CreateComputerTypeList(SetupInf
);
893 DisplayList
= CreateDisplayDriverList(SetupInf
);
894 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
895 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
896 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
899 wcscpy(SelectedLanguageId
, LocaleID
);
900 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
902 /* first we hack LanguageList */
903 ListEntry
= GetFirstListEntry(LanguageList
);
904 while (ListEntry
!= NULL
)
906 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
908 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
909 SetCurrentListEntry(LanguageList
, ListEntry
);
913 ListEntry
= GetNextListEntry(ListEntry
);
917 ListEntry
= GetFirstListEntry(LayoutList
);
918 while (ListEntry
!= NULL
)
920 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
922 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
923 SetCurrentListEntry(LayoutList
, ListEntry
);
927 ListEntry
= GetNextListEntry(ListEntry
);
930 SetConsoleCodePage();
932 return INSTALL_INTRO_PAGE
;
935 return LANGUAGE_PAGE
;
940 * Displays the IntroPage.
943 * InstallIntroPage (default)
949 * Number of the next page.
952 IntroPage(PINPUT_RECORD Ir
)
954 MUIDisplayPage(START_PAGE
);
958 CONSOLE_ConInKey(Ir
);
960 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
961 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
963 if (ConfirmQuit(Ir
) != FALSE
)
968 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
970 return INSTALL_INTRO_PAGE
;
972 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
974 return REPAIR_INTRO_PAGE
;
976 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
987 * Displays the License page.
990 * IntroPage (default)
993 * Number of the next page.
996 LicensePage(PINPUT_RECORD Ir
)
998 MUIDisplayPage(LICENSE_PAGE
);
1002 CONSOLE_ConInKey(Ir
);
1004 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1010 return LICENSE_PAGE
;
1015 * Displays the RepairIntroPage.
1018 * RebootPage (default)
1024 * Number of the next page.
1027 RepairIntroPage(PINPUT_RECORD Ir
)
1029 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1033 CONSOLE_ConInKey(Ir
);
1035 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1039 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1041 RepairUpdateFlag
= TRUE
;
1042 return INSTALL_INTRO_PAGE
;
1044 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1046 return RECOVERY_PAGE
;
1048 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1049 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1055 return REPAIR_INTRO_PAGE
;
1059 * Displays the InstallIntroPage.
1062 * DeviceSettingsPage (At once if repair or update is selected)
1063 * SelectPartitionPage (At once if unattended setup)
1064 * DeviceSettingsPage (default)
1068 * Number of the next page.
1071 InstallIntroPage(PINPUT_RECORD Ir
)
1073 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1075 if (RepairUpdateFlag
)
1077 //return SELECT_PARTITION_PAGE;
1078 return DEVICE_SETTINGS_PAGE
;
1081 if (IsUnattendedSetup
)
1083 return SELECT_PARTITION_PAGE
;
1088 CONSOLE_ConInKey(Ir
);
1090 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1091 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1093 if (ConfirmQuit(Ir
) != FALSE
)
1098 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1100 return DEVICE_SETTINGS_PAGE
;
1101 // return SCSI_CONTROLLER_PAGE;
1105 return INSTALL_INTRO_PAGE
;
1111 ScsiControllerPage(PINPUT_RECORD Ir
)
1113 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1115 /* FIXME: print loaded mass storage driver descriptions */
1117 SetTextXY(8, 10, "TEST device");
1121 SetStatusText(" ENTER = Continue F3 = Quit");
1127 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1128 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1130 if (ConfirmQuit(Ir
) != FALSE
)
1135 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1137 return DEVICE_SETTINGS_PAGE
;
1141 return SCSI_CONTROLLER_PAGE
;
1147 * Displays the DeviceSettingsPage.
1150 * SelectPartitionPage (At once if repair or update is selected)
1151 * ComputerSettingsPage
1152 * DisplaySettingsPage
1153 * KeyboardSettingsPage
1154 * LayoutsettingsPage
1155 * SelectPartitionPage
1165 * Number of the next page.
1168 DeviceSettingsPage(PINPUT_RECORD Ir
)
1170 static ULONG Line
= 16;
1171 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1173 /* Initialize the computer settings list */
1174 if (ComputerList
== NULL
)
1176 ComputerList
= CreateComputerTypeList(SetupInf
);
1177 if (ComputerList
== NULL
)
1179 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1184 /* Initialize the display settings list */
1185 if (DisplayList
== NULL
)
1187 DisplayList
= CreateDisplayDriverList(SetupInf
);
1188 if (DisplayList
== NULL
)
1190 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1195 /* Initialize the keyboard settings list */
1196 if (KeyboardList
== NULL
)
1198 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1199 if (KeyboardList
== NULL
)
1201 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1206 /* Initialize the keyboard layout list */
1207 if (LayoutList
== NULL
)
1209 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1210 if (LayoutList
== NULL
)
1212 /* FIXME: report error */
1213 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1218 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1221 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList
))));
1222 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList
))));
1223 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList
))));
1224 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList
))));
1226 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1228 if (RepairUpdateFlag
)
1230 return SELECT_PARTITION_PAGE
;
1235 CONSOLE_ConInKey(Ir
);
1237 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1238 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1240 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1244 else if (Line
== 16)
1249 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1251 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1252 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1254 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1258 else if (Line
== 16)
1263 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1265 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1266 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1268 if (ConfirmQuit(Ir
) != FALSE
)
1273 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1276 return COMPUTER_SETTINGS_PAGE
;
1277 else if (Line
== 12)
1278 return DISPLAY_SETTINGS_PAGE
;
1279 else if (Line
== 13)
1280 return KEYBOARD_SETTINGS_PAGE
;
1281 else if (Line
== 14)
1282 return LAYOUT_SETTINGS_PAGE
;
1283 else if (Line
== 16)
1284 return SELECT_PARTITION_PAGE
;
1288 return DEVICE_SETTINGS_PAGE
;
1293 * Handles generic selection lists.
1296 * GenericList: The list to handle.
1297 * nextPage: The page it needs to jump to after this page.
1298 * Ir: The PINPUT_RECORD
1301 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1302 PAGE_NUMBER nextPage
,
1307 CONSOLE_ConInKey(Ir
);
1309 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1310 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1312 ScrollDownGenericList(ListUi
);
1314 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1315 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1317 ScrollUpGenericList(ListUi
);
1319 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1320 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1322 ScrollPageDownGenericList(ListUi
);
1324 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1325 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1327 ScrollPageUpGenericList(ListUi
);
1329 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1330 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1332 if (ConfirmQuit(Ir
) != FALSE
)
1335 RedrawGenericList(ListUi
);
1337 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1338 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1340 RestoreGenericListState(ListUi
->List
);
1341 return nextPage
; // Use some "prevPage;" instead?
1343 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1347 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1350 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1357 * Displays the ComputerSettingsPage.
1360 * DeviceSettingsPage
1364 * Number of the next page.
1367 ComputerSettingsPage(PINPUT_RECORD Ir
)
1369 GENERIC_LIST_UI ListUi
;
1370 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1372 InitGenericListUi(&ListUi
, ComputerList
);
1373 DrawGenericList(&ListUi
,
1379 SaveGenericListState(ComputerList
);
1381 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1386 * Displays the DisplaySettingsPage.
1389 * DeviceSettingsPage
1393 * Number of the next page.
1396 DisplaySettingsPage(PINPUT_RECORD Ir
)
1398 GENERIC_LIST_UI ListUi
;
1399 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1401 InitGenericListUi(&ListUi
, DisplayList
);
1402 DrawGenericList(&ListUi
,
1408 SaveGenericListState(DisplayList
);
1410 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1415 * Displays the KeyboardSettingsPage.
1418 * DeviceSettingsPage
1422 * Number of the next page.
1425 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1427 GENERIC_LIST_UI ListUi
;
1428 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1430 InitGenericListUi(&ListUi
, KeyboardList
);
1431 DrawGenericList(&ListUi
,
1437 SaveGenericListState(KeyboardList
);
1439 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1444 * Displays the LayoutSettingsPage.
1447 * DeviceSettingsPage
1451 * Number of the next page.
1454 LayoutSettingsPage(PINPUT_RECORD Ir
)
1456 GENERIC_LIST_UI ListUi
;
1457 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1459 InitGenericListUi(&ListUi
, LayoutList
);
1460 DrawGenericList(&ListUi
,
1466 SaveGenericListState(LayoutList
);
1468 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1473 IsDiskSizeValid(PPARTENTRY PartEntry
)
1477 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1478 size
= (size
+ 524288) / 1048576; /* in MBytes */
1480 if (size
< RequiredPartitionDiskSpace
)
1482 /* partition is too small so ask for another partition */
1483 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1494 * Displays the SelectPartitionPage.
1497 * SelectFileSystemPage (At once if unattended)
1498 * SelectFileSystemPage (Default if free space is selected)
1499 * CreatePrimaryPartitionPage
1500 * CreateExtendedPartitionPage
1501 * CreateLogicalPartitionPage
1502 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1503 * DeletePartitionPage
1507 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1508 * Set InstallShortcut (only if not unattended + free space is selected)
1511 * Number of the next page.
1514 SelectPartitionPage(PINPUT_RECORD Ir
)
1519 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1521 if (PartitionList
== NULL
)
1523 PartitionList
= CreatePartitionList();
1524 if (PartitionList
== NULL
)
1526 /* FIXME: show an error dialog */
1527 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1530 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1532 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1536 TempPartition
= NULL
;
1537 FormatState
= Start
;
1540 InitPartitionListUi(&ListUi
, PartitionList
,
1545 DrawPartitionList(&ListUi
);
1547 if (IsUnattendedSetup
)
1549 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1553 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1555 CreateLogicalPartition(PartitionList
,
1556 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1561 CreatePrimaryPartition(PartitionList
,
1562 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1566 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1567 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1569 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1570 RequiredPartitionDiskSpace
);
1571 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1574 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1576 return SELECT_FILE_SYSTEM_PAGE
;
1581 DrawPartitionList(&ListUi
);
1583 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1584 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1586 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1587 RequiredPartitionDiskSpace
);
1588 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1591 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1593 return SELECT_FILE_SYSTEM_PAGE
;
1599 /* Update status text */
1600 if (PartitionList
->CurrentPartition
== NULL
)
1602 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1604 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1606 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1608 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1612 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1617 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1619 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1621 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1625 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1630 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1634 CONSOLE_ConInKey(Ir
);
1636 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1637 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1639 if (ConfirmQuit(Ir
) != FALSE
)
1641 DestroyPartitionList(PartitionList
);
1642 PartitionList
= NULL
;
1648 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1649 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1651 ScrollDownPartitionList(&ListUi
);
1653 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1654 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1656 ScrollUpPartitionList(&ListUi
);
1658 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1660 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1661 continue; // return SELECT_PARTITION_PAGE;
1663 if (PartitionList
->CurrentPartition
== NULL
||
1664 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1666 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1668 CreateLogicalPartition(PartitionList
,
1674 CreatePrimaryPartition(PartitionList
,
1680 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1682 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1683 RequiredPartitionDiskSpace
);
1684 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1687 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1689 return SELECT_FILE_SYSTEM_PAGE
;
1691 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1693 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1695 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1696 if (Error
!= NOT_AN_ERROR
)
1698 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1699 return SELECT_PARTITION_PAGE
;
1702 return CREATE_PRIMARY_PARTITION_PAGE
;
1705 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1707 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1709 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1710 if (Error
!= NOT_AN_ERROR
)
1712 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1713 return SELECT_PARTITION_PAGE
;
1716 return CREATE_EXTENDED_PARTITION_PAGE
;
1719 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1721 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1723 Error
= LogicalPartitionCreationChecks(PartitionList
);
1724 if (Error
!= NOT_AN_ERROR
)
1726 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1727 return SELECT_PARTITION_PAGE
;
1730 return CREATE_LOGICAL_PARTITION_PAGE
;
1733 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1735 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1737 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1738 return SELECT_PARTITION_PAGE
;
1741 if (PartitionList
->CurrentPartition
->BootIndicator
||
1742 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1744 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1747 return DELETE_PARTITION_PAGE
;
1751 return SELECT_PARTITION_PAGE
;
1755 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1756 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1757 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1760 ShowPartitionSizeInputBox(SHORT Left
,
1784 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1789 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1790 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1793 WriteConsoleOutputCharacterA(StdOutput
,
1799 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1800 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1802 WriteConsoleOutputCharacterA(StdOutput
,
1808 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1809 Length
= wcslen(InputBuffer
);
1811 CONSOLE_SetInputTextXY(iLeft
,
1813 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1815 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1816 CONSOLE_SetCursorType(TRUE
, TRUE
);
1820 CONSOLE_ConInKey(&Ir
);
1822 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1823 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1828 InputBuffer
[0] = UNICODE_NULL
;
1829 CONSOLE_SetCursorType(TRUE
, FALSE
);
1832 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1834 CONSOLE_SetCursorType(TRUE
, FALSE
);
1837 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1842 InputBuffer
[0] = UNICODE_NULL
;
1843 CONSOLE_SetCursorType(TRUE
, FALSE
);
1846 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1847 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1850 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1852 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1853 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1856 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1858 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1859 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1864 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1867 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1868 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1873 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1876 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1877 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1881 memmove(&InputBuffer
[Pos
],
1882 &InputBuffer
[Pos
+ 1],
1883 (Length
- Pos
- 1) * sizeof(WCHAR
));
1884 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1887 CONSOLE_SetInputTextXY(iLeft
,
1889 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1891 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1894 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1899 memmove(&InputBuffer
[Pos
- 1],
1901 (Length
- Pos
) * sizeof(WCHAR
));
1902 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1906 CONSOLE_SetInputTextXY(iLeft
,
1908 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1910 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1913 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1915 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1917 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1919 if ((ch
>= L
'0') && (ch
<= L
'9'))
1922 memmove(&InputBuffer
[Pos
+ 1],
1924 (Length
- Pos
) * sizeof(WCHAR
));
1925 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1926 InputBuffer
[Pos
] = ch
;
1930 CONSOLE_SetInputTextXY(iLeft
,
1932 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1934 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1943 * Displays the CreatePrimaryPartitionPage.
1946 * SelectPartitionPage
1947 * SelectFileSystemPage (default)
1951 * Number of the next page.
1954 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1956 PDISKENTRY DiskEntry
;
1957 PPARTENTRY PartEntry
;
1960 WCHAR InputBuffer
[50];
1964 ULONGLONG SectorCount
;
1967 if (PartitionList
== NULL
||
1968 PartitionList
->CurrentDisk
== NULL
||
1969 PartitionList
->CurrentPartition
== NULL
)
1971 /* FIXME: show an error dialog */
1975 DiskEntry
= PartitionList
->CurrentDisk
;
1976 PartEntry
= PartitionList
->CurrentPartition
;
1978 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1980 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1982 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1984 if (DiskSize
>= 10737418240) /* 10 GB */
1986 DiskSize
= DiskSize
/ 1073741824;
1987 Unit
= MUIGetString(STRING_GB
);
1992 DiskSize
= DiskSize
/ 1048576;
1996 Unit
= MUIGetString(STRING_MB
);
1999 if (DiskEntry
->DriverName
.Length
> 0)
2001 CONSOLE_PrintTextXY(6, 10,
2002 MUIGetString(STRING_HDINFOPARTCREATE
),
2005 DiskEntry
->DiskNumber
,
2009 &DiskEntry
->DriverName
);
2013 CONSOLE_PrintTextXY(6, 10,
2014 MUIGetString(STRING_HDDINFOUNK1
),
2017 DiskEntry
->DiskNumber
,
2023 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2026 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2027 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2030 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2032 PartEntry
= PartitionList
->CurrentPartition
;
2035 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2037 if (MaxSize
> PARTITION_MAXSIZE
)
2038 MaxSize
= PARTITION_MAXSIZE
;
2040 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2041 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2045 if (ConfirmQuit(Ir
) != FALSE
)
2050 else if (Cancel
!= FALSE
)
2052 return SELECT_PARTITION_PAGE
;
2056 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2064 if (PartSize
> MaxSize
)
2070 /* Convert to bytes */
2071 if (PartSize
== MaxSize
)
2073 /* Use all of the unpartitioned disk space */
2074 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2078 /* Calculate the sector count from the size in MB */
2079 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2081 /* But never get larger than the unpartitioned disk space */
2082 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2083 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2086 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2088 CreatePrimaryPartition(PartitionList
,
2092 return SELECT_PARTITION_PAGE
;
2096 return CREATE_PRIMARY_PARTITION_PAGE
;
2101 * Displays the CreateExtendedPartitionPage.
2104 * SelectPartitionPage (default)
2108 * Number of the next page.
2111 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2113 PDISKENTRY DiskEntry
;
2114 PPARTENTRY PartEntry
;
2117 WCHAR InputBuffer
[50];
2121 ULONGLONG SectorCount
;
2124 if (PartitionList
== NULL
||
2125 PartitionList
->CurrentDisk
== NULL
||
2126 PartitionList
->CurrentPartition
== NULL
)
2128 /* FIXME: show an error dialog */
2132 DiskEntry
= PartitionList
->CurrentDisk
;
2133 PartEntry
= PartitionList
->CurrentPartition
;
2135 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2137 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2139 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2141 if (DiskSize
>= 10737418240) /* 10 GB */
2143 DiskSize
= DiskSize
/ 1073741824;
2144 Unit
= MUIGetString(STRING_GB
);
2149 DiskSize
= DiskSize
/ 1048576;
2153 Unit
= MUIGetString(STRING_MB
);
2156 if (DiskEntry
->DriverName
.Length
> 0)
2158 CONSOLE_PrintTextXY(6, 10,
2159 MUIGetString(STRING_HDINFOPARTCREATE
),
2162 DiskEntry
->DiskNumber
,
2166 &DiskEntry
->DriverName
);
2170 CONSOLE_PrintTextXY(6, 10,
2171 MUIGetString(STRING_HDDINFOUNK1
),
2174 DiskEntry
->DiskNumber
,
2180 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2183 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2184 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2187 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2189 PartEntry
= PartitionList
->CurrentPartition
;
2192 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2194 if (MaxSize
> PARTITION_MAXSIZE
)
2195 MaxSize
= PARTITION_MAXSIZE
;
2197 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2198 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2202 if (ConfirmQuit(Ir
) != FALSE
)
2207 else if (Cancel
!= FALSE
)
2209 return SELECT_PARTITION_PAGE
;
2213 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2221 if (PartSize
> MaxSize
)
2227 /* Convert to bytes */
2228 if (PartSize
== MaxSize
)
2230 /* Use all of the unpartitioned disk space */
2231 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2235 /* Calculate the sector count from the size in MB */
2236 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2238 /* But never get larger than the unpartitioned disk space */
2239 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2240 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2243 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2245 CreateExtendedPartition(PartitionList
,
2248 return SELECT_PARTITION_PAGE
;
2252 return CREATE_EXTENDED_PARTITION_PAGE
;
2257 * Displays the CreateLogicalPartitionPage.
2260 * SelectFileSystemPage (default)
2264 * Number of the next page.
2267 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2269 PDISKENTRY DiskEntry
;
2270 PPARTENTRY PartEntry
;
2273 WCHAR InputBuffer
[50];
2277 ULONGLONG SectorCount
;
2280 if (PartitionList
== NULL
||
2281 PartitionList
->CurrentDisk
== NULL
||
2282 PartitionList
->CurrentPartition
== NULL
)
2284 /* FIXME: show an error dialog */
2288 DiskEntry
= PartitionList
->CurrentDisk
;
2289 PartEntry
= PartitionList
->CurrentPartition
;
2291 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2293 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2295 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2297 if (DiskSize
>= 10737418240) /* 10 GB */
2299 DiskSize
= DiskSize
/ 1073741824;
2300 Unit
= MUIGetString(STRING_GB
);
2305 DiskSize
= DiskSize
/ 1048576;
2309 Unit
= MUIGetString(STRING_MB
);
2312 if (DiskEntry
->DriverName
.Length
> 0)
2314 CONSOLE_PrintTextXY(6, 10,
2315 MUIGetString(STRING_HDINFOPARTCREATE
),
2318 DiskEntry
->DiskNumber
,
2322 &DiskEntry
->DriverName
);
2326 CONSOLE_PrintTextXY(6, 10,
2327 MUIGetString(STRING_HDDINFOUNK1
),
2330 DiskEntry
->DiskNumber
,
2336 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2339 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2340 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2343 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2345 PartEntry
= PartitionList
->CurrentPartition
;
2348 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2350 if (MaxSize
> PARTITION_MAXSIZE
)
2351 MaxSize
= PARTITION_MAXSIZE
;
2353 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2354 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2358 if (ConfirmQuit(Ir
) != FALSE
)
2363 else if (Cancel
!= FALSE
)
2365 return SELECT_PARTITION_PAGE
;
2369 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2377 if (PartSize
> MaxSize
)
2383 /* Convert to bytes */
2384 if (PartSize
== MaxSize
)
2386 /* Use all of the unpartitioned disk space */
2387 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2391 /* Calculate the sector count from the size in MB */
2392 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2394 /* But never get larger than the unpartitioned disk space */
2395 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2396 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2399 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2401 CreateLogicalPartition(PartitionList
,
2405 return SELECT_PARTITION_PAGE
;
2409 return CREATE_LOGICAL_PARTITION_PAGE
;
2414 * Displays the ConfirmDeleteSystemPartitionPage.
2417 * DeletePartitionPage (default)
2418 * SelectPartitionPage
2421 * Number of the next page.
2424 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2426 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2430 CONSOLE_ConInKey(Ir
);
2432 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2433 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2435 if (ConfirmQuit(Ir
) == TRUE
)
2440 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2442 return DELETE_PARTITION_PAGE
;
2444 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2446 return SELECT_PARTITION_PAGE
;
2450 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2455 * Displays the DeletePartitionPage.
2458 * SelectPartitionPage (default)
2462 * Number of the next page.
2465 DeletePartitionPage(PINPUT_RECORD Ir
)
2467 PDISKENTRY DiskEntry
;
2468 PPARTENTRY PartEntry
;
2472 CHAR PartTypeString
[32];
2474 if (PartitionList
== NULL
||
2475 PartitionList
->CurrentDisk
== NULL
||
2476 PartitionList
->CurrentPartition
== NULL
)
2478 /* FIXME: show an error dialog */
2482 DiskEntry
= PartitionList
->CurrentDisk
;
2483 PartEntry
= PartitionList
->CurrentPartition
;
2485 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2487 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2489 ARRAYSIZE(PartTypeString
));
2491 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2493 if (PartSize
>= 10737418240) /* 10 GB */
2495 PartSize
= PartSize
/ 1073741824;
2496 Unit
= MUIGetString(STRING_GB
);
2500 if (PartSize
>= 10485760) /* 10 MB */
2502 PartSize
= PartSize
/ 1048576;
2503 Unit
= MUIGetString(STRING_MB
);
2507 PartSize
= PartSize
/ 1024;
2508 Unit
= MUIGetString(STRING_KB
);
2511 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2513 CONSOLE_PrintTextXY(6, 10,
2514 MUIGetString(STRING_HDDINFOUNK2
),
2515 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2516 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2517 PartEntry
->PartitionType
,
2523 CONSOLE_PrintTextXY(6, 10,
2524 " %c%c %s %I64u %s",
2525 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2526 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2532 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2534 if (DiskSize
>= 10737418240) /* 10 GB */
2536 DiskSize
= DiskSize
/ 1073741824;
2537 Unit
= MUIGetString(STRING_GB
);
2542 DiskSize
= DiskSize
/ 1048576;
2546 Unit
= MUIGetString(STRING_MB
);
2549 if (DiskEntry
->DriverName
.Length
> 0)
2551 CONSOLE_PrintTextXY(6, 12,
2552 MUIGetString(STRING_HDINFOPARTDELETE
),
2555 DiskEntry
->DiskNumber
,
2559 &DiskEntry
->DriverName
);
2563 CONSOLE_PrintTextXY(6, 12,
2564 MUIGetString(STRING_HDDINFOUNK3
),
2567 DiskEntry
->DiskNumber
,
2575 CONSOLE_ConInKey(Ir
);
2577 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2578 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2580 if (ConfirmQuit(Ir
) != FALSE
)
2585 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2587 return SELECT_PARTITION_PAGE
;
2589 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2591 DeleteCurrentPartition(PartitionList
);
2593 return SELECT_PARTITION_PAGE
;
2597 return DELETE_PARTITION_PAGE
;
2602 * Displays the SelectFileSystemPage.
2605 * CheckFileSystemPage (At once if RepairUpdate is selected)
2606 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2607 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2608 * SelectPartitionPage (If the user aborts)
2609 * FormatPartitionPage (Default)
2613 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2614 * Calls CheckActiveSystemPartition()
2617 * Number of the next page.
2620 SelectFileSystemPage(PINPUT_RECORD Ir
)
2622 PDISKENTRY DiskEntry
;
2623 PPARTENTRY PartEntry
;
2628 CHAR PartTypeString
[32];
2629 FORMATMACHINESTATE PreviousFormatState
;
2631 DPRINT("SelectFileSystemPage()\n");
2633 if (PartitionList
== NULL
||
2634 PartitionList
->CurrentDisk
== NULL
||
2635 PartitionList
->CurrentPartition
== NULL
)
2637 /* FIXME: show an error dialog */
2641 /* Find or set the active system partition */
2642 CheckActiveSystemPartition(PartitionList
);
2643 if (PartitionList
->SystemPartition
== NULL
)
2645 /* FIXME: show an error dialog */
2649 PreviousFormatState
= FormatState
;
2650 switch (FormatState
)
2654 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2656 TempPartition
= PartitionList
->SystemPartition
;
2657 TempPartition
->NeedsCheck
= TRUE
;
2659 FormatState
= FormatSystemPartition
;
2660 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2664 TempPartition
= PartitionList
->CurrentPartition
;
2665 TempPartition
->NeedsCheck
= TRUE
;
2667 FormatState
= FormatInstallPartition
;
2668 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2673 case FormatSystemPartition
:
2675 TempPartition
= PartitionList
->CurrentPartition
;
2676 TempPartition
->NeedsCheck
= TRUE
;
2678 FormatState
= FormatInstallPartition
;
2679 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2683 case FormatInstallPartition
:
2685 if (GetNextUnformattedPartition(PartitionList
,
2689 FormatState
= FormatOtherPartition
;
2690 TempPartition
->NeedsCheck
= TRUE
;
2691 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2695 FormatState
= FormatDone
;
2696 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2697 return CHECK_FILE_SYSTEM_PAGE
;
2702 case FormatOtherPartition
:
2704 if (GetNextUnformattedPartition(PartitionList
,
2708 FormatState
= FormatOtherPartition
;
2709 TempPartition
->NeedsCheck
= TRUE
;
2710 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2714 FormatState
= FormatDone
;
2715 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2716 return CHECK_FILE_SYSTEM_PAGE
;
2723 DPRINT1("FormatState: Invalid value %ld\n", FormatState
);
2724 /* FIXME: show an error dialog */
2729 PartEntry
= TempPartition
;
2730 DiskEntry
= PartEntry
->DiskEntry
;
2732 /* Adjust disk size */
2733 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2734 if (DiskSize
>= 10737418240) /* 10 GB */
2736 DiskSize
= DiskSize
/ 1073741824;
2737 DiskUnit
= MUIGetString(STRING_GB
);
2741 DiskSize
= DiskSize
/ 1048576;
2742 DiskUnit
= MUIGetString(STRING_MB
);
2745 /* Adjust partition size */
2746 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2747 if (PartSize
>= 10737418240) /* 10 GB */
2749 PartSize
= PartSize
/ 1073741824;
2750 PartUnit
= MUIGetString(STRING_GB
);
2754 PartSize
= PartSize
/ 1048576;
2755 PartUnit
= MUIGetString(STRING_MB
);
2758 /* Adjust partition type */
2759 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2761 ARRAYSIZE(PartTypeString
));
2763 if (PartEntry
->AutoCreate
!= FALSE
)
2765 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2768 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2769 PartEntry
->PartitionNumber
,
2775 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED
),
2776 DiskEntry
->DiskNumber
,
2782 &DiskEntry
->DriverName
);
2784 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2786 PartEntry
->AutoCreate
= FALSE
;
2788 else if (PartEntry
->New
!= FALSE
)
2790 switch (FormatState
)
2792 case FormatSystemPartition
:
2793 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2796 case FormatInstallPartition
:
2797 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2800 case FormatOtherPartition
:
2801 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2808 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2812 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2814 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2816 CONSOLE_PrintTextXY(8, 10,
2817 MUIGetString(STRING_HDDINFOUNK4
),
2818 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2819 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2820 PartEntry
->PartitionType
,
2826 CONSOLE_PrintTextXY(8, 10,
2828 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2829 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2835 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS
),
2836 DiskEntry
->DiskNumber
,
2842 &DiskEntry
->DriverName
);
2845 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2847 if (FileSystemList
== NULL
)
2849 /* Create the file system list, and by default select the "FAT" file system */
2850 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2851 if (FileSystemList
== NULL
)
2853 /* FIXME: show an error dialog */
2858 DrawFileSystemList(FileSystemList
);
2860 if (RepairUpdateFlag
)
2862 return CHECK_FILE_SYSTEM_PAGE
;
2863 //return SELECT_PARTITION_PAGE;
2866 if (IsUnattendedSetup
)
2868 if (UnattendFormatPartition
)
2871 * We use whatever currently selected file system we have
2872 * (by default, this is "FAT", as per the initialization
2873 * performed above). Note that it may be interesting to specify
2874 * which file system to use in unattended installations, in the
2875 * txtsetup.sif file.
2877 return FORMAT_PARTITION_PAGE
;
2880 return CHECK_FILE_SYSTEM_PAGE
;
2885 CONSOLE_ConInKey(Ir
);
2887 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2888 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2890 if (ConfirmQuit(Ir
) != FALSE
)
2895 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2896 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2898 FormatState
= Start
;
2899 return SELECT_PARTITION_PAGE
;
2901 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2902 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2904 ScrollDownFileSystemList(FileSystemList
);
2906 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2907 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2909 ScrollUpFileSystemList(FileSystemList
);
2911 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2913 if (!FileSystemList
->Selected
->FileSystem
)
2914 return SELECT_FILE_SYSTEM_PAGE
;
2916 return FORMAT_PARTITION_PAGE
;
2920 FormatState
= PreviousFormatState
;
2922 return SELECT_FILE_SYSTEM_PAGE
;
2927 * Displays the FormatPartitionPage.
2930 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2931 * SelectPartitionPage (At once)
2935 * Sets PartitionList->CurrentPartition->FormatState
2936 * Sets DestinationRootPath
2939 * Number of the next page.
2942 FormatPartitionPage(PINPUT_RECORD Ir
)
2944 UNICODE_STRING PartitionRootPath
;
2945 WCHAR PathBuffer
[MAX_PATH
];
2946 PDISKENTRY DiskEntry
;
2947 PPARTENTRY PartEntry
;
2948 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2954 PPARTITION_INFORMATION PartitionInfo
;
2957 DPRINT("FormatPartitionPage()\n");
2959 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2961 if (PartitionList
== NULL
|| TempPartition
== NULL
)
2963 /* FIXME: show an error dialog */
2967 PartEntry
= TempPartition
;
2968 DiskEntry
= PartEntry
->DiskEntry
;
2970 SelectedFileSystem
= FileSystemList
->Selected
;
2974 if (!IsUnattendedSetup
)
2976 CONSOLE_ConInKey(Ir
);
2979 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2980 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2982 if (ConfirmQuit(Ir
) != FALSE
)
2987 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2989 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2991 if (!PreparePartitionForFormatting(PartEntry
, SelectedFileSystem
->FileSystem
))
2993 /* FIXME: show an error dialog */
2998 CONSOLE_PrintTextXY(6, 12,
2999 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3000 DiskEntry
->Cylinders
,
3001 DiskEntry
->TracksPerCylinder
,
3002 DiskEntry
->SectorsPerTrack
,
3003 DiskEntry
->BytesPerSector
,
3004 DiskEntry
->Dirty
? '*' : ' ');
3008 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3010 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3012 CONSOLE_PrintTextXY(6, Line
,
3013 "%2u: %2lu %c %12I64u %12I64u %02x",
3015 PartitionInfo
->PartitionNumber
,
3016 PartitionInfo
->BootIndicator
? 'A' : '-',
3017 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3018 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3019 PartitionInfo
->PartitionType
);
3024 /* Commit the partition changes to the disk */
3025 if (!WritePartitionsToDisk(PartitionList
))
3027 DPRINT("WritePartitionsToDisk() failed\n");
3028 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3032 /* Set PartitionRootPath */
3033 swprintf(PathBuffer
,
3034 L
"\\Device\\Harddisk%lu\\Partition%lu",
3035 DiskEntry
->DiskNumber
,
3036 PartEntry
->PartitionNumber
);
3037 RtlInitUnicodeString(&PartitionRootPath
,
3039 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3041 /* Format the partition */
3042 if (SelectedFileSystem
->FileSystem
)
3044 Status
= FormatPartition(&PartitionRootPath
,
3045 SelectedFileSystem
);
3046 if (!NT_SUCCESS(Status
))
3048 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3049 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3053 PartEntry
->FormatState
= Formatted
;
3054 // PartEntry->FileSystem = FileSystem;
3055 PartEntry
->New
= FALSE
;
3059 CONSOLE_SetStatusText(" Done. Press any key ...");
3060 CONSOLE_ConInKey(Ir
);
3063 return SELECT_FILE_SYSTEM_PAGE
;
3067 return FORMAT_PARTITION_PAGE
;
3072 * Displays the CheckFileSystemPage.
3075 * InstallDirectoryPage (At once)
3079 * Inits or reloads FileSystemList
3082 * Number of the next page.
3085 CheckFileSystemPage(PINPUT_RECORD Ir
)
3087 PFILE_SYSTEM CurrentFileSystem
;
3088 UNICODE_STRING PartitionRootPath
;
3089 WCHAR PathBuffer
[MAX_PATH
];
3090 CHAR Buffer
[MAX_PATH
];
3091 PDISKENTRY DiskEntry
;
3092 PPARTENTRY PartEntry
;
3095 if (PartitionList
== NULL
)
3097 /* FIXME: show an error dialog */
3101 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3103 return INSTALL_DIRECTORY_PAGE
;
3106 /* Set PartitionRootPath */
3107 swprintf(PathBuffer
,
3108 L
"\\Device\\Harddisk%lu\\Partition%lu",
3109 DiskEntry
->DiskNumber
,
3110 PartEntry
->PartitionNumber
);
3111 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3112 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3114 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3116 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3118 CurrentFileSystem
= PartEntry
->FileSystem
;
3119 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3120 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3122 /* HACK: Do not try to check a partition with an unknown filesystem */
3123 if (CurrentFileSystem
== NULL
)
3125 PartEntry
->NeedsCheck
= FALSE
;
3126 return CHECK_FILE_SYSTEM_PAGE
;
3129 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3132 "Setup is currently unable to check a partition formatted in %S.\n"
3134 " \x07 Press ENTER to continue Setup.\n"
3135 " \x07 Press F3 to quit Setup.",
3136 CurrentFileSystem
->FileSystemName
);
3139 MUIGetString(STRING_QUITCONTINUE
),
3140 NULL
, POPUP_WAIT_NONE
);
3144 CONSOLE_ConInKey(Ir
);
3146 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3147 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3149 if (ConfirmQuit(Ir
))
3152 return CHECK_FILE_SYSTEM_PAGE
;
3154 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3156 PartEntry
->NeedsCheck
= FALSE
;
3157 return CHECK_FILE_SYSTEM_PAGE
;
3163 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3164 if (!NT_SUCCESS(Status
))
3166 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3167 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3168 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3169 "(Status 0x%08lx).\n", Status
);
3171 // MUIGetString(STRING_REBOOTCOMPUTER),
3172 MUIGetString(STRING_CONTINUE
),
3173 Ir
, POPUP_WAIT_ENTER
);
3175 // return QUIT_PAGE;
3178 PartEntry
->NeedsCheck
= FALSE
;
3179 return CHECK_FILE_SYSTEM_PAGE
;
3186 BuildInstallPaths(PWCHAR InstallDir
,
3187 PDISKENTRY DiskEntry
,
3188 PPARTENTRY PartEntry
)
3190 WCHAR PathBuffer
[MAX_PATH
];
3192 /* Create 'InstallPath' string */
3193 RtlFreeUnicodeString(&InstallPath
);
3194 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3196 /* Create 'DestinationRootPath' string */
3197 RtlFreeUnicodeString(&DestinationRootPath
);
3198 swprintf(PathBuffer
,
3199 L
"\\Device\\Harddisk%lu\\Partition%lu",
3200 DiskEntry
->DiskNumber
,
3201 PartEntry
->PartitionNumber
);
3202 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3203 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3205 /* Create 'DestinationPath' string */
3206 RtlFreeUnicodeString(&DestinationPath
);
3207 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3209 if (InstallDir
[0] != L
'\\')
3210 wcscat(PathBuffer
, L
"\\");
3212 wcscat(PathBuffer
, InstallDir
);
3213 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3215 /* Create 'DestinationArcPath' */
3216 RtlFreeUnicodeString(&DestinationArcPath
);
3217 swprintf(PathBuffer
,
3218 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3219 DiskEntry
->BiosDiskNumber
,
3220 PartEntry
->PartitionNumber
);
3222 if (InstallDir
[0] != L
'\\')
3223 wcscat(PathBuffer
, L
"\\");
3225 wcscat(PathBuffer
, InstallDir
);
3226 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3231 * Displays the InstallDirectoryPage.
3234 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3238 * Number of the next page.
3241 InstallDirectoryPage(PINPUT_RECORD Ir
)
3243 PDISKENTRY DiskEntry
;
3244 PPARTENTRY PartEntry
;
3245 WCHAR InstallDir
[51];
3249 /* We do not need the filesystem list any more */
3250 if (FileSystemList
!= NULL
)
3252 DestroyFileSystemList(FileSystemList
);
3253 FileSystemList
= NULL
;
3256 if (PartitionList
== NULL
||
3257 PartitionList
->CurrentDisk
== NULL
||
3258 PartitionList
->CurrentPartition
== NULL
)
3260 /* FIXME: show an error dialog */
3264 DiskEntry
= PartitionList
->CurrentDisk
;
3265 PartEntry
= PartitionList
->CurrentPartition
;
3267 if (IsUnattendedSetup
)
3269 if (!IsValidPath(UnattendInstallationDirectory
))
3271 /* FIXME: Log the error? */
3275 BuildInstallPaths(UnattendInstallationDirectory
,
3279 return PREPARE_COPY_PAGE
;
3282 wcscpy(InstallDir
, L
"\\ReactOS");
3284 Length
= wcslen(InstallDir
);
3286 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3287 CONSOLE_SetCursorXY(8 + Pos
, 11);
3288 CONSOLE_SetCursorType(TRUE
, TRUE
);
3289 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3293 CONSOLE_ConInKey(Ir
);
3295 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3296 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3298 CONSOLE_SetCursorType(TRUE
, FALSE
);
3300 if (ConfirmQuit(Ir
) != FALSE
)
3303 CONSOLE_SetCursorType(TRUE
, TRUE
);
3306 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3307 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3311 memmove(&InstallDir
[Pos
],
3312 &InstallDir
[Pos
+ 1],
3313 (Length
- Pos
- 1) * sizeof(WCHAR
));
3314 InstallDir
[Length
- 1] = UNICODE_NULL
;
3317 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3318 CONSOLE_SetCursorXY(8 + Pos
, 11);
3321 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3322 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3325 CONSOLE_SetCursorXY(8 + Pos
, 11);
3327 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3328 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3331 CONSOLE_SetCursorXY(8 + Pos
, 11);
3333 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3334 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3339 CONSOLE_SetCursorXY(8 + Pos
, 11);
3342 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3343 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3348 CONSOLE_SetCursorXY(8 + Pos
, 11);
3351 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3353 CONSOLE_SetCursorType(TRUE
, FALSE
);
3356 * Check for the validity of the installation directory and pop up
3357 * an error if it is not the case. Then the user can fix its input.
3359 if (!IsValidPath(InstallDir
))
3361 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3362 return INSTALL_DIRECTORY_PAGE
;
3365 BuildInstallPaths(InstallDir
,
3369 return PREPARE_COPY_PAGE
;
3371 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3376 memmove(&InstallDir
[Pos
- 1],
3378 (Length
- Pos
) * sizeof(WCHAR
));
3379 InstallDir
[Length
- 1] = UNICODE_NULL
;
3383 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3384 CONSOLE_SetCursorXY(8 + Pos
, 11);
3387 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3391 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3392 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3395 memmove(&InstallDir
[Pos
+ 1],
3397 (Length
- Pos
) * sizeof(WCHAR
));
3398 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3399 InstallDir
[Pos
] = c
;
3403 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3404 CONSOLE_SetCursorXY(8 + Pos
, 11);
3410 return INSTALL_DIRECTORY_PAGE
;
3415 AddSectionToCopyQueueCab(HINF InfFile
,
3417 PWCHAR SourceCabinet
,
3418 PCUNICODE_STRING DestinationPath
,
3421 INFCONTEXT FilesContext
;
3422 INFCONTEXT DirContext
;
3424 PWCHAR FileKeyValue
;
3426 PWCHAR TargetFileName
;
3428 /* Search for the SectionName section */
3429 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3432 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3433 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3438 * Enumerate the files in the section
3439 * and add them to the file queue.
3443 /* Get source file name and target directory id */
3444 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3446 /* FIXME: Handle error! */
3447 DPRINT1("INF_GetData() failed\n");
3451 /* Get optional target file name */
3452 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3453 TargetFileName
= NULL
;
3455 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3457 /* Lookup target directory */
3458 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3460 /* FIXME: Handle error! */
3461 DPRINT1("SetupFindFirstLine() failed\n");
3465 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3467 /* FIXME: Handle error! */
3468 DPRINT1("INF_GetData() failed\n");
3472 if (!SetupQueueCopy(SetupFileQueue
,
3474 SourceRootPath
.Buffer
,
3475 SourceRootDir
.Buffer
,
3480 /* FIXME: Handle error! */
3481 DPRINT1("SetupQueueCopy() failed\n");
3483 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3490 AddSectionToCopyQueue(HINF InfFile
,
3492 PWCHAR SourceCabinet
,
3493 PCUNICODE_STRING DestinationPath
,
3496 INFCONTEXT FilesContext
;
3497 INFCONTEXT DirContext
;
3499 PWCHAR FileKeyValue
;
3501 PWCHAR TargetFileName
;
3503 WCHAR CompleteOrigDirName
[512];
3506 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3508 /* Search for the SectionName section */
3509 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3512 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3513 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3518 * Enumerate the files in the section
3519 * and add them to the file queue.
3523 /* Get source file name and target directory id */
3524 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3526 /* FIXME: Handle error! */
3527 DPRINT1("INF_GetData() failed\n");
3531 /* Get target directory id */
3532 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3534 /* FIXME: Handle error! */
3535 DPRINT1("INF_GetData() failed\n");
3539 /* Get optional target file name */
3540 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3541 TargetFileName
= NULL
;
3542 else if (!*TargetFileName
)
3543 TargetFileName
= NULL
;
3545 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3547 /* Lookup target directory */
3548 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3550 /* FIXME: Handle error! */
3551 DPRINT1("SetupFindFirstLine() failed\n");
3555 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3557 /* FIXME: Handle error! */
3558 DPRINT1("INF_GetData() failed\n");
3562 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3564 /* Installation path */
3565 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3567 else if (DirKeyValue
[0] == L
'\\')
3570 wcscpy(CompleteOrigDirName
, DirKeyValue
);
3572 else // if (DirKeyValue[0] != L'\\')
3574 /* Path relative to the installation path */
3575 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3576 wcscat(CompleteOrigDirName
, L
"\\");
3577 wcscat(CompleteOrigDirName
, DirKeyValue
);
3580 /* Remove trailing backslash */
3581 Length
= wcslen(CompleteOrigDirName
);
3582 if ((Length
> 0) && (CompleteOrigDirName
[Length
- 1] == L
'\\'))
3584 CompleteOrigDirName
[Length
- 1] = 0;
3587 if (!SetupQueueCopy(SetupFileQueue
,
3589 SourceRootPath
.Buffer
,
3590 CompleteOrigDirName
,
3595 /* FIXME: Handle error! */
3596 DPRINT1("SetupQueueCopy() failed\n");
3598 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3605 PrepareCopyPageInfFile(HINF InfFile
,
3606 PWCHAR SourceCabinet
,
3609 WCHAR PathBuffer
[MAX_PATH
];
3610 INFCONTEXT DirContext
;
3611 PWCHAR AdditionalSectionName
= NULL
;
3616 /* Add common files */
3617 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &DestinationPath
, Ir
))
3620 /* Add specific files depending of computer type */
3621 if (SourceCabinet
== NULL
)
3623 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3626 if (AdditionalSectionName
)
3628 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &DestinationPath
, Ir
))
3633 /* Create directories */
3637 * - Install directories like '\reactos\test' are not handled yet.
3638 * - Copying files to DestinationRootPath should be done from within
3639 * the SystemPartitionFiles section.
3640 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3641 * For installing to DestinationPath specify just '\' .
3644 /* Get destination path */
3645 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3647 /* Remove trailing backslash */
3648 Length
= wcslen(PathBuffer
);
3649 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3651 PathBuffer
[Length
- 1] = 0;
3654 /* Create the install directory */
3655 Status
= SetupCreateDirectory(PathBuffer
);
3656 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3658 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3659 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3663 /* Search for the 'Directories' section */
3664 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3668 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3672 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3678 /* Enumerate the directory values and create the subdirectories */
3681 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3687 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3689 /* Installation path */
3690 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3692 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3694 DPRINT("FullPath: '%S'\n", PathBuffer
);
3696 else if (DirKeyValue
[0] == L
'\\')
3699 DPRINT("Absolute Path: '%S'\n", DirKeyValue
);
3701 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3702 wcscat(PathBuffer
, DirKeyValue
);
3704 /* Remove trailing backslash */
3705 Length
= wcslen(PathBuffer
);
3706 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3708 PathBuffer
[Length
- 1] = 0;
3711 DPRINT("FullPath: '%S'\n", PathBuffer
);
3713 Status
= SetupCreateDirectory(PathBuffer
);
3714 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3716 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3717 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3721 else // if (DirKeyValue[0] != L'\\')
3723 /* Path relative to the installation path */
3724 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3726 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3727 wcscat(PathBuffer
, L
"\\");
3728 wcscat(PathBuffer
, DirKeyValue
);
3730 /* Remove trailing backslash */
3731 Length
= wcslen(PathBuffer
);
3732 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3734 PathBuffer
[Length
- 1] = 0;
3737 DPRINT("FullPath: '%S'\n", PathBuffer
);
3739 Status
= SetupCreateDirectory(PathBuffer
);
3740 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3742 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3743 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3747 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3754 * Displays the PrepareCopyPage.
3757 * FileCopyPage(At once)
3761 * Inits SetupFileQueue
3762 * Calls PrepareCopyPageInfFile
3765 * Number of the next page.
3768 PrepareCopyPage(PINPUT_RECORD Ir
)
3771 WCHAR PathBuffer
[MAX_PATH
];
3772 INFCONTEXT CabinetsContext
;
3778 MUIDisplayPage(PREPARE_COPY_PAGE
);
3780 /* Create the file queue */
3781 SetupFileQueue
= SetupOpenFileQueue();
3782 if (SetupFileQueue
== NULL
)
3784 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3788 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3790 /* FIXME: show an error dialog */
3794 /* Search for the 'Cabinets' section */
3795 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3797 return FILE_COPY_PAGE
;
3801 * Enumerate the directory values in the 'Cabinets'
3802 * section and parse their inf files.
3806 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3809 wcscpy(PathBuffer
, SourcePath
.Buffer
);
3810 wcscat(PathBuffer
, L
"\\");
3811 wcscat(PathBuffer
, KeyValue
);
3813 CabinetInitialize();
3814 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3815 CabinetSetCabinetName(PathBuffer
);
3817 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3819 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3821 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3822 if (InfFileData
== NULL
)
3824 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3830 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3831 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3835 InfHandle
= INF_OpenBufferedFileA((CHAR
*) InfFileData
,
3842 if (InfHandle
== INVALID_HANDLE_VALUE
)
3844 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3850 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3852 /* FIXME: show an error dialog */
3855 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3857 return FILE_COPY_PAGE
;
3863 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3866 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3868 /* Get the memory information from the system */
3869 NtQuerySystemInformation(SystemPerformanceInformation
,
3874 /* Check if this is initial setup */
3877 /* Set maximum limits to be total RAM pages */
3878 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3879 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3880 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3883 /* Set current values */
3884 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3885 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3886 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3892 FileCopyCallback(PVOID Context
,
3897 PCOPYCONTEXT CopyContext
;
3899 CopyContext
= (PCOPYCONTEXT
)Context
;
3901 switch (Notification
)
3903 case SPFILENOTIFY_STARTSUBQUEUE
:
3904 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3905 ProgressSetStepCount(CopyContext
->ProgressBar
,
3906 CopyContext
->TotalOperations
);
3907 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3910 case SPFILENOTIFY_STARTCOPY
:
3911 /* Display copy message */
3912 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3913 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3916 case SPFILENOTIFY_ENDCOPY
:
3917 CopyContext
->CompletedOperations
++;
3919 /* SYSREG checkpoint */
3920 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3921 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3923 ProgressNextStep(CopyContext
->ProgressBar
);
3924 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3933 * Displays the FileCopyPage.
3936 * RegistryPage(At once)
3939 * Calls SetupCommitFileQueueW
3940 * Calls SetupCloseFileQueue
3943 * Number of the next page.
3946 FileCopyPage(PINPUT_RECORD Ir
)
3948 COPYCONTEXT CopyContext
;
3949 unsigned int mem_bar_width
;
3951 MUIDisplayPage(FILE_COPY_PAGE
);
3953 /* Create context for the copy process */
3954 CopyContext
.DestinationRootPath
= DestinationRootPath
.Buffer
;
3955 CopyContext
.InstallPath
= InstallPath
.Buffer
;
3956 CopyContext
.TotalOperations
= 0;
3957 CopyContext
.CompletedOperations
= 0;
3959 /* Create the progress bar as well */
3960 CopyContext
.ProgressBar
= CreateProgressBar(13,
3967 MUIGetString(STRING_SETUPCOPYINGFILES
));
3969 // fit memory bars to screen width, distribute them uniform
3970 mem_bar_width
= (xScreen
- 26) / 5;
3971 mem_bar_width
-= mem_bar_width
% 2; // make even
3972 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
3973 /* Create the paged pool progress bar */
3974 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
3983 /* Create the non paged pool progress bar */
3984 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
3986 (xScreen
/ 2) + (mem_bar_width
/ 2),
3988 (xScreen
/ 2)- (mem_bar_width
/ 2),
3993 /* Create the global memory progress bar */
3994 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
3998 xScreen
- 13 - mem_bar_width
,
4003 /* Do the file copying */
4004 SetupCommitFileQueueW(NULL
,
4009 /* If we get here, we're done, so cleanup the queue and progress bar */
4010 SetupCloseFileQueue(SetupFileQueue
);
4011 DestroyProgressBar(CopyContext
.ProgressBar
);
4012 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4013 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4014 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4016 /* Go display the next page */
4017 return REGISTRY_PAGE
;
4022 * Displays the RegistryPage.
4025 * SuccessPage (if RepairUpdate)
4026 * BootLoaderPage (default)
4030 * Calls SetInstallPathValue
4031 * Calls NtInitializeRegistry
4032 * Calls ImportRegistryFile
4033 * Calls SetDefaultPagefile
4034 * Calls SetMountedDeviceValues
4037 * Number of the next page.
4040 RegistryPage(PINPUT_RECORD Ir
)
4042 INFCONTEXT InfContext
;
4049 MUIDisplayPage(REGISTRY_PAGE
);
4051 if (RepairUpdateFlag
)
4053 return SUCCESS_PAGE
;
4056 if (!SetInstallPathValue(&DestinationPath
))
4058 DPRINT1("SetInstallPathValue() failed\n");
4059 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4063 /* Create the default hives */
4064 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4065 if (!NT_SUCCESS(Status
))
4067 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
4068 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4072 /* Update registry */
4073 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4075 if (!SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
))
4077 DPRINT1("SetupFindFirstLine() failed\n");
4078 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4084 INF_GetDataField(&InfContext
, 0, &Action
);
4085 INF_GetDataField(&InfContext
, 1, &File
);
4086 INF_GetDataField(&InfContext
, 2, &Section
);
4088 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4093 if (!_wcsicmp(Action
, L
"AddReg"))
4097 else if (!_wcsicmp(Action
, L
"DelReg"))
4106 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4108 if (!ImportRegistryFile(File
, Section
, LanguageId
, Delete
))
4110 DPRINT1("Importing %S failed\n", File
);
4112 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4115 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4117 /* Update display registry settings */
4118 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4119 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4121 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4125 /* Set the locale */
4126 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4127 if (!ProcessLocaleRegistry(LanguageList
))
4129 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4133 /* Add keyboard layouts */
4134 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4135 if (!AddKeyboardLayouts())
4137 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4142 if (!SetGeoID(MUIGetGeoID()))
4144 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4148 if (!IsUnattendedSetup
)
4150 /* Update keyboard layout settings */
4151 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4152 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4154 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4159 /* Add codepage information to registry */
4160 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4163 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4167 /* Set the default pagefile entry */
4168 SetDefaultPagefile(DestinationDriveLetter
);
4170 /* Update the mounted devices list */
4171 SetMountedDeviceValues(PartitionList
);
4173 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4175 return BOOT_LOADER_PAGE
;
4180 * Displays the BootLoaderPage.
4183 * SuccessPage (if RepairUpdate)
4184 * BootLoaderHarddiskMbrPage
4185 * BootLoaderHarddiskVbrPage
4186 * BootLoaderFloppyPage
4191 * Calls SetInstallPathValue
4192 * Calls NtInitializeRegistry
4193 * Calls ImportRegistryFile
4194 * Calls SetDefaultPagefile
4195 * Calls SetMountedDeviceValues
4198 * Number of the next page.
4201 BootLoaderPage(PINPUT_RECORD Ir
)
4203 UCHAR PartitionType
;
4204 BOOLEAN InstallOnFloppy
;
4206 WCHAR PathBuffer
[MAX_PATH
];
4208 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4210 RtlFreeUnicodeString(&SystemRootPath
);
4211 swprintf(PathBuffer
,
4212 L
"\\Device\\Harddisk%lu\\Partition%lu",
4213 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4214 PartitionList
->SystemPartition
->PartitionNumber
);
4215 RtlCreateUnicodeString(&SystemRootPath
, PathBuffer
);
4216 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath
);
4218 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4220 if (IsUnattendedSetup
)
4222 if (UnattendMBRInstallType
== 0) /* skip MBR installation */
4224 return SUCCESS_PAGE
;
4226 else if (UnattendMBRInstallType
== 1) /* install on floppy */
4228 return BOOT_LOADER_FLOPPY_PAGE
;
4232 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4234 DPRINT("Error: system partition invalid (unused)\n");
4235 InstallOnFloppy
= TRUE
;
4237 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4239 /* OS/2 boot manager partition */
4240 DPRINT("Found OS/2 boot manager partition\n");
4241 InstallOnFloppy
= TRUE
;
4243 else if (PartitionType
== PARTITION_EXT2
)
4245 /* Linux EXT2 partition */
4246 DPRINT("Found Linux EXT2 partition\n");
4247 InstallOnFloppy
= FALSE
;
4249 else if (PartitionType
== PARTITION_IFS
)
4251 /* NTFS partition */
4252 DPRINT("Found NTFS partition\n");
4254 // FIXME: Make it FALSE when we'll support NTFS installation!
4255 InstallOnFloppy
= TRUE
;
4257 else if ((PartitionType
== PARTITION_FAT_12
) ||
4258 (PartitionType
== PARTITION_FAT_16
) ||
4259 (PartitionType
== PARTITION_HUGE
) ||
4260 (PartitionType
== PARTITION_XINT13
) ||
4261 (PartitionType
== PARTITION_FAT32
) ||
4262 (PartitionType
== PARTITION_FAT32_XINT13
))
4264 DPRINT("Found FAT partition\n");
4265 InstallOnFloppy
= FALSE
;
4269 /* Unknown partition */
4270 DPRINT("Unknown partition found\n");
4271 InstallOnFloppy
= TRUE
;
4274 if (InstallOnFloppy
!= FALSE
)
4276 return BOOT_LOADER_FLOPPY_PAGE
;
4279 /* Unattended install on hdd? */
4280 if (IsUnattendedSetup
&& UnattendMBRInstallType
== 2)
4282 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4285 MUIDisplayPage(BOOT_LOADER_PAGE
);
4286 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4290 CONSOLE_ConInKey(Ir
);
4292 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4293 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4295 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4304 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4306 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4307 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4309 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4318 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4320 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4321 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4323 if (ConfirmQuit(Ir
) != FALSE
)
4328 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4332 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4334 else if (Line
== 13)
4336 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4338 else if (Line
== 14)
4340 return BOOT_LOADER_FLOPPY_PAGE
;
4342 else if (Line
== 15)
4344 return SUCCESS_PAGE
;
4347 return BOOT_LOADER_PAGE
;
4351 return BOOT_LOADER_PAGE
;
4356 * Displays the BootLoaderFloppyPage.
4359 * SuccessPage (At once)
4363 * Calls InstallFatBootcodeToFloppy()
4366 * Number of the next page.
4369 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4373 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4375 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4379 CONSOLE_ConInKey(Ir
);
4381 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4382 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4384 if (ConfirmQuit(Ir
) != FALSE
)
4389 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4391 if (DoesFileExist(NULL
, L
"\\Device\\Floppy0", L
"\\") == FALSE
)
4393 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4394 return BOOT_LOADER_FLOPPY_PAGE
;
4397 Status
= InstallFatBootcodeToFloppy(&SourceRootPath
, &DestinationArcPath
);
4398 if (!NT_SUCCESS(Status
))
4400 /* Print error message */
4401 return BOOT_LOADER_FLOPPY_PAGE
;
4404 return SUCCESS_PAGE
;
4408 return BOOT_LOADER_FLOPPY_PAGE
;
4413 * Displays the BootLoaderHarddiskVbrPage.
4416 * SuccessPage (At once)
4420 * Calls InstallVBRToPartition()
4423 * Number of the next page.
4426 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4428 UCHAR PartitionType
;
4431 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4433 Status
= InstallVBRToPartition(&SystemRootPath
,
4435 &DestinationArcPath
,
4437 if (!NT_SUCCESS(Status
))
4439 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4443 return SUCCESS_PAGE
;
4448 * Displays the BootLoaderHarddiskMbrPage.
4451 * SuccessPage (At once)
4455 * Calls InstallVBRToPartition()
4456 * CallsInstallMbrBootCodeToDisk()
4459 * Number of the next page.
4462 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4464 UCHAR PartitionType
;
4466 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4467 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4468 WCHAR DstPath
[MAX_PATH
];
4470 /* Step 1: Write the VBR */
4471 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4473 Status
= InstallVBRToPartition(&SystemRootPath
,
4475 &DestinationArcPath
,
4477 if (!NT_SUCCESS(Status
))
4479 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4483 /* Step 2: Write the MBR */
4484 swprintf(DestinationDevicePathBuffer
,
4485 L
"\\Device\\Harddisk%d\\Partition0",
4486 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4488 wcscpy(SourceMbrPathBuffer
, SourceRootPath
.Buffer
);
4489 wcscat(SourceMbrPathBuffer
, L
"\\loader\\dosmbr.bin");
4491 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4493 /* Save current MBR */
4494 wcscpy(DstPath
, SystemRootPath
.Buffer
);
4495 wcscat(DstPath
, L
"\\mbr.old");
4497 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4498 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4499 if (!NT_SUCCESS(Status
))
4501 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4502 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4506 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4507 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4508 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4509 DestinationDevicePathBuffer
);
4510 if (!NT_SUCCESS(Status
))
4512 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4514 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4518 return SUCCESS_PAGE
;
4523 * Displays the QuitPage.
4526 * FlushPage (At once)
4532 * Number of the next page.
4535 QuitPage(PINPUT_RECORD Ir
)
4537 MUIDisplayPage(QUIT_PAGE
);
4539 /* Destroy the partition list */
4540 if (PartitionList
!= NULL
)
4542 DestroyPartitionList(PartitionList
);
4543 PartitionList
= NULL
;
4545 TempPartition
= NULL
;
4546 FormatState
= Start
;
4548 /* Destroy the filesystem list */
4549 if (FileSystemList
!= NULL
)
4551 DestroyFileSystemList(FileSystemList
);
4552 FileSystemList
= NULL
;
4555 /* Destroy the computer settings list */
4556 if (ComputerList
!= NULL
)
4558 DestroyGenericList(ComputerList
, TRUE
);
4559 ComputerList
= NULL
;
4562 /* Destroy the display settings list */
4563 if (DisplayList
!= NULL
)
4565 DestroyGenericList(DisplayList
, TRUE
);
4569 /* Destroy the keyboard settings list */
4570 if (KeyboardList
!= NULL
)
4572 DestroyGenericList(KeyboardList
, TRUE
);
4573 KeyboardList
= NULL
;
4576 /* Destroy the keyboard layout list */
4577 if (LayoutList
!= NULL
)
4579 DestroyGenericList(LayoutList
, TRUE
);
4583 /* Destroy the languages list */
4584 if (LanguageList
!= NULL
)
4586 DestroyGenericList(LanguageList
, FALSE
);
4587 LanguageList
= NULL
;
4590 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4594 CONSOLE_ConInKey(Ir
);
4596 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4605 * Displays the SuccessPage.
4608 * FlushPage (At once)
4614 * Number of the next page.
4617 SuccessPage(PINPUT_RECORD Ir
)
4619 MUIDisplayPage(SUCCESS_PAGE
);
4621 if (IsUnattendedSetup
)
4628 CONSOLE_ConInKey(Ir
);
4630 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4639 * Displays the FlushPage.
4642 * RebootPage (At once)
4645 * Number of the next page.
4648 FlushPage(PINPUT_RECORD Ir
)
4650 MUIDisplayPage(FLUSH_PAGE
);
4656 PnpEventThread(IN LPVOID lpParameter
);
4660 * The start routine and page management
4671 NtQuerySystemTime(&Time
);
4673 /* Create the PnP thread in suspended state */
4674 Status
= RtlCreateUserThread(NtCurrentProcess(),
4684 if (!NT_SUCCESS(Status
))
4685 hPnpThread
= INVALID_HANDLE_VALUE
;
4687 if (!CONSOLE_Init())
4689 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4690 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4691 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4693 /* Raise a hard error (crash the system/BSOD) */
4694 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4698 /* Initialize global unicode strings */
4699 RtlInitUnicodeString(&SourcePath
, NULL
);
4700 RtlInitUnicodeString(&SourceRootPath
, NULL
);
4701 RtlInitUnicodeString(&SourceRootDir
, NULL
);
4702 RtlInitUnicodeString(&InstallPath
, NULL
);
4703 RtlInitUnicodeString(&DestinationPath
, NULL
);
4704 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
4705 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
4706 RtlInitUnicodeString(&SystemRootPath
, NULL
);
4708 /* Hide the cursor */
4709 CONSOLE_SetCursorType(TRUE
, FALSE
);
4712 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4714 CONSOLE_ClearScreen();
4717 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4724 Page
= SetupStartPage(&Ir
);
4729 Page
= LanguagePage(&Ir
);
4734 Page
= LicensePage(&Ir
);
4739 Page
= IntroPage(&Ir
);
4743 case INSTALL_INTRO_PAGE
:
4744 Page
= InstallIntroPage(&Ir
);
4748 case SCSI_CONTROLLER_PAGE
:
4749 Page
= ScsiControllerPage(&Ir
);
4752 case OEM_DRIVER_PAGE
:
4753 Page
= OemDriverPage(&Ir
);
4757 case DEVICE_SETTINGS_PAGE
:
4758 Page
= DeviceSettingsPage(&Ir
);
4761 case COMPUTER_SETTINGS_PAGE
:
4762 Page
= ComputerSettingsPage(&Ir
);
4765 case DISPLAY_SETTINGS_PAGE
:
4766 Page
= DisplaySettingsPage(&Ir
);
4769 case KEYBOARD_SETTINGS_PAGE
:
4770 Page
= KeyboardSettingsPage(&Ir
);
4773 case LAYOUT_SETTINGS_PAGE
:
4774 Page
= LayoutSettingsPage(&Ir
);
4777 case SELECT_PARTITION_PAGE
:
4778 Page
= SelectPartitionPage(&Ir
);
4781 case CREATE_PRIMARY_PARTITION_PAGE
:
4782 Page
= CreatePrimaryPartitionPage(&Ir
);
4785 case CREATE_EXTENDED_PARTITION_PAGE
:
4786 Page
= CreateExtendedPartitionPage(&Ir
);
4789 case CREATE_LOGICAL_PARTITION_PAGE
:
4790 Page
= CreateLogicalPartitionPage(&Ir
);
4793 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4794 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4797 case DELETE_PARTITION_PAGE
:
4798 Page
= DeletePartitionPage(&Ir
);
4801 case SELECT_FILE_SYSTEM_PAGE
:
4802 Page
= SelectFileSystemPage(&Ir
);
4805 case FORMAT_PARTITION_PAGE
:
4806 Page
= FormatPartitionPage(&Ir
);
4809 case CHECK_FILE_SYSTEM_PAGE
:
4810 Page
= CheckFileSystemPage(&Ir
);
4813 case INSTALL_DIRECTORY_PAGE
:
4814 Page
= InstallDirectoryPage(&Ir
);
4817 case PREPARE_COPY_PAGE
:
4818 Page
= PrepareCopyPage(&Ir
);
4821 case FILE_COPY_PAGE
:
4822 Page
= FileCopyPage(&Ir
);
4826 Page
= RegistryPage(&Ir
);
4829 case BOOT_LOADER_PAGE
:
4830 Page
= BootLoaderPage(&Ir
);
4833 case BOOT_LOADER_FLOPPY_PAGE
:
4834 Page
= BootLoaderFloppyPage(&Ir
);
4837 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4838 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4841 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4842 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4846 case REPAIR_INTRO_PAGE
:
4847 Page
= RepairIntroPage(&Ir
);
4851 Page
= SuccessPage(&Ir
);
4855 Page
= FlushPage(&Ir
);
4859 Page
= QuitPage(&Ir
);
4868 if (Page
== RECOVERY_PAGE
)
4873 /* Avoid bugcheck */
4874 Time
.QuadPart
+= 50000000;
4875 NtDelayExecution(FALSE
, &Time
);
4878 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4879 NtShutdownSystem(ShutdownReboot
);
4880 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4881 NtTerminateProcess(NtCurrentProcess(), 0);
4886 NtProcessStartup(PPEB Peb
)
4888 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4890 ProcessHeap
= Peb
->ProcessHeap
;
4891 InfSetHeap(ProcessHeap
);