X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=base%2Fsetup%2Fusetup%2Fusetup.c;h=f16d6512b739bcf886a1f7cc1aed7a660f7bed86;hp=102db35f6d6e7b02c519be91f8da7be7c1442b96;hb=073c09e491f1003b07c10abfb5e209f0c5e122f5;hpb=e5c0bfacf1374abf34abbaf75047149a6252ca5e diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 102db35f6d6..f16d6512b73 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -21,7 +21,7 @@ * PROJECT: ReactOS text-mode setup * FILE: base/setup/usetup/usetup.c * PURPOSE: Text-mode setup - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * Hervé Poussineau (hpoussin@reactos.org) */ @@ -32,79 +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; -PPARTENTRY TempPartition = NULL; -FORMATMACHINESTATE FormatState = Start; - - -/* 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 *****/ + +PCWSTR SelectedLanguageId; +static WCHAR DefaultLanguage[20]; // Copy of string inside LanguageList +static WCHAR DefaultKBLayout[20]; // Copy of string inside KeyboardList -static WCHAR DestinationDriveLetter; // FIXME: Is it really useful?? +static BOOLEAN RepairUpdateFlag = FALSE; -static HINF SetupInf; +static HANDLE hPnpThread = NULL; -static HSPFILEQ SetupFileQueue = 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 ****************************************************************/ @@ -136,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, @@ -145,7 +108,7 @@ DrawBox(IN SHORT xLeft, coPos, &Written); - /* draw upper edge */ + /* Draw upper edge */ coPos.X = xLeft + 1; coPos.Y = yTop; FillConsoleOutputCharacterA(StdOutput, @@ -154,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, @@ -188,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, @@ -197,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, @@ -206,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, @@ -261,7 +224,7 @@ PopupError(PCCH Text, if (Length > MaxLength) MaxLength = Length; - if (LastLine != FALSE) + if (LastLine) break; pnext = p + 1; @@ -327,7 +290,7 @@ PopupError(PCCH Text, &Written); } - if (LastLine != FALSE) + if (LastLine) break; coPos.Y++; @@ -417,212 +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; - - CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2, SourcePath.Buffer, L"\\unattend.inf"); - - if (DoesFileExist(NULL, UnattendInfPath) == FALSE) - { - DPRINT("Does not exist: %S\n", UnattendInfPath); - return; - } - - /* 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 = (LONG)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); } } @@ -630,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. @@ -643,37 +471,40 @@ static PAGE_NUMBER LanguagePage(PINPUT_RECORD Ir) { GENERIC_LIST_UI ListUi; - PWCHAR NewLanguageId; + 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; } - InitGenericListUi(&ListUi, LanguageList); + InitGenericListUi(&ListUi, USetupData.LanguageList, GetSettingDescription); DrawGenericList(&ListUi, - 2, - 18, + 2, 18, xScreen - 3, yScreen - 3); @@ -712,16 +543,19 @@ LanguagePage(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; else RedrawGenericList(&ListUi); } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { - SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList)); + ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1); - LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); + SelectedLanguageId = + ((PGENENTRY)GetListEntryData(GetCurrentListEntry(USetupData.LanguageList)))->Id; + + USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF); if (wcscmp(SelectedLanguageId, DefaultLanguage)) { @@ -731,7 +565,7 @@ 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)) { @@ -742,9 +576,12 @@ LanguagePage(PINPUT_RECORD Ir) if (RefreshPage) { - NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList)); + ASSERT(GetNumberOfListEntries(USetupData.LanguageList) >= 1); + + NewLanguageId = + ((PGENENTRY)GetListEntryData(GetCurrentListEntry(USetupData.LanguageList)))->Id; - if (SelectedLanguageId != NewLanguageId) + if (wcscmp(SelectedLanguageId, NewLanguageId)) { /* Clear the language page */ MUIClearPage(LANGUAGE_PAGE); @@ -762,7 +599,7 @@ LanguagePage(PINPUT_RECORD Ir) } } - return INTRO_PAGE; + return WELCOME_PAGE; } @@ -776,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. @@ -792,135 +629,71 @@ LanguagePage(PINPUT_RECORD Ir) static PAGE_NUMBER SetupStartPage(PINPUT_RECORD Ir) { - NTSTATUS Status; - WCHAR FileNameBuffer[MAX_PATH]; - INFCONTEXT Context; - PWCHAR Value; - UINT ErrorLine; + ULONG Error; PGENERIC_LIST_ENTRY ListEntry; - INT IntValue; + PCWSTR LocaleId; CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - /* 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. */ - CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2, SourcePath.Buffer, L"\\txtsetup.sif"); - SetupInf = SetupOpenInfFileW(FileNameBuffer, - NULL, - INF_STYLE_WIN4, - LanguageId, - &ErrorLine); - - if (SetupInf == INVALID_HANDLE_VALUE) + /* Initialize Setup, phase 1 */ + Error = InitializeSetup(&USetupData, 1); + if (Error != ERROR_SUCCESS) { - MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); + MUIDisplayError(Error, 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)) - { - MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER); - return QUIT_PAGE; - } - - RequiredPartitionDiskSpace = (ULONG)IntValue; - /* Start the PnP thread */ - if (hPnpThread != INVALID_HANDLE_VALUE) + 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); + /* 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); + + USetupData.LayoutList = CreateKeyboardLayoutList(USetupData.SetupInf, SelectedLanguageId, DefaultKBLayout); /* first we hack LanguageList */ - ListEntry = GetFirstListEntry(LanguageList); - while (ListEntry != NULL) + 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(); @@ -933,11 +706,12 @@ SetupStartPage(PINPUT_RECORD Ir) /* - * Displays the IntroPage. + * Displays the WelcomePage. * * Next pages: * InstallIntroPage (default) * RepairIntroPage + * RecoveryPage * LicensePage * QuitPage * @@ -945,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) { @@ -956,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; @@ -967,7 +741,7 @@ 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') /* L */ { @@ -975,7 +749,7 @@ IntroPage(PINPUT_RECORD Ir) } } - return INTRO_PAGE; + return WELCOME_PAGE; } @@ -983,7 +757,7 @@ IntroPage(PINPUT_RECORD Ir) * Displays the License page. * * Next page: - * IntroPage (default) + * WelcomePage (default) * * RETURNS * Number of the next page. @@ -999,7 +773,7 @@ LicensePage(PINPUT_RECORD Ir) if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { - return INTRO_PAGE; + return WELCOME_PAGE; } } @@ -1044,13 +818,148 @@ 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; } } return REPAIR_INTRO_PAGE; } +/* + * Displays the UpgradeRepairPage. + * + * Next pages: + * RebootPage (default) + * InstallIntroPage + * RecoveryPage + * WelcomePage + * + * RETURNS + * Number of the next page. + */ +static PAGE_NUMBER +UpgradeRepairPage(PINPUT_RECORD Ir) +{ + GENERIC_LIST_UI ListUi; + +/*** HACK!! ***/ + if (PartitionList == NULL) + { + 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; + } +/**************/ + + 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) + { + 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) + { + 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; + + // return INSTALL_INTRO_PAGE; + return DEVICE_SETTINGS_PAGE; + // return SCSI_CONTROLLER_PAGE; + } + } + } + else + { + // 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)); + + DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n", + CurrentInstallation->InstallationName, CurrentInstallation->DiskNumber, CurrentInstallation->PartitionNumber); + + 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); + } + } + } + + return UPGRADE_REPAIR_PAGE; +} + + /* * Displays the InstallIntroPage. * @@ -1066,18 +975,25 @@ RepairIntroPage(PINPUT_RECORD Ir) static PAGE_NUMBER InstallIntroPage(PINPUT_RECORD Ir) { - MUIDisplayPage(INSTALL_INTRO_PAGE); - if (RepairUpdateFlag) { - //return SELECT_PARTITION_PAGE; +#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) { @@ -1086,15 +1002,14 @@ InstallIntroPage(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 */ { - return DEVICE_SETTINGS_PAGE; - // return SCSI_CONTROLLER_PAGE; + return UPGRADE_REPAIR_PAGE; } } @@ -1106,24 +1021,25 @@ InstallIntroPage(PINPUT_RECORD Ir) static PAGE_NUMBER ScsiControllerPage(PINPUT_RECORD Ir) { - SetTextXY(6, 8, "Setup detected the following mass storage devices:"); + // MUIDisplayPage(SCSI_CONTROLLER_PAGE); + + CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:"); /* FIXME: print loaded mass storage driver descriptions */ #if 0 - SetTextXY(8, 10, "TEST device"); + CONSOLE_SetTextXY(8, 10, "TEST device"); #endif - - SetStatusText(" ENTER = Continue F3 = Quit"); + CONSOLE_SetStatusText(" ENTER = Continue F3 = Quit"); while (TRUE) { - ConInKey(Ir); + 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; @@ -1136,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 @@ -1152,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. @@ -1164,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; @@ -1178,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; @@ -1189,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; @@ -1200,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); @@ -1211,20 +1158,20 @@ DeviceSettingsPage(PINPUT_RECORD Ir) } } - MUIDisplayPage(DEVICE_SETTINGS_PAGE); + if (RepairUpdateFlag) + return SELECT_PARTITION_PAGE; + // if (IsUnattendedSetup) + // return SELECT_PARTITION_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)))); + MUIDisplayPage(DEVICE_SETTINGS_PAGE); - CONSOLE_InvertTextXY(24, Line, 48, 1); + DrawGenericListCurrentItem(USetupData.ComputerList, GetSettingDescription, 25, 11); + DrawGenericListCurrentItem(USetupData.DisplayList , GetSettingDescription, 25, 12); + DrawGenericListCurrentItem(USetupData.KeyboardList, GetSettingDescription, 25, 13); + DrawGenericListCurrentItem(USetupData.LayoutList , GetSettingDescription, 25, 14); - if (RepairUpdateFlag) - { - return SELECT_PARTITION_PAGE; - } + CONSOLE_InvertTextXY(24, Line, 48, 1); while (TRUE) { @@ -1261,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; @@ -1325,7 +1272,7 @@ HandleGenericList(PGENERIC_LIST_UI 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; else RedrawGenericList(ListUi); @@ -1333,7 +1280,7 @@ HandleGenericList(PGENERIC_LIST_UI ListUi, else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ { - RestoreGenericListState(ListUi->List); + RestoreGenericListUiState(ListUi); return nextPage; // Use some "prevPage;" instead? } else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ @@ -1365,15 +1312,12 @@ ComputerSettingsPage(PINPUT_RECORD Ir) GENERIC_LIST_UI ListUi; MUIDisplayPage(COMPUTER_SETTINGS_PAGE); - InitGenericListUi(&ListUi, ComputerList); + InitGenericListUi(&ListUi, USetupData.ComputerList, GetSettingDescription); DrawGenericList(&ListUi, - 2, - 18, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(ComputerList); - return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1394,15 +1338,12 @@ DisplaySettingsPage(PINPUT_RECORD Ir) GENERIC_LIST_UI ListUi; MUIDisplayPage(DISPLAY_SETTINGS_PAGE); - InitGenericListUi(&ListUi, DisplayList); + InitGenericListUi(&ListUi, USetupData.DisplayList, GetSettingDescription); DrawGenericList(&ListUi, - 2, - 18, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(DisplayList); - return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1423,15 +1364,12 @@ KeyboardSettingsPage(PINPUT_RECORD Ir) GENERIC_LIST_UI ListUi; MUIDisplayPage(KEYBOARD_SETTINGS_PAGE); - InitGenericListUi(&ListUi, KeyboardList); + InitGenericListUi(&ListUi, USetupData.KeyboardList, GetSettingDescription); DrawGenericList(&ListUi, - 2, - 18, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(KeyboardList); - return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1452,15 +1390,12 @@ LayoutSettingsPage(PINPUT_RECORD Ir) GENERIC_LIST_UI ListUi; MUIDisplayPage(LAYOUT_SETTINGS_PAGE); - InitGenericListUi(&ListUi, LayoutList); + InitGenericListUi(&ListUi, USetupData.LayoutList, GetSettingDescription); DrawGenericList(&ListUi, - 2, - 18, + 2, 18, xScreen - 3, yScreen - 3); - SaveGenericListState(LayoutList); - return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir); } @@ -1471,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 @@ -1500,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 @@ -1512,8 +1446,6 @@ SelectPartitionPage(PINPUT_RECORD Ir) PARTLIST_UI ListUi; ULONG Error; - MUIDisplayPage(SELECT_PARTITION_PAGE); - if (PartitionList == NULL) { PartitionList = CreatePartitionList(); @@ -1533,6 +1465,22 @@ SelectPartitionPage(PINPUT_RECORD Ir) 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; + } + + MUIDisplayPage(SELECT_PARTITION_PAGE); + InitPartitionListUi(&ListUi, PartitionList, 2, 23, @@ -1542,9 +1490,11 @@ SelectPartitionPage(PINPUT_RECORD Ir) if (IsUnattendedSetup) { - if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, UnattendDestinationPartitionNumber)) + if (!SelectPartition(PartitionList, + USetupData.DestinationDiskNumber, + USetupData.DestinationPartitionNumber)) { - if (AutoPartition) + if (USetupData.AutoPartition) { if (PartitionList->CurrentPartition->LogicalPartition) { @@ -1563,12 +1513,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; } } @@ -1580,12 +1528,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; } } @@ -1632,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; @@ -1676,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 */ @@ -1714,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) @@ -1728,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) { @@ -1977,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; @@ -1995,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)); @@ -2028,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; @@ -2036,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; } @@ -2072,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) @@ -2134,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; @@ -2152,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)); @@ -2185,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; @@ -2193,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; } @@ -2229,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) @@ -2290,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; @@ -2308,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)); @@ -2341,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; @@ -2349,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; } @@ -2385,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) @@ -2428,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; @@ -2486,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); } @@ -2508,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, @@ -2518,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, @@ -2527,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; @@ -2545,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) @@ -2573,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; @@ -2599,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 @@ -2639,6 +2613,13 @@ SelectFileSystemPage(PINPUT_RECORD Ir) 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; } @@ -2727,27 +2708,27 @@ SelectFileSystemPage(PINPUT_RECORD Ir) /* 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 */ 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); } @@ -2756,7 +2737,9 @@ SelectFileSystemPage(PINPUT_RECORD Ir) PartTypeString, ARRAYSIZE(PartTypeString)); - if (PartEntry->AutoCreate != FALSE) + MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE); + + if (PartEntry->AutoCreate) { CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION)); @@ -2768,20 +2751,21 @@ 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 (FormatState) { @@ -2811,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, @@ -2821,25 +2805,24 @@ 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 */ @@ -2851,8 +2834,6 @@ SelectFileSystemPage(PINPUT_RECORD Ir) } } - DrawFileSystemList(FileSystemList); - if (RepairUpdateFlag) { return CHECK_FILE_SYSTEM_PAGE; @@ -2861,7 +2842,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir) if (IsUnattendedSetup) { - if (UnattendFormatPartition) + if (USetupData.FormatPartition) { /* * We use whatever currently selected file system we have @@ -2876,6 +2857,8 @@ SelectFileSystemPage(PINPUT_RECORD Ir) return CHECK_FILE_SYSTEM_PAGE; } + DrawFileSystemList(FileSystemList); + while (TRUE) { CONSOLE_ConInKey(Ir); @@ -2883,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; @@ -2929,7 +2912,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir) * * SIDEEFFECTS * Sets PartitionList->CurrentPartition->FormatState - * Sets DestinationRootPath + * Sets USetupData.DestinationRootPath * * RETURNS * Number of the next page. @@ -2937,12 +2920,13 @@ SelectFileSystemPage(PINPUT_RECORD Ir) static PAGE_NUMBER FormatPartitionPage(PINPUT_RECORD Ir) { - UNICODE_STRING PartitionRootPath; - WCHAR PathBuffer[MAX_PATH]; + NTSTATUS Status; PDISKENTRY DiskEntry; PPARTENTRY PartEntry; PFILE_SYSTEM_ITEM SelectedFileSystem; - NTSTATUS Status; + UNICODE_STRING PartitionRootPath; + WCHAR PathBuffer[MAX_PATH]; + CHAR Buffer[MAX_PATH]; #ifndef NDEBUG ULONG Line; @@ -2975,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; @@ -3026,12 +3010,11 @@ 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); /* Format the partition */ @@ -3039,7 +3022,38 @@ FormatPartitionPage(PINPUT_RECORD Ir) { Status = FormatPartition(&PartitionRootPath, SelectedFileSystem); - if (!NT_SUCCESS(Status)) + 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); @@ -3080,13 +3094,13 @@ FormatPartitionPage(PINPUT_RECORD Ir) static PAGE_NUMBER CheckFileSystemPage(PINPUT_RECORD Ir) { + 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) { @@ -3100,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); @@ -3122,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" @@ -3154,64 +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; + + 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; - /* 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); - CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2, - DestinationRootPath.Buffer, InstallDir); - RtlCreateUnicodeString(&DestinationPath, PathBuffer); - - /* Create 'DestinationArcPath' */ - RtlFreeUnicodeString(&DestinationArcPath); - swprintf(PathBuffer, - L"multi(0)disk(0)rdisk(%lu)partition(%lu)", - DiskEntry->BiosDiskNumber, - PartEntry->PartitionNumber); - ConcatPaths(PathBuffer, ARRAYSIZE(PathBuffer), 1, InstallDir); - RtlCreateUnicodeString(&DestinationArcPath, PathBuffer); + /* 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; } @@ -3219,7 +3254,7 @@ BuildInstallPaths(PWCHAR InstallDir, * Displays the InstallDirectoryPage. * * Next pages: - * PrepareCopyPage (As the direct result of InstallDirectoryPage1) + * PrepareCopyPage * QuitPage * * RETURNS @@ -3230,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); @@ -3252,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) { @@ -3285,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); @@ -3354,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 */ @@ -3399,343 +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] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL)) - { - /* 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 */ - CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 2, - SourceRootDir.Buffer, DirKeyValue); - } - - /* Remove trailing backslash */ - Length = wcslen(CompleteOrigDirName); - if ((Length > 0) && (CompleteOrigDirName[Length - 1] == L'\\')) - { - CompleteOrigDirName[Length - 1] = UNICODE_NULL; - } - - 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 '\' . - */ - - /* Get destination path */ - wcscpy(PathBuffer, DestinationPath.Buffer); - - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) - { - PathBuffer[Length - 1] = UNICODE_NULL; - } - - /* 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); - } + INPUT_RECORD Ir; + va_list arg_ptr; - return FALSE; - } + va_start(arg_ptr, pSetupData); - /* Enumerate the directory values and create the subdirectories */ - do + if (pSetupData->LastErrorNumber >= ERROR_SUCCESS && + pSetupData->LastErrorNumber < ERROR_LAST_ERROR_CODE) { - if (!INF_GetData(&DirContext, NULL, &DirKeyValue)) - { - DPRINT1("break\n"); - break; - } - - if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL)) - { - /* 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); - - CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2, - DestinationRootPath.Buffer, DirKeyValue); - - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) - { - PathBuffer[Length - 1] = UNICODE_NULL; - } - - 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); - - CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2, - DestinationPath.Buffer, DirKeyValue); - - /* Remove trailing backslash */ - Length = wcslen(PathBuffer); - if ((Length > 0) && (PathBuffer[Length - 1] == L'\\')) - { - PathBuffer[Length - 1] = UNICODE_NULL; - } - - 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)); + // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber... + MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr); + } - return TRUE; + va_end(arg_ptr); } - /* * Displays the PrepareCopyPage. * @@ -3744,8 +3498,7 @@ PrepareCopyPageInfFile(HINF InfFile, * QuitPage * * SIDEEFFECTS - * Inits SetupFileQueue - * Calls PrepareCopyPageInfFile + * Calls PrepareFileCopy * * RETURNS * Number of the next page. @@ -3753,98 +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; - - CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2, - SourcePath.Buffer, 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) { @@ -3871,7 +3556,6 @@ SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext, ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages); } - static UINT CALLBACK FileCopyCallback(PVOID Context, @@ -3879,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 */ @@ -3908,9 +3658,10 @@ FileCopyCallback(PVOID Context, ProgressNextStep(CopyContext->ProgressBar); SetupUpdateMemoryInfo(CopyContext, FALSE); break; + } } - return 0; + return FILEOP_DOIT; } @@ -3921,8 +3672,7 @@ FileCopyCallback(PVOID Context, * RegistryPage(At once) * * SIDEEFFECTS - * Calls SetupCommitFileQueueW - * Calls SetupCloseFileQueue + * Calls DoFileCopy * * RETURNS * Number of the next page. @@ -3931,13 +3681,11 @@ 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; @@ -3952,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, @@ -3966,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. * @@ -4012,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. @@ -4024,140 +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; } @@ -4173,8 +3833,7 @@ RegistryPage(PINPUT_RECORD Ir) * QuitPage * * SIDEEFFECTS - * Calls SetInstallPathValue - * Calls NtInitializeRegistry + * Calls RegInitializeRegistry * Calls ImportRegistryFile * Calls SetDefaultPagefile * Calls SetMountedDeviceValues @@ -4192,28 +3851,30 @@ BootLoaderPage(PINPUT_RECORD Ir) CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT)); - RtlFreeUnicodeString(&SystemRootPath); - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - PartitionList->SystemPartition->DiskEntry->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"); @@ -4225,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) @@ -4241,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"); @@ -4256,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); @@ -4280,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); } @@ -4294,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; @@ -4314,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; } @@ -4366,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 (DoesPathExist(NULL, L"\\Device\\Floppy0\\") == 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; } @@ -4410,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; } @@ -4438,7 +4130,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir) * * SIDEEFFECTS * Calls InstallVBRToPartition() - * CallsInstallMbrBootCodeToDisk() + * Calls InstallMbrBootCodeToDisk() * * RETURNS * Number of the next page. @@ -4446,55 +4138,33 @@ 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->SystemPartition->DiskEntry->DiskNumber); - - CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, SourceRootPath.Buffer, L"\\loader\\dosmbr.bin"); - - if (IsThereAValidBootSector(DestinationDevicePathBuffer)) - { - /* Save current MBR */ - CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath.Buffer, L"\\mbr.old"); - - DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath); - Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR)); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); - // Don't care if we succeeded or not saving the old MBR, just go ahead. - } - } - - DPRINT1("Install MBR bootcode: %S ==> %S\n", - SourceMbrPathBuffer, DestinationDevicePathBuffer); - Status = InstallMbrBootCodeToDisk(SourceMbrPathBuffer, + 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); + DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status); + MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER, L"MBR"); return QUIT_PAGE; } @@ -4548,7 +4218,7 @@ ProgressTimeOutStringHandler( (AlwaysUpdate || (Bar->Progress != OldProgress))) { RtlStringCchPrintfA(Buffer, cchBufferSize, - Bar->ProgressFormatText, Bar->Progress); + Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1); return TRUE; } @@ -4578,9 +4248,9 @@ ProgressCountdown( IN LONG TimeOut) { NTSTATUS Status; - ULONG StartTime; + ULONG StartTime, BarWidth, TimerDiv; LONG TimeElapsed; - LONG TimerValue = TimeOut, OldTimerValue; + LONG TimerValue, OldTimerValue; LARGE_INTEGER Timeout; PPROGRESSBAR ProgressBar; BOOLEAN RefreshProgress = TRUE; @@ -4598,14 +4268,20 @@ ProgressCountdown( 24, TRUE, FOREGROUND_RED | BACKGROUND_BLUE, - TimerValue, + 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) { @@ -4617,11 +4293,11 @@ ProgressCountdown( * elapsed if something slowed down. */ TimeElapsed = NtGetTickCount() - StartTime; - if (TimeElapsed >= 1000) + if (TimeElapsed >= TimerDiv) { - /* Increase StartTime by steps of 1 second */ - TimeElapsed /= 1000; - StartTime += (1000 * TimeElapsed); + /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */ + TimeElapsed /= TimerDiv; + StartTime += (TimerDiv * TimeElapsed); if (TimeElapsed <= TimerValue) TimerValue -= TimeElapsed; @@ -4651,10 +4327,10 @@ ProgressCountdown( /* Wait a maximum of 1 second for input events */ TimeElapsed = NtGetTickCount() - StartTime; - if (TimeElapsed < 1000) + if (TimeElapsed < TimerDiv) { /* Convert the time to NT Format */ - Timeout.QuadPart = (1000 - TimeElapsed) * -10000LL; + Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL; Status = NtWaitForSingleObject(StdInput, FALSE, &Timeout); } else @@ -4708,12 +4384,20 @@ QuitPage(PINPUT_RECORD Ir) { MUIDisplayPage(QUIT_PAGE); + /* Destroy the NTOS installations list */ + if (NtOsInstallsList != NULL) + { + DestroyGenericList(NtOsInstallsList, TRUE); + NtOsInstallsList = NULL; + } + /* Destroy the partition list */ if (PartitionList != NULL) { DestroyPartitionList(PartitionList); PartitionList = NULL; } + TempPartition = NULL; FormatState = Start; @@ -4724,41 +4408,6 @@ QuitPage(PINPUT_RECORD Ir) FileSystemList = NULL; } - /* Destroy the computer settings list */ - if (ComputerList != NULL) - { - DestroyGenericList(ComputerList, TRUE); - ComputerList = NULL; - } - - /* Destroy the display settings list */ - if (DisplayList != NULL) - { - DestroyGenericList(DisplayList, TRUE); - DisplayList = NULL; - } - - /* Destroy the keyboard settings list */ - if (KeyboardList != NULL) - { - DestroyGenericList(KeyboardList, TRUE); - KeyboardList = NULL; - } - - /* Destroy the keyboard layout list */ - if (LayoutList != NULL) - { - DestroyGenericList(LayoutList, TRUE); - LayoutList = NULL; - } - - /* Destroy the languages list */ - if (LanguageList != NULL) - { - DestroyGenericList(LanguageList, FALSE); - LanguageList = NULL; - } - CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2)); /* Wait for maximum 15 seconds or an ENTER key before quitting */ @@ -4817,16 +4466,20 @@ 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(), @@ -4836,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()) { @@ -4848,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); @@ -5005,6 +4650,10 @@ RunUSetup(VOID) Page = RepairIntroPage(&Ir); break; + case UPGRADE_REPAIR_PAGE: + Page = UpgradeRepairPage(&Ir); + break; + case SUCCESS_PAGE: Page = SuccessPage(&Ir); break; @@ -5023,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 */