X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=base%2Fsetup%2Fusetup%2Fusetup.c;h=f16d6512b739bcf886a1f7cc1aed7a660f7bed86;hp=d29f15d57c834842dfe5f8220a2794bca334d192;hb=073c09e491f1003b07c10abfb5e209f0c5e122f5;hpb=de824808b70cd88a0d04bf8b13e2f86832eba08c diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index d29f15d57c8..f16d6512b73 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -21,8 +21,7 @@ * PROJECT: ReactOS text-mode setup * FILE: base/setup/usetup/usetup.c * PURPOSE: Text-mode setup - * PROGRAMMER: Eric Kohl - * Casper S. Hornstrup (chorns@users.sourceforge.net) + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * Hervé Poussineau (hpoussin@reactos.org) */ @@ -33,75 +32,42 @@ #include "chkdsk.h" #include "cmdcons.h" #include "format.h" -#include "drivesup.h" -#include "settings.h" #define NDEBUG #include -/* GLOBALS ******************************************************************/ +/* GLOBALS & LOCALS *********************************************************/ HANDLE ProcessHeap; -UNICODE_STRING SourceRootPath; -UNICODE_STRING SourceRootDir; -UNICODE_STRING SourcePath; BOOLEAN IsUnattendedSetup = FALSE; -LONG UnattendDestinationDiskNumber; -LONG UnattendDestinationPartitionNumber; -LONG UnattendMBRInstallType = -1; -LONG UnattendFormatPartition = 0; -LONG AutoPartition = 0; -WCHAR UnattendInstallationDirectory[MAX_PATH]; -PWCHAR SelectedLanguageId; -WCHAR LocaleID[9]; -WCHAR DefaultLanguage[20]; -WCHAR DefaultKBLayout[20]; -BOOLEAN RepairUpdateFlag = FALSE; -HANDLE hPnpThread = INVALID_HANDLE_VALUE; -PPARTLIST PartitionList = NULL; - -/* LOCALS *******************************************************************/ -static PFILE_SYSTEM_LIST FileSystemList = NULL; +static USETUP_DATA USetupData; -static UNICODE_STRING InstallPath; +// FIXME: Is it really useful?? Just used for SetDefaultPagefile... +static WCHAR DestinationDriveLetter; -/* - * Path to the system partition, where the boot manager resides. - * On x86 PCs, this is usually the active partition. - * On ARC, (u)EFI, ... platforms, this is a dedicated partition. - * - * For more information, see: - * https://en.wikipedia.org/wiki/System_partition_and_boot_partition - * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html - * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html - * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html - * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html - * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html - */ -static UNICODE_STRING SystemRootPath; -/* Path to the install directory inside the ReactOS boot partition */ -static UNICODE_STRING DestinationPath; -static UNICODE_STRING DestinationArcPath; -static UNICODE_STRING DestinationRootPath; +/* OTHER Stuff *****/ -static WCHAR DestinationDriveLetter; +PCWSTR SelectedLanguageId; +static WCHAR DefaultLanguage[20]; // Copy of string inside LanguageList +static WCHAR DefaultKBLayout[20]; // Copy of string inside KeyboardList -static HINF SetupInf; +static BOOLEAN RepairUpdateFlag = FALSE; -static HSPFILEQ SetupFileQueue = NULL; +static HANDLE hPnpThread = NULL; + +static PPARTLIST PartitionList = NULL; +static PPARTENTRY TempPartition = NULL; +static PFILE_SYSTEM_LIST FileSystemList = NULL; +static FORMATMACHINESTATE FormatState = Start; -static PGENERIC_LIST ComputerList = NULL; -static PGENERIC_LIST DisplayList = NULL; -static PGENERIC_LIST KeyboardList = NULL; -static PGENERIC_LIST LayoutList = NULL; -static PGENERIC_LIST LanguageList = NULL; +/*****************************************************/ -static LANGID LanguageId = 0; +static PNTOS_INSTALLATION CurrentInstallation = NULL; +static PGENERIC_LIST NtOsInstallsList = NULL; -static ULONG RequiredPartitionDiskSpace = ~0; /* FUNCTIONS ****************************************************************/ @@ -133,7 +99,7 @@ DrawBox(IN SHORT xLeft, COORD coPos; DWORD Written; - /* draw upper left corner */ + /* Draw upper left corner */ coPos.X = xLeft; coPos.Y = yTop; FillConsoleOutputCharacterA(StdOutput, @@ -142,7 +108,7 @@ DrawBox(IN SHORT xLeft, coPos, &Written); - /* draw upper edge */ + /* Draw upper edge */ coPos.X = xLeft + 1; coPos.Y = yTop; FillConsoleOutputCharacterA(StdOutput, @@ -151,7 +117,7 @@ DrawBox(IN SHORT xLeft, coPos, &Written); - /* draw upper right corner */ + /* Draw upper right corner */ coPos.X = xLeft + Width - 1; coPos.Y = yTop; FillConsoleOutputCharacterA(StdOutput, @@ -185,7 +151,7 @@ DrawBox(IN SHORT xLeft, &Written); } - /* draw lower left corner */ + /* Draw lower left corner */ coPos.X = xLeft; coPos.Y = yTop + Height - 1; FillConsoleOutputCharacterA(StdOutput, @@ -194,7 +160,7 @@ DrawBox(IN SHORT xLeft, coPos, &Written); - /* draw lower edge */ + /* Draw lower edge */ coPos.X = xLeft + 1; coPos.Y = yTop + Height - 1; FillConsoleOutputCharacterA(StdOutput, @@ -203,7 +169,7 @@ DrawBox(IN SHORT xLeft, coPos, &Written); - /* draw lower right corner */ + /* Draw lower right corner */ coPos.X = xLeft + Width - 1; coPos.Y = yTop + Height - 1; FillConsoleOutputCharacterA(StdOutput, @@ -258,7 +224,7 @@ PopupError(PCCH Text, if (Length > MaxLength) MaxLength = Length; - if (LastLine != FALSE) + if (LastLine) break; pnext = p + 1; @@ -324,7 +290,7 @@ PopupError(PCCH Text, &Written); } - if (LastLine != FALSE) + if (LastLine) break; coPos.Y++; @@ -414,213 +380,77 @@ ConfirmQuit(PINPUT_RECORD Ir) } -VOID -CheckUnattendedSetup(VOID) +static VOID +UpdateKBLayout(VOID) { - WCHAR UnattendInfPath[MAX_PATH]; - INFCONTEXT Context; - HINF UnattendInf; - UINT ErrorLine; - INT IntValue; - PWCHAR Value; - - if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE) - { - DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf"); - return; - } - - wcscpy(UnattendInfPath, SourcePath.Buffer); - wcscat(UnattendInfPath, L"\\unattend.inf"); - - /* Load 'unattend.inf' from install media. */ - UnattendInf = SetupOpenInfFileW(UnattendInfPath, - NULL, - INF_STYLE_WIN4, - LanguageId, - &ErrorLine); - - if (UnattendInf == INVALID_HANDLE_VALUE) - { - DPRINT("SetupOpenInfFileW() failed\n"); - return; - } - - /* Open 'Unattend' section */ - if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context)) - { - DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - /* Get pointer 'Signature' key */ - if (!INF_GetData(&Context, NULL, &Value)) - { - DPRINT("INF_GetData() failed for key 'Signature'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - /* Check 'Signature' string */ - if (_wcsicmp(Value, L"$ReactOS$") != 0) - { - DPRINT("Signature not $ReactOS$\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - /* Check if Unattend setup is enabled */ - if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"UnattendSetupEnabled", &Context)) - { - DPRINT("Can't find key 'UnattendSetupEnabled'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - if (!INF_GetData(&Context, NULL, &Value)) - { - DPRINT("Can't read key 'UnattendSetupEnabled'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - if (_wcsicmp(Value, L"yes") != 0) - { - DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - /* Search for 'DestinationDiskNumber' in the 'Unattend' section */ - if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationDiskNumber", &Context)) - { - DPRINT("SetupFindFirstLine() failed for key 'DestinationDiskNumber'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - if (!SetupGetIntField(&Context, 1, &IntValue)) - { - DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - UnattendDestinationDiskNumber = (LONG)IntValue; - - /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */ - if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"DestinationPartitionNumber", &Context)) - { - DPRINT("SetupFindFirstLine() failed for key 'DestinationPartitionNumber'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - if (!SetupGetIntField(&Context, 1, &IntValue)) - { - DPRINT("SetupGetIntField() failed for key 'DestinationPartitionNumber'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - UnattendDestinationPartitionNumber = IntValue; - - /* Search for 'InstallationDirectory' in the 'Unattend' section */ - if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context)) - { - DPRINT("SetupFindFirstLine() failed for key 'InstallationDirectory'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - /* Get pointer 'InstallationDirectory' key */ - if (!INF_GetData(&Context, NULL, &Value)) - { - DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n"); - SetupCloseInfFile(UnattendInf); - return; - } - - wcscpy(UnattendInstallationDirectory, Value); - - IsUnattendedSetup = TRUE; + PGENERIC_LIST_ENTRY ListEntry; + PCWSTR pszNewLayout; - /* Search for 'MBRInstallType' in the 'Unattend' section */ - if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", &Context)) - { - if (SetupGetIntField(&Context, 1, &IntValue)) - { - UnattendMBRInstallType = IntValue; - } - } + pszNewLayout = MUIDefaultKeyboardLayout(SelectedLanguageId); - /* Search for 'FormatPartition' in the 'Unattend' section */ - if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", &Context)) + if (USetupData.LayoutList == NULL) { - if (SetupGetIntField(&Context, 1, &IntValue)) + USetupData.LayoutList = CreateKeyboardLayoutList(USetupData.SetupInf, SelectedLanguageId, DefaultKBLayout); + if (USetupData.LayoutList == NULL) { - UnattendFormatPartition = IntValue; + /* FIXME: Handle error! */ + return; } } - if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", &Context)) + /* Search for default layout (if provided) */ + if (pszNewLayout != NULL) { - if (SetupGetIntField(&Context, 1, &IntValue)) + for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry; + ListEntry = GetNextListEntry(ListEntry)) { - AutoPartition = IntValue; + if (!wcscmp(pszNewLayout, ((PGENENTRY)GetListEntryData(ListEntry))->Id)) + { + SetCurrentListEntry(USetupData.LayoutList, ListEntry); + break; + } } } - - /* search for LocaleID in the 'Unattend' section*/ - if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"LocaleID", &Context)) - { - if (INF_GetData(&Context, NULL, &Value)) - { - LONG Id = wcstol(Value, NULL, 16); - swprintf(LocaleID,L"%08lx", Id); - } - } - - SetupCloseInfFile(UnattendInf); - - DPRINT("Running unattended setup\n"); } -VOID -UpdateKBLayout(VOID) +static NTSTATUS +NTAPI +GetSettingDescription( + IN PGENERIC_LIST_ENTRY Entry, + OUT PSTR Buffer, + IN SIZE_T cchBufferSize) { - PGENERIC_LIST_ENTRY ListEntry; - LPCWSTR pszNewLayout; + return RtlStringCchPrintfA(Buffer, cchBufferSize, "%S", + ((PGENENTRY)GetListEntryData(Entry))->Value); +} - pszNewLayout = MUIDefaultKeyboardLayout(); +static NTSTATUS +NTAPI +GetNTOSInstallationName( + IN PGENERIC_LIST_ENTRY Entry, + OUT PSTR Buffer, + IN SIZE_T cchBufferSize) +{ + PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry); + PPARTENTRY PartEntry = NtOsInstall->PartEntry; - if (LayoutList == NULL) + if (PartEntry && PartEntry->DriveLetter) { - LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout); - if (LayoutList == NULL) - { - /* FIXME: Handle error! */ - return; - } + /* We have retrieved a partition that is mounted */ + return RtlStringCchPrintfA(Buffer, cchBufferSize, + "%C:%S \"%S\"", + PartEntry->DriveLetter, + NtOsInstall->PathComponent, + NtOsInstall->InstallationName); } - - ListEntry = GetFirstListEntry(LayoutList); - - /* Search for default layout (if provided) */ - if (pszNewLayout != NULL) + else { - while (ListEntry != NULL) - { - if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry))) - { - SetCurrentListEntry(LayoutList, ListEntry); - break; - } - - ListEntry = GetNextListEntry(ListEntry); - } + /* We failed somewhere, just show the NT path */ + return RtlStringCchPrintfA(Buffer, cchBufferSize, + "%wZ \"%S\"", + &NtOsInstall->SystemNtPath, + NtOsInstall->InstallationName); } } @@ -628,11 +458,11 @@ UpdateKBLayout(VOID) /* * Displays the LanguagePage. * - * Next pages: IntroPage, QuitPage + * Next pages: WelcomePage, QuitPage * * SIDEEFFECTS * Init SelectedLanguageId - * Init LanguageId + * Init USetupData.LanguageId * * RETURNS * Number of the next page. @@ -640,41 +470,45 @@ UpdateKBLayout(VOID) static PAGE_NUMBER LanguagePage(PINPUT_RECORD Ir) { - PWCHAR NewLanguageId; + GENERIC_LIST_UI ListUi; + PCWSTR NewLanguageId; BOOL RefreshPage = FALSE; /* Initialize the computer settings list */ - if (LanguageList == NULL) + if (USetupData.LanguageList == NULL) { - LanguageList = CreateLanguageList(SetupInf, DefaultLanguage); - - if (LanguageList == NULL) + USetupData.LanguageList = CreateLanguageList(USetupData.SetupInf, DefaultLanguage); + if (USetupData.LanguageList == NULL) { PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE); - return INTRO_PAGE; + return WELCOME_PAGE; } } - /* Load the font */ SelectedLanguageId = DefaultLanguage; + USetupData.LanguageId = 0; + + /* Load the font */ SetConsoleCodePage(); UpdateKBLayout(); - /* If there's just a single language in the list skip - * the language selection process altogether! */ - if (GenericListHasSingleEntry(LanguageList)) + /* + * If there is no language or just a single one in the list, + * skip the language selection process altogether. + */ + if (GetNumberOfListEntries(USetupData.LanguageList) <= 1) { - LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); - return INTRO_PAGE; + USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); + return WELCOME_PAGE; } - DrawGenericList(LanguageList, - 2, - 18, + InitGenericListUi(&ListUi, USetupData.LanguageList, GetSettingDescription); + DrawGenericList(&ListUi, + 2, 18, xScreen - 3, yScreen - 3); - ScrollToPositionGenericList(LanguageList, GetDefaultLanguageIndex()); + ScrollToPositionGenericList(&ListUi, GetDefaultLanguageIndex()); MUIDisplayPage(LANGUAGE_PAGE); @@ -685,40 +519,43 @@ LanguagePage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ { - ScrollDownGenericList(LanguageList); + ScrollDownGenericList(&ListUi); RefreshPage = TRUE; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */ { - ScrollUpGenericList(LanguageList); + ScrollUpGenericList(&ListUi); RefreshPage = TRUE; } if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */ { - ScrollPageDownGenericList(LanguageList); + ScrollPageDownGenericList(&ListUi); RefreshPage = TRUE; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */ { - ScrollPageUpGenericList(LanguageList); + ScrollPageUpGenericList(&ListUi); RefreshPage = TRUE; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; else - RedrawGenericList(LanguageList); + RedrawGenericList(&ListUi); } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { - SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList)); + ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1); + + SelectedLanguageId = + ((PGENENTRY)GetListEntryData(GetCurrentListEntry(USetupData.LanguageList)))->Id; - LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); + USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); if (wcscmp(SelectedLanguageId, DefaultLanguage)) { @@ -728,20 +565,23 @@ LanguagePage(PINPUT_RECORD Ir) /* Load the font */ SetConsoleCodePage(); - return INTRO_PAGE; + return WELCOME_PAGE; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) { /* a-z */ - GenericListKeyPress(LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar); + GenericListKeyPress(&ListUi, Ir->Event.KeyEvent.uChar.AsciiChar); RefreshPage = TRUE; } if (RefreshPage) { - NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList)); + ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1); - if (SelectedLanguageId != NewLanguageId) + NewLanguageId = + ((PGENENTRY)GetListEntryData(GetCurrentListEntry(USetupData.LanguageList)))->Id; + + if (wcscmp(SelectedLanguageId, NewLanguageId)) { /* Clear the language page */ MUIClearPage(LANGUAGE_PAGE); @@ -759,7 +599,7 @@ LanguagePage(PINPUT_RECORD Ir) } } - return INTRO_PAGE; + return WELCOME_PAGE; } @@ -773,15 +613,15 @@ LanguagePage(PINPUT_RECORD Ir) * * SIDEEFFECTS * Init Sdi - * Init SourcePath - * Init SourceRootPath - * Init SourceRootDir - * Init SetupInf - * Init RequiredPartitionDiskSpace + * Init USetupData.SourcePath + * Init USetupData.SourceRootPath + * Init USetupData.SourceRootDir + * Init USetupData.SetupInf + * Init USetupData.RequiredPartitionDiskSpace * Init IsUnattendedSetup * If unattended, init *List and sets the Codepage * If unattended, init SelectedLanguageId - * If unattended, init LanguageId + * If unattended, init USetupData.LanguageId * * RETURNS * Number of the next page. @@ -789,163 +629,71 @@ LanguagePage(PINPUT_RECORD Ir) static PAGE_NUMBER SetupStartPage(PINPUT_RECORD Ir) { - //SYSTEM_DEVICE_INFORMATION Sdi; - NTSTATUS Status; - WCHAR FileNameBuffer[MAX_PATH]; - INFCONTEXT Context; - PWCHAR Value; - UINT ErrorLine; - //ULONG ReturnSize; + ULONG Error; PGENERIC_LIST_ENTRY ListEntry; - INT IntValue; + PCWSTR LocaleId; CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); -#if 0 - /* Check whether a harddisk is available */ - Status = NtQuerySystemInformation(SystemDeviceInformation, - &Sdi, - sizeof(SYSTEM_DEVICE_INFORMATION), - &ReturnSize); - - if (!NT_SUCCESS(Status)) - { - CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status); - MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - if (Sdi.NumberOfDisks == 0) - { - MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } -#endif - - /* Get the source path and source root path */ - Status = GetSourcePaths(&SourcePath, - &SourceRootPath, - &SourceRootDir); - - if (!NT_SUCCESS(Status)) - { - CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status); - MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } -#if 0 - else - { - CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath); - CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath); - CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir); - } -#endif - - /* Load txtsetup.sif from install media. */ - wcscpy(FileNameBuffer, SourcePath.Buffer); - wcscat(FileNameBuffer, L"\\txtsetup.sif"); - - SetupInf = SetupOpenInfFileW(FileNameBuffer, - NULL, - INF_STYLE_WIN4, - LanguageId, - &ErrorLine); - - if (SetupInf == INVALID_HANDLE_VALUE) - { - MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Open 'Version' section */ - if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context)) - { - MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Get pointer 'Signature' key */ - if (!INF_GetData(&Context, NULL, &Value)) - { - MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Check 'Signature' string */ - if (_wcsicmp(Value, L"$ReactOS$") != 0) - { - MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Open 'DiskSpaceRequirements' section */ - if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", L"FreeSysPartDiskSpace", &Context)) - { - MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Get the 'FreeSysPartDiskSpace' value */ - if (!SetupGetIntField(&Context, 1, &IntValue)) + /* Initialize Setup, phase 1 */ + Error = InitializeSetup(&USetupData, 1); + if (Error != ERROR_SUCCESS) { - MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); + MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } - RequiredPartitionDiskSpace = (ULONG)IntValue; - - /* Start PnP thread */ - if (hPnpThread != INVALID_HANDLE_VALUE) + /* Start the PnP thread */ + if (hPnpThread != NULL) { NtResumeThread(hPnpThread, NULL); - hPnpThread = INVALID_HANDLE_VALUE; + hPnpThread = NULL; } - CheckUnattendedSetup(); + CheckUnattendedSetup(&USetupData); if (IsUnattendedSetup) { - //TODO - //read options from inf - ComputerList = CreateComputerTypeList(SetupInf); - DisplayList = CreateDisplayDriverList(SetupInf); - KeyboardList = CreateKeyboardDriverList(SetupInf); - LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout); - LanguageList = CreateLanguageList(SetupInf, DefaultLanguage); + // TODO: Read options from inf + /* Load the hardware, language and keyboard layout lists */ + + USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf); + USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf); + USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf); + + USetupData.LanguageList = CreateLanguageList(USetupData.SetupInf, DefaultLanguage); /* new part */ - wcscpy(SelectedLanguageId,LocaleID); - LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); + SelectedLanguageId = DefaultLanguage; + wcscpy(DefaultLanguage, USetupData.LocaleID); + USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); - /* first we hack LanguageList */ - ListEntry = GetFirstListEntry(LanguageList); + USetupData.LayoutList = CreateKeyboardLayoutList(USetupData.SetupInf, SelectedLanguageId, DefaultKBLayout); - while (ListEntry != NULL) + /* first we hack LanguageList */ + for (ListEntry = GetFirstListEntry(USetupData.LanguageList); ListEntry; + ListEntry = GetNextListEntry(ListEntry)) { - if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry))) + LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id; + if (!wcsicmp(USetupData.LocaleID, LocaleId)) { - DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry)); - SetCurrentListEntry(LanguageList, ListEntry); + DPRINT("found %S in LanguageList\n", LocaleId); + SetCurrentListEntry(USetupData.LanguageList, ListEntry); break; } - - ListEntry = GetNextListEntry(ListEntry); } /* now LayoutList */ - ListEntry = GetFirstListEntry(LayoutList); - - while (ListEntry != NULL) + for (ListEntry = GetFirstListEntry(USetupData.LayoutList); ListEntry; + ListEntry = GetNextListEntry(ListEntry)) { - if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry))) + LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id; + if (!wcsicmp(USetupData.LocaleID, LocaleId)) { - DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry)); - SetCurrentListEntry(LayoutList, ListEntry); + DPRINT("found %S in LayoutList\n", LocaleId); + SetCurrentListEntry(USetupData.LayoutList, ListEntry); break; } - - ListEntry = GetNextListEntry(ListEntry); } SetConsoleCodePage(); @@ -958,11 +706,12 @@ SetupStartPage(PINPUT_RECORD Ir) /* - * Displays the IntroPage. + * Displays the WelcomePage. * * Next pages: * InstallIntroPage (default) * RepairIntroPage + * RecoveryPage * LicensePage * QuitPage * @@ -970,9 +719,9 @@ SetupStartPage(PINPUT_RECORD Ir) * Number of the next page. */ static PAGE_NUMBER -IntroPage(PINPUT_RECORD Ir) +WelcomePage(PINPUT_RECORD Ir) { - MUIDisplayPage(START_PAGE); + MUIDisplayPage(WELCOME_PAGE); while (TRUE) { @@ -981,7 +730,7 @@ IntroPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -992,15 +741,15 @@ IntroPage(PINPUT_RECORD Ir) } else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */ { - return REPAIR_INTRO_PAGE; + return RECOVERY_PAGE; // REPAIR_INTRO_PAGE; } - else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */ + else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */ { return LICENSE_PAGE; } } - return INTRO_PAGE; + return WELCOME_PAGE; } @@ -1008,7 +757,7 @@ IntroPage(PINPUT_RECORD Ir) * Displays the License page. * * Next page: - * IntroPage (default) + * WelcomePage (default) * * RETURNS * Number of the next page. @@ -1024,7 +773,7 @@ LicensePage(PINPUT_RECORD Ir) if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { - return INTRO_PAGE; + return WELCOME_PAGE; } } @@ -1069,7 +818,7 @@ RepairIntroPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ { - return INTRO_PAGE; + return WELCOME_PAGE; } } @@ -1077,78 +826,220 @@ RepairIntroPage(PINPUT_RECORD Ir) } /* - * Displays the InstallIntroPage. + * Displays the UpgradeRepairPage. * * Next pages: - * DeviceSettingsPage (At once if repair or update is selected) - * SelectPartitionPage (At once if unattended setup) - * DeviceSettingsPage (default) - * QuitPage + * RebootPage (default) + * InstallIntroPage + * RecoveryPage + * WelcomePage * * RETURNS * Number of the next page. */ static PAGE_NUMBER -InstallIntroPage(PINPUT_RECORD Ir) +UpgradeRepairPage(PINPUT_RECORD Ir) { - MUIDisplayPage(INSTALL_INTRO_PAGE); + GENERIC_LIST_UI ListUi; - if (RepairUpdateFlag) +/*** HACK!! ***/ + if (PartitionList == NULL) { - //return SELECT_PARTITION_PAGE; - return DEVICE_SETTINGS_PAGE; + PartitionList = CreatePartitionList(); + if (PartitionList == NULL) + { + /* FIXME: show an error dialog */ + MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER); + return QUIT_PAGE; + } + else if (IsListEmpty(&PartitionList->DiskListHead)) + { + MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); + return QUIT_PAGE; + } + + TempPartition = NULL; + FormatState = Start; } +/**************/ - if (IsUnattendedSetup) + NtOsInstallsList = CreateNTOSInstallationsList(PartitionList); + if (!NtOsInstallsList) + DPRINT1("Failed to get a list of NTOS installations; continue installation...\n"); + + /* + * If there is no available installation (or just a single one??) that can + * be updated in the list, just continue with the regular installation. + */ + if (!NtOsInstallsList || GetNumberOfListEntries(NtOsInstallsList) == 0) { - return SELECT_PARTITION_PAGE; + RepairUpdateFlag = FALSE; + + // return INSTALL_INTRO_PAGE; + return DEVICE_SETTINGS_PAGE; + // return SCSI_CONTROLLER_PAGE; } + MUIDisplayPage(UPGRADE_REPAIR_PAGE); + + InitGenericListUi(&ListUi, NtOsInstallsList, GetNTOSInstallationName); + DrawGenericList(&ListUi, + 2, 23, + xScreen - 3, + yScreen - 3); + + // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); while (TRUE) { CONSOLE_ConInKey(Ir); - if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && - (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) { - if (ConfirmQuit(Ir) != FALSE) - return QUIT_PAGE; + switch (Ir->Event.KeyEvent.wVirtualKeyCode) + { + case VK_DOWN: /* DOWN */ + ScrollDownGenericList(&ListUi); + break; + case VK_UP: /* UP */ + ScrollUpGenericList(&ListUi); + break; + case VK_NEXT: /* PAGE DOWN */ + ScrollPageDownGenericList(&ListUi); + break; + case VK_PRIOR: /* PAGE UP */ + ScrollPageUpGenericList(&ListUi); + break; + case VK_F3: /* F3 */ + { + if (ConfirmQuit(Ir)) + return QUIT_PAGE; + else + RedrawGenericList(&ListUi); + break; + } + case VK_ESCAPE: /* ESC */ + { + RestoreGenericListUiState(&ListUi); + // return nextPage; // prevPage; - break; + // return INSTALL_INTRO_PAGE; + return DEVICE_SETTINGS_PAGE; + // return SCSI_CONTROLLER_PAGE; + } + } } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else { - return DEVICE_SETTINGS_PAGE; - // return SCSI_CONTROLLER_PAGE; - } - } - - return INSTALL_INTRO_PAGE; -} + // switch (toupper(Ir->Event.KeyEvent.uChar.AsciiChar)) + // if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U') /* U */ + { + /* Retrieve the current installation */ + ASSERT(GetNumberOfListEntries(NtOsInstallsList) >= 1); + CurrentInstallation = + (PNTOS_INSTALLATION)GetListEntryData(GetCurrentListEntry(NtOsInstallsList)); -#if 0 -static PAGE_NUMBER -ScsiControllerPage(PINPUT_RECORD Ir) -{ - SetTextXY(6, 8, "Setup detected the following mass storage devices:"); + DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n", + CurrentInstallation->InstallationName, CurrentInstallation->DiskNumber, CurrentInstallation->PartitionNumber); - /* FIXME: print loaded mass storage driver descriptions */ -#if 0 - SetTextXY(8, 10, "TEST device"); -#endif + RepairUpdateFlag = TRUE; + // return nextPage; + /***/return INSTALL_INTRO_PAGE;/***/ + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && + (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) /* a-z */ + { + GenericListKeyPress(&ListUi, Ir->Event.KeyEvent.uChar.AsciiChar); + } + } + } - SetStatusText(" ENTER = Continue F3 = Quit"); + return UPGRADE_REPAIR_PAGE; +} - while (TRUE) - { - ConInKey(Ir); + +/* + * Displays the InstallIntroPage. + * + * Next pages: + * DeviceSettingsPage (At once if repair or update is selected) + * SelectPartitionPage (At once if unattended setup) + * DeviceSettingsPage (default) + * QuitPage + * + * RETURNS + * Number of the next page. + */ +static PAGE_NUMBER +InstallIntroPage(PINPUT_RECORD Ir) +{ + if (RepairUpdateFlag) + { +#if 1 /* Old code that looks good */ + + // return SELECT_PARTITION_PAGE; + return DEVICE_SETTINGS_PAGE; + +#else /* Possible new code? */ + + return DEVICE_SETTINGS_PAGE; + // return SCSI_CONTROLLER_PAGE; + +#endif + } + + if (IsUnattendedSetup) + return SELECT_PARTITION_PAGE; + + MUIDisplayPage(INSTALL_INTRO_PAGE); + + while (TRUE) + { + CONSOLE_ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir)) + return QUIT_PAGE; + + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return UPGRADE_REPAIR_PAGE; + } + } + + return INSTALL_INTRO_PAGE; +} + + +#if 0 +static PAGE_NUMBER +ScsiControllerPage(PINPUT_RECORD Ir) +{ + // MUIDisplayPage(SCSI_CONTROLLER_PAGE); + + CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:"); + + /* FIXME: print loaded mass storage driver descriptions */ +#if 0 + CONSOLE_SetTextXY(8, 10, "TEST device"); +#endif + + CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit"); + + while (TRUE) + { + CONSOLE_ConInKey(Ir); if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -1161,6 +1052,38 @@ ScsiControllerPage(PINPUT_RECORD Ir) return SCSI_CONTROLLER_PAGE; } + +static PAGE_NUMBER +OemDriverPage(PINPUT_RECORD Ir) +{ + // MUIDisplayPage(OEM_DRIVER_PAGE); + + CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!"); + + /* FIXME: Implement!! */ + + CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit"); + + while (TRUE) + { + CONSOLE_ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir)) + return QUIT_PAGE; + + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return DEVICE_SETTINGS_PAGE; + } + } + + return OEM_DRIVER_PAGE; +} #endif @@ -1177,10 +1100,10 @@ ScsiControllerPage(PINPUT_RECORD Ir) * QuitPage * * SIDEEFFECTS - * Init ComputerList - * Init DisplayList - * Init KeyboardList - * Init LayoutList + * Init USetupData.ComputerList + * Init USetupData.DisplayList + * Init USetupData.KeyboardList + * Init USetupData.LayoutList * * RETURNS * Number of the next page. @@ -1189,13 +1112,12 @@ static PAGE_NUMBER DeviceSettingsPage(PINPUT_RECORD Ir) { static ULONG Line = 16; - MUIDisplayPage(DEVICE_SETTINGS_PAGE); /* Initialize the computer settings list */ - if (ComputerList == NULL) + if (USetupData.ComputerList == NULL) { - ComputerList = CreateComputerTypeList(SetupInf); - if (ComputerList == NULL) + USetupData.ComputerList = CreateComputerTypeList(USetupData.SetupInf); + if (USetupData.ComputerList == NULL) { MUIDisplayError(ERROR_LOAD_COMPUTER, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; @@ -1203,10 +1125,10 @@ DeviceSettingsPage(PINPUT_RECORD Ir) } /* Initialize the display settings list */ - if (DisplayList == NULL) + if (USetupData.DisplayList == NULL) { - DisplayList = CreateDisplayDriverList(SetupInf); - if (DisplayList == NULL) + USetupData.DisplayList = CreateDisplayDriverList(USetupData.SetupInf); + if (USetupData.DisplayList == NULL) { MUIDisplayError(ERROR_LOAD_DISPLAY, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; @@ -1214,10 +1136,10 @@ DeviceSettingsPage(PINPUT_RECORD Ir) } /* Initialize the keyboard settings list */ - if (KeyboardList == NULL) + if (USetupData.KeyboardList == NULL) { - KeyboardList = CreateKeyboardDriverList(SetupInf); - if (KeyboardList == NULL) + USetupData.KeyboardList = CreateKeyboardDriverList(USetupData.SetupInf); + if (USetupData.KeyboardList == NULL) { MUIDisplayError(ERROR_LOAD_KEYBOARD, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; @@ -1225,10 +1147,10 @@ DeviceSettingsPage(PINPUT_RECORD Ir) } /* Initialize the keyboard layout list */ - if (LayoutList == NULL) + if (USetupData.LayoutList == NULL) { - LayoutList = CreateKeyboardLayoutList(SetupInf, DefaultKBLayout); - if (LayoutList == NULL) + USetupData.LayoutList = CreateKeyboardLayoutList(USetupData.SetupInf, SelectedLanguageId, DefaultKBLayout); + if (USetupData.LayoutList == NULL) { /* FIXME: report error */ MUIDisplayError(ERROR_LOAD_KBLAYOUT, Ir, POPUP_WAIT_ENTER); @@ -1236,21 +1158,21 @@ DeviceSettingsPage(PINPUT_RECORD Ir) } } - MUIDisplayPage(DEVICE_SETTINGS_PAGE); + if (RepairUpdateFlag) + return SELECT_PARTITION_PAGE; + + // if (IsUnattendedSetup) + // return SELECT_PARTITION_PAGE; + MUIDisplayPage(DEVICE_SETTINGS_PAGE); - CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry((ComputerList)))); - CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry((DisplayList)))); - CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry((KeyboardList)))); - CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry((LayoutList)))); + DrawGenericListCurrentItem(USetupData.ComputerList, GetSettingDescription, 25, 11); + DrawGenericListCurrentItem(USetupData.DisplayList , GetSettingDescription, 25, 12); + DrawGenericListCurrentItem(USetupData.KeyboardList, GetSettingDescription, 25, 13); + DrawGenericListCurrentItem(USetupData.LayoutList , GetSettingDescription, 25, 14); CONSOLE_InvertTextXY(24, Line, 48, 1); - if (RepairUpdateFlag) - { - return SELECT_PARTITION_PAGE; - } - while (TRUE) { CONSOLE_ConInKey(Ir); @@ -1286,7 +1208,7 @@ DeviceSettingsPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -1319,7 +1241,7 @@ DeviceSettingsPage(PINPUT_RECORD Ir) * Ir: The PINPUT_RECORD */ static PAGE_NUMBER -HandleGenericList(PGENERIC_LIST GenericList, +HandleGenericList(PGENERIC_LIST_UI ListUi, PAGE_NUMBER nextPage, PINPUT_RECORD Ir) { @@ -1330,36 +1252,36 @@ HandleGenericList(PGENERIC_LIST GenericList, if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ { - ScrollDownGenericList(GenericList); + ScrollDownGenericList(ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */ { - ScrollUpGenericList(GenericList); + ScrollUpGenericList(ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT)) /* PAGE DOWN */ { - ScrollPageDownGenericList(GenericList); + ScrollPageDownGenericList(ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)) /* PAGE UP */ { - ScrollPageUpGenericList(GenericList); + ScrollPageUpGenericList(ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; - - continue; + else + RedrawGenericList(ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ { - RestoreGenericListState(GenericList); - return nextPage; + RestoreGenericListUiState(ListUi); + return nextPage; // Use some "prevPage;" instead? } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { @@ -1368,7 +1290,7 @@ HandleGenericList(PGENERIC_LIST GenericList, else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b)) { /* a-z */ - GenericListKeyPress(GenericList, Ir->Event.KeyEvent.uChar.AsciiChar); + GenericListKeyPress(ListUi, Ir->Event.KeyEvent.uChar.AsciiChar); } } } @@ -1387,20 +1309,19 @@ HandleGenericList(PGENERIC_LIST GenericList, static PAGE_NUMBER ComputerSettingsPage(PINPUT_RECORD Ir) { + GENERIC_LIST_UI ListUi; MUIDisplayPage(COMPUTER_SETTINGS_PAGE); - DrawGenericList(ComputerList, - 2, - 18, + InitGenericListUi(&ListUi, USetupData.ComputerList, GetSettingDescription); + DrawGenericList(&ListUi, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(ComputerList); - - return HandleGenericList(ComputerList, DEVICE_SETTINGS_PAGE, Ir); + return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } - - + + /* * Displays the DisplaySettingsPage. * @@ -1414,17 +1335,16 @@ ComputerSettingsPage(PINPUT_RECORD Ir) static PAGE_NUMBER DisplaySettingsPage(PINPUT_RECORD Ir) { + GENERIC_LIST_UI ListUi; MUIDisplayPage(DISPLAY_SETTINGS_PAGE); - DrawGenericList(DisplayList, - 2, - 18, + InitGenericListUi(&ListUi, USetupData.DisplayList, GetSettingDescription); + DrawGenericList(&ListUi, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(DisplayList); - - return HandleGenericList(DisplayList, DEVICE_SETTINGS_PAGE, Ir); + return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1441,17 +1361,16 @@ DisplaySettingsPage(PINPUT_RECORD Ir) static PAGE_NUMBER KeyboardSettingsPage(PINPUT_RECORD Ir) { + GENERIC_LIST_UI ListUi; MUIDisplayPage(KEYBOARD_SETTINGS_PAGE); - DrawGenericList(KeyboardList, - 2, - 18, + InitGenericListUi(&ListUi, USetupData.KeyboardList, GetSettingDescription); + DrawGenericList(&ListUi, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(KeyboardList); - - return HandleGenericList(KeyboardList, DEVICE_SETTINGS_PAGE, Ir); + return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1468,17 +1387,16 @@ KeyboardSettingsPage(PINPUT_RECORD Ir) static PAGE_NUMBER LayoutSettingsPage(PINPUT_RECORD Ir) { + GENERIC_LIST_UI ListUi; MUIDisplayPage(LAYOUT_SETTINGS_PAGE); - DrawGenericList(LayoutList, - 2, - 18, + InitGenericListUi(&ListUi, USetupData.LayoutList, GetSettingDescription); + DrawGenericList(&ListUi, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(LayoutList); - - return HandleGenericList(LayoutList, DEVICE_SETTINGS_PAGE, Ir); + return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1488,12 +1406,12 @@ IsDiskSizeValid(PPARTENTRY PartEntry) ULONGLONG size; size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector; - size = (size + 524288) / 1048576; /* in MBytes */ + size = (size + (512 * KB)) / MB; /* in MBytes */ - if (size < RequiredPartitionDiskSpace) + if (size < USetupData.RequiredPartitionDiskSpace) { - /* partition is too small so ask for another partition */ - DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, RequiredPartitionDiskSpace); + /* Partition is too small so ask for another one */ + DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace); return FALSE; } else @@ -1517,7 +1435,6 @@ IsDiskSizeValid(PPARTENTRY PartEntry) * QuitPage * * SIDEEFFECTS - * Init DestinationDriveLetter (only if unattended or not free space is selected) * Set InstallShortcut (only if not unattended + free space is selected) * * RETURNS @@ -1526,19 +1443,16 @@ IsDiskSizeValid(PPARTENTRY PartEntry) static PAGE_NUMBER SelectPartitionPage(PINPUT_RECORD Ir) { + PARTLIST_UI ListUi; ULONG Error; - MUIDisplayPage(SELECT_PARTITION_PAGE); - if (PartitionList == NULL) { - PartitionList = CreatePartitionList(2, - 23, - xScreen - 3, - yScreen - 3); + PartitionList = CreatePartitionList(); if (PartitionList == NULL) { /* FIXME: show an error dialog */ + MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } else if (IsListEmpty(&PartitionList->DiskListHead)) @@ -1546,15 +1460,41 @@ SelectPartitionPage(PINPUT_RECORD Ir) MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } + + TempPartition = NULL; + FormatState = Start; + } + + if (RepairUpdateFlag) + { + /* Determine the selected installation disk & partition */ + if (!SelectPartition(PartitionList, + CurrentInstallation->DiskNumber, + CurrentInstallation->PartitionNumber)) + { + DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n"); + ASSERT(FALSE); + } + + return SELECT_FILE_SYSTEM_PAGE; } - DrawPartitionList(PartitionList); + MUIDisplayPage(SELECT_PARTITION_PAGE); + + InitPartitionListUi(&ListUi, PartitionList, + 2, + 23, + xScreen - 3, + yScreen - 3); + DrawPartitionList(&ListUi); if (IsUnattendedSetup) { - if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber)) + if (!SelectPartition(PartitionList, + USetupData.DestinationDiskNumber, + USetupData.DestinationPartitionNumber)) { - if (AutoPartition) + if (USetupData.AutoPartition) { if (PartitionList->CurrentPartition->LogicalPartition) { @@ -1569,29 +1509,29 @@ SelectPartitionPage(PINPUT_RECORD Ir) TRUE); } +// FIXME?? Aren't we going to enter an infinite loop, if this test fails?? if (!IsDiskSizeValid(PartitionList->CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, - RequiredPartitionDiskSpace); + USetupData.RequiredPartitionDiskSpace); return SELECT_PARTITION_PAGE; /* let the user select another partition */ } - DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter; - return SELECT_FILE_SYSTEM_PAGE; } } else { + DrawPartitionList(&ListUi); + +// FIXME?? Aren't we going to enter an infinite loop, if this test fails?? if (!IsDiskSizeValid(PartitionList->CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, - RequiredPartitionDiskSpace); + USetupData.RequiredPartitionDiskSpace); return SELECT_PARTITION_PAGE; /* let the user select another partition */ } - DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter; - return SELECT_FILE_SYSTEM_PAGE; } } @@ -1605,32 +1545,32 @@ SelectPartitionPage(PINPUT_RECORD Ir) } else if (PartitionList->CurrentPartition->LogicalPartition) { - if (PartitionList->CurrentPartition->IsPartitioned) - { - CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION)); - } - else - { - CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL)); - } + if (PartitionList->CurrentPartition->IsPartitioned) + { + CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION)); + } + else + { + CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL)); + } } else { - if (PartitionList->CurrentPartition->IsPartitioned) - { - if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType)) - { - CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION)); - } - else - { - CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION)); - } - } - else - { - CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION)); - } + if (PartitionList->CurrentPartition->IsPartitioned) + { + if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType)) + { + CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION)); + } + else + { + CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION)); + } + } + else + { + CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION)); + } } CONSOLE_ConInKey(Ir); @@ -1638,7 +1578,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) { DestroyPartitionList(PartitionList); PartitionList = NULL; @@ -1650,19 +1590,17 @@ SelectPartitionPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ { - if (ScrollDownPartitionList(PartitionList)) - DrawPartitionList(PartitionList); + ScrollDownPartitionList(&ListUi); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */ { - if (ScrollUpPartitionList(PartitionList)) - DrawPartitionList(PartitionList); + ScrollUpPartitionList(&ListUi); } else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ { if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType)) - continue; //return SELECT_PARTITION_PAGE; + continue; // return SELECT_PARTITION_PAGE; if (PartitionList->CurrentPartition == NULL || PartitionList->CurrentPartition->IsPartitioned == FALSE) @@ -1684,12 +1622,10 @@ SelectPartitionPage(PINPUT_RECORD Ir) if (!IsDiskSizeValid(PartitionList->CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, - RequiredPartitionDiskSpace); + USetupData.RequiredPartitionDiskSpace); return SELECT_PARTITION_PAGE; /* let the user select another partition */ } - DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter; - return SELECT_FILE_SYSTEM_PAGE; } else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P') /* P */ @@ -1722,7 +1658,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) } else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L') /* L */ { - if (PartitionList->CurrentPartition->LogicalPartition != FALSE) + if (PartitionList->CurrentPartition->LogicalPartition) { Error = LogicalPartitionCreationChecks(PartitionList); if (Error != NOT_AN_ERROR) @@ -1736,12 +1672,34 @@ SelectPartitionPage(PINPUT_RECORD Ir) } else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */ { + WCHAR PathBuffer[MAX_PATH]; + UNICODE_STRING CurrentPartition; + if (PartitionList->CurrentPartition->IsPartitioned == FALSE) { MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY); return SELECT_PARTITION_PAGE; } + RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), + L"\\Device\\Harddisk%lu\\Partition%lu\\", + PartitionList->CurrentDisk->DiskNumber, + PartitionList->CurrentPartition->PartitionNumber); + RtlInitUnicodeString(&CurrentPartition, PathBuffer); + + /* + * Check whether the user attempts to delete the partition on which + * the installation source is present. If so, fail with an error. + */ + // &USetupData.SourceRootPath + if (RtlPrefixUnicodeString(&CurrentPartition, &USetupData.SourcePath, TRUE)) + { + PopupError("You cannot delete the partition containing the installation source!", + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); + return SELECT_PARTITION_PAGE; + } + if (PartitionList->CurrentPartition->BootIndicator || PartitionList->CurrentPartition == PartitionList->SystemPartition) { @@ -1985,15 +1943,15 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir) DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; #if 0 - if (DiskSize >= 10737418240) /* 10 GB */ + if (DiskSize >= 10 * GB) /* 10 GB */ { - DiskSize = DiskSize / 1073741824; + DiskSize = DiskSize / GB; Unit = MUIGetString(STRING_GB); } else #endif { - DiskSize = DiskSize / 1048576; + DiskSize = DiskSize / MB; if (DiskSize == 0) DiskSize = 1; @@ -2003,32 +1961,34 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir) if (DiskEntry->DriverName.Length > 0) { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDINFOPARTCREATE), + MUIGetString(STRING_HDINFOPARTCREATE_1), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); } else { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDDINFOUNK1), + MUIGetString(STRING_HDINFOPARTCREATE_2), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, - DiskEntry->Id); + DiskEntry->Id, + DiskEntry->NoMbr ? "GPT" : "MBR"); } CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE)); #if 0 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB", - PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576); + PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB); #endif CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION)); @@ -2036,7 +1996,7 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir) PartEntry = PartitionList->CurrentPartition; while (TRUE) { - MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */ + MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */ if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE; @@ -2044,14 +2004,14 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir) ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */ MaxSize, InputBuffer, &Quit, &Cancel); - if (Quit != FALSE) + if (Quit) { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; } - else if (Cancel != FALSE) + else if (Cancel) { return SELECT_PARTITION_PAGE; } @@ -2080,7 +2040,7 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir) else { /* Calculate the sector count from the size in MB */ - SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector; + SectorCount = PartSize * MB / DiskEntry->BytesPerSector; /* But never get larger than the unpartitioned disk space */ if (SectorCount > PartEntry->SectorCount.QuadPart) @@ -2142,15 +2102,15 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir) DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; #if 0 - if (DiskSize >= 10737418240) /* 10 GB */ + if (DiskSize >= 10 * GB) /* 10 GB */ { - DiskSize = DiskSize / 1073741824; + DiskSize = DiskSize / GB; Unit = MUIGetString(STRING_GB); } else #endif { - DiskSize = DiskSize / 1048576; + DiskSize = DiskSize / MB; if (DiskSize == 0) DiskSize = 1; @@ -2160,32 +2120,34 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir) if (DiskEntry->DriverName.Length > 0) { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDINFOPARTCREATE), + MUIGetString(STRING_HDINFOPARTCREATE_1), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); } else { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDDINFOUNK1), + MUIGetString(STRING_HDINFOPARTCREATE_2), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, - DiskEntry->Id); + DiskEntry->Id, + DiskEntry->NoMbr ? "GPT" : "MBR"); } CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE)); #if 0 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB", - PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576); + PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB); #endif CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION)); @@ -2193,7 +2155,7 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir) PartEntry = PartitionList->CurrentPartition; while (TRUE) { - MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */ + MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */ if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE; @@ -2201,14 +2163,14 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir) ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */ MaxSize, InputBuffer, &Quit, &Cancel); - if (Quit != FALSE) + if (Quit) { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; } - else if (Cancel != FALSE) + else if (Cancel) { return SELECT_PARTITION_PAGE; } @@ -2237,7 +2199,7 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir) else { /* Calculate the sector count from the size in MB */ - SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector; + SectorCount = PartSize * MB / DiskEntry->BytesPerSector; /* But never get larger than the unpartitioned disk space */ if (SectorCount > PartEntry->SectorCount.QuadPart) @@ -2298,15 +2260,15 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir) DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; #if 0 - if (DiskSize >= 10737418240) /* 10 GB */ + if (DiskSize >= 10 * GB) /* 10 GB */ { - DiskSize = DiskSize / 1073741824; + DiskSize = DiskSize / GB; Unit = MUIGetString(STRING_GB); } else #endif { - DiskSize = DiskSize / 1048576; + DiskSize = DiskSize / MB; if (DiskSize == 0) DiskSize = 1; @@ -2316,32 +2278,34 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir) if (DiskEntry->DriverName.Length > 0) { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDINFOPARTCREATE), + MUIGetString(STRING_HDINFOPARTCREATE_1), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); } else { CONSOLE_PrintTextXY(6, 10, - MUIGetString(STRING_HDDINFOUNK1), + MUIGetString(STRING_HDINFOPARTCREATE_2), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, - DiskEntry->Id); + DiskEntry->Id, + DiskEntry->NoMbr ? "GPT" : "MBR"); } CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE)); #if 0 CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB", - PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576); + PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB); #endif CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION)); @@ -2349,7 +2313,7 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir) PartEntry = PartitionList->CurrentPartition; while (TRUE) { - MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576; /* in MBytes (rounded) */ + MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */ if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE; @@ -2357,14 +2321,14 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir) ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */ MaxSize, InputBuffer, &Quit, &Cancel); - if (Quit != FALSE) + if (Quit) { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; } - else if (Cancel != FALSE) + else if (Cancel) { return SELECT_PARTITION_PAGE; } @@ -2393,7 +2357,7 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir) else { /* Calculate the sector count from the size in MB */ - SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector; + SectorCount = PartSize * MB / DiskEntry->BytesPerSector; /* But never get larger than the unpartitioned disk space */ if (SectorCount > PartEntry->SectorCount.QuadPart) @@ -2436,7 +2400,7 @@ ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) == TRUE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -2494,21 +2458,21 @@ DeletePartitionPage(PINPUT_RECORD Ir) PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; #if 0 - if (PartSize >= 10737418240) /* 10 GB */ + if (PartSize >= 10 * GB) /* 10 GB */ { - PartSize = PartSize / 1073741824; + PartSize = PartSize / GB; Unit = MUIGetString(STRING_GB); } else #endif - if (PartSize >= 10485760) /* 10 MB */ + if (PartSize >= 10 * MB) /* 10 MB */ { - PartSize = PartSize / 1048576; + PartSize = PartSize / MB; Unit = MUIGetString(STRING_MB); } else { - PartSize = PartSize / 1024; + PartSize = PartSize / KB; Unit = MUIGetString(STRING_KB); } @@ -2516,7 +2480,7 @@ DeletePartitionPage(PINPUT_RECORD Ir) { CONSOLE_PrintTextXY(6, 10, MUIGetString(STRING_HDDINFOUNK2), - (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter, (PartEntry->DriveLetter == 0) ? '-' : ':', PartEntry->PartitionType, PartSize, @@ -2526,7 +2490,7 @@ DeletePartitionPage(PINPUT_RECORD Ir) { CONSOLE_PrintTextXY(6, 10, " %c%c %s %I64u %s", - (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter, (PartEntry->DriveLetter == 0) ? '-' : ':', PartTypeString, PartSize, @@ -2535,15 +2499,15 @@ DeletePartitionPage(PINPUT_RECORD Ir) DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; #if 0 - if (DiskSize >= 10737418240) /* 10 GB */ + if (DiskSize >= 10 * GB) /* 10 GB */ { - DiskSize = DiskSize / 1073741824; + DiskSize = DiskSize / GB; Unit = MUIGetString(STRING_GB); } else #endif { - DiskSize = DiskSize / 1048576; + DiskSize = DiskSize / MB; if (DiskSize == 0) DiskSize = 1; @@ -2553,25 +2517,27 @@ DeletePartitionPage(PINPUT_RECORD Ir) if (DiskEntry->DriverName.Length > 0) { CONSOLE_PrintTextXY(6, 12, - MUIGetString(STRING_HDINFOPARTDELETE), + MUIGetString(STRING_HDINFOPARTDELETE_1), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); } else { CONSOLE_PrintTextXY(6, 12, - MUIGetString(STRING_HDDINFOUNK3), + MUIGetString(STRING_HDINFOPARTDELETE_2), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, - DiskEntry->Id); + DiskEntry->Id, + DiskEntry->NoMbr ? "GPT" : "MBR"); } while (TRUE) @@ -2581,7 +2547,7 @@ DeletePartitionPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -2607,8 +2573,8 @@ DeletePartitionPage(PINPUT_RECORD Ir) * * Next pages: * CheckFileSystemPage (At once if RepairUpdate is selected) - * CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition) - * FormatPartitionPage (At once if Unattended and UnattendFormatPartition) + * CheckFileSystemPage (At once if Unattended and not USetupData.FormatPartition) + * FormatPartitionPage (At once if Unattended and USetupData.FormatPartition) * SelectPartitionPage (If the user aborts) * FormatPartitionPage (Default) * QuitPage @@ -2642,137 +2608,138 @@ SelectFileSystemPage(PINPUT_RECORD Ir) return QUIT_PAGE; } - /*** HACK! ***/ - if (FileSystemList == NULL) - { - FileSystemList = CreateFileSystemList(6, 26, PartitionList->CurrentPartition->New, L"FAT"); - if (FileSystemList == NULL) - { - /* FIXME: show an error dialog */ - return QUIT_PAGE; - } - - /* FIXME: Add file systems to list */ - } - /* Find or set the active system partition */ - CheckActiveSystemPartition(PartitionList, FileSystemList); - - if (PartitionList->SystemDisk == NULL || - PartitionList->SystemPartition == NULL) + CheckActiveSystemPartition(PartitionList); + if (PartitionList->SystemPartition == NULL) { /* FIXME: show an error dialog */ + // + // Error dialog should say that we cannot find a suitable + // system partition and create one on the system. At this point, + // it may be nice to ask the user whether he wants to continue, + // or use an external drive as the system drive/partition + // (e.g. floppy, USB drive, etc...) + // return QUIT_PAGE; } - PreviousFormatState = PartitionList->FormatState; - switch (PartitionList->FormatState) + PreviousFormatState = FormatState; + switch (FormatState) { case Start: + { if (PartitionList->CurrentPartition != PartitionList->SystemPartition) { - PartitionList->TempDisk = PartitionList->SystemDisk; - PartitionList->TempPartition = PartitionList->SystemPartition; - PartitionList->TempPartition->NeedsCheck = TRUE; + TempPartition = PartitionList->SystemPartition; + TempPartition->NeedsCheck = TRUE; - PartitionList->FormatState = FormatSystemPartition; + FormatState = FormatSystemPartition; DPRINT1("FormatState: Start --> FormatSystemPartition\n"); } else { - PartitionList->TempDisk = PartitionList->CurrentDisk; - PartitionList->TempPartition = PartitionList->CurrentPartition; - PartitionList->TempPartition->NeedsCheck = TRUE; + TempPartition = PartitionList->CurrentPartition; + TempPartition->NeedsCheck = TRUE; - PartitionList->FormatState = FormatInstallPartition; + FormatState = FormatInstallPartition; DPRINT1("FormatState: Start --> FormatInstallPartition\n"); } break; + } case FormatSystemPartition: - PartitionList->TempDisk = PartitionList->CurrentDisk; - PartitionList->TempPartition = PartitionList->CurrentPartition; - PartitionList->TempPartition->NeedsCheck = TRUE; + { + TempPartition = PartitionList->CurrentPartition; + TempPartition->NeedsCheck = TRUE; - PartitionList->FormatState = FormatInstallPartition; + FormatState = FormatInstallPartition; DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n"); break; + } case FormatInstallPartition: + { if (GetNextUnformattedPartition(PartitionList, - &PartitionList->TempDisk, - &PartitionList->TempPartition)) + NULL, + &TempPartition)) { - PartitionList->FormatState = FormatOtherPartition; - PartitionList->TempPartition->NeedsCheck = TRUE; + FormatState = FormatOtherPartition; + TempPartition->NeedsCheck = TRUE; DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n"); } else { - PartitionList->FormatState = FormatDone; + FormatState = FormatDone; DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n"); return CHECK_FILE_SYSTEM_PAGE; } break; + } case FormatOtherPartition: + { if (GetNextUnformattedPartition(PartitionList, - &PartitionList->TempDisk, - &PartitionList->TempPartition)) + NULL, + &TempPartition)) { - PartitionList->FormatState = FormatOtherPartition; - PartitionList->TempPartition->NeedsCheck = TRUE; + FormatState = FormatOtherPartition; + TempPartition->NeedsCheck = TRUE; DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n"); } else { - PartitionList->FormatState = FormatDone; + FormatState = FormatDone; DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n"); return CHECK_FILE_SYSTEM_PAGE; } break; + } default: - DPRINT1("FormatState: Invalid value %ld\n", PartitionList->FormatState); + { + DPRINT1("FormatState: Invalid value %ld\n", FormatState); /* FIXME: show an error dialog */ return QUIT_PAGE; + } } - DiskEntry = PartitionList->TempDisk; - PartEntry = PartitionList->TempPartition; + PartEntry = TempPartition; + DiskEntry = PartEntry->DiskEntry; - /* adjust disk size */ + /* Adjust disk size */ DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; - if (DiskSize >= 10737418240) /* 10 GB */ + if (DiskSize >= 10 * GB) /* 10 GB */ { - DiskSize = DiskSize / 1073741824; + DiskSize = DiskSize / GB; DiskUnit = MUIGetString(STRING_GB); } else { - DiskSize = DiskSize / 1048576; + DiskSize = DiskSize / MB; DiskUnit = MUIGetString(STRING_MB); } - /* adjust partition size */ + /* Adjust partition size */ PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; - if (PartSize >= 10737418240) /* 10 GB */ + if (PartSize >= 10 * GB) /* 10 GB */ { - PartSize = PartSize / 1073741824; + PartSize = PartSize / GB; PartUnit = MUIGetString(STRING_GB); } else { - PartSize = PartSize / 1048576; + PartSize = PartSize / MB; PartUnit = MUIGetString(STRING_MB); } - /* adjust partition type */ + /* Adjust partition type */ GetPartTypeStringFromPartitionType(PartEntry->PartitionType, PartTypeString, ARRAYSIZE(PartTypeString)); - if (PartEntry->AutoCreate != FALSE) + MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE); + + if (PartEntry->AutoCreate) { CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION)); @@ -2784,23 +2751,23 @@ SelectFileSystemPage(PINPUT_RECORD Ir) PartTypeString); #endif - CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED), + CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1), DiskEntry->DiskNumber, DiskSize, DiskUnit, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT)); - PartEntry->AutoCreate = FALSE; } - else if (PartEntry->New != FALSE) + else if (PartEntry->New) { - switch (PartitionList->FormatState) + switch (FormatState) { case FormatSystemPartition: CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART)); @@ -2828,7 +2795,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir) { CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDDINFOUNK4), - (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter, (PartEntry->DriveLetter == 0) ? '-' : ':', PartEntry->PartitionType, PartSize, @@ -2838,39 +2805,35 @@ SelectFileSystemPage(PINPUT_RECORD Ir) { CONSOLE_PrintTextXY(8, 10, "%c%c %s %I64u %s", - (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter, (PartEntry->DriveLetter == 0) ? '-' : ':', PartTypeString, PartSize, PartUnit); } - CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS), + CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1), DiskEntry->DiskNumber, DiskSize, DiskUnit, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, - &DiskEntry->DriverName); + &DiskEntry->DriverName, + DiskEntry->NoMbr ? "GPT" : "MBR"); } - MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE); - if (FileSystemList == NULL) { + /* Create the file system list, and by default select the "FAT" file system */ FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT"); if (FileSystemList == NULL) { /* FIXME: show an error dialog */ return QUIT_PAGE; } - - /* FIXME: Add file systems to list */ } - DrawFileSystemList(FileSystemList); - if (RepairUpdateFlag) { return CHECK_FILE_SYSTEM_PAGE; @@ -2879,15 +2842,23 @@ SelectFileSystemPage(PINPUT_RECORD Ir) if (IsUnattendedSetup) { - if (UnattendFormatPartition) + if (USetupData.FormatPartition) { - PartEntry->FileSystem = GetFileSystemByName(FileSystemList, L"FAT"); + /* + * We use whatever currently selected file system we have + * (by default, this is "FAT", as per the initialization + * performed above). Note that it may be interesting to specify + * which file system to use in unattended installations, in the + * txtsetup.sif file. + */ return FORMAT_PARTITION_PAGE; } return CHECK_FILE_SYSTEM_PAGE; } + DrawFileSystemList(FileSystemList); + while (TRUE) { CONSOLE_ConInKey(Ir); @@ -2895,7 +2866,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -2903,7 +2874,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ { - PartitionList->FormatState = Start; + FormatState = Start; return SELECT_PARTITION_PAGE; } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && @@ -2918,19 +2889,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir) } else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ { - if (!FileSystemList->Selected->FormatFunc) - { - return SELECT_FILE_SYSTEM_PAGE; - } + if (!FileSystemList->Selected->FileSystem) + return SELECT_FILE_SYSTEM_PAGE; else - { - PartEntry->FileSystem = FileSystemList->Selected; return FORMAT_PARTITION_PAGE; - } } } - PartitionList->FormatState = PreviousFormatState; + FormatState = PreviousFormatState; return SELECT_FILE_SYSTEM_PAGE; } @@ -2946,19 +2912,21 @@ SelectFileSystemPage(PINPUT_RECORD Ir) * * SIDEEFFECTS * Sets PartitionList->CurrentPartition->FormatState - * Sets DestinationRootPath + * Sets USetupData.DestinationRootPath * * RETURNS * Number of the next page. */ -static ULONG +static PAGE_NUMBER FormatPartitionPage(PINPUT_RECORD Ir) { - UNICODE_STRING PartitionRootPath; - WCHAR PathBuffer[MAX_PATH]; + NTSTATUS Status; PDISKENTRY DiskEntry; PPARTENTRY PartEntry; - NTSTATUS Status; + PFILE_SYSTEM_ITEM SelectedFileSystem; + UNICODE_STRING PartitionRootPath; + WCHAR PathBuffer[MAX_PATH]; + CHAR Buffer[MAX_PATH]; #ifndef NDEBUG ULONG Line; @@ -2970,16 +2938,16 @@ FormatPartitionPage(PINPUT_RECORD Ir) MUIDisplayPage(FORMAT_PARTITION_PAGE); - if (PartitionList == NULL || - PartitionList->TempDisk == NULL || - PartitionList->TempPartition == NULL) + if (PartitionList == NULL || TempPartition == NULL) { /* FIXME: show an error dialog */ return QUIT_PAGE; } - DiskEntry = PartitionList->TempDisk; - PartEntry = PartitionList->TempPartition; + PartEntry = TempPartition; + DiskEntry = PartEntry->DiskEntry; + + SelectedFileSystem = FileSystemList->Selected; while (TRUE) { @@ -2991,7 +2959,7 @@ FormatPartitionPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -3000,72 +2968,7 @@ FormatPartitionPage(PINPUT_RECORD Ir) { CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - if (wcscmp(PartEntry->FileSystem->FileSystemName, L"FAT") == 0) - { - if (PartEntry->SectorCount.QuadPart < 8192) - { - /* FAT12 CHS partition (disk is smaller than 4.1MB) */ - PartEntry->PartitionType = PARTITION_FAT_12; - } - else if (PartEntry->StartSector.QuadPart < 1450560) - { - /* Partition starts below the 8.4GB boundary ==> CHS partition */ - - if (PartEntry->SectorCount.QuadPart < 65536) - { - /* FAT16 CHS partition (partition size < 32MB) */ - PartEntry->PartitionType = PARTITION_FAT_16; - } - else if (PartEntry->SectorCount.QuadPart < 1048576) - { - /* FAT16 CHS partition (partition size < 512MB) */ - PartEntry->PartitionType = PARTITION_HUGE; - } - else - { - /* FAT32 CHS partition (partition size >= 512MB) */ - PartEntry->PartitionType = PARTITION_FAT32; - } - } - else - { - /* Partition starts above the 8.4GB boundary ==> LBA partition */ - - if (PartEntry->SectorCount.QuadPart < 1048576) - { - /* FAT16 LBA partition (partition size < 512MB) */ - PartEntry->PartitionType = PARTITION_XINT13; - } - else - { - /* FAT32 LBA partition (partition size >= 512MB) */ - PartEntry->PartitionType = PARTITION_FAT32_XINT13; - } - } - - DiskEntry->Dirty = TRUE; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE; - } -#if 0 - else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"EXT2") == 0) - { - PartEntry->PartitionType = PARTITION_EXT2; - - DiskEntry->Dirty = TRUE; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE; - } - else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"NTFS") == 0) - { - PartEntry->PartitionType = PARTITION_IFS; - - DiskEntry->Dirty = TRUE; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType; - DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE; - } -#endif - else if (!PartEntry->FileSystem->FormatFunc) + if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem)) { /* FIXME: show an error dialog */ return QUIT_PAGE; @@ -3098,7 +3001,8 @@ FormatPartitionPage(PINPUT_RECORD Ir) } #endif - if (WritePartitionsToDisk(PartitionList) == FALSE) + /* Commit the partition changes to the disk */ + if (!WritePartitionsToDisk(PartitionList)) { DPRINT("WritePartitionsToDisk() failed\n"); MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); @@ -3106,25 +3010,58 @@ FormatPartitionPage(PINPUT_RECORD Ir) } /* Set PartitionRootPath */ - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - DiskEntry->DiskNumber, - PartEntry->PartitionNumber); - RtlInitUnicodeString(&PartitionRootPath, - PathBuffer); + RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), + L"\\Device\\Harddisk%lu\\Partition%lu", + DiskEntry->DiskNumber, + PartEntry->PartitionNumber); + RtlInitUnicodeString(&PartitionRootPath, PathBuffer); DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath); - if (PartEntry->FileSystem->FormatFunc) + /* Format the partition */ + if (SelectedFileSystem->FileSystem) { Status = FormatPartition(&PartitionRootPath, - PartEntry->FileSystem); - if (!NT_SUCCESS(Status)) + SelectedFileSystem); + if (Status == STATUS_NOT_SUPPORTED) + { + sprintf(Buffer, + "Setup is currently unable to format a partition in %S.\n" + "\n" + " \x07 Press ENTER to continue Setup.\n" + " \x07 Press F3 to quit Setup.", + SelectedFileSystem->FileSystem->FileSystemName); + + PopupError(Buffer, + MUIGetString(STRING_QUITCONTINUE), + NULL, POPUP_WAIT_NONE); + + while (TRUE) + { + CONSOLE_ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 && + Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */ + { + if (ConfirmQuit(Ir)) + return QUIT_PAGE; + else + return SELECT_FILE_SYSTEM_PAGE; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */ + { + return SELECT_FILE_SYSTEM_PAGE; + } + } + } + else if (!NT_SUCCESS(Status)) { DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status); MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer); return QUIT_PAGE; } + PartEntry->FormatState = Formatted; + // PartEntry->FileSystem = FileSystem; PartEntry->New = FALSE; } @@ -3154,16 +3091,16 @@ FormatPartitionPage(PINPUT_RECORD Ir) * RETURNS * Number of the next page. */ -static ULONG +static PAGE_NUMBER CheckFileSystemPage(PINPUT_RECORD Ir) { - PFILE_SYSTEM_ITEM CurrentFileSystem; + NTSTATUS Status; + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PFILE_SYSTEM CurrentFileSystem; UNICODE_STRING PartitionRootPath; WCHAR PathBuffer[MAX_PATH]; CHAR Buffer[MAX_PATH]; - PDISKENTRY DiskEntry; - PPARTENTRY PartEntry; - NTSTATUS Status; if (PartitionList == NULL) { @@ -3177,10 +3114,10 @@ CheckFileSystemPage(PINPUT_RECORD Ir) } /* Set PartitionRootPath */ - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - DiskEntry->DiskNumber, - PartEntry->PartitionNumber); + RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), + L"\\Device\\Harddisk%lu\\Partition%lu", + DiskEntry->DiskNumber, + PartEntry->PartitionNumber); RtlInitUnicodeString(&PartitionRootPath, PathBuffer); DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath); @@ -3188,7 +3125,7 @@ CheckFileSystemPage(PINPUT_RECORD Ir) CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - CurrentFileSystem = GetFileSystem(FileSystemList, PartEntry); + CurrentFileSystem = PartEntry->FileSystem; DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n", PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a")); @@ -3199,7 +3136,8 @@ CheckFileSystemPage(PINPUT_RECORD Ir) return CHECK_FILE_SYSTEM_PAGE; } - if (CurrentFileSystem->ChkdskFunc == NULL) + Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem); + if (Status == STATUS_NOT_SUPPORTED) { sprintf(Buffer, "Setup is currently unable to check a partition formatted in %S.\n" @@ -3231,72 +3169,84 @@ CheckFileSystemPage(PINPUT_RECORD Ir) } } } - else + else if (!NT_SUCCESS(Status)) { - Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem); - if (!NT_SUCCESS(Status)) - { - DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status); - // sprintf(Buffer, "Setup failed to verify the selected partition.\n" - sprintf(Buffer, "ChkDsk detected some disk errors.\n" - "(Status 0x%08lx).\n", Status); - PopupError(Buffer, - // MUIGetString(STRING_REBOOTCOMPUTER), - MUIGetString(STRING_CONTINUE), - Ir, POPUP_WAIT_ENTER); - - // return QUIT_PAGE; - } + DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status); + // sprintf(Buffer, "Setup failed to verify the selected partition.\n" + sprintf(Buffer, "ChkDsk detected some disk errors.\n" + "(Status 0x%08lx).\n", Status); + PopupError(Buffer, + // MUIGetString(STRING_REBOOTCOMPUTER), + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); - PartEntry->NeedsCheck = FALSE; - return CHECK_FILE_SYSTEM_PAGE; + // return QUIT_PAGE; } + + PartEntry->NeedsCheck = FALSE; + return CHECK_FILE_SYSTEM_PAGE; } -static -VOID -BuildInstallPaths(PWCHAR InstallDir, +static VOID +BuildInstallPaths(PWSTR InstallDir, PDISKENTRY DiskEntry, PPARTENTRY PartEntry) { - WCHAR PathBuffer[MAX_PATH]; + NTSTATUS Status; - /* Create 'InstallPath' string */ - RtlFreeUnicodeString(&InstallPath); - RtlCreateUnicodeString(&InstallPath, InstallDir); - - /* Create 'DestinationRootPath' string */ - RtlFreeUnicodeString(&DestinationRootPath); - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - DiskEntry->DiskNumber, - PartEntry->PartitionNumber); - RtlCreateUnicodeString(&DestinationRootPath, PathBuffer); - DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath); - - /* Create 'DestinationPath' string */ - RtlFreeUnicodeString(&DestinationPath); - wcscpy(PathBuffer, DestinationRootPath.Buffer); - - if (InstallDir[0] != L'\\') - wcscat(PathBuffer, L"\\"); - - wcscat(PathBuffer, InstallDir); - RtlCreateUnicodeString(&DestinationPath, PathBuffer); - - /* Create 'DestinationArcPath' */ - RtlFreeUnicodeString(&DestinationArcPath); - swprintf(PathBuffer, - L"multi(0)disk(0)rdisk(%lu)partition(%lu)", - DiskEntry->BiosDiskNumber, - PartEntry->PartitionNumber); - - if (InstallDir[0] != L'\\') - wcscat(PathBuffer, L"\\"); - - wcscat(PathBuffer, InstallDir); - RtlCreateUnicodeString(&DestinationArcPath, PathBuffer); + Status = InitDestinationPaths(&USetupData, InstallDir, DiskEntry, PartEntry); + // TODO: Check Status + UNREFERENCED_PARAMETER(Status); + + /* Initialize DestinationDriveLetter */ + DestinationDriveLetter = PartEntry->DriveLetter; +} + + +static BOOLEAN +IsValidPath( + IN PCWSTR InstallDir) +{ + UINT i, Length; + + Length = wcslen(InstallDir); + + // TODO: Add check for 8.3 too. + + /* Path must be at least 2 characters long */ +// if (Length < 2) +// return FALSE; + + /* Path must start with a backslash */ +// if (InstallDir[0] != L'\\') +// return FALSE; + + /* Path must not end with a backslash */ + if (InstallDir[Length - 1] == L'\\') + return FALSE; + + /* Path must not contain whitespace characters */ + for (i = 0; i < Length; i++) + { + if (iswspace(InstallDir[i])) + return FALSE; + } + + /* Path component must not end with a dot */ + for (i = 0; i < Length; i++) + { + if (InstallDir[i] == L'\\' && i > 0) + { + if (InstallDir[i - 1] == L'.') + return FALSE; + } + } + + if (InstallDir[Length - 1] == L'.') + return FALSE; + + return TRUE; } @@ -3304,7 +3254,7 @@ BuildInstallPaths(PWCHAR InstallDir, * Displays the InstallDirectoryPage. * * Next pages: - * PrepareCopyPage (As the direct result of InstallDirectoryPage1) + * PrepareCopyPage * QuitPage * * RETURNS @@ -3315,11 +3265,11 @@ InstallDirectoryPage(PINPUT_RECORD Ir) { PDISKENTRY DiskEntry; PPARTENTRY PartEntry; - WCHAR InstallDir[51]; + WCHAR InstallDir[MAX_PATH]; WCHAR c; ULONG Length, Pos; - /* We do not need the filesystem list any more */ + /* We do not need the filesystem list anymore */ if (FileSystemList != NULL) { DestroyFileSystemList(FileSystemList); @@ -3337,29 +3287,50 @@ InstallDirectoryPage(PINPUT_RECORD Ir) DiskEntry = PartitionList->CurrentDisk; PartEntry = PartitionList->CurrentPartition; - if (IsUnattendedSetup) - { - if (!IsValidPath(UnattendInstallationDirectory)) - { - /* FIXME: Log the error? */ - return QUIT_PAGE; - } + // if (IsUnattendedSetup) + if (RepairUpdateFlag) + wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath + else if (USetupData.InstallationDirectory[0]) + wcscpy(InstallDir, USetupData.InstallationDirectory); + else + wcscpy(InstallDir, L"\\ReactOS"); - BuildInstallPaths(UnattendInstallationDirectory, + /* + * Check the validity of the predefined 'InstallDir'. If we are either + * in unattended setup or in update/repair mode, and the installation path + * is valid, just perform the installation. Otherwise (either in the case + * of an invalid path, or we are in regular setup), display the UI and allow + * the user to specify a new installation path. + */ + if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir)) + { + BuildInstallPaths(InstallDir, DiskEntry, PartEntry); + /* + * Check whether the user attempts to install ReactOS within the + * installation source directory, or in a subdirectory thereof. + * If so, fail with an error. + */ + if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE)) + { + PopupError("You cannot install ReactOS within the installation source directory!", + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); + return INSTALL_DIRECTORY_PAGE; + } + return PREPARE_COPY_PAGE; } - wcscpy(InstallDir, L"\\ReactOS"); - Length = wcslen(InstallDir); Pos = Length; + + MUIDisplayPage(INSTALL_DIRECTORY_PAGE); CONSOLE_SetInputTextXY(8, 11, 51, InstallDir); CONSOLE_SetCursorXY(8 + Pos, 11); CONSOLE_SetCursorType(TRUE, TRUE); - MUIDisplayPage(INSTALL_DIRECTORY_PAGE); while (TRUE) { @@ -3370,7 +3341,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir) { CONSOLE_SetCursorType(TRUE, FALSE); - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; CONSOLE_SetCursorType(TRUE, TRUE); @@ -3439,6 +3410,19 @@ InstallDirectoryPage(PINPUT_RECORD Ir) DiskEntry, PartEntry); + /* + * Check whether the user attempts to install ReactOS within the + * installation source directory, or in a subdirectory thereof. + * If so, fail with an error. + */ + if (RtlPrefixUnicodeString(&USetupData.SourcePath, &USetupData.DestinationPath, TRUE)) + { + PopupError("You cannot install ReactOS within the installation source directory!", + MUIGetString(STRING_CONTINUE), + Ir, POPUP_WAIT_ENTER); + return INSTALL_DIRECTORY_PAGE; + } + return PREPARE_COPY_PAGE; } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */ @@ -3484,345 +3468,28 @@ InstallDirectoryPage(PINPUT_RECORD Ir) } -static BOOLEAN -AddSectionToCopyQueueCab(HINF InfFile, - PWCHAR SectionName, - PWCHAR SourceCabinet, - PCUNICODE_STRING DestinationPath, - PINPUT_RECORD Ir) -{ - INFCONTEXT FilesContext; - INFCONTEXT DirContext; - PWCHAR FileKeyName; - PWCHAR FileKeyValue; - PWCHAR DirKeyValue; - PWCHAR TargetFileName; - - /* Search for the SectionName section */ - if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext)) - { - char Buffer[128]; - sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName); - PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER); - return FALSE; - } - - /* - * Enumerate the files in the section - * and add them to the file queue. - */ - do - { - /* Get source file name and target directory id */ - if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue)) - { - /* FIXME: Handle error! */ - DPRINT1("INF_GetData() failed\n"); - break; - } - - /* Get optional target file name */ - if (!INF_GetDataField(&FilesContext, 2, &TargetFileName)) - TargetFileName = NULL; - - DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue); - - /* Lookup target directory */ - if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext)) - { - /* FIXME: Handle error! */ - DPRINT1("SetupFindFirstLine() failed\n"); - break; - } - - if (!INF_GetData(&DirContext, NULL, &DirKeyValue)) - { - /* FIXME: Handle error! */ - DPRINT1("INF_GetData() failed\n"); - break; - } - - if (!SetupQueueCopy(SetupFileQueue, - SourceCabinet, - SourceRootPath.Buffer, - SourceRootDir.Buffer, - FileKeyName, - DirKeyValue, - TargetFileName)) - { - /* FIXME: Handle error! */ - DPRINT1("SetupQueueCopy() failed\n"); - } - } while (SetupFindNextLine(&FilesContext, &FilesContext)); - - return TRUE; -} - - -static BOOLEAN -AddSectionToCopyQueue(HINF InfFile, - PWCHAR SectionName, - PWCHAR SourceCabinet, - PCUNICODE_STRING DestinationPath, - PINPUT_RECORD Ir) -{ - INFCONTEXT FilesContext; - INFCONTEXT DirContext; - PWCHAR FileKeyName; - PWCHAR FileKeyValue; - PWCHAR DirKeyValue; - PWCHAR TargetFileName; - ULONG Length; - WCHAR CompleteOrigDirName[512]; - - if (SourceCabinet) - return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir); - - /* Search for the SectionName section */ - if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext)) - { - char Buffer[128]; - sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName); - PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER); - return FALSE; - } - - /* - * Enumerate the files in the section - * and add them to the file queue. - */ - do - { - /* Get source file name and target directory id */ - if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue)) - { - /* FIXME: Handle error! */ - DPRINT1("INF_GetData() failed\n"); - break; - } - - /* Get target directory id */ - if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue)) - { - /* FIXME: Handle error! */ - DPRINT1("INF_GetData() failed\n"); - break; - } - - /* Get optional target file name */ - if (!INF_GetDataField(&FilesContext, 11, &TargetFileName)) - TargetFileName = NULL; - else if (!*TargetFileName) - TargetFileName = NULL; - - DPRINT("FileKeyName: '%S' FileKeyValue: '%S'\n", FileKeyName, FileKeyValue); - - /* Lookup target directory */ - if (!SetupFindFirstLineW(InfFile, L"Directories", FileKeyValue, &DirContext)) - { - /* FIXME: Handle error! */ - DPRINT1("SetupFindFirstLine() failed\n"); - break; - } - - if (!INF_GetData(&DirContext, NULL, &DirKeyValue)) - { - /* FIXME: Handle error! */ - DPRINT1("INF_GetData() failed\n"); - break; - } - - if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0)) - { - /* Installation path */ - wcscpy(CompleteOrigDirName, SourceRootDir.Buffer); - } - else if (DirKeyValue[0] == L'\\') - { - /* Absolute path */ - wcscpy(CompleteOrigDirName, DirKeyValue); - } - else // if (DirKeyValue[0] != L'\\') - { - /* Path relative to the installation path */ - wcscpy(CompleteOrigDirName, SourceRootDir.Buffer); - wcscat(CompleteOrigDirName, L"\\"); - wcscat(CompleteOrigDirName, DirKeyValue); - } - - /* Remove trailing backslash */ - Length = wcslen(CompleteOrigDirName); - if ((Length > 0) && (CompleteOrigDirName[Length - 1] == L'\\')) - { - CompleteOrigDirName[Length - 1] = 0; - } - - if (!SetupQueueCopy(SetupFileQueue, - SourceCabinet, - SourceRootPath.Buffer, - CompleteOrigDirName, - FileKeyName, - DirKeyValue, - TargetFileName)) - { - /* FIXME: Handle error! */ - DPRINT1("SetupQueueCopy() failed\n"); - } - } while (SetupFindNextLine(&FilesContext, &FilesContext)); - - return TRUE; -} - - -static BOOLEAN -PrepareCopyPageInfFile(HINF InfFile, - PWCHAR SourceCabinet, - PINPUT_RECORD Ir) +// PSETUP_ERROR_ROUTINE +static VOID +__cdecl +USetupErrorRoutine( + IN PUSETUP_DATA pSetupData, + ...) { - WCHAR PathBuffer[MAX_PATH]; - INFCONTEXT DirContext; - PWCHAR AdditionalSectionName = NULL; - PWCHAR DirKeyValue; - ULONG Length; - NTSTATUS Status; - - /* Add common files */ - if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir)) - return FALSE; - - /* Add specific files depending of computer type */ - if (SourceCabinet == NULL) - { - if (!ProcessComputerFiles(InfFile, ComputerList, &AdditionalSectionName)) - return FALSE; - - if (AdditionalSectionName) - { - if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &DestinationPath, Ir)) - return FALSE; - } - } - - /* Create directories */ - - /* - * FIXME: - * - Install directories like '\reactos\test' are not handled yet. - * - Copying files to DestinationRootPath should be done from within - * the SystemPartitionFiles section. - * At the moment we check whether we specify paths like '\foo' or '\\' for that. - * For installing to DestinationPath specify just '\' . - */ + INPUT_RECORD Ir; + va_list arg_ptr; - /* Get destination path */ - wcscpy(PathBuffer, DestinationPath.Buffer); + va_start(arg_ptr, pSetupData); - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) + if (pSetupData->LastErrorNumber >= ERROR_SUCCESS && + pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE) { - PathBuffer[Length - 1] = 0; + // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber... + MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr); } - /* Create the install directory */ - Status = SetupCreateDirectory(PathBuffer); - if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION) - { - DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status); - MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER); - return FALSE; - } - - /* Search for the 'Directories' section */ - if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext)) - { - if (SourceCabinet) - { - MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER); - } - else - { - MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER); - } - - return FALSE; - } - - /* Enumerate the directory values and create the subdirectories */ - do - { - if (!INF_GetData(&DirContext, NULL, &DirKeyValue)) - { - DPRINT1("break\n"); - break; - } - - if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0)) - { - /* Installation path */ - DPRINT("InstallationPath: '%S'\n", DirKeyValue); - - wcscpy(PathBuffer, DestinationPath.Buffer); - - DPRINT("FullPath: '%S'\n", PathBuffer); - } - else if (DirKeyValue[0] == L'\\') - { - /* Absolute path */ - DPRINT("Absolute Path: '%S'\n", DirKeyValue); - - wcscpy(PathBuffer, DestinationRootPath.Buffer); - wcscat(PathBuffer, DirKeyValue); - - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) - { - PathBuffer[Length - 1] = 0; - } - - DPRINT("FullPath: '%S'\n", PathBuffer); - - Status = SetupCreateDirectory(PathBuffer); - if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION) - { - DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status); - MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER); - return FALSE; - } - } - else // if (DirKeyValue[0] != L'\\') - { - /* Path relative to the installation path */ - DPRINT("RelativePath: '%S'\n", DirKeyValue); - - wcscpy(PathBuffer, DestinationPath.Buffer); - wcscat(PathBuffer, L"\\"); - wcscat(PathBuffer, DirKeyValue); - - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) - { - PathBuffer[Length - 1] = 0; - } - - DPRINT("FullPath: '%S'\n", PathBuffer); - - Status = SetupCreateDirectory(PathBuffer); - if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION) - { - DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status); - MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER); - return FALSE; - } - } - } while (SetupFindNextLine(&DirContext, &DirContext)); - - return TRUE; + va_end(arg_ptr); } - /* * Displays the PrepareCopyPage. * @@ -3831,8 +3498,7 @@ PrepareCopyPageInfFile(HINF InfFile, * QuitPage * * SIDEEFFECTS - * Inits SetupFileQueue - * Calls PrepareCopyPageInfFile + * Calls PrepareFileCopy * * RETURNS * Number of the next page. @@ -3840,99 +3506,30 @@ PrepareCopyPageInfFile(HINF InfFile, static PAGE_NUMBER PrepareCopyPage(PINPUT_RECORD Ir) { - HINF InfHandle; - WCHAR PathBuffer[MAX_PATH]; - INFCONTEXT CabinetsContext; - ULONG InfFileSize; - PWCHAR KeyValue; - UINT ErrorLine; - PVOID InfFileData; + // ERROR_NUMBER ErrorNumber; + BOOLEAN Success; MUIDisplayPage(PREPARE_COPY_PAGE); - /* Create the file queue */ - SetupFileQueue = SetupOpenFileQueue(); - if (SetupFileQueue == NULL) - { - MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - if (!PrepareCopyPageInfFile(SetupInf, NULL, Ir)) + /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL); + if (/*ErrorNumber != ERROR_SUCCESS*/ !Success) { - /* FIXME: show an error dialog */ + // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } - /* Search for the 'Cabinets' section */ - if (!SetupFindFirstLineW(SetupInf, L"Cabinets", NULL, &CabinetsContext)) - { - return FILE_COPY_PAGE; - } - - /* - * Enumerate the directory values in the 'Cabinets' - * section and parse their inf files. - */ - do - { - if (!INF_GetData(&CabinetsContext, NULL, &KeyValue)) - break; - - wcscpy(PathBuffer, SourcePath.Buffer); - wcscat(PathBuffer, L"\\"); - wcscat(PathBuffer, KeyValue); - - CabinetInitialize(); - CabinetSetEventHandlers(NULL, NULL, NULL); - CabinetSetCabinetName(PathBuffer); - - if (CabinetOpen() == CAB_STATUS_SUCCESS) - { - DPRINT("Cabinet %S\n", CabinetGetCabinetName()); - - InfFileData = CabinetGetCabinetReservedArea(&InfFileSize); - if (InfFileData == NULL) - { - MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - } - else - { - DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName()); - MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - InfHandle = INF_OpenBufferedFileA((CHAR*) InfFileData, - InfFileSize, - (const CHAR*) NULL, - INF_STYLE_WIN4, - LanguageId, - &ErrorLine); - - if (InfHandle == INVALID_HANDLE_VALUE) - { - MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - CabinetCleanup(); - - if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir)) - { - /* FIXME: show an error dialog */ - return QUIT_PAGE; - } - } while (SetupFindNextLine(&CabinetsContext, &CabinetsContext)); - return FILE_COPY_PAGE; } +typedef struct _COPYCONTEXT +{ + ULONG TotalOperations; + ULONG CompletedOperations; + PPROGRESSBAR ProgressBar; + PPROGRESSBAR MemoryBars[4]; +} COPYCONTEXT, *PCOPYCONTEXT; -VOID -NTAPI +static VOID SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext, IN BOOLEAN First) { @@ -3959,7 +3556,6 @@ SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext, ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages); } - static UINT CALLBACK FileCopyCallback(PVOID Context, @@ -3967,26 +3563,92 @@ FileCopyCallback(PVOID Context, UINT_PTR Param1, UINT_PTR Param2) { - PCOPYCONTEXT CopyContext; - - CopyContext = (PCOPYCONTEXT)Context; + PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context; + PFILEPATHS_W FilePathInfo; + PCWSTR SrcFileName, DstFileName; switch (Notification) { case SPFILENOTIFY_STARTSUBQUEUE: + { CopyContext->TotalOperations = (ULONG)Param2; + CopyContext->CompletedOperations = 0; ProgressSetStepCount(CopyContext->ProgressBar, CopyContext->TotalOperations); SetupUpdateMemoryInfo(CopyContext, TRUE); break; + } + case SPFILENOTIFY_STARTDELETE: + case SPFILENOTIFY_STARTRENAME: case SPFILENOTIFY_STARTCOPY: - /* Display copy message */ - CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1); + { + FilePathInfo = (PFILEPATHS_W)Param1; + + if (Notification == SPFILENOTIFY_STARTDELETE) + { + /* Display delete message */ + ASSERT(Param2 == FILEOP_DELETE); + + DstFileName = wcsrchr(FilePathInfo->Target, L'\\'); + if (DstFileName) ++DstFileName; + else DstFileName = FilePathInfo->Target; + + CONSOLE_SetStatusText(MUIGetString(STRING_DELETING), + DstFileName); + } + else if (Notification == SPFILENOTIFY_STARTRENAME) + { + /* Display move/rename message */ + ASSERT(Param2 == FILEOP_RENAME); + + SrcFileName = wcsrchr(FilePathInfo->Source, L'\\'); + if (SrcFileName) ++SrcFileName; + else SrcFileName = FilePathInfo->Source; + + DstFileName = wcsrchr(FilePathInfo->Target, L'\\'); + if (DstFileName) ++DstFileName; + else DstFileName = FilePathInfo->Target; + + if (!wcsicmp(SrcFileName, DstFileName)) + Param2 = STRING_MOVING; + else + Param2 = STRING_RENAMING; + + CONSOLE_SetStatusText(MUIGetString(Param2), + SrcFileName, DstFileName); + } + else if (Notification == SPFILENOTIFY_STARTCOPY) + { + /* Display copy message */ + ASSERT(Param2 == FILEOP_COPY); + + /* NOTE: When extracting from CABs the Source is the CAB name */ + DstFileName = wcsrchr(FilePathInfo->Target, L'\\'); + if (DstFileName) ++DstFileName; + else DstFileName = FilePathInfo->Target; + + CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), + DstFileName); + } + SetupUpdateMemoryInfo(CopyContext, FALSE); break; + } + + case SPFILENOTIFY_COPYERROR: + { + FilePathInfo = (PFILEPATHS_W)Param1; + + DPRINT1("An error happened while trying to copy file '%S' (error 0x%08lx), skipping it...\n", + FilePathInfo->Target, FilePathInfo->Win32Error); + return FILEOP_SKIP; + } + case SPFILENOTIFY_ENDDELETE: + case SPFILENOTIFY_ENDRENAME: case SPFILENOTIFY_ENDCOPY: + { CopyContext->CompletedOperations++; /* SYSREG checkpoint */ @@ -3996,9 +3658,10 @@ FileCopyCallback(PVOID Context, ProgressNextStep(CopyContext->ProgressBar); SetupUpdateMemoryInfo(CopyContext, FALSE); break; + } } - return 0; + return FILEOP_DOIT; } @@ -4009,24 +3672,20 @@ FileCopyCallback(PVOID Context, * RegistryPage(At once) * * SIDEEFFECTS - * Calls SetupCommitFileQueueW - * Calls SetupCloseFileQueue + * Calls DoFileCopy * * RETURNS * Number of the next page. */ -static -PAGE_NUMBER +static PAGE_NUMBER FileCopyPage(PINPUT_RECORD Ir) { COPYCONTEXT CopyContext; - unsigned int mem_bar_width; + UINT MemBarWidth; MUIDisplayPage(FILE_COPY_PAGE); /* Create context for the copy process */ - CopyContext.DestinationRootPath = DestinationRootPath.Buffer; - CopyContext.InstallPath = InstallPath.Buffer; CopyContext.TotalOperations = 0; CopyContext.CompletedOperations = 0; @@ -4041,13 +3700,13 @@ FileCopyPage(PINPUT_RECORD Ir) MUIGetString(STRING_SETUPCOPYINGFILES)); // fit memory bars to screen width, distribute them uniform - mem_bar_width = (xScreen - 26) / 5; - mem_bar_width -= mem_bar_width % 2; // make even + MemBarWidth = (xScreen - 26) / 5; + MemBarWidth -= MemBarWidth % 2; // make even /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */ /* Create the paged pool progress bar */ CopyContext.MemoryBars[0] = CreateProgressBar(13, 40, - 13 + mem_bar_width, + 13 + MemBarWidth, 43, 13, 44, @@ -4055,43 +3714,73 @@ FileCopyPage(PINPUT_RECORD Ir) "Kernel Pool"); /* Create the non paged pool progress bar */ - CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2), + CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2), 40, - (xScreen / 2) + (mem_bar_width / 2), + (xScreen / 2) + (MemBarWidth / 2), 43, - (xScreen / 2)- (mem_bar_width / 2), + (xScreen / 2)- (MemBarWidth / 2), 44, FALSE, "Kernel Cache"); /* Create the global memory progress bar */ - CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width, + CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth, 40, xScreen - 13, 43, - xScreen - 13 - mem_bar_width, + xScreen - 13 - MemBarWidth, 44, FALSE, "Free Memory"); /* Do the file copying */ - SetupCommitFileQueueW(NULL, - SetupFileQueue, - FileCopyCallback, - &CopyContext); + DoFileCopy(&USetupData, FileCopyCallback, &CopyContext); - /* If we get here, we're done, so cleanup the queue and progress bar */ - SetupCloseFileQueue(SetupFileQueue); + /* If we get here, we're done, so cleanup the progress bar */ DestroyProgressBar(CopyContext.ProgressBar); DestroyProgressBar(CopyContext.MemoryBars[0]); DestroyProgressBar(CopyContext.MemoryBars[1]); DestroyProgressBar(CopyContext.MemoryBars[2]); + /* Create the $winnt$.inf file */ + InstallSetupInfFile(&USetupData); + /* Go display the next page */ return REGISTRY_PAGE; } - + +static VOID +__cdecl +RegistryStatus(IN REGISTRY_STATUS RegStatus, ...) +{ + /* WARNING: Please keep this lookup table in sync with the resources! */ + static const UINT StringIDs[] = + { + STRING_DONE, /* Success */ + STRING_REGHIVEUPDATE, /* RegHiveUpdate */ + STRING_IMPORTFILE, /* ImportRegHive */ + STRING_DISPLAYSETTINGSUPDATE, /* DisplaySettingsUpdate */ + STRING_LOCALESETTINGSUPDATE, /* LocaleSettingsUpdate */ + STRING_ADDKBLAYOUTS, /* KeybLayouts */ + STRING_KEYBOARDSETTINGSUPDATE, /* KeybSettingsUpdate */ + STRING_CODEPAGEINFOUPDATE, /* CodePageInfoUpdate */ + }; + + va_list args; + + if (RegStatus < ARRAYSIZE(StringIDs)) + { + va_start(args, RegStatus); + CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args); + va_end(args); + } + else + { + CONSOLE_SetStatusText("Unknown status %d", RegStatus); + } +} + /* * Displays the RegistryPage. * @@ -4101,11 +3790,7 @@ FileCopyPage(PINPUT_RECORD Ir) * QuitPage * * SIDEEFFECTS - * Calls SetInstallPathValue - * Calls NtInitializeRegistry - * Calls ImportRegistryFile - * Calls SetDefaultPagefile - * Calls SetMountedDeviceValues + * Calls UpdateRegistry * * RETURNS * Number of the next page. @@ -4113,141 +3798,26 @@ FileCopyPage(PINPUT_RECORD Ir) static PAGE_NUMBER RegistryPage(PINPUT_RECORD Ir) { - INFCONTEXT InfContext; - PWSTR Action; - PWSTR File; - PWSTR Section; - BOOLEAN Delete; - NTSTATUS Status; + ULONG Error; MUIDisplayPage(REGISTRY_PAGE); - if (RepairUpdateFlag) - { - return SUCCESS_PAGE; - } - - if (!SetInstallPathValue(&DestinationPath)) - { - DPRINT1("SetInstallPathValue() failed\n"); - MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Create the default hives */ - Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status); - MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Update registry */ - CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE)); - - if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext)) - { - DPRINT1("SetupFindFirstLine() failed\n"); - MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - do - { - INF_GetDataField(&InfContext, 0, &Action); - INF_GetDataField(&InfContext, 1, &File); - INF_GetDataField(&InfContext, 2, &Section); - - DPRINT("Action: %S File: %S Section %S\n", Action, File, Section); - - if (Action == NULL) - break; // Hackfix - - if (!_wcsicmp(Action, L"AddReg")) - { - Delete = FALSE; - } - else if (!_wcsicmp(Action, L"DelReg")) - { - Delete = TRUE; - } - else - { - continue; - } - - CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File); - - if (!ImportRegistryFile(File, Section, LanguageId, Delete)) - { - DPRINT1("Importing %S failed\n", File); - - MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - } while (SetupFindNextLine(&InfContext, &InfContext)); - - /* Update display registry settings */ - CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE)); - if (!ProcessDisplayRegistry(SetupInf, DisplayList)) - { - MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Set the locale */ - CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE)); - if (!ProcessLocaleRegistry(LanguageList)) - { - MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Add keyboard layouts */ - CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS)); - if (!AddKeyboardLayouts()) - { - MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - /* Set GeoID */ - - if (!SetGeoID(MUIGetGeoID())) + Error = UpdateRegistry(&USetupData, + RepairUpdateFlag, + PartitionList, + DestinationDriveLetter, + SelectedLanguageId, + RegistryStatus); + if (Error != ERROR_SUCCESS) { - MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER); + MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } - - if (!IsUnattendedSetup) - { - /* Update keyboard layout settings */ - CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE)); - if (!ProcessKeyboardLayoutRegistry(LayoutList)) - { - MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - } - - /* Add codepage information to registry */ - CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE)); - if (!AddCodePage()) + else { - MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; + CONSOLE_SetStatusText(MUIGetString(STRING_DONE)); + return BOOT_LOADER_PAGE; } - - /* Set the default pagefile entry */ - SetDefaultPagefile(DestinationDriveLetter); - - /* Update the mounted devices list */ - SetMountedDeviceValues(PartitionList); - - CONSOLE_SetStatusText(MUIGetString(STRING_DONE)); - - return BOOT_LOADER_PAGE; } @@ -4263,8 +3833,7 @@ RegistryPage(PINPUT_RECORD Ir) * QuitPage * * SIDEEFFECTS - * Calls SetInstallPathValue - * Calls NtInitializeRegistry + * Calls RegInitializeRegistry * Calls ImportRegistryFile * Calls SetDefaultPagefile * Calls SetMountedDeviceValues @@ -4282,28 +3851,30 @@ BootLoaderPage(PINPUT_RECORD Ir) CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - RtlFreeUnicodeString(&SystemRootPath); - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - PartitionList->SystemDisk->DiskNumber, - PartitionList->SystemPartition->PartitionNumber); - RtlCreateUnicodeString(&SystemRootPath, PathBuffer); - DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath); + RtlFreeUnicodeString(&USetupData.SystemRootPath); + RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), + L"\\Device\\Harddisk%lu\\Partition%lu\\", + PartitionList->SystemPartition->DiskEntry->DiskNumber, + PartitionList->SystemPartition->PartitionNumber); + RtlCreateUnicodeString(&USetupData.SystemRootPath, PathBuffer); + DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath); PartitionType = PartitionList->SystemPartition->PartitionType; + /* For unattended setup, skip MBR installation or install on floppy if needed */ if (IsUnattendedSetup) { - if (UnattendMBRInstallType == 0) /* skip MBR installation */ - { - return SUCCESS_PAGE; - } - else if (UnattendMBRInstallType == 1) /* install on floppy */ + if ((USetupData.MBRInstallType == 0) || + (USetupData.MBRInstallType == 1)) { - return BOOT_LOADER_FLOPPY_PAGE; + goto Quit; } } + /* + * We may install an MBR or VBR, but before that, check whether + * we need to actually install the VBR on floppy. + */ if (PartitionType == PARTITION_ENTRY_UNUSED) { DPRINT("Error: system partition invalid (unused)\n"); @@ -4315,10 +3886,10 @@ BootLoaderPage(PINPUT_RECORD Ir) DPRINT("Found OS/2 boot manager partition\n"); InstallOnFloppy = TRUE; } - else if (PartitionType == PARTITION_EXT2) + else if (PartitionType == PARTITION_LINUX) { - /* Linux EXT2 partition */ - DPRINT("Found Linux EXT2 partition\n"); + /* Linux partition */ + DPRINT("Found Linux native partition (ext2/ext3/ReiserFS/BTRFS/etc)\n"); InstallOnFloppy = FALSE; } else if (PartitionType == PARTITION_IFS) @@ -4331,9 +3902,9 @@ BootLoaderPage(PINPUT_RECORD Ir) } else if ((PartitionType == PARTITION_FAT_12) || (PartitionType == PARTITION_FAT_16) || - (PartitionType == PARTITION_HUGE) || + (PartitionType == PARTITION_HUGE) || (PartitionType == PARTITION_XINT13) || - (PartitionType == PARTITION_FAT32) || + (PartitionType == PARTITION_FAT32) || (PartitionType == PARTITION_FAT32_XINT13)) { DPRINT("Found FAT partition\n"); @@ -4346,15 +3917,21 @@ BootLoaderPage(PINPUT_RECORD Ir) InstallOnFloppy = TRUE; } - if (InstallOnFloppy != FALSE) + /* We should install on floppy */ + if (InstallOnFloppy) { - return BOOT_LOADER_FLOPPY_PAGE; + USetupData.MBRInstallType = 1; + goto Quit; } - /* Unattended install on hdd? */ - if (IsUnattendedSetup && UnattendMBRInstallType == 2) + /* Is it an unattended install on hdd? */ + if (IsUnattendedSetup) { - return BOOT_LOADER_HARDDISK_MBR_PAGE; + if ((USetupData.MBRInstallType == 2) || + (USetupData.MBRInstallType == 3)) + { + goto Quit; + } } MUIDisplayPage(BOOT_LOADER_PAGE); @@ -4370,11 +3947,11 @@ BootLoaderPage(PINPUT_RECORD Ir) CONSOLE_NormalTextXY(8, Line, 60, 1); Line++; - if (Line<12) - Line=15; + if (Line < 12) + Line = 15; - if (Line>15) - Line=12; + if (Line > 15) + Line = 12; CONSOLE_InvertTextXY(8, Line, 60, 1); } @@ -4384,18 +3961,18 @@ BootLoaderPage(PINPUT_RECORD Ir) CONSOLE_NormalTextXY(8, Line, 60, 1); Line--; - if (Line<12) - Line=15; + if (Line < 12) + Line = 15; - if (Line>15) - Line=12; + if (Line > 15) + Line = 12; CONSOLE_InvertTextXY(8, Line, 60, 1); } else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; @@ -4404,25 +3981,53 @@ BootLoaderPage(PINPUT_RECORD Ir) { if (Line == 12) { - return BOOT_LOADER_HARDDISK_MBR_PAGE; + /* Install on both MBR and VBR */ + USetupData.MBRInstallType = 2; + break; } else if (Line == 13) { - return BOOT_LOADER_HARDDISK_VBR_PAGE; + /* Install on VBR only */ + USetupData.MBRInstallType = 3; + break; } else if (Line == 14) { - return BOOT_LOADER_FLOPPY_PAGE; + /* Install on floppy */ + USetupData.MBRInstallType = 1; + break; } else if (Line == 15) { - return SUCCESS_PAGE; + /* Skip MBR installation */ + USetupData.MBRInstallType = 0; + break; } return BOOT_LOADER_PAGE; } } +Quit: + switch (USetupData.MBRInstallType) + { + /* Skip MBR installation */ + case 0: + return SUCCESS_PAGE; + + /* Install on floppy */ + case 1: + return BOOT_LOADER_FLOPPY_PAGE; + + /* Install on both MBR and VBR */ + case 2: + return BOOT_LOADER_HARDDISK_MBR_PAGE; + + /* Install on VBR only */ + case 3: + return BOOT_LOADER_HARDDISK_VBR_PAGE; + } + return BOOT_LOADER_PAGE; } @@ -4447,7 +4052,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir) MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE); -// SetStatusText(" Please wait..."); +// CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); while (TRUE) { @@ -4456,23 +4061,21 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir) if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { - if (ConfirmQuit(Ir) != FALSE) + if (ConfirmQuit(Ir)) return QUIT_PAGE; break; } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { - if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE) - { - MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER); - return BOOT_LOADER_FLOPPY_PAGE; - } - - Status = InstallFatBootcodeToFloppy(&SourceRootPath, &DestinationArcPath); + Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath, + &USetupData.DestinationArcPath); if (!NT_SUCCESS(Status)) { - /* Print error message */ + if (Status == STATUS_DEVICE_NOT_READY) + MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER); + + /* TODO: Print error message */ return BOOT_LOADER_FLOPPY_PAGE; } @@ -4500,18 +4103,17 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir) static PAGE_NUMBER BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir) { - UCHAR PartitionType; NTSTATUS Status; - PartitionType = PartitionList->SystemPartition->PartitionType; - - Status = InstallVBRToPartition(&SystemRootPath, - &SourceRootPath, - &DestinationArcPath, - PartitionType); + // FIXME! We must not use the partition type, but instead use the partition FileSystem!! + Status = InstallVBRToPartition(&USetupData.SystemRootPath, + &USetupData.SourceRootPath, + &USetupData.DestinationArcPath, + PartitionList->SystemPartition->PartitionType); if (!NT_SUCCESS(Status)) { - MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER); + MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER, + PartitionList->SystemPartition->FileSystem->FileSystemName); return QUIT_PAGE; } @@ -4528,7 +4130,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir) * * SIDEEFFECTS * Calls InstallVBRToPartition() - * CallsInstallMbrBootCodeToDisk() + * Calls InstallMbrBootCodeToDisk() * * RETURNS * Number of the next page. @@ -4536,61 +4138,232 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir) static PAGE_NUMBER BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir) { - UCHAR PartitionType; NTSTATUS Status; WCHAR DestinationDevicePathBuffer[MAX_PATH]; - WCHAR SourceMbrPathBuffer[MAX_PATH]; - WCHAR DstPath[MAX_PATH]; /* Step 1: Write the VBR */ - PartitionType = PartitionList->SystemPartition->PartitionType; - - Status = InstallVBRToPartition(&SystemRootPath, - &SourceRootPath, - &DestinationArcPath, - PartitionType); + // FIXME! We must not use the partition type, but instead use the partition FileSystem!! + Status = InstallVBRToPartition(&USetupData.SystemRootPath, + &USetupData.SourceRootPath, + &USetupData.DestinationArcPath, + PartitionList->SystemPartition->PartitionType); if (!NT_SUCCESS(Status)) { - MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER); + MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER, + PartitionList->SystemPartition->FileSystem->FileSystemName); return QUIT_PAGE; } /* Step 2: Write the MBR */ - swprintf(DestinationDevicePathBuffer, - L"\\Device\\Harddisk%d\\Partition0", - PartitionList->SystemDisk->DiskNumber); + RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer), + L"\\Device\\Harddisk%d\\Partition0", + PartitionList->SystemPartition->DiskEntry->DiskNumber); + Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath, + &USetupData.SourceRootPath, + DestinationDevicePathBuffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status); + MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER, L"MBR"); + return QUIT_PAGE; + } + + return SUCCESS_PAGE; +} + + +/** + * @name ProgressTimeOutStringHandler + * + * Handles the generation (displaying) of the timeout + * countdown to the screen dynamically. + * + * @param Bar + * A pointer to a progress bar. + * + * @param AlwaysUpdate + * Constantly update the progress bar (boolean type). + * + * @param Buffer + * A pointer to a string buffer. + * + * @param cchBufferSize + * The buffer's size in number of characters. + * + * @return + * TRUE or FALSE on function termination. + * + */ +static +BOOLEAN NTAPI +ProgressTimeOutStringHandler( + IN PPROGRESSBAR Bar, + IN BOOLEAN AlwaysUpdate, + OUT PSTR Buffer, + IN SIZE_T cchBufferSize) +{ + ULONG OldProgress = Bar->Progress; + + if (Bar->StepCount == 0) + { + Bar->Progress = 0; + } + else + { + Bar->Progress = Bar->StepCount - Bar->CurrentStep; + } + + /* Build the progress string if it has changed */ + if (Bar->ProgressFormatText && + (AlwaysUpdate || (Bar->Progress != OldProgress))) + { + RtlStringCchPrintfA(Buffer, cchBufferSize, + Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1); + + return TRUE; + } + + return FALSE; +} - wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer); - wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin"); +/** + * @name ProgressCountdown + * + * Displays and draws a red-coloured progress bar with a countdown. + * When the timeout is reached, the flush page is displayed for reboot. + * + * @param Ir + * A pointer to an input keyboard record. + * + * @param TimeOut + * Initial countdown value in seconds. + * + * @return + * Nothing. + * + */ +static VOID +ProgressCountdown( + IN PINPUT_RECORD Ir, + IN LONG TimeOut) +{ + NTSTATUS Status; + ULONG StartTime, BarWidth, TimerDiv; + LONG TimeElapsed; + LONG TimerValue, OldTimerValue; + LARGE_INTEGER Timeout; + PPROGRESSBAR ProgressBar; + BOOLEAN RefreshProgress = TRUE; + + /* Bail out if the timeout is already zero */ + if (TimeOut <= 0) + return; - if (IsThereAValidBootSector(DestinationDevicePathBuffer)) + /* Create the timeout progress bar and set it up */ + ProgressBar = CreateProgressBarEx(13, + 26, + xScreen - 13, + yScreen - 20, + 10, + 24, + TRUE, + FOREGROUND_RED | BACKGROUND_BLUE, + 0, + NULL, + MUIGetString(STRING_REBOOTPROGRESSBAR), + ProgressTimeOutStringHandler); + + BarWidth = max(1, ProgressBar->Width); + TimerValue = TimeOut * BarWidth; + ProgressSetStepCount(ProgressBar, TimerValue); + + StartTime = NtGetTickCount(); + CONSOLE_Flush(); + + TimerDiv = 1000 / BarWidth; + TimerDiv = max(1, TimerDiv); + OldTimerValue = TimerValue; + while (TRUE) { - /* Save current MBR */ - wcscpy(DstPath, SystemRootPath.Buffer); - wcscat(DstPath, L"\\mbr.old"); + /* Decrease the timer */ - DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath); - Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR)); - if (!NT_SUCCESS(Status)) + /* + * Compute how much time the previous operations took. + * This allows us in particular to take account for any time + * elapsed if something slowed down. + */ + TimeElapsed = NtGetTickCount() - StartTime; + if (TimeElapsed >= TimerDiv) { - DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); - // Don't care if we succeeded or not saving the old MBR, just go ahead. + /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */ + TimeElapsed /= TimerDiv; + StartTime += (TimerDiv * TimeElapsed); + + if (TimeElapsed <= TimerValue) + TimerValue -= TimeElapsed; + else + TimerValue = 0; + + RefreshProgress = TRUE; } - } - DPRINT1("Install MBR bootcode: %S ==> %S\n", - SourceMbrPathBuffer, DestinationDevicePathBuffer); - Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer, - DestinationDevicePathBuffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", - Status); - MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; + if (RefreshProgress) + { + ProgressSetStep(ProgressBar, OldTimerValue - TimerValue); + RefreshProgress = FALSE; + } + + /* Stop when the timer reaches zero */ + if (TimerValue <= 0) + break; + + /* Check for user key presses */ + + /* + * If the timer is used, use a passive wait of maximum 1 second + * while monitoring for incoming console input events, so that + * we are still able to display the timing count. + */ + + /* Wait a maximum of 1 second for input events */ + TimeElapsed = NtGetTickCount() - StartTime; + if (TimeElapsed < TimerDiv) + { + /* Convert the time to NT Format */ + Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL; + Status = NtWaitForSingleObject(StdInput, FALSE, &Timeout); + } + else + { + Status = STATUS_TIMEOUT; + } + + /* Check whether the input event has been signaled, or a timeout happened */ + if (Status == STATUS_TIMEOUT) + { + continue; + } + if (Status != STATUS_WAIT_0) + { + /* An error happened, bail out */ + DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status); + break; + } + + /* Check for an ENTER key press */ + while (CONSOLE_ConInKeyPeek(Ir)) + { + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + /* Found it, stop waiting */ + goto Exit; + } + } } - return SUCCESS_PAGE; +Exit: + /* Destroy the progress bar and quit */ + DestroyProgressBar(ProgressBar); } @@ -4611,65 +4384,35 @@ QuitPage(PINPUT_RECORD Ir) { MUIDisplayPage(QUIT_PAGE); - /* Destroy partition list */ + /* Destroy the NTOS installations list */ + if (NtOsInstallsList != NULL) + { + DestroyGenericList(NtOsInstallsList, TRUE); + NtOsInstallsList = NULL; + } + + /* Destroy the partition list */ if (PartitionList != NULL) { DestroyPartitionList(PartitionList); PartitionList = NULL; } - /* Destroy filesystem list */ + TempPartition = NULL; + FormatState = Start; + + /* Destroy the filesystem list */ if (FileSystemList != NULL) { DestroyFileSystemList(FileSystemList); FileSystemList = NULL; } - /* Destroy computer settings list */ - if (ComputerList != NULL) - { - DestroyGenericList(ComputerList, TRUE); - ComputerList = NULL; - } - - /* Destroy display settings list */ - if (DisplayList != NULL) - { - DestroyGenericList(DisplayList, TRUE); - DisplayList = NULL; - } - - /* Destroy keyboard settings list */ - if (KeyboardList != NULL) - { - DestroyGenericList(KeyboardList, TRUE); - KeyboardList = NULL; - } - - /* Destroy keyboard layout list */ - if (LayoutList != NULL) - { - DestroyGenericList(LayoutList, TRUE); - LayoutList = NULL; - } - - if (LanguageList != NULL) - { - DestroyGenericList(LanguageList, FALSE); - LanguageList = NULL; - } - CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2)); - while (TRUE) - { - CONSOLE_ConInKey(Ir); - - if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ - { - return FLUSH_PAGE; - } - } + /* Wait for maximum 15 seconds or an ENTER key before quitting */ + ProgressCountdown(Ir, 15); + return FLUSH_PAGE; } @@ -4691,19 +4434,11 @@ SuccessPage(PINPUT_RECORD Ir) MUIDisplayPage(SUCCESS_PAGE); if (IsUnattendedSetup) - { return FLUSH_PAGE; - } - - while (TRUE) - { - CONSOLE_ConInKey(Ir); - if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ - { - return FLUSH_PAGE; - } - } + /* Wait for maximum 15 seconds or an ENTER key before quitting */ + ProgressCountdown(Ir, 15); + return FLUSH_PAGE; } @@ -4731,17 +4466,22 @@ PnpEventThread(IN LPVOID lpParameter); /* * The start routine and page management */ -VOID +NTSTATUS RunUSetup(VOID) { + NTSTATUS Status; INPUT_RECORD Ir; PAGE_NUMBER Page; - LARGE_INTEGER Time; - NTSTATUS Status; BOOLEAN Old; - NtQuerySystemTime(&Time); + InfSetHeap(ProcessHeap); + + /* Tell the Cm this is a setup boot, and it has to behave accordingly */ + Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP); + if (!NT_SUCCESS(Status)) + DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status); + /* Create the PnP thread in suspended state */ Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, @@ -4749,11 +4489,11 @@ RunUSetup(VOID) 0, 0, PnpEventThread, - &SetupInf, + &USetupData.SetupInf, &hPnpThread, NULL); if (!NT_SUCCESS(Status)) - hPnpThread = INVALID_HANDLE_VALUE; + hPnpThread = NULL; if (!CONSOLE_Init()) { @@ -4761,55 +4501,47 @@ RunUSetup(VOID) PrintString(MUIGetString(STRING_CONSOLEFAIL2)); PrintString(MUIGetString(STRING_CONSOLEFAIL3)); - /* Raise a hard error (crash the system/BSOD) */ - NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, - 0,0,0,0,0); + /* We failed to initialize the video, just quit the installer */ + return STATUS_APP_INIT_FAILURE; } - /* Initialize global unicode strings */ - RtlInitUnicodeString(&SourcePath, NULL); - RtlInitUnicodeString(&SourceRootPath, NULL); - RtlInitUnicodeString(&SourceRootDir, NULL); - RtlInitUnicodeString(&InstallPath, NULL); - RtlInitUnicodeString(&DestinationPath, NULL); - RtlInitUnicodeString(&DestinationArcPath, NULL); - RtlInitUnicodeString(&DestinationRootPath, NULL); - RtlInitUnicodeString(&SystemRootPath, NULL); + /* Initialize Setup, phase 0 */ + InitializeSetup(&USetupData, 0); + USetupData.ErrorRoutine = USetupErrorRoutine; /* Hide the cursor */ CONSOLE_SetCursorType(TRUE, FALSE); - Page = START_PAGE; + /* Global Initialization page */ + CONSOLE_ClearScreen(); + CONSOLE_Flush(); + Page = SetupStartPage(&Ir); + while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE) { CONSOLE_ClearScreen(); CONSOLE_Flush(); - //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup "); - //CONSOLE_Flush(); + // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup "); + // CONSOLE_Flush(); switch (Page) { - /* Start page */ - case START_PAGE: - Page = SetupStartPage(&Ir); - break; - /* Language page */ case LANGUAGE_PAGE: Page = LanguagePage(&Ir); break; + /* Welcome page */ + case WELCOME_PAGE: + Page = WelcomePage(&Ir); + break; + /* License page */ case LICENSE_PAGE: Page = LicensePage(&Ir); break; - /* Intro page */ - case INTRO_PAGE: - Page = IntroPage(&Ir); - break; - /* Install pages */ case INSTALL_INTRO_PAGE: Page = InstallIntroPage(&Ir); @@ -4819,9 +4551,7 @@ RunUSetup(VOID) case SCSI_CONTROLLER_PAGE: Page = ScsiControllerPage(&Ir); break; -#endif -#if 0 case OEM_DRIVER_PAGE: Page = OemDriverPage(&Ir); break; @@ -4876,11 +4606,11 @@ RunUSetup(VOID) break; case FORMAT_PARTITION_PAGE: - Page = (PAGE_NUMBER) FormatPartitionPage(&Ir); + Page = FormatPartitionPage(&Ir); break; case CHECK_FILE_SYSTEM_PAGE: - Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir); + Page = CheckFileSystemPage(&Ir); break; case INSTALL_DIRECTORY_PAGE: @@ -4920,6 +4650,10 @@ RunUSetup(VOID) Page = RepairIntroPage(&Ir); break; + case UPGRADE_REPAIR_PAGE: + Page = UpgradeRepairPage(&Ir); + break; + case SUCCESS_PAGE: Page = SuccessPage(&Ir); break; @@ -4938,31 +4672,58 @@ RunUSetup(VOID) } } + /* Setup has finished */ + FinishSetup(&USetupData); + if (Page == RECOVERY_PAGE) RecoveryConsole(); FreeConsole(); - /* Avoid bugcheck */ - Time.QuadPart += 50000000; - NtDelayExecution(FALSE, &Time); - /* Reboot */ RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); NtShutdownSystem(ShutdownReboot); RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old); - NtTerminateProcess(NtCurrentProcess(), 0); + + return STATUS_SUCCESS; } VOID NTAPI NtProcessStartup(PPEB Peb) { + NTSTATUS Status; + LARGE_INTEGER Time; + RtlNormalizeProcessParams(Peb->ProcessParameters); ProcessHeap = Peb->ProcessHeap; - InfSetHeap(ProcessHeap); - RunUSetup(); + + NtQuerySystemTime(&Time); + + Status = RunUSetup(); + + if (NT_SUCCESS(Status)) + { + /* + * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing + * a protective waiting. + * This wait is needed because, since we are started as SMSS.EXE, + * the NT kernel explicitly waits 5 seconds for the initial process + * SMSS.EXE to initialize (as a protective measure), and otherwise + * bugchecks with the code SESSION5_INITIALIZATION_FAILED. + */ + Time.QuadPart += 50000000; + NtDelayExecution(FALSE, &Time); + } + else + { + /* The installer failed to start: raise a hard error (crash the system/BSOD) */ + Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, + 0, 0, NULL, 0, NULL); + } + + NtTerminateProcess(NtCurrentProcess(), Status); } /* EOF */