3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/usetup.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hervé Poussineau (hpoussin@reactos.org)
43 /* GLOBALS ******************************************************************/
46 UNICODE_STRING SourceRootPath
;
47 UNICODE_STRING SourceRootDir
;
48 UNICODE_STRING SourcePath
;
49 BOOLEAN IsUnattendedSetup
= FALSE
;
50 LONG UnattendDestinationDiskNumber
;
51 LONG UnattendDestinationPartitionNumber
;
52 LONG UnattendMBRInstallType
= -1;
53 LONG UnattendFormatPartition
= 0;
54 LONG AutoPartition
= 0;
55 WCHAR UnattendInstallationDirectory
[MAX_PATH
];
56 PWCHAR SelectedLanguageId
;
58 WCHAR DefaultLanguage
[20];
59 WCHAR DefaultKBLayout
[20];
60 BOOLEAN RepairUpdateFlag
= FALSE
;
61 HANDLE hPnpThread
= INVALID_HANDLE_VALUE
;
62 PPARTLIST PartitionList
= NULL
;
64 /* LOCALS *******************************************************************/
66 static PFILE_SYSTEM_LIST FileSystemList
= NULL
;
68 static UNICODE_STRING InstallPath
;
71 * Path to the system partition, where the boot manager resides.
72 * On x86 PCs, this is usually the active partition.
73 * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
75 * For more information, see:
76 * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
77 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
78 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
79 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
80 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
81 * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
83 static UNICODE_STRING SystemRootPath
;
85 /* Path to the install directory inside the ReactOS boot partition */
86 static UNICODE_STRING DestinationPath
;
87 static UNICODE_STRING DestinationArcPath
;
88 static UNICODE_STRING DestinationRootPath
;
90 static WCHAR DestinationDriveLetter
;
94 static HSPFILEQ SetupFileQueue
= NULL
;
96 static PGENERIC_LIST ComputerList
= NULL
;
97 static PGENERIC_LIST DisplayList
= NULL
;
98 static PGENERIC_LIST KeyboardList
= NULL
;
99 static PGENERIC_LIST LayoutList
= NULL
;
100 static PGENERIC_LIST LanguageList
= NULL
;
102 static LANGID LanguageId
= 0;
104 static ULONG RequiredPartitionDiskSpace
= ~0;
106 /* FUNCTIONS ****************************************************************/
109 PrintString(char* fmt
,...)
113 UNICODE_STRING UnicodeString
;
114 ANSI_STRING AnsiString
;
117 vsprintf(buffer
, fmt
, ap
);
120 RtlInitAnsiString(&AnsiString
, buffer
);
121 RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, TRUE
);
122 NtDisplayString(&UnicodeString
);
123 RtlFreeUnicodeString(&UnicodeString
);
128 DrawBox(IN SHORT xLeft
,
136 /* draw upper left corner */
139 FillConsoleOutputCharacterA(StdOutput
,
145 /* draw upper edge */
148 FillConsoleOutputCharacterA(StdOutput
,
154 /* draw upper right corner */
155 coPos
.X
= xLeft
+ Width
- 1;
157 FillConsoleOutputCharacterA(StdOutput
,
163 /* Draw right edge, inner space and left edge */
164 for (coPos
.Y
= yTop
+ 1; coPos
.Y
< yTop
+ Height
- 1; coPos
.Y
++)
167 FillConsoleOutputCharacterA(StdOutput
,
174 FillConsoleOutputCharacterA(StdOutput
,
180 coPos
.X
= xLeft
+ Width
- 1;
181 FillConsoleOutputCharacterA(StdOutput
,
188 /* draw lower left corner */
190 coPos
.Y
= yTop
+ Height
- 1;
191 FillConsoleOutputCharacterA(StdOutput
,
197 /* draw lower edge */
199 coPos
.Y
= yTop
+ Height
- 1;
200 FillConsoleOutputCharacterA(StdOutput
,
206 /* draw lower right corner */
207 coPos
.X
= xLeft
+ Width
- 1;
208 coPos
.Y
= yTop
+ Height
- 1;
209 FillConsoleOutputCharacterA(StdOutput
,
218 PopupError(PCCH Text
,
236 /* Count text lines and longest line */
243 p
= strchr(pnext
, '\n');
247 Length
= strlen(pnext
);
252 Length
= (ULONG
)(p
- pnext
);
258 if (Length
> MaxLength
)
261 if (LastLine
!= FALSE
)
267 /* Check length of status line */
270 Length
= strlen(Status
);
272 if (Length
> MaxLength
)
276 Width
= MaxLength
+ 4;
282 yTop
= (yScreen
- Height
) / 2;
283 xLeft
= (xScreen
- Width
) / 2;
286 /* Set screen attributes */
288 for (coPos
.Y
= yTop
; coPos
.Y
< yTop
+ Height
; coPos
.Y
++)
290 FillConsoleOutputAttribute(StdOutput
,
291 FOREGROUND_RED
| BACKGROUND_WHITE
,
297 DrawBox(xLeft
, yTop
, Width
, Height
);
299 /* Print message text */
304 p
= strchr(pnext
, '\n');
308 Length
= strlen(pnext
);
313 Length
= (ULONG
)(p
- pnext
);
320 WriteConsoleOutputCharacterA(StdOutput
,
327 if (LastLine
!= FALSE
)
334 /* Print separator line and status text */
337 coPos
.Y
= yTop
+ Height
- 3;
339 FillConsoleOutputCharacterA(StdOutput
,
346 FillConsoleOutputCharacterA(StdOutput
,
352 coPos
.X
= xLeft
+ Width
- 1;
353 FillConsoleOutputCharacterA(StdOutput
,
361 WriteConsoleOutputCharacterA(StdOutput
,
363 min(strlen(Status
), (SIZE_T
)Width
- 4),
368 if (WaitEvent
== POPUP_WAIT_NONE
)
373 CONSOLE_ConInKey(Ir
);
375 if (WaitEvent
== POPUP_WAIT_ANY_KEY
||
376 Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D)
388 * FALSE: Don't quit setup.
391 ConfirmQuit(PINPUT_RECORD Ir
)
394 MUIDisplayError(ERROR_NOT_INSTALLED
, NULL
, POPUP_WAIT_NONE
);
398 CONSOLE_ConInKey(Ir
);
400 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
401 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
406 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
418 CheckUnattendedSetup(VOID
)
420 WCHAR UnattendInfPath
[MAX_PATH
];
427 if (DoesFileExist(NULL
, SourcePath
.Buffer
, L
"unattend.inf") == FALSE
)
429 DPRINT("Does not exist: %S\\%S\n", SourcePath
.Buffer
, L
"unattend.inf");
433 wcscpy(UnattendInfPath
, SourcePath
.Buffer
);
434 wcscat(UnattendInfPath
, L
"\\unattend.inf");
436 /* Load 'unattend.inf' from install media. */
437 UnattendInf
= SetupOpenInfFileW(UnattendInfPath
,
443 if (UnattendInf
== INVALID_HANDLE_VALUE
)
445 DPRINT("SetupOpenInfFileW() failed\n");
449 /* Open 'Unattend' section */
450 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"Signature", &Context
))
452 DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
453 SetupCloseInfFile(UnattendInf
);
457 /* Get pointer 'Signature' key */
458 if (!INF_GetData(&Context
, NULL
, &Value
))
460 DPRINT("INF_GetData() failed for key 'Signature'\n");
461 SetupCloseInfFile(UnattendInf
);
465 /* Check 'Signature' string */
466 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
468 DPRINT("Signature not $ReactOS$\n");
469 SetupCloseInfFile(UnattendInf
);
473 /* Check if Unattend setup is enabled */
474 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"UnattendSetupEnabled", &Context
))
476 DPRINT("Can't find key 'UnattendSetupEnabled'\n");
477 SetupCloseInfFile(UnattendInf
);
481 if (!INF_GetData(&Context
, NULL
, &Value
))
483 DPRINT("Can't read key 'UnattendSetupEnabled'\n");
484 SetupCloseInfFile(UnattendInf
);
488 if (_wcsicmp(Value
, L
"yes") != 0)
490 DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
491 SetupCloseInfFile(UnattendInf
);
495 /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
496 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationDiskNumber", &Context
))
498 DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n");
499 SetupCloseInfFile(UnattendInf
);
503 if (!SetupGetIntField(&Context
, 1, &IntValue
))
505 DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
506 SetupCloseInfFile(UnattendInf
);
510 UnattendDestinationDiskNumber
= (LONG
)IntValue
;
512 /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
513 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"DestinationPartitionNumber", &Context
))
515 DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n");
516 SetupCloseInfFile(UnattendInf
);
520 if (!SetupGetIntField(&Context
, 1, &IntValue
))
522 DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n");
523 SetupCloseInfFile(UnattendInf
);
527 UnattendDestinationPartitionNumber
= IntValue
;
529 /* Search for 'InstallationDirectory' in the 'Unattend' section */
530 if (!SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"InstallationDirectory", &Context
))
532 DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n");
533 SetupCloseInfFile(UnattendInf
);
537 /* Get pointer 'InstallationDirectory' key */
538 if (!INF_GetData(&Context
, NULL
, &Value
))
540 DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
541 SetupCloseInfFile(UnattendInf
);
545 wcscpy(UnattendInstallationDirectory
, Value
);
547 IsUnattendedSetup
= TRUE
;
549 /* Search for 'MBRInstallType' in the 'Unattend' section */
550 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"MBRInstallType", &Context
))
552 if (SetupGetIntField(&Context
, 1, &IntValue
))
554 UnattendMBRInstallType
= IntValue
;
558 /* Search for 'FormatPartition' in the 'Unattend' section */
559 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"FormatPartition", &Context
))
561 if (SetupGetIntField(&Context
, 1, &IntValue
))
563 UnattendFormatPartition
= IntValue
;
567 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"AutoPartition", &Context
))
569 if (SetupGetIntField(&Context
, 1, &IntValue
))
571 AutoPartition
= IntValue
;
575 /* search for LocaleID in the 'Unattend' section*/
576 if (SetupFindFirstLineW(UnattendInf
, L
"Unattend", L
"LocaleID", &Context
))
578 if (INF_GetData(&Context
, NULL
, &Value
))
580 LONG Id
= wcstol(Value
, NULL
, 16);
581 swprintf(LocaleID
,L
"%08lx", Id
);
585 SetupCloseInfFile(UnattendInf
);
587 DPRINT("Running unattended setup\n");
594 PGENERIC_LIST_ENTRY ListEntry
;
595 LPCWSTR pszNewLayout
;
597 pszNewLayout
= MUIDefaultKeyboardLayout();
599 if (LayoutList
== NULL
)
601 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
602 if (LayoutList
== NULL
)
604 /* FIXME: Handle error! */
609 ListEntry
= GetFirstListEntry(LayoutList
);
611 /* Search for default layout (if provided) */
612 if (pszNewLayout
!= NULL
)
614 while (ListEntry
!= NULL
)
616 if (!wcscmp(pszNewLayout
, GetListEntryUserData(ListEntry
)))
618 SetCurrentListEntry(LayoutList
, ListEntry
);
622 ListEntry
= GetNextListEntry(ListEntry
);
629 * Displays the LanguagePage.
631 * Next pages: IntroPage, QuitPage
634 * Init SelectedLanguageId
638 * Number of the next page.
641 LanguagePage(PINPUT_RECORD Ir
)
643 GENERIC_LIST_UI ListUi
;
644 PWCHAR NewLanguageId
;
645 BOOL RefreshPage
= FALSE
;
647 /* Initialize the computer settings list */
648 if (LanguageList
== NULL
)
650 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
651 if (LanguageList
== NULL
)
653 PopupError("Setup failed to initialize available translations", NULL
, NULL
, POPUP_WAIT_NONE
);
659 SelectedLanguageId
= DefaultLanguage
;
660 SetConsoleCodePage();
663 /* If there's just a single language in the list skip
664 * the language selection process altogether! */
665 if (GenericListHasSingleEntry(LanguageList
))
667 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
671 InitGenericListUi(&ListUi
, LanguageList
);
672 DrawGenericList(&ListUi
,
678 ScrollToPositionGenericList(&ListUi
, GetDefaultLanguageIndex());
680 MUIDisplayPage(LANGUAGE_PAGE
);
684 CONSOLE_ConInKey(Ir
);
686 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
687 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
689 ScrollDownGenericList(&ListUi
);
692 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
693 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
695 ScrollUpGenericList(&ListUi
);
698 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
699 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
701 ScrollPageDownGenericList(&ListUi
);
704 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
705 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
707 ScrollPageUpGenericList(&ListUi
);
710 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
711 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
713 if (ConfirmQuit(Ir
) != FALSE
)
716 RedrawGenericList(&ListUi
);
718 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
720 SelectedLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
722 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
724 if (wcscmp(SelectedLanguageId
, DefaultLanguage
))
730 SetConsoleCodePage();
734 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
737 GenericListKeyPress(&ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
743 NewLanguageId
= (PWCHAR
)GetListEntryUserData(GetCurrentListEntry(LanguageList
));
745 if (SelectedLanguageId
!= NewLanguageId
)
747 /* Clear the language page */
748 MUIClearPage(LANGUAGE_PAGE
);
750 SelectedLanguageId
= NewLanguageId
;
753 SetConsoleCodePage();
755 /* Redraw language selection page in native language */
756 MUIDisplayPage(LANGUAGE_PAGE
);
771 * LanguagePage (at once, default)
772 * InstallIntroPage (at once, if unattended)
778 * Init SourceRootPath
781 * Init RequiredPartitionDiskSpace
782 * Init IsUnattendedSetup
783 * If unattended, init *List and sets the Codepage
784 * If unattended, init SelectedLanguageId
785 * If unattended, init LanguageId
788 * Number of the next page.
791 SetupStartPage(PINPUT_RECORD Ir
)
794 WCHAR FileNameBuffer
[MAX_PATH
];
798 PGENERIC_LIST_ENTRY ListEntry
;
801 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
803 /* Get the source path and source root path */
804 Status
= GetSourcePaths(&SourcePath
,
808 if (!NT_SUCCESS(Status
))
810 CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status
);
811 MUIDisplayError(ERROR_NO_SOURCE_DRIVE
, Ir
, POPUP_WAIT_ENTER
);
817 CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath
);
818 CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath
);
819 CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir
);
823 /* Load txtsetup.sif from install media. */
824 wcscpy(FileNameBuffer
, SourcePath
.Buffer
);
825 wcscat(FileNameBuffer
, L
"\\txtsetup.sif");
827 SetupInf
= SetupOpenInfFileW(FileNameBuffer
,
833 if (SetupInf
== INVALID_HANDLE_VALUE
)
835 MUIDisplayError(ERROR_LOAD_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
839 /* Open 'Version' section */
840 if (!SetupFindFirstLineW(SetupInf
, L
"Version", L
"Signature", &Context
))
842 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
846 /* Get pointer 'Signature' key */
847 if (!INF_GetData(&Context
, NULL
, &Value
))
849 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
853 /* Check 'Signature' string */
854 if (_wcsicmp(Value
, L
"$ReactOS$") != 0)
856 MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
860 /* Open 'DiskSpaceRequirements' section */
861 if (!SetupFindFirstLineW(SetupInf
, L
"DiskSpaceRequirements", L
"FreeSysPartDiskSpace", &Context
))
863 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
867 /* Get the 'FreeSysPartDiskSpace' value */
868 if (!SetupGetIntField(&Context
, 1, &IntValue
))
870 MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF
, Ir
, POPUP_WAIT_ENTER
);
874 RequiredPartitionDiskSpace
= (ULONG
)IntValue
;
876 /* Start the PnP thread */
877 if (hPnpThread
!= INVALID_HANDLE_VALUE
)
879 NtResumeThread(hPnpThread
, NULL
);
880 hPnpThread
= INVALID_HANDLE_VALUE
;
883 CheckUnattendedSetup();
885 if (IsUnattendedSetup
)
887 // TODO: Read options from inf
888 ComputerList
= CreateComputerTypeList(SetupInf
);
889 DisplayList
= CreateDisplayDriverList(SetupInf
);
890 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
891 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
892 LanguageList
= CreateLanguageList(SetupInf
, DefaultLanguage
);
895 wcscpy(SelectedLanguageId
, LocaleID
);
896 LanguageId
= (LANGID
)(wcstol(SelectedLanguageId
, NULL
, 16) & 0xFFFF);
898 /* first we hack LanguageList */
899 ListEntry
= GetFirstListEntry(LanguageList
);
900 while (ListEntry
!= NULL
)
902 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
904 DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry
));
905 SetCurrentListEntry(LanguageList
, ListEntry
);
909 ListEntry
= GetNextListEntry(ListEntry
);
913 ListEntry
= GetFirstListEntry(LayoutList
);
914 while (ListEntry
!= NULL
)
916 if (!wcsicmp(LocaleID
, GetListEntryUserData(ListEntry
)))
918 DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry
));
919 SetCurrentListEntry(LayoutList
, ListEntry
);
923 ListEntry
= GetNextListEntry(ListEntry
);
926 SetConsoleCodePage();
928 return INSTALL_INTRO_PAGE
;
931 return LANGUAGE_PAGE
;
936 * Displays the IntroPage.
939 * InstallIntroPage (default)
945 * Number of the next page.
948 IntroPage(PINPUT_RECORD Ir
)
950 MUIDisplayPage(START_PAGE
);
954 CONSOLE_ConInKey(Ir
);
956 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
957 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
959 if (ConfirmQuit(Ir
) != FALSE
)
964 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
966 return INSTALL_INTRO_PAGE
;
968 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
970 return REPAIR_INTRO_PAGE
;
972 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'L') /* L */
983 * Displays the License page.
986 * IntroPage (default)
989 * Number of the next page.
992 LicensePage(PINPUT_RECORD Ir
)
994 MUIDisplayPage(LICENSE_PAGE
);
998 CONSOLE_ConInKey(Ir
);
1000 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1006 return LICENSE_PAGE
;
1011 * Displays the RepairIntroPage.
1014 * RebootPage (default)
1020 * Number of the next page.
1023 RepairIntroPage(PINPUT_RECORD Ir
)
1025 MUIDisplayPage(REPAIR_INTRO_PAGE
);
1029 CONSOLE_ConInKey(Ir
);
1031 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1035 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'U') /* U */
1037 RepairUpdateFlag
= TRUE
;
1038 return INSTALL_INTRO_PAGE
;
1040 else if (toupper(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
) == 'R') /* R */
1042 return RECOVERY_PAGE
;
1044 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1045 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1051 return REPAIR_INTRO_PAGE
;
1055 * Displays the InstallIntroPage.
1058 * DeviceSettingsPage (At once if repair or update is selected)
1059 * SelectPartitionPage (At once if unattended setup)
1060 * DeviceSettingsPage (default)
1064 * Number of the next page.
1067 InstallIntroPage(PINPUT_RECORD Ir
)
1069 MUIDisplayPage(INSTALL_INTRO_PAGE
);
1071 if (RepairUpdateFlag
)
1073 //return SELECT_PARTITION_PAGE;
1074 return DEVICE_SETTINGS_PAGE
;
1077 if (IsUnattendedSetup
)
1079 return SELECT_PARTITION_PAGE
;
1084 CONSOLE_ConInKey(Ir
);
1086 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1087 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1089 if (ConfirmQuit(Ir
) != FALSE
)
1094 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1096 return DEVICE_SETTINGS_PAGE
;
1097 // return SCSI_CONTROLLER_PAGE;
1101 return INSTALL_INTRO_PAGE
;
1107 ScsiControllerPage(PINPUT_RECORD Ir
)
1109 SetTextXY(6, 8, "Setup detected the following mass storage devices:");
1111 /* FIXME: print loaded mass storage driver descriptions */
1113 SetTextXY(8, 10, "TEST device");
1117 SetStatusText(" ENTER = Continue F3 = Quit");
1123 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1124 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1126 if (ConfirmQuit(Ir
) != FALSE
)
1131 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1133 return DEVICE_SETTINGS_PAGE
;
1137 return SCSI_CONTROLLER_PAGE
;
1143 * Displays the DeviceSettingsPage.
1146 * SelectPartitionPage (At once if repair or update is selected)
1147 * ComputerSettingsPage
1148 * DisplaySettingsPage
1149 * KeyboardSettingsPage
1150 * LayoutsettingsPage
1151 * SelectPartitionPage
1161 * Number of the next page.
1164 DeviceSettingsPage(PINPUT_RECORD Ir
)
1166 static ULONG Line
= 16;
1167 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1169 /* Initialize the computer settings list */
1170 if (ComputerList
== NULL
)
1172 ComputerList
= CreateComputerTypeList(SetupInf
);
1173 if (ComputerList
== NULL
)
1175 MUIDisplayError(ERROR_LOAD_COMPUTER
, Ir
, POPUP_WAIT_ENTER
);
1180 /* Initialize the display settings list */
1181 if (DisplayList
== NULL
)
1183 DisplayList
= CreateDisplayDriverList(SetupInf
);
1184 if (DisplayList
== NULL
)
1186 MUIDisplayError(ERROR_LOAD_DISPLAY
, Ir
, POPUP_WAIT_ENTER
);
1191 /* Initialize the keyboard settings list */
1192 if (KeyboardList
== NULL
)
1194 KeyboardList
= CreateKeyboardDriverList(SetupInf
);
1195 if (KeyboardList
== NULL
)
1197 MUIDisplayError(ERROR_LOAD_KEYBOARD
, Ir
, POPUP_WAIT_ENTER
);
1202 /* Initialize the keyboard layout list */
1203 if (LayoutList
== NULL
)
1205 LayoutList
= CreateKeyboardLayoutList(SetupInf
, DefaultKBLayout
);
1206 if (LayoutList
== NULL
)
1208 /* FIXME: report error */
1209 MUIDisplayError(ERROR_LOAD_KBLAYOUT
, Ir
, POPUP_WAIT_ENTER
);
1214 MUIDisplayPage(DEVICE_SETTINGS_PAGE
);
1217 CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList
))));
1218 CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList
))));
1219 CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList
))));
1220 CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList
))));
1222 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1224 if (RepairUpdateFlag
)
1226 return SELECT_PARTITION_PAGE
;
1231 CONSOLE_ConInKey(Ir
);
1233 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1234 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1236 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1240 else if (Line
== 16)
1245 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1247 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1248 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1250 CONSOLE_NormalTextXY(24, Line
, 48, 1);
1254 else if (Line
== 16)
1259 CONSOLE_InvertTextXY(24, Line
, 48, 1);
1261 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1262 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1264 if (ConfirmQuit(Ir
) != FALSE
)
1269 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1272 return COMPUTER_SETTINGS_PAGE
;
1273 else if (Line
== 12)
1274 return DISPLAY_SETTINGS_PAGE
;
1275 else if (Line
== 13)
1276 return KEYBOARD_SETTINGS_PAGE
;
1277 else if (Line
== 14)
1278 return LAYOUT_SETTINGS_PAGE
;
1279 else if (Line
== 16)
1280 return SELECT_PARTITION_PAGE
;
1284 return DEVICE_SETTINGS_PAGE
;
1289 * Handles generic selection lists.
1292 * GenericList: The list to handle.
1293 * nextPage: The page it needs to jump to after this page.
1294 * Ir: The PINPUT_RECORD
1297 HandleGenericList(PGENERIC_LIST_UI ListUi
,
1298 PAGE_NUMBER nextPage
,
1303 CONSOLE_ConInKey(Ir
);
1305 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1306 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1308 ScrollDownGenericList(ListUi
);
1310 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1311 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1313 ScrollUpGenericList(ListUi
);
1315 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1316 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_NEXT
)) /* PAGE DOWN */
1318 ScrollPageDownGenericList(ListUi
);
1320 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1321 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_PRIOR
)) /* PAGE UP */
1323 ScrollPageUpGenericList(ListUi
);
1325 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1326 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1328 if (ConfirmQuit(Ir
) != FALSE
)
1331 RedrawGenericList(ListUi
);
1333 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1334 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
1336 RestoreGenericListState(ListUi
->List
);
1337 return nextPage
; // Use some "prevPage;" instead?
1339 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
1343 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
> 0x60) && (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
< 0x7b))
1346 GenericListKeyPress(ListUi
, Ir
->Event
.KeyEvent
.uChar
.AsciiChar
);
1353 * Displays the ComputerSettingsPage.
1356 * DeviceSettingsPage
1360 * Number of the next page.
1363 ComputerSettingsPage(PINPUT_RECORD Ir
)
1365 GENERIC_LIST_UI ListUi
;
1366 MUIDisplayPage(COMPUTER_SETTINGS_PAGE
);
1368 InitGenericListUi(&ListUi
, ComputerList
);
1369 DrawGenericList(&ListUi
,
1375 SaveGenericListState(ComputerList
);
1377 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1382 * Displays the DisplaySettingsPage.
1385 * DeviceSettingsPage
1389 * Number of the next page.
1392 DisplaySettingsPage(PINPUT_RECORD Ir
)
1394 GENERIC_LIST_UI ListUi
;
1395 MUIDisplayPage(DISPLAY_SETTINGS_PAGE
);
1397 InitGenericListUi(&ListUi
, DisplayList
);
1398 DrawGenericList(&ListUi
,
1404 SaveGenericListState(DisplayList
);
1406 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1411 * Displays the KeyboardSettingsPage.
1414 * DeviceSettingsPage
1418 * Number of the next page.
1421 KeyboardSettingsPage(PINPUT_RECORD Ir
)
1423 GENERIC_LIST_UI ListUi
;
1424 MUIDisplayPage(KEYBOARD_SETTINGS_PAGE
);
1426 InitGenericListUi(&ListUi
, KeyboardList
);
1427 DrawGenericList(&ListUi
,
1433 SaveGenericListState(KeyboardList
);
1435 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1440 * Displays the LayoutSettingsPage.
1443 * DeviceSettingsPage
1447 * Number of the next page.
1450 LayoutSettingsPage(PINPUT_RECORD Ir
)
1452 GENERIC_LIST_UI ListUi
;
1453 MUIDisplayPage(LAYOUT_SETTINGS_PAGE
);
1455 InitGenericListUi(&ListUi
, LayoutList
);
1456 DrawGenericList(&ListUi
,
1462 SaveGenericListState(LayoutList
);
1464 return HandleGenericList(&ListUi
, DEVICE_SETTINGS_PAGE
, Ir
);
1469 IsDiskSizeValid(PPARTENTRY PartEntry
)
1473 size
= PartEntry
->SectorCount
.QuadPart
* PartEntry
->DiskEntry
->BytesPerSector
;
1474 size
= (size
+ 524288) / 1048576; /* in MBytes */
1476 if (size
< RequiredPartitionDiskSpace
)
1478 /* partition is too small so ask for another partition */
1479 DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size
, RequiredPartitionDiskSpace
);
1490 * Displays the SelectPartitionPage.
1493 * SelectFileSystemPage (At once if unattended)
1494 * SelectFileSystemPage (Default if free space is selected)
1495 * CreatePrimaryPartitionPage
1496 * CreateExtendedPartitionPage
1497 * CreateLogicalPartitionPage
1498 * ConfirmDeleteSystemPartitionPage (if the selected partition is the system partition, aka with the boot flag set)
1499 * DeletePartitionPage
1503 * Init DestinationDriveLetter (only if unattended or not free space is selected)
1504 * Set InstallShortcut (only if not unattended + free space is selected)
1507 * Number of the next page.
1510 SelectPartitionPage(PINPUT_RECORD Ir
)
1515 MUIDisplayPage(SELECT_PARTITION_PAGE
);
1517 if (PartitionList
== NULL
)
1519 PartitionList
= CreatePartitionList();
1520 if (PartitionList
== NULL
)
1522 /* FIXME: show an error dialog */
1523 MUIDisplayError(ERROR_DRIVE_INFORMATION
, Ir
, POPUP_WAIT_ENTER
);
1526 else if (IsListEmpty(&PartitionList
->DiskListHead
))
1528 MUIDisplayError(ERROR_NO_HDD
, Ir
, POPUP_WAIT_ENTER
);
1533 InitPartitionListUi(&ListUi
, PartitionList
,
1538 DrawPartitionList(&ListUi
);
1540 if (IsUnattendedSetup
)
1542 if (!SelectPartition(PartitionList
, UnattendDestinationDiskNumber
, UnattendDestinationPartitionNumber
))
1546 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1548 CreateLogicalPartition(PartitionList
,
1549 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1554 CreatePrimaryPartition(PartitionList
,
1555 PartitionList
->CurrentPartition
->SectorCount
.QuadPart
,
1559 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1560 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1562 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1563 RequiredPartitionDiskSpace
);
1564 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1567 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1569 return SELECT_FILE_SYSTEM_PAGE
;
1574 DrawPartitionList(&ListUi
);
1576 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
1577 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1579 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1580 RequiredPartitionDiskSpace
);
1581 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1584 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1586 return SELECT_FILE_SYSTEM_PAGE
;
1592 /* Update status text */
1593 if (PartitionList
->CurrentPartition
== NULL
)
1595 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1597 else if (PartitionList
->CurrentPartition
->LogicalPartition
)
1599 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1601 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1605 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL
));
1610 if (PartitionList
->CurrentPartition
->IsPartitioned
)
1612 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1614 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION
));
1618 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION
));
1623 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION
));
1627 CONSOLE_ConInKey(Ir
);
1629 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1630 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1632 if (ConfirmQuit(Ir
) != FALSE
)
1634 DestroyPartitionList(PartitionList
);
1635 PartitionList
= NULL
;
1641 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1642 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
1644 ScrollDownPartitionList(&ListUi
);
1646 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1647 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
1649 ScrollUpPartitionList(&ListUi
);
1651 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1653 if (IsContainerPartition(PartitionList
->CurrentPartition
->PartitionType
))
1654 continue; // return SELECT_PARTITION_PAGE;
1656 if (PartitionList
->CurrentPartition
== NULL
||
1657 PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1659 if (PartitionList
->CurrentPartition
->LogicalPartition
)
1661 CreateLogicalPartition(PartitionList
,
1667 CreatePrimaryPartition(PartitionList
,
1673 if (!IsDiskSizeValid(PartitionList
->CurrentPartition
))
1675 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE
, Ir
, POPUP_WAIT_ANY_KEY
,
1676 RequiredPartitionDiskSpace
);
1677 return SELECT_PARTITION_PAGE
; /* let the user select another partition */
1680 DestinationDriveLetter
= (WCHAR
)PartitionList
->CurrentPartition
->DriveLetter
;
1682 return SELECT_FILE_SYSTEM_PAGE
;
1684 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'P') /* P */
1686 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1688 Error
= PrimaryPartitionCreationChecks(PartitionList
);
1689 if (Error
!= NOT_AN_ERROR
)
1691 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1692 return SELECT_PARTITION_PAGE
;
1695 return CREATE_PRIMARY_PARTITION_PAGE
;
1698 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'E') /* E */
1700 if (PartitionList
->CurrentPartition
->LogicalPartition
== FALSE
)
1702 Error
= ExtendedPartitionCreationChecks(PartitionList
);
1703 if (Error
!= NOT_AN_ERROR
)
1705 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1706 return SELECT_PARTITION_PAGE
;
1709 return CREATE_EXTENDED_PARTITION_PAGE
;
1712 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'L') /* L */
1714 if (PartitionList
->CurrentPartition
->LogicalPartition
!= FALSE
)
1716 Error
= LogicalPartitionCreationChecks(PartitionList
);
1717 if (Error
!= NOT_AN_ERROR
)
1719 MUIDisplayError(Error
, Ir
, POPUP_WAIT_ANY_KEY
);
1720 return SELECT_PARTITION_PAGE
;
1723 return CREATE_LOGICAL_PARTITION_PAGE
;
1726 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
1728 if (PartitionList
->CurrentPartition
->IsPartitioned
== FALSE
)
1730 MUIDisplayError(ERROR_DELETE_SPACE
, Ir
, POPUP_WAIT_ANY_KEY
);
1731 return SELECT_PARTITION_PAGE
;
1734 if (PartitionList
->CurrentPartition
->BootIndicator
||
1735 PartitionList
->CurrentPartition
== PartitionList
->SystemPartition
)
1737 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
1740 return DELETE_PARTITION_PAGE
;
1744 return SELECT_PARTITION_PAGE
;
1748 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
1749 /* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
1750 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
1753 ShowPartitionSizeInputBox(SHORT Left
,
1777 DrawBox(Left
, Top
, Right
- Left
+ 1, Bottom
- Top
+ 1);
1782 strcpy(Buffer
, MUIGetString(STRING_PARTITIONSIZE
));
1783 iLeft
= coPos
.X
+ strlen(Buffer
) + 1;
1786 WriteConsoleOutputCharacterA(StdOutput
,
1792 sprintf(Buffer
, MUIGetString(STRING_MAXSIZE
), MaxSize
);
1793 coPos
.X
= iLeft
+ PARTITION_SIZE_INPUT_FIELD_LENGTH
+ 1;
1795 WriteConsoleOutputCharacterA(StdOutput
,
1801 swprintf(InputBuffer
, L
"%lu", MaxSize
);
1802 Length
= wcslen(InputBuffer
);
1804 CONSOLE_SetInputTextXY(iLeft
,
1806 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1808 CONSOLE_SetCursorXY(iLeft
+ Length
, iTop
);
1809 CONSOLE_SetCursorType(TRUE
, TRUE
);
1813 CONSOLE_ConInKey(&Ir
);
1815 if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1816 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
1821 InputBuffer
[0] = UNICODE_NULL
;
1822 CONSOLE_SetCursorType(TRUE
, FALSE
);
1825 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
1827 CONSOLE_SetCursorType(TRUE
, FALSE
);
1830 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESCAPE */
1835 InputBuffer
[0] = UNICODE_NULL
;
1836 CONSOLE_SetCursorType(TRUE
, FALSE
);
1839 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1840 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
1843 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1845 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1846 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
1849 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1851 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1852 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
1857 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1860 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1861 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
1866 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1869 else if ((Ir
.Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
1870 (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
1874 memmove(&InputBuffer
[Pos
],
1875 &InputBuffer
[Pos
+ 1],
1876 (Length
- Pos
- 1) * sizeof(WCHAR
));
1877 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1880 CONSOLE_SetInputTextXY(iLeft
,
1882 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1884 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1887 else if (Ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_BACK
) /* BACKSPACE */
1892 memmove(&InputBuffer
[Pos
- 1],
1894 (Length
- Pos
) * sizeof(WCHAR
));
1895 InputBuffer
[Length
- 1] = UNICODE_NULL
;
1899 CONSOLE_SetInputTextXY(iLeft
,
1901 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1903 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1906 else if (Ir
.Event
.KeyEvent
.uChar
.AsciiChar
!= 0x00)
1908 if (Length
< PARTITION_SIZE_INPUT_FIELD_LENGTH
- 1)
1910 ch
= (WCHAR
)Ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
1912 if ((ch
>= L
'0') && (ch
<= L
'9'))
1915 memmove(&InputBuffer
[Pos
+ 1],
1917 (Length
- Pos
) * sizeof(WCHAR
));
1918 InputBuffer
[Length
+ 1] = UNICODE_NULL
;
1919 InputBuffer
[Pos
] = ch
;
1923 CONSOLE_SetInputTextXY(iLeft
,
1925 PARTITION_SIZE_INPUT_FIELD_LENGTH
,
1927 CONSOLE_SetCursorXY(iLeft
+ Pos
, iTop
);
1936 * Displays the CreatePrimaryPartitionPage.
1939 * SelectPartitionPage
1940 * SelectFileSystemPage (default)
1944 * Number of the next page.
1947 CreatePrimaryPartitionPage(PINPUT_RECORD Ir
)
1949 PDISKENTRY DiskEntry
;
1950 PPARTENTRY PartEntry
;
1953 WCHAR InputBuffer
[50];
1957 ULONGLONG SectorCount
;
1960 if (PartitionList
== NULL
||
1961 PartitionList
->CurrentDisk
== NULL
||
1962 PartitionList
->CurrentPartition
== NULL
)
1964 /* FIXME: show an error dialog */
1968 DiskEntry
= PartitionList
->CurrentDisk
;
1969 PartEntry
= PartitionList
->CurrentPartition
;
1971 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
1973 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION
));
1975 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1977 if (DiskSize
>= 10737418240) /* 10 GB */
1979 DiskSize
= DiskSize
/ 1073741824;
1980 Unit
= MUIGetString(STRING_GB
);
1985 DiskSize
= DiskSize
/ 1048576;
1989 Unit
= MUIGetString(STRING_MB
);
1992 if (DiskEntry
->DriverName
.Length
> 0)
1994 CONSOLE_PrintTextXY(6, 10,
1995 MUIGetString(STRING_HDINFOPARTCREATE
),
1998 DiskEntry
->DiskNumber
,
2002 &DiskEntry
->DriverName
);
2006 CONSOLE_PrintTextXY(6, 10,
2007 MUIGetString(STRING_HDDINFOUNK1
),
2010 DiskEntry
->DiskNumber
,
2016 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2019 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2020 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2023 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2025 PartEntry
= PartitionList
->CurrentPartition
;
2028 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2030 if (MaxSize
> PARTITION_MAXSIZE
)
2031 MaxSize
= PARTITION_MAXSIZE
;
2033 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2034 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2038 if (ConfirmQuit(Ir
) != FALSE
)
2043 else if (Cancel
!= FALSE
)
2045 return SELECT_PARTITION_PAGE
;
2049 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2057 if (PartSize
> MaxSize
)
2063 /* Convert to bytes */
2064 if (PartSize
== MaxSize
)
2066 /* Use all of the unpartitioned disk space */
2067 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2071 /* Calculate the sector count from the size in MB */
2072 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2074 /* But never get larger than the unpartitioned disk space */
2075 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2076 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2079 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2081 CreatePrimaryPartition(PartitionList
,
2085 return SELECT_PARTITION_PAGE
;
2089 return CREATE_PRIMARY_PARTITION_PAGE
;
2094 * Displays the CreateExtendedPartitionPage.
2097 * SelectPartitionPage (default)
2101 * Number of the next page.
2104 CreateExtendedPartitionPage(PINPUT_RECORD Ir
)
2106 PDISKENTRY DiskEntry
;
2107 PPARTENTRY PartEntry
;
2110 WCHAR InputBuffer
[50];
2114 ULONGLONG SectorCount
;
2117 if (PartitionList
== NULL
||
2118 PartitionList
->CurrentDisk
== NULL
||
2119 PartitionList
->CurrentPartition
== NULL
)
2121 /* FIXME: show an error dialog */
2125 DiskEntry
= PartitionList
->CurrentDisk
;
2126 PartEntry
= PartitionList
->CurrentPartition
;
2128 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2130 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_EXTENDED_PARTITION
));
2132 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2134 if (DiskSize
>= 10737418240) /* 10 GB */
2136 DiskSize
= DiskSize
/ 1073741824;
2137 Unit
= MUIGetString(STRING_GB
);
2142 DiskSize
= DiskSize
/ 1048576;
2146 Unit
= MUIGetString(STRING_MB
);
2149 if (DiskEntry
->DriverName
.Length
> 0)
2151 CONSOLE_PrintTextXY(6, 10,
2152 MUIGetString(STRING_HDINFOPARTCREATE
),
2155 DiskEntry
->DiskNumber
,
2159 &DiskEntry
->DriverName
);
2163 CONSOLE_PrintTextXY(6, 10,
2164 MUIGetString(STRING_HDDINFOUNK1
),
2167 DiskEntry
->DiskNumber
,
2173 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2176 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2177 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2180 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2182 PartEntry
= PartitionList
->CurrentPartition
;
2185 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2187 if (MaxSize
> PARTITION_MAXSIZE
)
2188 MaxSize
= PARTITION_MAXSIZE
;
2190 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2191 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2195 if (ConfirmQuit(Ir
) != FALSE
)
2200 else if (Cancel
!= FALSE
)
2202 return SELECT_PARTITION_PAGE
;
2206 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2214 if (PartSize
> MaxSize
)
2220 /* Convert to bytes */
2221 if (PartSize
== MaxSize
)
2223 /* Use all of the unpartitioned disk space */
2224 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2228 /* Calculate the sector count from the size in MB */
2229 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2231 /* But never get larger than the unpartitioned disk space */
2232 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2233 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2236 DPRINT ("Partition size: %I64u bytes\n", PartSize
);
2238 CreateExtendedPartition(PartitionList
,
2241 return SELECT_PARTITION_PAGE
;
2245 return CREATE_EXTENDED_PARTITION_PAGE
;
2250 * Displays the CreateLogicalPartitionPage.
2253 * SelectFileSystemPage (default)
2257 * Number of the next page.
2260 CreateLogicalPartitionPage(PINPUT_RECORD Ir
)
2262 PDISKENTRY DiskEntry
;
2263 PPARTENTRY PartEntry
;
2266 WCHAR InputBuffer
[50];
2270 ULONGLONG SectorCount
;
2273 if (PartitionList
== NULL
||
2274 PartitionList
->CurrentDisk
== NULL
||
2275 PartitionList
->CurrentPartition
== NULL
)
2277 /* FIXME: show an error dialog */
2281 DiskEntry
= PartitionList
->CurrentDisk
;
2282 PartEntry
= PartitionList
->CurrentPartition
;
2284 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2286 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSE_NEW_LOGICAL_PARTITION
));
2288 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2290 if (DiskSize
>= 10737418240) /* 10 GB */
2292 DiskSize
= DiskSize
/ 1073741824;
2293 Unit
= MUIGetString(STRING_GB
);
2298 DiskSize
= DiskSize
/ 1048576;
2302 Unit
= MUIGetString(STRING_MB
);
2305 if (DiskEntry
->DriverName
.Length
> 0)
2307 CONSOLE_PrintTextXY(6, 10,
2308 MUIGetString(STRING_HDINFOPARTCREATE
),
2311 DiskEntry
->DiskNumber
,
2315 &DiskEntry
->DriverName
);
2319 CONSOLE_PrintTextXY(6, 10,
2320 MUIGetString(STRING_HDDINFOUNK1
),
2323 DiskEntry
->DiskNumber
,
2329 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE
));
2332 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
2333 PartitionList
->CurrentPartition
->SectorCount
* DiskEntry
->BytesPerSector
/ 1048576);
2336 CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION
));
2338 PartEntry
= PartitionList
->CurrentPartition
;
2341 MaxSize
= (PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
) / 1048576; /* in MBytes (rounded) */
2343 if (MaxSize
> PARTITION_MAXSIZE
)
2344 MaxSize
= PARTITION_MAXSIZE
;
2346 ShowPartitionSizeInputBox(12, 14, xScreen
- 12, 17, /* left, top, right, bottom */
2347 MaxSize
, InputBuffer
, &Quit
, &Cancel
);
2351 if (ConfirmQuit(Ir
) != FALSE
)
2356 else if (Cancel
!= FALSE
)
2358 return SELECT_PARTITION_PAGE
;
2362 PartSize
= _wcstoui64(InputBuffer
, NULL
, 10);
2370 if (PartSize
> MaxSize
)
2376 /* Convert to bytes */
2377 if (PartSize
== MaxSize
)
2379 /* Use all of the unpartitioned disk space */
2380 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2384 /* Calculate the sector count from the size in MB */
2385 SectorCount
= PartSize
* 1048576 / DiskEntry
->BytesPerSector
;
2387 /* But never get larger than the unpartitioned disk space */
2388 if (SectorCount
> PartEntry
->SectorCount
.QuadPart
)
2389 SectorCount
= PartEntry
->SectorCount
.QuadPart
;
2392 DPRINT("Partition size: %I64u bytes\n", PartSize
);
2394 CreateLogicalPartition(PartitionList
,
2398 return SELECT_PARTITION_PAGE
;
2402 return CREATE_LOGICAL_PARTITION_PAGE
;
2407 * Displays the ConfirmDeleteSystemPartitionPage.
2410 * DeletePartitionPage (default)
2411 * SelectPartitionPage
2414 * Number of the next page.
2417 ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir
)
2419 MUIDisplayPage(CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
);
2423 CONSOLE_ConInKey(Ir
);
2425 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2426 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2428 if (ConfirmQuit(Ir
) == TRUE
)
2433 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2435 return DELETE_PARTITION_PAGE
;
2437 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2439 return SELECT_PARTITION_PAGE
;
2443 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
;
2448 * Displays the DeletePartitionPage.
2451 * SelectPartitionPage (default)
2455 * Number of the next page.
2458 DeletePartitionPage(PINPUT_RECORD Ir
)
2460 PDISKENTRY DiskEntry
;
2461 PPARTENTRY PartEntry
;
2465 CHAR PartTypeString
[32];
2467 if (PartitionList
== NULL
||
2468 PartitionList
->CurrentDisk
== NULL
||
2469 PartitionList
->CurrentPartition
== NULL
)
2471 /* FIXME: show an error dialog */
2475 DiskEntry
= PartitionList
->CurrentDisk
;
2476 PartEntry
= PartitionList
->CurrentPartition
;
2478 MUIDisplayPage(DELETE_PARTITION_PAGE
);
2480 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2482 ARRAYSIZE(PartTypeString
));
2484 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2486 if (PartSize
>= 10737418240) /* 10 GB */
2488 PartSize
= PartSize
/ 1073741824;
2489 Unit
= MUIGetString(STRING_GB
);
2493 if (PartSize
>= 10485760) /* 10 MB */
2495 PartSize
= PartSize
/ 1048576;
2496 Unit
= MUIGetString(STRING_MB
);
2500 PartSize
= PartSize
/ 1024;
2501 Unit
= MUIGetString(STRING_KB
);
2504 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2506 CONSOLE_PrintTextXY(6, 10,
2507 MUIGetString(STRING_HDDINFOUNK2
),
2508 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2509 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2510 PartEntry
->PartitionType
,
2516 CONSOLE_PrintTextXY(6, 10,
2517 " %c%c %s %I64u %s",
2518 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2519 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2525 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2527 if (DiskSize
>= 10737418240) /* 10 GB */
2529 DiskSize
= DiskSize
/ 1073741824;
2530 Unit
= MUIGetString(STRING_GB
);
2535 DiskSize
= DiskSize
/ 1048576;
2539 Unit
= MUIGetString(STRING_MB
);
2542 if (DiskEntry
->DriverName
.Length
> 0)
2544 CONSOLE_PrintTextXY(6, 12,
2545 MUIGetString(STRING_HDINFOPARTDELETE
),
2548 DiskEntry
->DiskNumber
,
2552 &DiskEntry
->DriverName
);
2556 CONSOLE_PrintTextXY(6, 12,
2557 MUIGetString(STRING_HDDINFOUNK3
),
2560 DiskEntry
->DiskNumber
,
2568 CONSOLE_ConInKey(Ir
);
2570 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2571 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2573 if (ConfirmQuit(Ir
) != FALSE
)
2578 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) /* ESC */
2580 return SELECT_PARTITION_PAGE
;
2582 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== 'D') /* D */
2584 DeleteCurrentPartition(PartitionList
);
2586 return SELECT_PARTITION_PAGE
;
2590 return DELETE_PARTITION_PAGE
;
2595 * Displays the SelectFileSystemPage.
2598 * CheckFileSystemPage (At once if RepairUpdate is selected)
2599 * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
2600 * FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
2601 * SelectPartitionPage (If the user aborts)
2602 * FormatPartitionPage (Default)
2606 * Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
2607 * Calls CheckActiveSystemPartition()
2610 * Number of the next page.
2613 SelectFileSystemPage(PINPUT_RECORD Ir
)
2615 PDISKENTRY DiskEntry
;
2616 PPARTENTRY PartEntry
;
2621 CHAR PartTypeString
[32];
2622 FORMATMACHINESTATE PreviousFormatState
;
2624 DPRINT("SelectFileSystemPage()\n");
2626 if (PartitionList
== NULL
||
2627 PartitionList
->CurrentDisk
== NULL
||
2628 PartitionList
->CurrentPartition
== NULL
)
2630 /* FIXME: show an error dialog */
2636 if (FileSystemList
== NULL
)
2638 FileSystemList
= CreateFileSystemList(6, 26, PartitionList
->CurrentPartition
->New
, L
"FAT");
2639 if (FileSystemList
== NULL
)
2641 /* FIXME: show an error dialog */
2645 /* FIXME: Add file systems to list */
2649 /* Find or set the active system partition */
2650 CheckActiveSystemPartition(PartitionList
/*, FileSystemList*/);
2651 if (PartitionList
->SystemPartition
== NULL
)
2653 /* FIXME: show an error dialog */
2657 PreviousFormatState
= PartitionList
->FormatState
;
2658 switch (PartitionList
->FormatState
)
2661 if (PartitionList
->CurrentPartition
!= PartitionList
->SystemPartition
)
2663 PartitionList
->TempPartition
= PartitionList
->SystemPartition
;
2664 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2666 PartitionList
->FormatState
= FormatSystemPartition
;
2667 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
2671 PartitionList
->TempPartition
= PartitionList
->CurrentPartition
;
2672 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2674 PartitionList
->FormatState
= FormatInstallPartition
;
2675 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
2679 case FormatSystemPartition
:
2680 PartitionList
->TempPartition
= PartitionList
->CurrentPartition
;
2681 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2683 PartitionList
->FormatState
= FormatInstallPartition
;
2684 DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
2687 case FormatInstallPartition
:
2688 if (GetNextUnformattedPartition(PartitionList
,
2690 &PartitionList
->TempPartition
))
2692 PartitionList
->FormatState
= FormatOtherPartition
;
2693 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2694 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
2698 PartitionList
->FormatState
= FormatDone
;
2699 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
2700 return CHECK_FILE_SYSTEM_PAGE
;
2704 case FormatOtherPartition
:
2705 if (GetNextUnformattedPartition(PartitionList
,
2707 &PartitionList
->TempPartition
))
2709 PartitionList
->FormatState
= FormatOtherPartition
;
2710 PartitionList
->TempPartition
->NeedsCheck
= TRUE
;
2711 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
2715 PartitionList
->FormatState
= FormatDone
;
2716 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
2717 return CHECK_FILE_SYSTEM_PAGE
;
2722 DPRINT1("FormatState: Invalid value %ld\n", PartitionList
->FormatState
);
2723 /* FIXME: show an error dialog */
2727 PartEntry
= PartitionList
->TempPartition
;
2728 DiskEntry
= PartEntry
->DiskEntry
;
2730 /* Adjust disk size */
2731 DiskSize
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2732 if (DiskSize
>= 10737418240) /* 10 GB */
2734 DiskSize
= DiskSize
/ 1073741824;
2735 DiskUnit
= MUIGetString(STRING_GB
);
2739 DiskSize
= DiskSize
/ 1048576;
2740 DiskUnit
= MUIGetString(STRING_MB
);
2743 /* Adjust partition size */
2744 PartSize
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2745 if (PartSize
>= 10737418240) /* 10 GB */
2747 PartSize
= PartSize
/ 1073741824;
2748 PartUnit
= MUIGetString(STRING_GB
);
2752 PartSize
= PartSize
/ 1048576;
2753 PartUnit
= MUIGetString(STRING_MB
);
2756 /* Adjust partition type */
2757 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
2759 ARRAYSIZE(PartTypeString
));
2761 if (PartEntry
->AutoCreate
!= FALSE
)
2763 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION
));
2766 CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
2767 PartEntry
->PartitionNumber
,
2773 CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED
),
2774 DiskEntry
->DiskNumber
,
2780 &DiskEntry
->DriverName
);
2782 CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT
));
2784 PartEntry
->AutoCreate
= FALSE
;
2786 else if (PartEntry
->New
!= FALSE
)
2788 switch (PartitionList
->FormatState
)
2790 case FormatSystemPartition
:
2791 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART
));
2794 case FormatInstallPartition
:
2795 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDPART
));
2798 case FormatOtherPartition
:
2799 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDOTHERPART
));
2806 CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT
));
2810 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_INSTALLONPART
));
2812 if (*PartTypeString
== '\0') // STRING_FORMATUNKNOWN ??
2814 CONSOLE_PrintTextXY(8, 10,
2815 MUIGetString(STRING_HDDINFOUNK4
),
2816 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2817 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2818 PartEntry
->PartitionType
,
2824 CONSOLE_PrintTextXY(8, 10,
2826 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
2827 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
2833 CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS
),
2834 DiskEntry
->DiskNumber
,
2840 &DiskEntry
->DriverName
);
2843 MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE
);
2845 if (FileSystemList
== NULL
)
2847 /* Create the file system list, and by default select the "FAT" file system */
2848 FileSystemList
= CreateFileSystemList(6, 26, PartEntry
->New
, L
"FAT");
2849 if (FileSystemList
== NULL
)
2851 /* FIXME: show an error dialog */
2855 /* FIXME: Add file systems to list */
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 // PartEntry->FileSystem = GetFileSystemByName(FileSystemList, L"FAT");
2878 return FORMAT_PARTITION_PAGE
;
2881 return CHECK_FILE_SYSTEM_PAGE
;
2886 CONSOLE_ConInKey(Ir
);
2888 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2889 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2891 if (ConfirmQuit(Ir
) != FALSE
)
2896 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2897 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
)) /* ESC */
2899 PartitionList
->FormatState
= Start
;
2900 return SELECT_PARTITION_PAGE
;
2902 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2903 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
2905 ScrollDownFileSystemList(FileSystemList
);
2907 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2908 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
2910 ScrollUpFileSystemList(FileSystemList
);
2912 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
) /* ENTER */
2914 if (!FileSystemList
->Selected
->FileSystem
)
2916 return SELECT_FILE_SYSTEM_PAGE
;
2920 // PartEntry->FileSystem = FileSystemList->Selected;
2921 return FORMAT_PARTITION_PAGE
;
2926 PartitionList
->FormatState
= PreviousFormatState
;
2928 return SELECT_FILE_SYSTEM_PAGE
;
2933 * Displays the FormatPartitionPage.
2936 * InstallDirectoryPage (At once if IsUnattendedSetup or InstallShortcut)
2937 * SelectPartitionPage (At once)
2941 * Sets PartitionList->CurrentPartition->FormatState
2942 * Sets DestinationRootPath
2945 * Number of the next page.
2948 FormatPartitionPage(PINPUT_RECORD Ir
)
2950 UNICODE_STRING PartitionRootPath
;
2951 WCHAR PathBuffer
[MAX_PATH
];
2952 PDISKENTRY DiskEntry
;
2953 PPARTENTRY PartEntry
;
2954 PFILE_SYSTEM_ITEM SelectedFileSystem
;
2960 PPARTITION_INFORMATION PartitionInfo
;
2963 DPRINT("FormatPartitionPage()\n");
2965 MUIDisplayPage(FORMAT_PARTITION_PAGE
);
2967 if (PartitionList
== NULL
||
2968 PartitionList
->TempPartition
== NULL
)
2970 /* FIXME: show an error dialog */
2974 PartEntry
= PartitionList
->TempPartition
;
2975 DiskEntry
= PartEntry
->DiskEntry
;
2977 SelectedFileSystem
= FileSystemList
->Selected
; // PartEntry->FileSystem; // FIXME!!!!
2981 if (!IsUnattendedSetup
)
2983 CONSOLE_ConInKey(Ir
);
2986 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
2987 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
2989 if (ConfirmQuit(Ir
) != FALSE
)
2994 else if (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RETURN
|| IsUnattendedSetup
) /* ENTER */
2996 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
2998 if (wcscmp(SelectedFileSystem
->FileSystemName
, L
"FAT") == 0)
3000 if (PartEntry
->SectorCount
.QuadPart
< 8192)
3002 /* FAT12 CHS partition (disk is smaller than 4.1MB) */
3003 SetPartitionType(PartEntry
, PARTITION_FAT_12
);
3005 else if (PartEntry
->StartSector
.QuadPart
< 1450560)
3007 /* Partition starts below the 8.4GB boundary ==> CHS partition */
3009 if (PartEntry
->SectorCount
.QuadPart
< 65536)
3011 /* FAT16 CHS partition (partition size < 32MB) */
3012 SetPartitionType(PartEntry
, PARTITION_FAT_16
);
3014 else if (PartEntry
->SectorCount
.QuadPart
< 1048576)
3016 /* FAT16 CHS partition (partition size < 512MB) */
3017 SetPartitionType(PartEntry
, PARTITION_HUGE
);
3021 /* FAT32 CHS partition (partition size >= 512MB) */
3022 SetPartitionType(PartEntry
, PARTITION_FAT32
);
3027 /* Partition starts above the 8.4GB boundary ==> LBA partition */
3029 if (PartEntry
->SectorCount
.QuadPart
< 1048576)
3031 /* FAT16 LBA partition (partition size < 512MB) */
3032 SetPartitionType(PartEntry
, PARTITION_XINT13
);
3036 /* FAT32 LBA partition (partition size >= 512MB) */
3037 SetPartitionType(PartEntry
, PARTITION_FAT32_XINT13
);
3042 else if (wcscmp(SelectedFileSystem
->FileSystemName
, L
"EXT2") == 0)
3044 SetPartitionType(PartEntry
, PARTITION_EXT2
);
3046 else if (wcscmp(SelectedFileSystem
->FileSystemName
, L
"NTFS") == 0)
3048 SetPartitionType(PartEntry
, PARTITION_IFS
);
3051 else if (!SelectedFileSystem
->FileSystem
)
3053 /* FIXME: show an error dialog */
3058 CONSOLE_PrintTextXY(6, 12,
3059 "Cylinders: %I64u Tracks/Cyl: %lu Sectors/Trk: %lu Bytes/Sec: %lu %c",
3060 DiskEntry
->Cylinders
,
3061 DiskEntry
->TracksPerCylinder
,
3062 DiskEntry
->SectorsPerTrack
,
3063 DiskEntry
->BytesPerSector
,
3064 DiskEntry
->Dirty
? '*' : ' ');
3068 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
3070 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
3072 CONSOLE_PrintTextXY(6, Line
,
3073 "%2u: %2lu %c %12I64u %12I64u %02x",
3075 PartitionInfo
->PartitionNumber
,
3076 PartitionInfo
->BootIndicator
? 'A' : '-',
3077 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
3078 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
3079 PartitionInfo
->PartitionType
);
3084 if (WritePartitionsToDisk(PartitionList
) == FALSE
)
3086 DPRINT("WritePartitionsToDisk() failed\n");
3087 MUIDisplayError(ERROR_WRITE_PTABLE
, Ir
, POPUP_WAIT_ENTER
);
3091 /* Set PartitionRootPath */
3092 swprintf(PathBuffer
,
3093 L
"\\Device\\Harddisk%lu\\Partition%lu",
3094 DiskEntry
->DiskNumber
,
3095 PartEntry
->PartitionNumber
);
3096 RtlInitUnicodeString(&PartitionRootPath
,
3098 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3100 if (SelectedFileSystem
->FileSystem
)
3102 Status
= FormatPartition(&PartitionRootPath
,
3103 SelectedFileSystem
);
3104 if (!NT_SUCCESS(Status
))
3106 DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status
);
3107 MUIDisplayError(ERROR_FORMATTING_PARTITION
, Ir
, POPUP_WAIT_ANY_KEY
, PathBuffer
);
3111 PartEntry
->New
= FALSE
;
3115 CONSOLE_SetStatusText(" Done. Press any key ...");
3116 CONSOLE_ConInKey(Ir
);
3119 return SELECT_FILE_SYSTEM_PAGE
;
3123 return FORMAT_PARTITION_PAGE
;
3128 * Displays the CheckFileSystemPage.
3131 * InstallDirectoryPage (At once)
3135 * Inits or reloads FileSystemList
3138 * Number of the next page.
3141 CheckFileSystemPage(PINPUT_RECORD Ir
)
3143 PFILE_SYSTEM CurrentFileSystem
;
3144 UNICODE_STRING PartitionRootPath
;
3145 WCHAR PathBuffer
[MAX_PATH
];
3146 CHAR Buffer
[MAX_PATH
];
3147 PDISKENTRY DiskEntry
;
3148 PPARTENTRY PartEntry
;
3151 if (PartitionList
== NULL
)
3153 /* FIXME: show an error dialog */
3157 if (!GetNextUncheckedPartition(PartitionList
, &DiskEntry
, &PartEntry
))
3159 return INSTALL_DIRECTORY_PAGE
;
3162 /* Set PartitionRootPath */
3163 swprintf(PathBuffer
,
3164 L
"\\Device\\Harddisk%lu\\Partition%lu",
3165 DiskEntry
->DiskNumber
,
3166 PartEntry
->PartitionNumber
);
3167 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
3168 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
3170 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART
));
3172 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
3174 CurrentFileSystem
= PartEntry
->FileSystem
;
3175 DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
3176 PartEntry
->PartitionType
, (CurrentFileSystem
? CurrentFileSystem
->FileSystemName
: L
"n/a"));
3178 /* HACK: Do not try to check a partition with an unknown filesystem */
3179 if (CurrentFileSystem
== NULL
)
3181 PartEntry
->NeedsCheck
= FALSE
;
3182 return CHECK_FILE_SYSTEM_PAGE
;
3185 if (CurrentFileSystem
->ChkdskFunc
== NULL
)
3188 "Setup is currently unable to check a partition formatted in %S.\n"
3190 " \x07 Press ENTER to continue Setup.\n"
3191 " \x07 Press F3 to quit Setup.",
3192 CurrentFileSystem
->FileSystemName
);
3195 MUIGetString(STRING_QUITCONTINUE
),
3196 NULL
, POPUP_WAIT_NONE
);
3200 CONSOLE_ConInKey(Ir
);
3202 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00 &&
3203 Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
) /* F3 */
3205 if (ConfirmQuit(Ir
))
3208 return CHECK_FILE_SYSTEM_PAGE
;
3210 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== VK_RETURN
) /* ENTER */
3212 PartEntry
->NeedsCheck
= FALSE
;
3213 return CHECK_FILE_SYSTEM_PAGE
;
3219 Status
= ChkdskPartition(&PartitionRootPath
, CurrentFileSystem
);
3220 if (!NT_SUCCESS(Status
))
3222 DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status
);
3223 // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
3224 sprintf(Buffer
, "ChkDsk detected some disk errors.\n"
3225 "(Status 0x%08lx).\n", Status
);
3227 // MUIGetString(STRING_REBOOTCOMPUTER),
3228 MUIGetString(STRING_CONTINUE
),
3229 Ir
, POPUP_WAIT_ENTER
);
3231 // return QUIT_PAGE;
3234 PartEntry
->NeedsCheck
= FALSE
;
3235 return CHECK_FILE_SYSTEM_PAGE
;
3242 BuildInstallPaths(PWCHAR InstallDir
,
3243 PDISKENTRY DiskEntry
,
3244 PPARTENTRY PartEntry
)
3246 WCHAR PathBuffer
[MAX_PATH
];
3248 /* Create 'InstallPath' string */
3249 RtlFreeUnicodeString(&InstallPath
);
3250 RtlCreateUnicodeString(&InstallPath
, InstallDir
);
3252 /* Create 'DestinationRootPath' string */
3253 RtlFreeUnicodeString(&DestinationRootPath
);
3254 swprintf(PathBuffer
,
3255 L
"\\Device\\Harddisk%lu\\Partition%lu",
3256 DiskEntry
->DiskNumber
,
3257 PartEntry
->PartitionNumber
);
3258 RtlCreateUnicodeString(&DestinationRootPath
, PathBuffer
);
3259 DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath
);
3261 /* Create 'DestinationPath' string */
3262 RtlFreeUnicodeString(&DestinationPath
);
3263 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3265 if (InstallDir
[0] != L
'\\')
3266 wcscat(PathBuffer
, L
"\\");
3268 wcscat(PathBuffer
, InstallDir
);
3269 RtlCreateUnicodeString(&DestinationPath
, PathBuffer
);
3271 /* Create 'DestinationArcPath' */
3272 RtlFreeUnicodeString(&DestinationArcPath
);
3273 swprintf(PathBuffer
,
3274 L
"multi(0)disk(0)rdisk(%lu)partition(%lu)",
3275 DiskEntry
->BiosDiskNumber
,
3276 PartEntry
->PartitionNumber
);
3278 if (InstallDir
[0] != L
'\\')
3279 wcscat(PathBuffer
, L
"\\");
3281 wcscat(PathBuffer
, InstallDir
);
3282 RtlCreateUnicodeString(&DestinationArcPath
, PathBuffer
);
3287 * Displays the InstallDirectoryPage.
3290 * PrepareCopyPage (As the direct result of InstallDirectoryPage1)
3294 * Number of the next page.
3297 InstallDirectoryPage(PINPUT_RECORD Ir
)
3299 PDISKENTRY DiskEntry
;
3300 PPARTENTRY PartEntry
;
3301 WCHAR InstallDir
[51];
3305 /* We do not need the filesystem list any more */
3306 if (FileSystemList
!= NULL
)
3308 DestroyFileSystemList(FileSystemList
);
3309 FileSystemList
= NULL
;
3312 if (PartitionList
== NULL
||
3313 PartitionList
->CurrentDisk
== NULL
||
3314 PartitionList
->CurrentPartition
== NULL
)
3316 /* FIXME: show an error dialog */
3320 DiskEntry
= PartitionList
->CurrentDisk
;
3321 PartEntry
= PartitionList
->CurrentPartition
;
3323 if (IsUnattendedSetup
)
3325 if (!IsValidPath(UnattendInstallationDirectory
))
3327 /* FIXME: Log the error? */
3331 BuildInstallPaths(UnattendInstallationDirectory
,
3335 return PREPARE_COPY_PAGE
;
3338 wcscpy(InstallDir
, L
"\\ReactOS");
3340 Length
= wcslen(InstallDir
);
3342 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3343 CONSOLE_SetCursorXY(8 + Pos
, 11);
3344 CONSOLE_SetCursorType(TRUE
, TRUE
);
3345 MUIDisplayPage(INSTALL_DIRECTORY_PAGE
);
3349 CONSOLE_ConInKey(Ir
);
3351 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3352 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
3354 CONSOLE_SetCursorType(TRUE
, FALSE
);
3356 if (ConfirmQuit(Ir
) != FALSE
)
3359 CONSOLE_SetCursorType(TRUE
, TRUE
);
3362 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3363 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DELETE
)) /* DEL */
3367 memmove(&InstallDir
[Pos
],
3368 &InstallDir
[Pos
+ 1],
3369 (Length
- Pos
- 1) * sizeof(WCHAR
));
3370 InstallDir
[Length
- 1] = UNICODE_NULL
;
3373 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3374 CONSOLE_SetCursorXY(8 + Pos
, 11);
3377 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3378 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_HOME
)) /* HOME */
3381 CONSOLE_SetCursorXY(8 + Pos
, 11);
3383 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3384 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_END
)) /* END */
3387 CONSOLE_SetCursorXY(8 + Pos
, 11);
3389 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3390 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_LEFT
)) /* LEFT */
3395 CONSOLE_SetCursorXY(8 + Pos
, 11);
3398 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
3399 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_RIGHT
)) /* RIGHT */
3404 CONSOLE_SetCursorXY(8 + Pos
, 11);
3407 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
3409 CONSOLE_SetCursorType(TRUE
, FALSE
);
3412 * Check for the validity of the installation directory and pop up
3413 * an error if it is not the case. Then the user can fix its input.
3415 if (!IsValidPath(InstallDir
))
3417 MUIDisplayError(ERROR_DIRECTORY_NAME
, Ir
, POPUP_WAIT_ENTER
);
3418 return INSTALL_DIRECTORY_PAGE
;
3421 BuildInstallPaths(InstallDir
,
3425 return PREPARE_COPY_PAGE
;
3427 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x08) /* BACKSPACE */
3432 memmove(&InstallDir
[Pos
- 1],
3434 (Length
- Pos
) * sizeof(WCHAR
));
3435 InstallDir
[Length
- 1] = UNICODE_NULL
;
3439 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3440 CONSOLE_SetCursorXY(8 + Pos
, 11);
3443 else if (isprint(Ir
->Event
.KeyEvent
.uChar
.AsciiChar
))
3447 c
= (WCHAR
)Ir
->Event
.KeyEvent
.uChar
.AsciiChar
;
3448 if (iswalpha(c
) || iswdigit(c
) || c
== '.' || c
== '\\' || c
== '-' || c
== '_')
3451 memmove(&InstallDir
[Pos
+ 1],
3453 (Length
- Pos
) * sizeof(WCHAR
));
3454 InstallDir
[Length
+ 1] = UNICODE_NULL
;
3455 InstallDir
[Pos
] = c
;
3459 CONSOLE_SetInputTextXY(8, 11, 51, InstallDir
);
3460 CONSOLE_SetCursorXY(8 + Pos
, 11);
3466 return INSTALL_DIRECTORY_PAGE
;
3471 AddSectionToCopyQueueCab(HINF InfFile
,
3473 PWCHAR SourceCabinet
,
3474 PCUNICODE_STRING DestinationPath
,
3477 INFCONTEXT FilesContext
;
3478 INFCONTEXT DirContext
;
3480 PWCHAR FileKeyValue
;
3482 PWCHAR TargetFileName
;
3484 /* Search for the SectionName section */
3485 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3488 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3489 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3494 * Enumerate the files in the section
3495 * and add them to the file queue.
3499 /* Get source file name and target directory id */
3500 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3502 /* FIXME: Handle error! */
3503 DPRINT1("INF_GetData() failed\n");
3507 /* Get optional target file name */
3508 if (!INF_GetDataField(&FilesContext
, 2, &TargetFileName
))
3509 TargetFileName
= NULL
;
3511 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3513 /* Lookup target directory */
3514 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3516 /* FIXME: Handle error! */
3517 DPRINT1("SetupFindFirstLine() failed\n");
3521 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3523 /* FIXME: Handle error! */
3524 DPRINT1("INF_GetData() failed\n");
3528 if (!SetupQueueCopy(SetupFileQueue
,
3530 SourceRootPath
.Buffer
,
3531 SourceRootDir
.Buffer
,
3536 /* FIXME: Handle error! */
3537 DPRINT1("SetupQueueCopy() failed\n");
3539 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3546 AddSectionToCopyQueue(HINF InfFile
,
3548 PWCHAR SourceCabinet
,
3549 PCUNICODE_STRING DestinationPath
,
3552 INFCONTEXT FilesContext
;
3553 INFCONTEXT DirContext
;
3555 PWCHAR FileKeyValue
;
3557 PWCHAR TargetFileName
;
3559 WCHAR CompleteOrigDirName
[512];
3562 return AddSectionToCopyQueueCab(InfFile
, L
"SourceFiles", SourceCabinet
, DestinationPath
, Ir
);
3564 /* Search for the SectionName section */
3565 if (!SetupFindFirstLineW(InfFile
, SectionName
, NULL
, &FilesContext
))
3568 sprintf(Buffer
, MUIGetString(STRING_TXTSETUPFAILED
), SectionName
);
3569 PopupError(Buffer
, MUIGetString(STRING_REBOOTCOMPUTER
), Ir
, POPUP_WAIT_ENTER
);
3574 * Enumerate the files in the section
3575 * and add them to the file queue.
3579 /* Get source file name and target directory id */
3580 if (!INF_GetData(&FilesContext
, &FileKeyName
, &FileKeyValue
))
3582 /* FIXME: Handle error! */
3583 DPRINT1("INF_GetData() failed\n");
3587 /* Get target directory id */
3588 if (!INF_GetDataField(&FilesContext
, 13, &FileKeyValue
))
3590 /* FIXME: Handle error! */
3591 DPRINT1("INF_GetData() failed\n");
3595 /* Get optional target file name */
3596 if (!INF_GetDataField(&FilesContext
, 11, &TargetFileName
))
3597 TargetFileName
= NULL
;
3598 else if (!*TargetFileName
)
3599 TargetFileName
= NULL
;
3601 DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName
, FileKeyValue
);
3603 /* Lookup target directory */
3604 if (!SetupFindFirstLineW(InfFile
, L
"Directories", FileKeyValue
, &DirContext
))
3606 /* FIXME: Handle error! */
3607 DPRINT1("SetupFindFirstLine() failed\n");
3611 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3613 /* FIXME: Handle error! */
3614 DPRINT1("INF_GetData() failed\n");
3618 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3620 /* Installation path */
3621 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3623 else if (DirKeyValue
[0] == L
'\\')
3626 wcscpy(CompleteOrigDirName
, DirKeyValue
);
3628 else // if (DirKeyValue[0] != L'\\')
3630 /* Path relative to the installation path */
3631 wcscpy(CompleteOrigDirName
, SourceRootDir
.Buffer
);
3632 wcscat(CompleteOrigDirName
, L
"\\");
3633 wcscat(CompleteOrigDirName
, DirKeyValue
);
3636 /* Remove trailing backslash */
3637 Length
= wcslen(CompleteOrigDirName
);
3638 if ((Length
> 0) && (CompleteOrigDirName
[Length
- 1] == L
'\\'))
3640 CompleteOrigDirName
[Length
- 1] = 0;
3643 if (!SetupQueueCopy(SetupFileQueue
,
3645 SourceRootPath
.Buffer
,
3646 CompleteOrigDirName
,
3651 /* FIXME: Handle error! */
3652 DPRINT1("SetupQueueCopy() failed\n");
3654 } while (SetupFindNextLine(&FilesContext
, &FilesContext
));
3661 PrepareCopyPageInfFile(HINF InfFile
,
3662 PWCHAR SourceCabinet
,
3665 WCHAR PathBuffer
[MAX_PATH
];
3666 INFCONTEXT DirContext
;
3667 PWCHAR AdditionalSectionName
= NULL
;
3672 /* Add common files */
3673 if (!AddSectionToCopyQueue(InfFile
, L
"SourceDisksFiles", SourceCabinet
, &DestinationPath
, Ir
))
3676 /* Add specific files depending of computer type */
3677 if (SourceCabinet
== NULL
)
3679 if (!ProcessComputerFiles(InfFile
, ComputerList
, &AdditionalSectionName
))
3682 if (AdditionalSectionName
)
3684 if (!AddSectionToCopyQueue(InfFile
, AdditionalSectionName
, SourceCabinet
, &DestinationPath
, Ir
))
3689 /* Create directories */
3693 * - Install directories like '\reactos\test' are not handled yet.
3694 * - Copying files to DestinationRootPath should be done from within
3695 * the SystemPartitionFiles section.
3696 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
3697 * For installing to DestinationPath specify just '\' .
3700 /* Get destination path */
3701 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3703 /* Remove trailing backslash */
3704 Length
= wcslen(PathBuffer
);
3705 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3707 PathBuffer
[Length
- 1] = 0;
3710 /* Create the install directory */
3711 Status
= SetupCreateDirectory(PathBuffer
);
3712 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3714 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3715 MUIDisplayError(ERROR_CREATE_INSTALL_DIR
, Ir
, POPUP_WAIT_ENTER
);
3719 /* Search for the 'Directories' section */
3720 if (!SetupFindFirstLineW(InfFile
, L
"Directories", NULL
, &DirContext
))
3724 MUIDisplayError(ERROR_CABINET_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3728 MUIDisplayError(ERROR_TXTSETUP_SECTION
, Ir
, POPUP_WAIT_ENTER
);
3734 /* Enumerate the directory values and create the subdirectories */
3737 if (!INF_GetData(&DirContext
, NULL
, &DirKeyValue
))
3743 if ((DirKeyValue
[0] == 0) || (DirKeyValue
[0] == L
'\\' && DirKeyValue
[1] == 0))
3745 /* Installation path */
3746 DPRINT("InstallationPath: '%S'\n", DirKeyValue
);
3748 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3750 DPRINT("FullPath: '%S'\n", PathBuffer
);
3752 else if (DirKeyValue
[0] == L
'\\')
3755 DPRINT("Absolute Path: '%S'\n", DirKeyValue
);
3757 wcscpy(PathBuffer
, DestinationRootPath
.Buffer
);
3758 wcscat(PathBuffer
, DirKeyValue
);
3760 /* Remove trailing backslash */
3761 Length
= wcslen(PathBuffer
);
3762 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3764 PathBuffer
[Length
- 1] = 0;
3767 DPRINT("FullPath: '%S'\n", PathBuffer
);
3769 Status
= SetupCreateDirectory(PathBuffer
);
3770 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3772 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3773 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3777 else // if (DirKeyValue[0] != L'\\')
3779 /* Path relative to the installation path */
3780 DPRINT("RelativePath: '%S'\n", DirKeyValue
);
3782 wcscpy(PathBuffer
, DestinationPath
.Buffer
);
3783 wcscat(PathBuffer
, L
"\\");
3784 wcscat(PathBuffer
, DirKeyValue
);
3786 /* Remove trailing backslash */
3787 Length
= wcslen(PathBuffer
);
3788 if ((Length
> 0) && (PathBuffer
[Length
- 1] == L
'\\'))
3790 PathBuffer
[Length
- 1] = 0;
3793 DPRINT("FullPath: '%S'\n", PathBuffer
);
3795 Status
= SetupCreateDirectory(PathBuffer
);
3796 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_COLLISION
)
3798 DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer
, Status
);
3799 MUIDisplayError(ERROR_CREATE_DIR
, Ir
, POPUP_WAIT_ENTER
);
3803 } while (SetupFindNextLine(&DirContext
, &DirContext
));
3810 * Displays the PrepareCopyPage.
3813 * FileCopyPage(At once)
3817 * Inits SetupFileQueue
3818 * Calls PrepareCopyPageInfFile
3821 * Number of the next page.
3824 PrepareCopyPage(PINPUT_RECORD Ir
)
3827 WCHAR PathBuffer
[MAX_PATH
];
3828 INFCONTEXT CabinetsContext
;
3834 MUIDisplayPage(PREPARE_COPY_PAGE
);
3836 /* Create the file queue */
3837 SetupFileQueue
= SetupOpenFileQueue();
3838 if (SetupFileQueue
== NULL
)
3840 MUIDisplayError(ERROR_COPY_QUEUE
, Ir
, POPUP_WAIT_ENTER
);
3844 if (!PrepareCopyPageInfFile(SetupInf
, NULL
, Ir
))
3846 /* FIXME: show an error dialog */
3850 /* Search for the 'Cabinets' section */
3851 if (!SetupFindFirstLineW(SetupInf
, L
"Cabinets", NULL
, &CabinetsContext
))
3853 return FILE_COPY_PAGE
;
3857 * Enumerate the directory values in the 'Cabinets'
3858 * section and parse their inf files.
3862 if (!INF_GetData(&CabinetsContext
, NULL
, &KeyValue
))
3865 wcscpy(PathBuffer
, SourcePath
.Buffer
);
3866 wcscat(PathBuffer
, L
"\\");
3867 wcscat(PathBuffer
, KeyValue
);
3869 CabinetInitialize();
3870 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
3871 CabinetSetCabinetName(PathBuffer
);
3873 if (CabinetOpen() == CAB_STATUS_SUCCESS
)
3875 DPRINT("Cabinet %S\n", CabinetGetCabinetName());
3877 InfFileData
= CabinetGetCabinetReservedArea(&InfFileSize
);
3878 if (InfFileData
== NULL
)
3880 MUIDisplayError(ERROR_CABINET_SCRIPT
, Ir
, POPUP_WAIT_ENTER
);
3886 DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
3887 MUIDisplayError(ERROR_CABINET_MISSING
, Ir
, POPUP_WAIT_ENTER
);
3891 InfHandle
= INF_OpenBufferedFileA((CHAR
*) InfFileData
,
3898 if (InfHandle
== INVALID_HANDLE_VALUE
)
3900 MUIDisplayError(ERROR_INVALID_CABINET_INF
, Ir
, POPUP_WAIT_ENTER
);
3906 if (!PrepareCopyPageInfFile(InfHandle
, KeyValue
, Ir
))
3908 /* FIXME: show an error dialog */
3911 } while (SetupFindNextLine(&CabinetsContext
, &CabinetsContext
));
3913 return FILE_COPY_PAGE
;
3919 SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext
,
3922 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
3924 /* Get the memory information from the system */
3925 NtQuerySystemInformation(SystemPerformanceInformation
,
3930 /* Check if this is initial setup */
3933 /* Set maximum limits to be total RAM pages */
3934 ProgressSetStepCount(CopyContext
->MemoryBars
[0], PerfInfo
.CommitLimit
);
3935 ProgressSetStepCount(CopyContext
->MemoryBars
[1], PerfInfo
.CommitLimit
);
3936 ProgressSetStepCount(CopyContext
->MemoryBars
[2], PerfInfo
.CommitLimit
);
3939 /* Set current values */
3940 ProgressSetStep(CopyContext
->MemoryBars
[0], PerfInfo
.PagedPoolPages
+ PerfInfo
.NonPagedPoolPages
);
3941 ProgressSetStep(CopyContext
->MemoryBars
[1], PerfInfo
.ResidentSystemCachePage
);
3942 ProgressSetStep(CopyContext
->MemoryBars
[2], PerfInfo
.AvailablePages
);
3948 FileCopyCallback(PVOID Context
,
3953 PCOPYCONTEXT CopyContext
;
3955 CopyContext
= (PCOPYCONTEXT
)Context
;
3957 switch (Notification
)
3959 case SPFILENOTIFY_STARTSUBQUEUE
:
3960 CopyContext
->TotalOperations
= (ULONG
)Param2
;
3961 ProgressSetStepCount(CopyContext
->ProgressBar
,
3962 CopyContext
->TotalOperations
);
3963 SetupUpdateMemoryInfo(CopyContext
, TRUE
);
3966 case SPFILENOTIFY_STARTCOPY
:
3967 /* Display copy message */
3968 CONSOLE_SetStatusText(MUIGetString(STRING_COPYING
), (PWSTR
)Param1
);
3969 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3972 case SPFILENOTIFY_ENDCOPY
:
3973 CopyContext
->CompletedOperations
++;
3975 /* SYSREG checkpoint */
3976 if (CopyContext
->TotalOperations
>> 1 == CopyContext
->CompletedOperations
)
3977 DPRINT1("CHECKPOINT:HALF_COPIED\n");
3979 ProgressNextStep(CopyContext
->ProgressBar
);
3980 SetupUpdateMemoryInfo(CopyContext
, FALSE
);
3989 * Displays the FileCopyPage.
3992 * RegistryPage(At once)
3995 * Calls SetupCommitFileQueueW
3996 * Calls SetupCloseFileQueue
3999 * Number of the next page.
4002 FileCopyPage(PINPUT_RECORD Ir
)
4004 COPYCONTEXT CopyContext
;
4005 unsigned int mem_bar_width
;
4007 MUIDisplayPage(FILE_COPY_PAGE
);
4009 /* Create context for the copy process */
4010 CopyContext
.DestinationRootPath
= DestinationRootPath
.Buffer
;
4011 CopyContext
.InstallPath
= InstallPath
.Buffer
;
4012 CopyContext
.TotalOperations
= 0;
4013 CopyContext
.CompletedOperations
= 0;
4015 /* Create the progress bar as well */
4016 CopyContext
.ProgressBar
= CreateProgressBar(13,
4023 MUIGetString(STRING_SETUPCOPYINGFILES
));
4025 // fit memory bars to screen width, distribute them uniform
4026 mem_bar_width
= (xScreen
- 26) / 5;
4027 mem_bar_width
-= mem_bar_width
% 2; // make even
4028 /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */
4029 /* Create the paged pool progress bar */
4030 CopyContext
.MemoryBars
[0] = CreateProgressBar(13,
4039 /* Create the non paged pool progress bar */
4040 CopyContext
.MemoryBars
[1] = CreateProgressBar((xScreen
/ 2)- (mem_bar_width
/ 2),
4042 (xScreen
/ 2) + (mem_bar_width
/ 2),
4044 (xScreen
/ 2)- (mem_bar_width
/ 2),
4049 /* Create the global memory progress bar */
4050 CopyContext
.MemoryBars
[2] = CreateProgressBar(xScreen
- 13 - mem_bar_width
,
4054 xScreen
- 13 - mem_bar_width
,
4059 /* Do the file copying */
4060 SetupCommitFileQueueW(NULL
,
4065 /* If we get here, we're done, so cleanup the queue and progress bar */
4066 SetupCloseFileQueue(SetupFileQueue
);
4067 DestroyProgressBar(CopyContext
.ProgressBar
);
4068 DestroyProgressBar(CopyContext
.MemoryBars
[0]);
4069 DestroyProgressBar(CopyContext
.MemoryBars
[1]);
4070 DestroyProgressBar(CopyContext
.MemoryBars
[2]);
4072 /* Go display the next page */
4073 return REGISTRY_PAGE
;
4078 * Displays the RegistryPage.
4081 * SuccessPage (if RepairUpdate)
4082 * BootLoaderPage (default)
4086 * Calls SetInstallPathValue
4087 * Calls NtInitializeRegistry
4088 * Calls ImportRegistryFile
4089 * Calls SetDefaultPagefile
4090 * Calls SetMountedDeviceValues
4093 * Number of the next page.
4096 RegistryPage(PINPUT_RECORD Ir
)
4098 INFCONTEXT InfContext
;
4105 MUIDisplayPage(REGISTRY_PAGE
);
4107 if (RepairUpdateFlag
)
4109 return SUCCESS_PAGE
;
4112 if (!SetInstallPathValue(&DestinationPath
))
4114 DPRINT1("SetInstallPathValue() failed\n");
4115 MUIDisplayError(ERROR_INITIALIZE_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4119 /* Create the default hives */
4120 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
4121 if (!NT_SUCCESS(Status
))
4123 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
4124 MUIDisplayError(ERROR_CREATE_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4128 /* Update registry */
4129 CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE
));
4131 if (!SetupFindFirstLineW(SetupInf
, L
"HiveInfs.Install", NULL
, &InfContext
))
4133 DPRINT1("SetupFindFirstLine() failed\n");
4134 MUIDisplayError(ERROR_FIND_REGISTRY
, Ir
, POPUP_WAIT_ENTER
);
4140 INF_GetDataField(&InfContext
, 0, &Action
);
4141 INF_GetDataField(&InfContext
, 1, &File
);
4142 INF_GetDataField(&InfContext
, 2, &Section
);
4144 DPRINT("Action: %S File: %S Section %S\n", Action
, File
, Section
);
4149 if (!_wcsicmp(Action
, L
"AddReg"))
4153 else if (!_wcsicmp(Action
, L
"DelReg"))
4162 CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE
), File
);
4164 if (!ImportRegistryFile(File
, Section
, LanguageId
, Delete
))
4166 DPRINT1("Importing %S failed\n", File
);
4168 MUIDisplayError(ERROR_IMPORT_HIVE
, Ir
, POPUP_WAIT_ENTER
);
4171 } while (SetupFindNextLine(&InfContext
, &InfContext
));
4173 /* Update display registry settings */
4174 CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE
));
4175 if (!ProcessDisplayRegistry(SetupInf
, DisplayList
))
4177 MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4181 /* Set the locale */
4182 CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE
));
4183 if (!ProcessLocaleRegistry(LanguageList
))
4185 MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4189 /* Add keyboard layouts */
4190 CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS
));
4191 if (!AddKeyboardLayouts())
4193 MUIDisplayError(ERROR_ADDING_KBLAYOUTS
, Ir
, POPUP_WAIT_ENTER
);
4198 if (!SetGeoID(MUIGetGeoID()))
4200 MUIDisplayError(ERROR_UPDATE_GEOID
, Ir
, POPUP_WAIT_ENTER
);
4204 if (!IsUnattendedSetup
)
4206 /* Update keyboard layout settings */
4207 CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE
));
4208 if (!ProcessKeyboardLayoutRegistry(LayoutList
))
4210 MUIDisplayError(ERROR_UPDATE_KBSETTINGS
, Ir
, POPUP_WAIT_ENTER
);
4215 /* Add codepage information to registry */
4216 CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE
));
4219 MUIDisplayError(ERROR_ADDING_CODEPAGE
, Ir
, POPUP_WAIT_ENTER
);
4223 /* Set the default pagefile entry */
4224 SetDefaultPagefile(DestinationDriveLetter
);
4226 /* Update the mounted devices list */
4227 SetMountedDeviceValues(PartitionList
);
4229 CONSOLE_SetStatusText(MUIGetString(STRING_DONE
));
4231 return BOOT_LOADER_PAGE
;
4236 * Displays the BootLoaderPage.
4239 * SuccessPage (if RepairUpdate)
4240 * BootLoaderHarddiskMbrPage
4241 * BootLoaderHarddiskVbrPage
4242 * BootLoaderFloppyPage
4247 * Calls SetInstallPathValue
4248 * Calls NtInitializeRegistry
4249 * Calls ImportRegistryFile
4250 * Calls SetDefaultPagefile
4251 * Calls SetMountedDeviceValues
4254 * Number of the next page.
4257 BootLoaderPage(PINPUT_RECORD Ir
)
4259 UCHAR PartitionType
;
4260 BOOLEAN InstallOnFloppy
;
4262 WCHAR PathBuffer
[MAX_PATH
];
4264 CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT
));
4266 RtlFreeUnicodeString(&SystemRootPath
);
4267 swprintf(PathBuffer
,
4268 L
"\\Device\\Harddisk%lu\\Partition%lu",
4269 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
,
4270 PartitionList
->SystemPartition
->PartitionNumber
);
4271 RtlCreateUnicodeString(&SystemRootPath
, PathBuffer
);
4272 DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath
);
4274 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4276 if (IsUnattendedSetup
)
4278 if (UnattendMBRInstallType
== 0) /* skip MBR installation */
4280 return SUCCESS_PAGE
;
4282 else if (UnattendMBRInstallType
== 1) /* install on floppy */
4284 return BOOT_LOADER_FLOPPY_PAGE
;
4288 if (PartitionType
== PARTITION_ENTRY_UNUSED
)
4290 DPRINT("Error: system partition invalid (unused)\n");
4291 InstallOnFloppy
= TRUE
;
4293 else if (PartitionType
== PARTITION_OS2BOOTMGR
)
4295 /* OS/2 boot manager partition */
4296 DPRINT("Found OS/2 boot manager partition\n");
4297 InstallOnFloppy
= TRUE
;
4299 else if (PartitionType
== PARTITION_EXT2
)
4301 /* Linux EXT2 partition */
4302 DPRINT("Found Linux EXT2 partition\n");
4303 InstallOnFloppy
= FALSE
;
4305 else if (PartitionType
== PARTITION_IFS
)
4307 /* NTFS partition */
4308 DPRINT("Found NTFS partition\n");
4310 // FIXME: Make it FALSE when we'll support NTFS installation!
4311 InstallOnFloppy
= TRUE
;
4313 else if ((PartitionType
== PARTITION_FAT_12
) ||
4314 (PartitionType
== PARTITION_FAT_16
) ||
4315 (PartitionType
== PARTITION_HUGE
) ||
4316 (PartitionType
== PARTITION_XINT13
) ||
4317 (PartitionType
== PARTITION_FAT32
) ||
4318 (PartitionType
== PARTITION_FAT32_XINT13
))
4320 DPRINT("Found FAT partition\n");
4321 InstallOnFloppy
= FALSE
;
4325 /* Unknown partition */
4326 DPRINT("Unknown partition found\n");
4327 InstallOnFloppy
= TRUE
;
4330 if (InstallOnFloppy
!= FALSE
)
4332 return BOOT_LOADER_FLOPPY_PAGE
;
4335 /* Unattended install on hdd? */
4336 if (IsUnattendedSetup
&& UnattendMBRInstallType
== 2)
4338 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4341 MUIDisplayPage(BOOT_LOADER_PAGE
);
4342 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4346 CONSOLE_ConInKey(Ir
);
4348 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4349 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
)) /* DOWN */
4351 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4360 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4362 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4363 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)) /* UP */
4365 CONSOLE_NormalTextXY(8, Line
, 60, 1);
4374 CONSOLE_InvertTextXY(8, Line
, 60, 1);
4376 else if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4377 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4379 if (ConfirmQuit(Ir
) != FALSE
)
4384 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4388 return BOOT_LOADER_HARDDISK_MBR_PAGE
;
4390 else if (Line
== 13)
4392 return BOOT_LOADER_HARDDISK_VBR_PAGE
;
4394 else if (Line
== 14)
4396 return BOOT_LOADER_FLOPPY_PAGE
;
4398 else if (Line
== 15)
4400 return SUCCESS_PAGE
;
4403 return BOOT_LOADER_PAGE
;
4407 return BOOT_LOADER_PAGE
;
4412 * Displays the BootLoaderFloppyPage.
4415 * SuccessPage (At once)
4419 * Calls InstallFatBootcodeToFloppy()
4422 * Number of the next page.
4425 BootLoaderFloppyPage(PINPUT_RECORD Ir
)
4429 MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE
);
4431 // CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
4435 CONSOLE_ConInKey(Ir
);
4437 if ((Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x00) &&
4438 (Ir
->Event
.KeyEvent
.wVirtualKeyCode
== VK_F3
)) /* F3 */
4440 if (ConfirmQuit(Ir
) != FALSE
)
4445 else if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4447 if (DoesFileExist(NULL
, L
"\\Device\\Floppy0", L
"\\") == FALSE
)
4449 MUIDisplayError(ERROR_NO_FLOPPY
, Ir
, POPUP_WAIT_ENTER
);
4450 return BOOT_LOADER_FLOPPY_PAGE
;
4453 Status
= InstallFatBootcodeToFloppy(&SourceRootPath
, &DestinationArcPath
);
4454 if (!NT_SUCCESS(Status
))
4456 /* Print error message */
4457 return BOOT_LOADER_FLOPPY_PAGE
;
4460 return SUCCESS_PAGE
;
4464 return BOOT_LOADER_FLOPPY_PAGE
;
4469 * Displays the BootLoaderHarddiskVbrPage.
4472 * SuccessPage (At once)
4476 * Calls InstallVBRToPartition()
4479 * Number of the next page.
4482 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir
)
4484 UCHAR PartitionType
;
4487 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4489 Status
= InstallVBRToPartition(&SystemRootPath
,
4491 &DestinationArcPath
,
4493 if (!NT_SUCCESS(Status
))
4495 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4499 return SUCCESS_PAGE
;
4504 * Displays the BootLoaderHarddiskMbrPage.
4507 * SuccessPage (At once)
4511 * Calls InstallVBRToPartition()
4512 * CallsInstallMbrBootCodeToDisk()
4515 * Number of the next page.
4518 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir
)
4520 UCHAR PartitionType
;
4522 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
4523 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
4524 WCHAR DstPath
[MAX_PATH
];
4526 /* Step 1: Write the VBR */
4527 PartitionType
= PartitionList
->SystemPartition
->PartitionType
;
4529 Status
= InstallVBRToPartition(&SystemRootPath
,
4531 &DestinationArcPath
,
4533 if (!NT_SUCCESS(Status
))
4535 MUIDisplayError(ERROR_WRITE_BOOT
, Ir
, POPUP_WAIT_ENTER
);
4539 /* Step 2: Write the MBR */
4540 swprintf(DestinationDevicePathBuffer
,
4541 L
"\\Device\\Harddisk%d\\Partition0",
4542 PartitionList
->SystemPartition
->DiskEntry
->DiskNumber
);
4544 wcscpy(SourceMbrPathBuffer
, SourceRootPath
.Buffer
);
4545 wcscat(SourceMbrPathBuffer
, L
"\\loader\\dosmbr.bin");
4547 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
4549 /* Save current MBR */
4550 wcscpy(DstPath
, SystemRootPath
.Buffer
);
4551 wcscat(DstPath
, L
"\\mbr.old");
4553 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
4554 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
4555 if (!NT_SUCCESS(Status
))
4557 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
4558 // Don't care if we succeeded or not saving the old MBR, just go ahead.
4562 DPRINT1("Install MBR bootcode: %S ==> %S\n",
4563 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
4564 Status
= InstallMbrBootCodeToDisk(SourceMbrPathBuffer
,
4565 DestinationDevicePathBuffer
);
4566 if (!NT_SUCCESS(Status
))
4568 DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
4570 MUIDisplayError(ERROR_INSTALL_BOOTCODE
, Ir
, POPUP_WAIT_ENTER
);
4574 return SUCCESS_PAGE
;
4579 * Displays the QuitPage.
4582 * FlushPage (At once)
4588 * Number of the next page.
4591 QuitPage(PINPUT_RECORD Ir
)
4593 MUIDisplayPage(QUIT_PAGE
);
4595 /* Destroy the partition list */
4596 if (PartitionList
!= NULL
)
4598 DestroyPartitionList(PartitionList
);
4599 PartitionList
= NULL
;
4602 /* Destroy the filesystem list */
4603 if (FileSystemList
!= NULL
)
4605 DestroyFileSystemList(FileSystemList
);
4606 FileSystemList
= NULL
;
4609 /* Destroy the computer settings list */
4610 if (ComputerList
!= NULL
)
4612 DestroyGenericList(ComputerList
, TRUE
);
4613 ComputerList
= NULL
;
4616 /* Destroy the display settings list */
4617 if (DisplayList
!= NULL
)
4619 DestroyGenericList(DisplayList
, TRUE
);
4623 /* Destroy the keyboard settings list */
4624 if (KeyboardList
!= NULL
)
4626 DestroyGenericList(KeyboardList
, TRUE
);
4627 KeyboardList
= NULL
;
4630 /* Destroy the keyboard layout list */
4631 if (LayoutList
!= NULL
)
4633 DestroyGenericList(LayoutList
, TRUE
);
4637 /* Destroy the languages list */
4638 if (LanguageList
!= NULL
)
4640 DestroyGenericList(LanguageList
, FALSE
);
4641 LanguageList
= NULL
;
4644 CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2
));
4648 CONSOLE_ConInKey(Ir
);
4650 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4659 * Displays the SuccessPage.
4662 * FlushPage (At once)
4668 * Number of the next page.
4671 SuccessPage(PINPUT_RECORD Ir
)
4673 MUIDisplayPage(SUCCESS_PAGE
);
4675 if (IsUnattendedSetup
)
4682 CONSOLE_ConInKey(Ir
);
4684 if (Ir
->Event
.KeyEvent
.uChar
.AsciiChar
== 0x0D) /* ENTER */
4693 * Displays the FlushPage.
4696 * RebootPage (At once)
4699 * Number of the next page.
4702 FlushPage(PINPUT_RECORD Ir
)
4704 MUIDisplayPage(FLUSH_PAGE
);
4710 PnpEventThread(IN LPVOID lpParameter
);
4714 * The start routine and page management
4725 NtQuerySystemTime(&Time
);
4727 /* Create the PnP thread in suspended state */
4728 Status
= RtlCreateUserThread(NtCurrentProcess(),
4738 if (!NT_SUCCESS(Status
))
4739 hPnpThread
= INVALID_HANDLE_VALUE
;
4741 if (!CONSOLE_Init())
4743 PrintString(MUIGetString(STRING_CONSOLEFAIL1
));
4744 PrintString(MUIGetString(STRING_CONSOLEFAIL2
));
4745 PrintString(MUIGetString(STRING_CONSOLEFAIL3
));
4747 /* Raise a hard error (crash the system/BSOD) */
4748 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
4752 /* Initialize global unicode strings */
4753 RtlInitUnicodeString(&SourcePath
, NULL
);
4754 RtlInitUnicodeString(&SourceRootPath
, NULL
);
4755 RtlInitUnicodeString(&SourceRootDir
, NULL
);
4756 RtlInitUnicodeString(&InstallPath
, NULL
);
4757 RtlInitUnicodeString(&DestinationPath
, NULL
);
4758 RtlInitUnicodeString(&DestinationArcPath
, NULL
);
4759 RtlInitUnicodeString(&DestinationRootPath
, NULL
);
4760 RtlInitUnicodeString(&SystemRootPath
, NULL
);
4762 /* Hide the cursor */
4763 CONSOLE_SetCursorType(TRUE
, FALSE
);
4766 while (Page
!= REBOOT_PAGE
&& Page
!= RECOVERY_PAGE
)
4768 CONSOLE_ClearScreen();
4771 //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
4778 Page
= SetupStartPage(&Ir
);
4783 Page
= LanguagePage(&Ir
);
4788 Page
= LicensePage(&Ir
);
4793 Page
= IntroPage(&Ir
);
4797 case INSTALL_INTRO_PAGE
:
4798 Page
= InstallIntroPage(&Ir
);
4802 case SCSI_CONTROLLER_PAGE
:
4803 Page
= ScsiControllerPage(&Ir
);
4806 case OEM_DRIVER_PAGE
:
4807 Page
= OemDriverPage(&Ir
);
4811 case DEVICE_SETTINGS_PAGE
:
4812 Page
= DeviceSettingsPage(&Ir
);
4815 case COMPUTER_SETTINGS_PAGE
:
4816 Page
= ComputerSettingsPage(&Ir
);
4819 case DISPLAY_SETTINGS_PAGE
:
4820 Page
= DisplaySettingsPage(&Ir
);
4823 case KEYBOARD_SETTINGS_PAGE
:
4824 Page
= KeyboardSettingsPage(&Ir
);
4827 case LAYOUT_SETTINGS_PAGE
:
4828 Page
= LayoutSettingsPage(&Ir
);
4831 case SELECT_PARTITION_PAGE
:
4832 Page
= SelectPartitionPage(&Ir
);
4835 case CREATE_PRIMARY_PARTITION_PAGE
:
4836 Page
= CreatePrimaryPartitionPage(&Ir
);
4839 case CREATE_EXTENDED_PARTITION_PAGE
:
4840 Page
= CreateExtendedPartitionPage(&Ir
);
4843 case CREATE_LOGICAL_PARTITION_PAGE
:
4844 Page
= CreateLogicalPartitionPage(&Ir
);
4847 case CONFIRM_DELETE_SYSTEM_PARTITION_PAGE
:
4848 Page
= ConfirmDeleteSystemPartitionPage(&Ir
);
4851 case DELETE_PARTITION_PAGE
:
4852 Page
= DeletePartitionPage(&Ir
);
4855 case SELECT_FILE_SYSTEM_PAGE
:
4856 Page
= SelectFileSystemPage(&Ir
);
4859 case FORMAT_PARTITION_PAGE
:
4860 Page
= FormatPartitionPage(&Ir
);
4863 case CHECK_FILE_SYSTEM_PAGE
:
4864 Page
= CheckFileSystemPage(&Ir
);
4867 case INSTALL_DIRECTORY_PAGE
:
4868 Page
= InstallDirectoryPage(&Ir
);
4871 case PREPARE_COPY_PAGE
:
4872 Page
= PrepareCopyPage(&Ir
);
4875 case FILE_COPY_PAGE
:
4876 Page
= FileCopyPage(&Ir
);
4880 Page
= RegistryPage(&Ir
);
4883 case BOOT_LOADER_PAGE
:
4884 Page
= BootLoaderPage(&Ir
);
4887 case BOOT_LOADER_FLOPPY_PAGE
:
4888 Page
= BootLoaderFloppyPage(&Ir
);
4891 case BOOT_LOADER_HARDDISK_MBR_PAGE
:
4892 Page
= BootLoaderHarddiskMbrPage(&Ir
);
4895 case BOOT_LOADER_HARDDISK_VBR_PAGE
:
4896 Page
= BootLoaderHarddiskVbrPage(&Ir
);
4900 case REPAIR_INTRO_PAGE
:
4901 Page
= RepairIntroPage(&Ir
);
4905 Page
= SuccessPage(&Ir
);
4909 Page
= FlushPage(&Ir
);
4913 Page
= QuitPage(&Ir
);
4922 if (Page
== RECOVERY_PAGE
)
4927 /* Avoid bugcheck */
4928 Time
.QuadPart
+= 50000000;
4929 NtDelayExecution(FALSE
, &Time
);
4932 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
4933 NtShutdownSystem(ShutdownReboot
);
4934 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, Old
, FALSE
, &Old
);
4935 NtTerminateProcess(NtCurrentProcess(), 0);
4940 NtProcessStartup(PPEB Peb
)
4942 RtlNormalizeProcessParams(Peb
->ProcessParameters
);
4944 ProcessHeap
= Peb
->ProcessHeap
;
4945 InfSetHeap(ProcessHeap
);