2003-01-17 13:18:15 +00:00
|
|
|
/*
|
2024-08-30 11:40:34 +00:00
|
|
|
* PROJECT: ReactOS Setup Library
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
* PURPOSE: Bootloader support functions
|
|
|
|
* COPYRIGHT: ...
|
|
|
|
* Copyright 2017-2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
2003-01-17 13:18:15 +00:00
|
|
|
*/
|
|
|
|
|
2017-08-26 11:42:32 +00:00
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
#include <ntddstor.h> // For STORAGE_DEVICE_NUMBER
|
|
|
|
|
2017-08-26 11:42:32 +00:00
|
|
|
#include "bldrsup.h"
|
2024-08-30 11:40:34 +00:00
|
|
|
#include "devutils.h"
|
2017-08-26 11:42:32 +00:00
|
|
|
#include "filesup.h"
|
|
|
|
#include "partlist.h"
|
2020-10-17 18:29:47 +00:00
|
|
|
#include "bootcode.h"
|
|
|
|
#include "fsutil.h"
|
2017-08-26 11:42:32 +00:00
|
|
|
|
2024-11-22 20:45:06 +00:00
|
|
|
#include "setuplib.h" // HACK for IsUnattendedSetup
|
2017-08-26 11:42:32 +00:00
|
|
|
|
|
|
|
#include "bootsup.h"
|
2003-01-17 13:18:15 +00:00
|
|
|
|
2010-06-07 21:38:49 +00:00
|
|
|
#define NDEBUG
|
2003-12-01 18:28:54 +00:00
|
|
|
#include <debug.h>
|
2003-01-17 13:18:15 +00:00
|
|
|
|
2017-05-31 02:03:10 +00:00
|
|
|
/*
|
|
|
|
* BIG FIXME!!
|
|
|
|
* ===========
|
|
|
|
*
|
2020-10-17 18:29:47 +00:00
|
|
|
* bootsup.c can deal with MBR code (actually it'll have at some point
|
|
|
|
* to share or give it to partlist.c, because when we'll support GPT disks,
|
|
|
|
* things will change a bit).
|
|
|
|
* And, bootsup.c can manage initializing / adding boot entries into NTLDR
|
|
|
|
* and FREELDR, and installing the latter, and saving the old MBR / boot
|
|
|
|
* sectors in files.
|
2017-05-31 02:03:10 +00:00
|
|
|
*/
|
2010-09-06 01:46:06 +00:00
|
|
|
|
2003-01-17 13:18:15 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2017-05-31 02:03:10 +00:00
|
|
|
static VOID
|
|
|
|
TrimTrailingPathSeparators_UStr(
|
|
|
|
IN OUT PUNICODE_STRING UnicodeString)
|
|
|
|
{
|
|
|
|
while (UnicodeString->Length >= sizeof(WCHAR) &&
|
|
|
|
UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
|
|
|
|
{
|
|
|
|
UnicodeString->Length -= sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
}
|
2003-01-17 13:18:15 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
static VOID
|
|
|
|
CreateFreeLoaderReactOSEntries(
|
|
|
|
IN PVOID BootStoreHandle,
|
|
|
|
IN PCWSTR ArcPath)
|
2003-01-17 13:18:15 +00:00
|
|
|
{
|
2017-06-08 17:30:23 +00:00
|
|
|
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
|
|
|
|
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
|
2017-06-08 02:43:51 +00:00
|
|
|
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
|
2017-06-08 17:30:23 +00:00
|
|
|
BOOT_STORE_OPTIONS BootOptions;
|
2017-06-08 02:43:51 +00:00
|
|
|
|
2017-06-08 17:30:23 +00:00
|
|
|
BootEntry->Version = FreeLdr;
|
2017-06-08 02:43:51 +00:00
|
|
|
BootEntry->BootFilePath = NULL;
|
|
|
|
|
|
|
|
BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
|
|
|
|
RtlCopyMemory(Options->Signature,
|
|
|
|
NTOS_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
|
|
|
|
|
|
|
|
Options->OsLoadPath = ArcPath;
|
|
|
|
|
|
|
|
/* ReactOS */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS\"";
|
2023-11-05 08:23:43 +00:00
|
|
|
Options->OsLoadOptions = L"/FASTDETECT";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* ReactOS_Debug */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
#ifdef _WINKD_
|
|
|
|
/* ReactOS_VBoxDebug */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
|
2020-06-14 11:49:22 +00:00
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (VBox Debug)\"";
|
2017-06-08 02:43:51 +00:00
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
|
2017-06-08 02:43:51 +00:00
|
|
|
#endif
|
|
|
|
#if DBG
|
|
|
|
#ifndef _WINKD_
|
|
|
|
/* ReactOS_KdSerial */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\"";
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
|
2017-06-08 02:43:51 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ReactOS_Screen */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* ReactOS_LogFile */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* ReactOS_Ram */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\"";
|
|
|
|
Options->OsLoadPath = L"ramdisk(0)\\ReactOS";
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* ReactOS_EMS */
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
|
|
|
|
BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\"";
|
|
|
|
Options->OsLoadPath = ArcPath;
|
|
|
|
Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
|
2017-06-08 02:43:51 +00:00
|
|
|
#endif
|
2003-01-17 13:18:15 +00:00
|
|
|
|
|
|
|
|
2021-09-07 20:25:34 +00:00
|
|
|
/* DefaultOS=ReactOS */
|
|
|
|
#if DBG && !defined(_WINKD_)
|
2011-07-20 17:54:28 +00:00
|
|
|
if (IsUnattendedSetup)
|
|
|
|
{
|
2024-05-04 10:47:13 +00:00
|
|
|
BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
else
|
2006-10-30 12:41:17 +00:00
|
|
|
#endif
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2021-09-07 20:25:34 +00:00
|
|
|
#if DBG
|
2024-05-04 10:47:13 +00:00
|
|
|
BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
|
2021-09-07 20:25:34 +00:00
|
|
|
#else
|
2024-05-04 10:47:13 +00:00
|
|
|
BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS");
|
2021-09-07 20:25:34 +00:00
|
|
|
#endif
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
2003-01-17 13:18:15 +00:00
|
|
|
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2011-07-20 17:54:28 +00:00
|
|
|
if (IsUnattendedSetup)
|
2006-10-30 12:41:17 +00:00
|
|
|
#endif
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Timeout=0 for unattended or non debug */
|
|
|
|
BootOptions.Timeout = 0;
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
2009-06-17 12:44:05 +00:00
|
|
|
#if DBG
|
2011-07-20 17:54:28 +00:00
|
|
|
else
|
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Timeout=10 */
|
|
|
|
BootOptions.Timeout = 10;
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
2006-04-25 01:31:00 +00:00
|
|
|
#endif
|
2003-01-17 13:18:15 +00:00
|
|
|
|
2024-05-04 10:47:13 +00:00
|
|
|
SetBootStoreOptions(BootStoreHandle, &BootOptions,
|
|
|
|
BOOT_OPTIONS_TIMEOUT | BOOT_OPTIONS_NEXT_BOOTENTRY_KEY);
|
2015-12-30 18:26:42 +00:00
|
|
|
}
|
2008-02-27 20:13:34 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
static NTSTATUS
|
2015-12-30 18:26:42 +00:00
|
|
|
CreateFreeLoaderIniForReactOS(
|
2017-06-08 02:43:51 +00:00
|
|
|
IN PCWSTR IniPath,
|
|
|
|
IN PCWSTR ArcPath)
|
2015-12-30 18:26:42 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BootStoreHandle;
|
2015-12-30 18:26:42 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Initialize the INI file and create the common FreeLdr sections */
|
2024-05-04 10:38:07 +00:00
|
|
|
Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
|
|
|
|
BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
|
2017-06-08 02:43:51 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2015-12-30 18:26:42 +00:00
|
|
|
|
|
|
|
/* Add the ReactOS entries */
|
2017-06-08 02:43:51 +00:00
|
|
|
CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
|
2015-12-30 18:26:42 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Close the INI file */
|
2017-06-08 17:30:23 +00:00
|
|
|
CloseBootStore(BootStoreHandle);
|
2015-12-30 18:26:42 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
static NTSTATUS
|
2016-02-02 01:55:05 +00:00
|
|
|
CreateFreeLoaderIniForReactOSAndBootSector(
|
2017-05-31 01:43:12 +00:00
|
|
|
IN PCWSTR IniPath,
|
|
|
|
IN PCWSTR ArcPath,
|
|
|
|
IN PCWSTR Section,
|
|
|
|
IN PCWSTR Description,
|
2024-04-23 15:02:06 +00:00
|
|
|
IN PCWSTR BootPath,
|
2017-05-31 01:43:12 +00:00
|
|
|
IN PCWSTR BootSector)
|
2003-01-30 14:41:45 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
NTSTATUS Status;
|
2017-06-08 02:43:51 +00:00
|
|
|
PVOID BootStoreHandle;
|
2024-04-23 15:02:06 +00:00
|
|
|
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOTSECTOR_OPTIONS)];
|
2017-06-08 17:30:23 +00:00
|
|
|
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
|
2024-04-23 15:02:06 +00:00
|
|
|
PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
|
|
|
|
WCHAR BootPathBuffer[MAX_PATH] = L"";
|
|
|
|
|
|
|
|
/* Since the BootPath given here is in NT format
|
|
|
|
* (not ARC), we need to hack-generate a mapping */
|
|
|
|
ULONG DiskNumber = 0, PartitionNumber = 0;
|
|
|
|
PCWSTR PathComponent = NULL;
|
|
|
|
|
|
|
|
/* From the NT path, compute the disk, partition and path components */
|
|
|
|
// NOTE: this function doesn't support stuff like \Device\FloppyX ...
|
|
|
|
if (NtPathToDiskPartComponents(BootPath, &DiskNumber, &PartitionNumber, &PathComponent))
|
|
|
|
{
|
|
|
|
DPRINT1("BootPath = '%S' points to disk #%d, partition #%d, path '%S'\n",
|
|
|
|
BootPath, DiskNumber, PartitionNumber, PathComponent);
|
|
|
|
|
|
|
|
/* HACK-build a possible ARC path:
|
|
|
|
* Hard disk path: multi(0)disk(0)rdisk(x)partition(y)[\path] */
|
|
|
|
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
|
|
|
|
L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
|
|
|
|
DiskNumber, PartitionNumber);
|
|
|
|
if (PathComponent && *PathComponent &&
|
|
|
|
(PathComponent[0] != L'\\' || PathComponent[1]))
|
|
|
|
{
|
|
|
|
RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
|
|
|
|
PathComponent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PCWSTR Path = BootPath;
|
|
|
|
|
|
|
|
if ((_wcsnicmp(Path, L"\\Device\\Floppy", 14) == 0) &&
|
|
|
|
(Path += 14) && iswdigit(*Path))
|
|
|
|
{
|
|
|
|
DiskNumber = wcstoul(Path, (PWSTR*)&PathComponent, 10);
|
|
|
|
if (PathComponent && *PathComponent && *PathComponent != L'\\')
|
|
|
|
PathComponent = NULL;
|
|
|
|
|
|
|
|
/* HACK-build a possible ARC path:
|
|
|
|
* Floppy disk path: multi(0)disk(0)fdisk(x)[\path] */
|
|
|
|
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
|
|
|
|
L"multi(0)disk(0)fdisk(%lu)", DiskNumber);
|
|
|
|
if (PathComponent && *PathComponent &&
|
|
|
|
(PathComponent[0] != L'\\' || PathComponent[1]))
|
|
|
|
{
|
|
|
|
RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
|
|
|
|
PathComponent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* HACK: Just keep the unresolved NT path and hope for the best... */
|
|
|
|
|
|
|
|
/* Remove any trailing backslash if needed */
|
|
|
|
UNICODE_STRING RootPartition;
|
|
|
|
RtlInitUnicodeString(&RootPartition, BootPath);
|
|
|
|
TrimTrailingPathSeparators_UStr(&RootPartition);
|
|
|
|
|
|
|
|
/* RootPartition is BootPath without counting any trailing
|
|
|
|
* path separator. Because of this, we need to copy the string
|
|
|
|
* in the buffer, instead of just using a pointer to it. */
|
|
|
|
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
|
|
|
|
L"%wZ", &RootPartition);
|
|
|
|
|
|
|
|
DPRINT1("Unhandled NT path '%S'\n", BootPath);
|
|
|
|
}
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Initialize the INI file and create the common FreeLdr sections */
|
2024-05-04 10:38:07 +00:00
|
|
|
Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
|
|
|
|
BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
|
2003-01-30 14:41:45 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
2003-01-30 14:41:45 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Add the ReactOS entries */
|
|
|
|
CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2017-06-08 17:30:23 +00:00
|
|
|
BootEntry->Version = FreeLdr;
|
2017-06-08 02:43:51 +00:00
|
|
|
BootEntry->BootFilePath = NULL;
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
BootEntry->OsOptionsLength = sizeof(BOOTSECTOR_OPTIONS);
|
2017-06-08 02:43:51 +00:00
|
|
|
RtlCopyMemory(Options->Signature,
|
2024-04-23 15:02:06 +00:00
|
|
|
BOOTSECTOR_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(BOOTSECTOR_OPTIONS, Signature));
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Options->BootPath = BootPathBuffer;
|
|
|
|
Options->FileName = BootSector;
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(Section);
|
|
|
|
BootEntry->FriendlyName = Description;
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Close the INI file */
|
2017-06-08 17:30:23 +00:00
|
|
|
CloseBootStore(BootStoreHandle);
|
2011-07-20 17:54:28 +00:00
|
|
|
return STATUS_SUCCESS;
|
2003-01-28 17:29:22 +00:00
|
|
|
}
|
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
//
|
|
|
|
// I think this function can be generalizable as:
|
|
|
|
// "find the corresponding 'ReactOS' boot entry in this loader config file
|
|
|
|
// (here abstraction comes there), and if none, add a new one".
|
|
|
|
//
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
typedef struct _ENUM_REACTOS_ENTRIES_DATA
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
BOOLEAN UseExistingEntry;
|
|
|
|
PCWSTR ArcPath;
|
|
|
|
WCHAR SectionName[80];
|
|
|
|
WCHAR OsName[80];
|
|
|
|
} ENUM_REACTOS_ENTRIES_DATA, *PENUM_REACTOS_ENTRIES_DATA;
|
|
|
|
|
|
|
|
// PENUM_BOOT_ENTRIES_ROUTINE
|
|
|
|
static NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
EnumerateReactOSEntries(
|
2017-06-08 17:30:23 +00:00
|
|
|
IN BOOT_STORE_TYPE Type,
|
|
|
|
IN PBOOT_STORE_ENTRY BootEntry,
|
2017-06-08 02:43:51 +00:00
|
|
|
IN PVOID Parameter OPTIONAL)
|
|
|
|
{
|
2017-12-23 19:17:38 +00:00
|
|
|
NTSTATUS Status;
|
2017-06-08 02:43:51 +00:00
|
|
|
PENUM_REACTOS_ENTRIES_DATA Data = (PENUM_REACTOS_ENTRIES_DATA)Parameter;
|
|
|
|
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
|
|
|
|
WCHAR SystemPath[MAX_PATH];
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* We have a boot entry */
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Check for supported boot type "Windows2003" */
|
|
|
|
if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
|
|
|
|
RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
|
|
|
|
NTOS_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) !=
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature))
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
/* This is not a ReactOS entry */
|
2018-10-28 22:33:29 +00:00
|
|
|
// DPRINT(" An installation '%S' of unsupported type '%S'\n",
|
|
|
|
// BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
|
|
|
|
DPRINT(" An installation '%S' of unsupported type %lu\n",
|
|
|
|
BootEntry->FriendlyName, BootEntry->OsOptionsLength);
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Continue the enumeration */
|
|
|
|
goto SkipThisEntry;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* BootType is Windows2003, now check OsLoadPath */
|
|
|
|
if (!Options->OsLoadPath || !*Options->OsLoadPath)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Certainly not a ReactOS installation */
|
|
|
|
DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
|
|
|
|
/* Continue the enumeration */
|
|
|
|
goto SkipThisEntry;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
2017-12-23 19:17:38 +00:00
|
|
|
if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
2017-12-23 19:17:38 +00:00
|
|
|
/* Not found, retry with a quoted path */
|
|
|
|
Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
|
|
|
|
if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This entry is a ReactOS entry, but the SystemRoot
|
|
|
|
* does not match the one we are looking for.
|
|
|
|
*/
|
|
|
|
/* Continue the enumeration */
|
|
|
|
goto SkipThisEntry;
|
|
|
|
}
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
|
|
|
|
BootEntry->FriendlyName, Options->OsLoadPath);
|
|
|
|
// DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
|
|
|
|
// BootEntry->FriendlyName, Options->OsLoadPath);
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2018-10-28 22:33:29 +00:00
|
|
|
DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
Data->UseExistingEntry = TRUE;
|
|
|
|
RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
|
|
|
|
|
|
|
|
/* We have found our entry, stop the enumeration now! */
|
|
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
|
|
|
|
|
|
SkipThisEntry:
|
|
|
|
Data->UseExistingEntry = FALSE;
|
|
|
|
if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
|
|
|
|
L"ReactOS_%lu", Data->i);
|
|
|
|
RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
|
|
|
|
L"\"ReactOS %lu\"", Data->i);
|
|
|
|
Data->i++;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
2017-06-08 02:43:51 +00:00
|
|
|
return STATUS_SUCCESS;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
NTSTATUS
|
2017-06-08 02:43:51 +00:00
|
|
|
UpdateFreeLoaderIni(
|
|
|
|
IN PCWSTR IniPath,
|
|
|
|
IN PCWSTR ArcPath)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2017-06-08 02:43:51 +00:00
|
|
|
PVOID BootStoreHandle;
|
|
|
|
ENUM_REACTOS_ENTRIES_DATA Data;
|
2017-06-08 17:30:23 +00:00
|
|
|
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
|
|
|
|
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
|
2017-06-08 02:43:51 +00:00
|
|
|
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
|
|
|
|
|
|
|
|
/* Open the INI file */
|
2024-05-04 10:38:07 +00:00
|
|
|
Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
|
|
|
|
BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
|
2017-06-08 02:43:51 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Find an existing usable or an unused section name */
|
|
|
|
Data.UseExistingEntry = TRUE;
|
|
|
|
Data.i = 1;
|
|
|
|
Data.ArcPath = ArcPath;
|
|
|
|
RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
|
|
|
|
RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
//
|
2017-06-08 17:30:23 +00:00
|
|
|
// FIXME: We temporarily use EnumerateBootStoreEntries, until
|
|
|
|
// both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
|
2017-06-08 02:43:51 +00:00
|
|
|
//
|
2017-06-08 17:30:23 +00:00
|
|
|
Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Create a new "ReactOS" entry if there is none already existing that suits us */
|
|
|
|
if (!Data.UseExistingEntry)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
// RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
|
|
|
|
// RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 17:30:23 +00:00
|
|
|
BootEntry->Version = FreeLdr;
|
2017-06-08 02:43:51 +00:00
|
|
|
BootEntry->BootFilePath = NULL;
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
|
|
|
|
RtlCopyMemory(Options->Signature,
|
|
|
|
NTOS_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
Options->OsLoadPath = ArcPath;
|
|
|
|
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
|
|
|
|
BootEntry->FriendlyName = Data.OsName;
|
|
|
|
Options->OsLoadOptions = NULL; // L"";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Close the INI file */
|
2017-06-08 17:30:23 +00:00
|
|
|
CloseBootStore(BootStoreHandle);
|
2017-06-08 02:43:51 +00:00
|
|
|
return STATUS_SUCCESS;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
UpdateBootIni(
|
2017-06-08 02:43:51 +00:00
|
|
|
IN PCWSTR IniPath,
|
|
|
|
IN PCWSTR EntryName, // ~= ArcPath
|
|
|
|
IN PCWSTR EntryValue)
|
2017-05-31 01:47:39 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2017-06-08 02:43:51 +00:00
|
|
|
PVOID BootStoreHandle;
|
|
|
|
ENUM_REACTOS_ENTRIES_DATA Data;
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
// NOTE: Technically it would be "BootSector"...
|
2017-06-08 17:30:23 +00:00
|
|
|
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
|
|
|
|
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
|
2017-06-08 02:43:51 +00:00
|
|
|
PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
|
2017-05-31 01:47:39 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Open the INI file */
|
2024-05-04 10:38:07 +00:00
|
|
|
Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr,
|
|
|
|
BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
|
2017-05-31 01:47:39 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Find an existing usable or an unused section name */
|
|
|
|
Data.UseExistingEntry = TRUE;
|
|
|
|
// Data.i = 1;
|
|
|
|
Data.ArcPath = EntryName;
|
|
|
|
// RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
|
|
|
|
RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
|
|
|
|
|
|
|
|
//
|
2017-06-08 17:30:23 +00:00
|
|
|
// FIXME: We temporarily use EnumerateBootStoreEntries, until
|
|
|
|
// both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
|
2017-06-08 02:43:51 +00:00
|
|
|
//
|
2017-06-08 17:30:23 +00:00
|
|
|
Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
|
2017-06-08 02:43:51 +00:00
|
|
|
|
|
|
|
/* If either the key was not found, or contains something else, add a new one */
|
|
|
|
if (!Data.UseExistingEntry /* ||
|
|
|
|
( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
|
|
|
|
{
|
2017-06-08 17:30:23 +00:00
|
|
|
BootEntry->Version = NtLdr;
|
2017-06-08 02:43:51 +00:00
|
|
|
BootEntry->BootFilePath = NULL;
|
|
|
|
|
|
|
|
BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
|
|
|
|
RtlCopyMemory(Options->Signature,
|
|
|
|
NTOS_OPTIONS_SIGNATURE,
|
|
|
|
RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
|
|
|
|
|
|
|
|
Options->OsLoadPath = EntryName;
|
|
|
|
|
|
|
|
// BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
|
|
|
|
// BootEntry->FriendlyName = Data.OsName;
|
|
|
|
BootEntry->FriendlyName = EntryValue;
|
|
|
|
Options->OsLoadOptions = NULL; // L"";
|
2017-06-08 17:30:23 +00:00
|
|
|
AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
|
2017-06-08 02:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Close the INI file */
|
2017-06-08 17:30:23 +00:00
|
|
|
CloseBootStore(BootStoreHandle);
|
2017-06-08 02:43:51 +00:00
|
|
|
return STATUS_SUCCESS; // Status;
|
2017-05-31 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-26 11:42:32 +00:00
|
|
|
static
|
2016-02-02 01:55:05 +00:00
|
|
|
BOOLEAN
|
2017-05-31 02:03:10 +00:00
|
|
|
IsThereAValidBootSector(
|
|
|
|
IN PCWSTR RootPath)
|
2016-02-02 01:55:05 +00:00
|
|
|
{
|
|
|
|
/*
|
2017-05-09 15:31:53 +00:00
|
|
|
* We first demand that the bootsector has a valid signature at its end.
|
|
|
|
* We then check the first 3 bytes (as a ULONG) of the bootsector for a
|
|
|
|
* potential "valid" instruction (the BIOS starts execution of the bootsector
|
|
|
|
* at its beginning). Currently this criterium is that this ULONG must be
|
|
|
|
* non-zero. If both these tests pass, then the bootsector is valid; otherwise
|
|
|
|
* it is invalid and certainly needs to be overwritten.
|
2016-02-02 01:55:05 +00:00
|
|
|
*/
|
2017-05-31 02:03:10 +00:00
|
|
|
|
2017-05-09 15:31:53 +00:00
|
|
|
BOOLEAN IsValid = FALSE;
|
2016-02-02 01:55:05 +00:00
|
|
|
NTSTATUS Status;
|
2017-05-31 02:03:10 +00:00
|
|
|
UNICODE_STRING RootPartition;
|
2020-10-17 18:29:47 +00:00
|
|
|
BOOTCODE BootSector = {0};
|
2016-02-02 01:55:05 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Allocate and read the root partition bootsector.
|
|
|
|
* Remove any trailing backslash if needed. */
|
2017-05-31 02:03:10 +00:00
|
|
|
RtlInitUnicodeString(&RootPartition, RootPath);
|
|
|
|
TrimTrailingPathSeparators_UStr(&RootPartition);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = ReadBootCodeFromFile(&BootSector, &RootPartition, SECTORSIZE);
|
2017-05-09 15:31:53 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2020-10-17 18:29:47 +00:00
|
|
|
return FALSE;
|
2016-02-02 01:55:05 +00:00
|
|
|
|
2017-12-24 21:37:19 +00:00
|
|
|
/* Check for the existence of the bootsector signature */
|
2020-10-17 18:29:47 +00:00
|
|
|
IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
|
2017-12-24 21:37:19 +00:00
|
|
|
if (IsValid)
|
|
|
|
{
|
|
|
|
/* Check for the first instruction encoded on three bytes */
|
2020-10-17 18:29:47 +00:00
|
|
|
IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
|
2017-12-24 21:37:19 +00:00
|
|
|
}
|
2017-05-09 15:31:53 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Free the bootsector and return */
|
|
|
|
FreeBootCode(&BootSector);
|
2017-12-24 21:37:19 +00:00
|
|
|
return IsValid;
|
2016-02-02 01:55:05 +00:00
|
|
|
}
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2017-08-26 11:42:32 +00:00
|
|
|
static
|
2003-04-05 15:36:34 +00:00
|
|
|
NTSTATUS
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
SaveBootSector(
|
2017-05-31 02:03:10 +00:00
|
|
|
IN PCWSTR RootPath,
|
|
|
|
IN PCWSTR DstPath,
|
|
|
|
IN ULONG Length)
|
2003-04-05 15:36:34 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING Name;
|
2010-09-06 01:46:06 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
HANDLE FileHandle;
|
2020-10-17 18:29:47 +00:00
|
|
|
// LARGE_INTEGER FileOffset;
|
|
|
|
BOOTCODE BootSector = {0};
|
2003-04-05 15:36:34 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Allocate and read the root partition bootsector.
|
|
|
|
* Remove any trailing backslash if needed. */
|
2011-07-20 17:54:28 +00:00
|
|
|
RtlInitUnicodeString(&Name, RootPath);
|
2017-05-31 02:03:10 +00:00
|
|
|
TrimTrailingPathSeparators_UStr(&Name);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = ReadBootCodeFromFile(&BootSector, &Name, Length);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Write the bootsector to DstPath */
|
2011-07-20 17:54:28 +00:00
|
|
|
RtlInitUnicodeString(&Name, DstPath);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
2017-12-23 19:17:38 +00:00
|
|
|
OBJ_CASE_INSENSITIVE,
|
2011-07-20 17:54:28 +00:00
|
|
|
NULL,
|
|
|
|
NULL);
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2011-07-20 17:54:28 +00:00
|
|
|
Status = NtCreateFile(&FileHandle,
|
2013-07-19 14:03:46 +00:00
|
|
|
GENERIC_WRITE | SYNCHRONIZE,
|
2011-07-20 17:54:28 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
NULL,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
0,
|
|
|
|
FILE_SUPERSEDE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
|
|
|
|
NULL,
|
|
|
|
0);
|
2003-01-28 17:29:22 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
FreeBootCode(&BootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2011-07-20 17:54:28 +00:00
|
|
|
Status = NtWriteFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&IoStatusBlock,
|
2020-10-17 18:29:47 +00:00
|
|
|
BootSector.BootCode,
|
|
|
|
BootSector.Length,
|
2011-07-20 17:54:28 +00:00
|
|
|
NULL,
|
|
|
|
NULL);
|
2003-01-28 17:29:22 +00:00
|
|
|
NtClose(FileHandle);
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Free the bootsector and return */
|
|
|
|
FreeBootCode(&BootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
2003-01-28 17:29:22 +00:00
|
|
|
}
|
|
|
|
|
2017-08-26 11:42:32 +00:00
|
|
|
|
|
|
|
static
|
2003-01-28 17:29:22 +00:00
|
|
|
NTSTATUS
|
2020-10-17 18:29:47 +00:00
|
|
|
InstallBootCodeToDisk(
|
2017-05-31 02:03:10 +00:00
|
|
|
IN PCWSTR SrcPath,
|
2020-10-17 18:29:47 +00:00
|
|
|
IN PCWSTR RootPath,
|
|
|
|
IN PFS_INSTALL_BOOTCODE InstallBootCode)
|
2003-01-28 17:29:22 +00:00
|
|
|
{
|
2020-12-03 16:13:38 +00:00
|
|
|
NTSTATUS Status, LockStatus;
|
2016-02-02 01:55:05 +00:00
|
|
|
UNICODE_STRING Name;
|
2011-07-20 17:54:28 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2020-10-17 18:29:47 +00:00
|
|
|
HANDLE PartitionHandle;
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/*
|
|
|
|
* Open the root partition from which the bootcode (MBR, VBR) parameters
|
|
|
|
* will be obtained; this is also where we will write the updated bootcode.
|
|
|
|
* Remove any trailing backslash if needed.
|
|
|
|
*/
|
2017-05-31 02:03:10 +00:00
|
|
|
RtlInitUnicodeString(&Name, RootPath);
|
|
|
|
TrimTrailingPathSeparators_UStr(&Name);
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2011-07-20 17:54:28 +00:00
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = NtOpenFile(&PartitionHandle,
|
|
|
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
2011-07-20 17:54:28 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
2018-11-11 16:14:13 +00:00
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
2020-10-17 18:29:47 +00:00
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2003-01-28 17:29:22 +00:00
|
|
|
|
2020-12-03 16:13:38 +00:00
|
|
|
/* Lock the volume */
|
|
|
|
LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
|
|
|
|
if (!NT_SUCCESS(LockStatus))
|
|
|
|
{
|
|
|
|
DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
|
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Install the bootcode (MBR, VBR) */
|
|
|
|
Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-12-03 16:13:38 +00:00
|
|
|
/* dismount & Unlock the volume */
|
|
|
|
if (NT_SUCCESS(LockStatus))
|
|
|
|
{
|
|
|
|
LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
|
|
|
|
if (!NT_SUCCESS(LockStatus))
|
|
|
|
{
|
2021-02-05 13:10:15 +00:00
|
|
|
DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
|
2020-12-03 16:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
|
|
|
|
if (!NT_SUCCESS(LockStatus))
|
|
|
|
{
|
|
|
|
DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Close the partition */
|
|
|
|
NtClose(PartitionHandle);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
InstallBootCodeToFile(
|
|
|
|
IN PCWSTR SrcPath,
|
|
|
|
IN PCWSTR DstPath,
|
|
|
|
IN PCWSTR RootPath,
|
|
|
|
IN PFS_INSTALL_BOOTCODE InstallBootCode)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
HANDLE PartitionHandle, FileHandle;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open the root partition from which the bootcode (MBR, VBR)
|
|
|
|
* parameters will be obtained.
|
|
|
|
*
|
|
|
|
* FIXME? It might be possible that we need to also open it for writing
|
|
|
|
* access in case we really need to still write the second portion of
|
|
|
|
* the boot sector ????
|
|
|
|
*
|
|
|
|
* Remove any trailing backslash if needed.
|
|
|
|
*/
|
|
|
|
RtlInitUnicodeString(&Name, RootPath);
|
|
|
|
TrimTrailingPathSeparators_UStr(&Name);
|
2004-06-23 14:09:55 +00:00
|
|
|
|
2011-07-20 17:54:28 +00:00
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = NtOpenFile(&PartitionHandle,
|
2013-07-19 14:03:46 +00:00
|
|
|
GENERIC_READ | SYNCHRONIZE,
|
2011-07-20 17:54:28 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
2020-10-17 18:29:47 +00:00
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Open or create the file where the new bootsector will be saved */
|
|
|
|
RtlInitUnicodeString(&Name, DstPath);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtCreateFile(&FileHandle,
|
|
|
|
GENERIC_WRITE | SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
NULL,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
0,
|
|
|
|
FILE_SUPERSEDE, // FILE_OVERWRITE_IF
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
|
|
|
|
NULL,
|
|
|
|
0);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
|
|
|
|
NtClose(PartitionHandle);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Install the bootcode (MBR, VBR) */
|
|
|
|
Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Close the file and the partition */
|
|
|
|
NtClose(FileHandle);
|
|
|
|
NtClose(PartitionHandle);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
InstallMbrBootCode(
|
|
|
|
IN PCWSTR SrcPath, // MBR source file (on the installation medium)
|
|
|
|
IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information
|
|
|
|
IN HANDLE DiskHandle) // Disk holding the (old) MBR information
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
LARGE_INTEGER FileOffset;
|
|
|
|
BOOTCODE OrigBootSector = {0};
|
|
|
|
BOOTCODE NewBootSector = {0};
|
|
|
|
|
|
|
|
C_ASSERT(sizeof(PARTITION_SECTOR) == SECTORSIZE);
|
|
|
|
|
|
|
|
/* Allocate and read the current original MBR bootsector */
|
|
|
|
Status = ReadBootCodeByHandle(&OrigBootSector,
|
|
|
|
DiskHandle,
|
|
|
|
sizeof(PARTITION_SECTOR));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
/* Allocate and read the new bootsector from SrcPath */
|
|
|
|
RtlInitUnicodeString(&Name, SrcPath);
|
|
|
|
Status = ReadBootCodeFromFile(&NewBootSector,
|
|
|
|
&Name,
|
|
|
|
sizeof(PARTITION_SECTOR));
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
FreeBootCode(&OrigBootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/*
|
|
|
|
* Copy the disk signature, the reserved fields and
|
|
|
|
* the partition table from the old MBR to the new one.
|
|
|
|
*/
|
|
|
|
RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
|
|
|
|
&((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
|
|
|
|
sizeof(PARTITION_SECTOR) -
|
|
|
|
FIELD_OFFSET(PARTITION_SECTOR, Signature)
|
|
|
|
/* Length of partition table */);
|
|
|
|
|
|
|
|
/* Free the original bootsector */
|
|
|
|
FreeBootCode(&OrigBootSector);
|
|
|
|
|
|
|
|
/* Write the new bootsector to DstPath */
|
2017-05-31 01:47:39 +00:00
|
|
|
FileOffset.QuadPart = 0ULL;
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = NtWriteFile(DstPath,
|
2011-07-20 17:54:28 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&IoStatusBlock,
|
2020-10-17 18:29:47 +00:00
|
|
|
NewBootSector.BootCode,
|
|
|
|
NewBootSector.Length,
|
2017-05-31 01:47:39 +00:00
|
|
|
&FileOffset,
|
2011-07-20 17:54:28 +00:00
|
|
|
NULL);
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Free the new bootsector */
|
|
|
|
FreeBootCode(&NewBootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
static
|
2017-08-26 11:42:32 +00:00
|
|
|
NTSTATUS
|
|
|
|
InstallMbrBootCodeToDisk(
|
2024-08-30 11:40:34 +00:00
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCWSTR DestinationDevicePathBuffer)
|
2017-08-26 11:42:32 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
WCHAR SourceMbrPathBuffer[MAX_PATH];
|
|
|
|
WCHAR DstPath[MAX_PATH];
|
|
|
|
|
|
|
|
#if 0
|
2017-12-23 19:17:38 +00:00
|
|
|
/*
|
|
|
|
* The DestinationDevicePathBuffer parameter has been built with
|
|
|
|
* the following instruction by the caller; I'm not yet sure whether
|
|
|
|
* I actually want this function to build the path instead, hence
|
|
|
|
* I keep this code here but disabled for now...
|
|
|
|
*/
|
2017-08-26 11:42:32 +00:00
|
|
|
WCHAR DestinationDevicePathBuffer[MAX_PATH];
|
2017-09-03 20:05:11 +00:00
|
|
|
RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
|
|
|
|
L"\\Device\\Harddisk%d\\Partition0",
|
|
|
|
DiskNumber);
|
2017-08-26 11:42:32 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Install the MBR */
|
|
|
|
return InstallBootCodeToDisk(SourceMbrPathBuffer,
|
|
|
|
DestinationDevicePathBuffer,
|
|
|
|
InstallMbrBootCode);
|
2017-08-26 11:42:32 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 02:03:10 +00:00
|
|
|
|
2024-10-17 11:37:25 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
InstallBootloaderFiles(
|
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
WCHAR SrcPath[MAX_PATH];
|
|
|
|
WCHAR DstPath[MAX_PATH];
|
|
|
|
|
|
|
|
/* Copy FreeLoader to the system partition, always overwriting the older version */
|
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
|
|
|
|
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
|
|
|
|
|
|
|
|
DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
|
|
|
|
Status = SetupCopyFile(SrcPath, DstPath, FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
static
|
2011-07-20 17:54:28 +00:00
|
|
|
NTSTATUS
|
2020-10-17 18:29:47 +00:00
|
|
|
InstallFatBootcodeToPartition(
|
2024-08-30 11:40:34 +00:00
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath,
|
|
|
|
_In_ PCWSTR FileSystemName)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
NTSTATUS Status;
|
2020-10-17 18:29:47 +00:00
|
|
|
BOOLEAN DoesFreeLdrExist;
|
|
|
|
WCHAR SrcPath[MAX_PATH];
|
|
|
|
WCHAR DstPath[MAX_PATH];
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* FAT or FAT32 partition */
|
|
|
|
DPRINT("System path: '%wZ'\n", SystemRootPath);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2024-10-17 11:37:25 +00:00
|
|
|
/* Install the bootloader */
|
|
|
|
Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2024-10-17 11:37:25 +00:00
|
|
|
DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Prepare for possibly updating 'freeldr.ini' */
|
|
|
|
DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
|
|
|
|
if (DoesFreeLdrExist)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Update existing 'freeldr.ini' */
|
|
|
|
DPRINT1("Update existing 'freeldr.ini'\n");
|
|
|
|
Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Check for NT and other bootloaders */
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
// FIXME: Check for Vista+ bootloader!
|
|
|
|
/*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
|
|
|
|
/*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Search root directory for 'NTLDR' and 'BOOT.INI' */
|
|
|
|
DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
|
2016-02-02 01:55:05 +00:00
|
|
|
|
|
|
|
/* Create or update 'freeldr.ini' */
|
|
|
|
if (DoesFreeLdrExist == FALSE)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
|
|
|
/* Create new 'freeldr.ini' */
|
|
|
|
DPRINT1("Create new 'freeldr.ini'\n");
|
2017-06-08 02:43:51 +00:00
|
|
|
Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-04-18 09:21:51 +00:00
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Install new bootcode into a file */
|
2017-05-31 01:43:12 +00:00
|
|
|
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
|
2016-02-02 01:55:05 +00:00
|
|
|
|
2024-05-11 16:23:44 +00:00
|
|
|
if (_wcsicmp(FileSystemName, L"FAT32") == 0)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
|
|
|
/* Install FAT32 bootcode */
|
2017-05-23 22:30:54 +00:00
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
|
|
|
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = InstallBootCodeToFile(SrcPath, DstPath,
|
|
|
|
SystemRootPath->Buffer,
|
|
|
|
InstallFat32BootCode);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
2020-10-19 21:49:26 +00:00
|
|
|
else // if (wcsicmp(FileSystemName, L"FAT") == 0)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
|
|
|
/* Install FAT16 bootcode */
|
2017-05-23 22:30:54 +00:00
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
|
|
|
|
Status = InstallBootCodeToFile(SrcPath, DstPath,
|
|
|
|
SystemRootPath->Buffer,
|
|
|
|
InstallFat16BootCode);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update 'boot.ini' */
|
2018-08-28 10:45:03 +00:00
|
|
|
/* Windows' NTLDR loads an external bootsector file when the specified drive
|
|
|
|
letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
|
2017-06-08 02:43:51 +00:00
|
|
|
DPRINT1("Update 'boot.ini'\n");
|
|
|
|
Status = UpdateBootIni(SystemRootPath->Buffer,
|
2011-07-20 17:54:28 +00:00
|
|
|
L"C:\\bootsect.ros",
|
|
|
|
L"\"ReactOS\"");
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
2016-02-02 01:55:05 +00:00
|
|
|
else
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Non-NT bootloaders: install our own bootloader */
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2017-05-31 01:43:12 +00:00
|
|
|
PCWSTR Section;
|
|
|
|
PCWSTR Description;
|
|
|
|
PCWSTR BootSector;
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2017-05-31 01:43:12 +00:00
|
|
|
/* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"CPQDOS";
|
|
|
|
Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2017-05-31 01:43:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Search for Microsoft DOS or Windows 9x boot loader */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
|
|
|
|
// WINBOOT.SYS
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"MSDOS";
|
|
|
|
Description = L"\"MS-DOS/Windows\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2017-05-31 01:43:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"IBMDOS";
|
|
|
|
Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2017-05-31 01:43:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Search for DR-DOS 3.x boot loader */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found DR-DOS 3.x\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"DRDOS";
|
|
|
|
Description = L"\"DR-DOS 3.x\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2017-05-31 01:43:12 +00:00
|
|
|
}
|
|
|
|
else
|
2017-06-06 23:44:56 +00:00
|
|
|
/* Search for Dell Real-Mode Kernel (DRMK) OS */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found Dell Real-Mode Kernel OS\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"DRMK";
|
|
|
|
Description = L"\"Dell Real-Mode Kernel OS\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2017-06-06 23:44:56 +00:00
|
|
|
}
|
|
|
|
else
|
2017-05-31 01:43:12 +00:00
|
|
|
/* Search for MS OS/2 1.x */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found MS OS/2 1.x\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"MSOS2";
|
|
|
|
Description = L"\"MS OS/2 1.x\"";
|
|
|
|
BootSector = L"BOOTSECT.OS2";
|
2017-05-31 01:43:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Search for MS or IBM OS/2 */
|
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
|
|
|
|
DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
|
|
|
|
{
|
|
|
|
DPRINT1("Found MS/IBM OS/2\n");
|
2016-02-02 01:55:05 +00:00
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"IBMOS2";
|
|
|
|
Description = L"\"MS/IBM OS/2\"";
|
|
|
|
BootSector = L"BOOTSECT.OS2";
|
2016-02-02 01:55:05 +00:00
|
|
|
}
|
|
|
|
else
|
2017-05-31 01:43:12 +00:00
|
|
|
/* Search for FreeDOS boot loader */
|
2017-05-24 16:37:49 +00:00
|
|
|
if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
|
2016-02-02 01:55:05 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Found FreeDOS boot loader\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"FDOS";
|
|
|
|
Description = L"\"FreeDOS\"";
|
|
|
|
BootSector = L"BOOTSECT.DOS";
|
2016-02-02 01:55:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No or unknown boot loader */
|
|
|
|
DPRINT1("No or unknown boot loader found\n");
|
|
|
|
|
2024-04-23 15:02:06 +00:00
|
|
|
Section = L"Unknown";
|
|
|
|
Description = L"\"Unknown Operating System\"";
|
|
|
|
BootSector = L"BOOTSECT.OLD";
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Create or update 'freeldr.ini' */
|
2016-02-02 01:55:05 +00:00
|
|
|
if (DoesFreeLdrExist == FALSE)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
|
|
|
/* Create new 'freeldr.ini' */
|
|
|
|
DPRINT1("Create new 'freeldr.ini'\n");
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
if (IsThereAValidBootSector(SystemRootPath->Buffer))
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
Status = CreateFreeLoaderIniForReactOSAndBootSector(
|
2017-06-08 02:43:51 +00:00
|
|
|
SystemRootPath->Buffer, DestinationArcPath->Buffer,
|
2016-02-02 01:55:05 +00:00
|
|
|
Section, Description,
|
2024-04-23 15:02:06 +00:00
|
|
|
SystemRootPath->Buffer, BootSector);
|
2016-02-02 01:55:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Save current bootsector */
|
2017-05-31 01:43:12 +00:00
|
|
|
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
|
2016-02-02 01:55:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
|
2016-02-02 01:55:05 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
2016-02-02 01:55:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Install new bootsector on the disk */
|
2024-05-11 16:23:44 +00:00
|
|
|
if (_wcsicmp(FileSystemName, L"FAT32") == 0)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Install FAT32 bootcode */
|
2017-05-23 22:30:54 +00:00
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
|
|
|
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
|
2020-12-03 16:13:38 +00:00
|
|
|
DPRINT1("Status: 0x%08X\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
2020-10-19 21:49:26 +00:00
|
|
|
else // if (wcsicmp(FileSystemName, L"FAT") == 0)
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Install FAT16 bootcode */
|
2017-05-23 22:30:54 +00:00
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-02 01:55:05 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
NTSTATUS
|
2018-06-13 23:30:06 +00:00
|
|
|
InstallBtrfsBootcodeToPartition(
|
2024-08-30 11:40:34 +00:00
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath)
|
2016-02-02 01:55:05 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN DoesFreeLdrExist;
|
|
|
|
WCHAR SrcPath[MAX_PATH];
|
|
|
|
WCHAR DstPath[MAX_PATH];
|
|
|
|
|
2018-06-13 23:30:06 +00:00
|
|
|
/* BTRFS partition */
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT("System path: '%wZ'\n", SystemRootPath);
|
|
|
|
|
2024-10-17 11:37:25 +00:00
|
|
|
/* Install the bootloader */
|
|
|
|
Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
|
2016-02-02 01:55:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2024-10-17 11:37:25 +00:00
|
|
|
DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
|
2016-02-02 01:55:05 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2017-06-08 02:43:51 +00:00
|
|
|
/* Prepare for possibly updating 'freeldr.ini' */
|
|
|
|
DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
|
2016-02-02 01:55:05 +00:00
|
|
|
if (DoesFreeLdrExist)
|
|
|
|
{
|
|
|
|
/* Update existing 'freeldr.ini' */
|
|
|
|
DPRINT1("Update existing 'freeldr.ini'\n");
|
2017-06-08 02:43:51 +00:00
|
|
|
Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2016-02-02 01:55:05 +00:00
|
|
|
}
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Check for *nix bootloaders */
|
|
|
|
|
|
|
|
/* Create or update 'freeldr.ini' */
|
|
|
|
if (DoesFreeLdrExist == FALSE)
|
|
|
|
{
|
|
|
|
/* Create new 'freeldr.ini' */
|
|
|
|
DPRINT1("Create new 'freeldr.ini'\n");
|
|
|
|
|
|
|
|
/* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
|
|
|
|
DPRINT1("*nix or unknown boot loader found\n");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
if (IsThereAValidBootSector(SystemRootPath->Buffer))
|
|
|
|
{
|
2017-05-31 01:43:12 +00:00
|
|
|
PCWSTR BootSector = L"BOOTSECT.OLD";
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
Status = CreateFreeLoaderIniForReactOSAndBootSector(
|
2017-06-08 02:43:51 +00:00
|
|
|
SystemRootPath->Buffer, DestinationArcPath->Buffer,
|
2016-02-02 01:55:05 +00:00
|
|
|
L"Linux", L"\"Linux\"",
|
2024-04-23 15:02:06 +00:00
|
|
|
SystemRootPath->Buffer, BootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
/* Save current bootsector */
|
2017-05-31 01:43:12 +00:00
|
|
|
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
|
2020-10-17 18:29:47 +00:00
|
|
|
Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2016-02-02 01:55:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-08 02:43:51 +00:00
|
|
|
Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
2016-02-02 01:55:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2011-07-20 17:54:28 +00:00
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
}
|
2016-02-02 01:55:05 +00:00
|
|
|
|
|
|
|
/* Install new bootsector on the disk */
|
2020-10-17 18:29:47 +00:00
|
|
|
/* Install BTRFS bootcode */
|
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
|
2011-07-20 17:54:28 +00:00
|
|
|
|
2020-10-17 18:29:47 +00:00
|
|
|
DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
|
|
|
|
Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
2011-07-20 17:54:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2004-06-23 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 00:02:24 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
InstallNtfsBootcodeToPartition(
|
2024-08-30 11:40:34 +00:00
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath)
|
2022-10-19 00:02:24 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN DoesFreeLdrExist;
|
|
|
|
WCHAR SrcPath[MAX_PATH];
|
|
|
|
WCHAR DstPath[MAX_PATH];
|
|
|
|
|
|
|
|
/* NTFS partition */
|
|
|
|
DPRINT("System path: '%wZ'\n", SystemRootPath);
|
|
|
|
|
2024-10-17 11:37:25 +00:00
|
|
|
/* Install the bootloader */
|
|
|
|
Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
|
2022-10-19 00:02:24 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2024-10-17 11:37:25 +00:00
|
|
|
DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
|
2022-10-19 00:02:24 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prepare for possibly updating 'freeldr.ini' */
|
|
|
|
DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
|
|
|
|
if (DoesFreeLdrExist)
|
|
|
|
{
|
|
|
|
/* Update existing 'freeldr.ini' */
|
|
|
|
DPRINT1("Update existing 'freeldr.ini'\n");
|
|
|
|
Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for *nix bootloaders */
|
|
|
|
|
|
|
|
DPRINT1("Create new 'freeldr.ini'\n");
|
|
|
|
|
|
|
|
/* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
|
|
|
|
DPRINT1("*nix or unknown boot loader found\n");
|
|
|
|
|
|
|
|
if (IsThereAValidBootSector(SystemRootPath->Buffer))
|
|
|
|
{
|
|
|
|
PCWSTR BootSector = L"BOOTSECT.OLD";
|
|
|
|
|
|
|
|
Status = CreateFreeLoaderIniForReactOSAndBootSector(
|
|
|
|
SystemRootPath->Buffer, DestinationArcPath->Buffer,
|
|
|
|
L"Linux", L"\"Linux\"",
|
2024-04-23 15:02:06 +00:00
|
|
|
SystemRootPath->Buffer, BootSector);
|
2022-10-19 00:02:24 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save current bootsector */
|
|
|
|
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
|
|
|
|
|
|
|
|
DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
|
|
|
|
Status = SaveBootSector(SystemRootPath->Buffer, DstPath, NTFS_BOOTSECTOR_SIZE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Install new bootsector on the disk */
|
|
|
|
|
|
|
|
/* Install NTFS bootcode */
|
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\ntfs.bin");
|
|
|
|
|
|
|
|
DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
|
|
|
|
Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallNtfsBootCode);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
static
|
2010-09-05 17:09:18 +00:00
|
|
|
NTSTATUS
|
2011-07-20 17:54:28 +00:00
|
|
|
InstallVBRToPartition(
|
2024-08-30 11:40:34 +00:00
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath,
|
|
|
|
_In_ PCWSTR FileSystemName)
|
2010-09-05 17:09:18 +00:00
|
|
|
{
|
2024-05-11 16:23:44 +00:00
|
|
|
if (_wcsicmp(FileSystemName, L"FAT") == 0 ||
|
|
|
|
_wcsicmp(FileSystemName, L"FAT32") == 0)
|
2016-02-02 01:55:05 +00:00
|
|
|
{
|
2020-10-19 21:49:26 +00:00
|
|
|
return InstallFatBootcodeToPartition(SystemRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
DestinationArcPath,
|
|
|
|
FileSystemName);
|
|
|
|
}
|
2024-05-11 16:23:44 +00:00
|
|
|
else if (_wcsicmp(FileSystemName, L"NTFS") == 0)
|
2020-10-19 21:49:26 +00:00
|
|
|
{
|
2022-10-19 00:02:24 +00:00
|
|
|
return InstallNtfsBootcodeToPartition(SystemRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
DestinationArcPath);
|
2020-10-19 21:49:26 +00:00
|
|
|
}
|
2024-05-11 16:23:44 +00:00
|
|
|
else if (_wcsicmp(FileSystemName, L"BTRFS") == 0)
|
2020-10-19 21:49:26 +00:00
|
|
|
{
|
|
|
|
return InstallBtrfsBootcodeToPartition(SystemRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
DestinationArcPath);
|
|
|
|
}
|
|
|
|
/*
|
2024-05-11 16:23:44 +00:00
|
|
|
else if (_wcsicmp(FileSystemName, L"EXT2") == 0 ||
|
|
|
|
_wcsicmp(FileSystemName, L"EXT3") == 0 ||
|
|
|
|
_wcsicmp(FileSystemName, L"EXT4") == 0)
|
2020-10-19 21:49:26 +00:00
|
|
|
{
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unknown file system */
|
|
|
|
DPRINT1("Unknown file system '%S'\n", FileSystemName);
|
2010-09-05 17:09:18 +00:00
|
|
|
}
|
2011-06-29 20:27:07 +00:00
|
|
|
|
2020-10-19 21:49:26 +00:00
|
|
|
return STATUS_NOT_SUPPORTED;
|
2010-09-05 17:09:18 +00:00
|
|
|
}
|
|
|
|
|
2004-06-23 14:09:55 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* GENERIC FUNCTIONS *********************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Helper for InstallBootManagerAndBootEntries().
|
|
|
|
*
|
|
|
|
* @param[in] ArchType
|
|
|
|
* @param[in] SystemRootPath
|
|
|
|
* See InstallBootManagerAndBootEntries() parameters.
|
|
|
|
*
|
|
|
|
* @param[in] DiskNumber
|
|
|
|
* The NT disk number of the system disk that contains the system partition.
|
|
|
|
*
|
|
|
|
* @param[in] DiskStyle
|
|
|
|
* The partitioning style of the system disk.
|
|
|
|
*
|
|
|
|
* @param[in] IsSuperFloppy
|
|
|
|
* Whether the system disk is a super-floppy.
|
|
|
|
*
|
|
|
|
* @param[in] FileSystem
|
|
|
|
* The file system of the system partition.
|
|
|
|
*
|
|
|
|
* @param[in] SourceRootPath
|
|
|
|
* @param[in] DestinationArcPath
|
|
|
|
* @param[in] Options
|
|
|
|
* See InstallBootManagerAndBootEntries() parameters.
|
|
|
|
*
|
|
|
|
* @return An NTSTATUS code indicating success or failure.
|
|
|
|
**/
|
|
|
|
static
|
2004-06-23 14:09:55 +00:00
|
|
|
NTSTATUS
|
2024-08-30 11:40:34 +00:00
|
|
|
InstallBootManagerAndBootEntriesWorker(
|
|
|
|
_In_ ARCHITECTURE_TYPE ArchType,
|
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ ULONG DiskNumber, // const STORAGE_DEVICE_NUMBER* DeviceNumber,
|
|
|
|
_In_ PARTITION_STYLE DiskStyle,
|
|
|
|
_In_ BOOLEAN IsSuperFloppy,
|
|
|
|
_In_ PCWSTR FileSystem,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath,
|
|
|
|
_In_ ULONG_PTR Options)
|
2004-06-23 14:09:55 +00:00
|
|
|
{
|
2024-08-30 11:40:34 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN IsBIOS = ((ArchType == ARCH_PcAT) || (ArchType == ARCH_NEC98x86));
|
|
|
|
UCHAR InstallType = (Options & 0x03);
|
2019-02-24 16:52:33 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
// FIXME: We currently only support BIOS-based PCs
|
|
|
|
// TODO: Support other platforms
|
|
|
|
if (!IsBIOS)
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
if (InstallType <= 1)
|
|
|
|
{
|
|
|
|
/* Step 1: Write the VBR */
|
|
|
|
Status = InstallVBRToPartition(SystemRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
DestinationArcPath,
|
|
|
|
FileSystem);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallVBRToPartition() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return ERROR_WRITE_BOOT; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Step 2: Write the MBR if the disk containing the
|
|
|
|
* system partition is MBR and not a super-floppy */
|
|
|
|
if ((InstallType == 1) && (DiskStyle == PARTITION_STYLE_MBR) && !IsSuperFloppy)
|
|
|
|
{
|
|
|
|
WCHAR SystemDiskPath[MAX_PATH];
|
|
|
|
RtlStringCchPrintfW(SystemDiskPath, _countof(SystemDiskPath),
|
|
|
|
L"\\Device\\Harddisk%d\\Partition0",
|
|
|
|
DiskNumber);
|
|
|
|
Status = InstallMbrBootCodeToDisk(SystemRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
SystemDiskPath);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallMbrBootCodeToDisk() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return ERROR_INSTALL_BOOTCODE; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (InstallType == 2)
|
|
|
|
{
|
|
|
|
WCHAR SrcPath[MAX_PATH];
|
|
|
|
|
|
|
|
// FIXME: We currently only support FAT12 file system.
|
|
|
|
if (_wcsicmp(FileSystem, L"FAT") != 0)
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
// TODO: In the future, we'll be able to use InstallVBRToPartition()
|
|
|
|
// directly, instead of re-doing manually the copy steps below.
|
|
|
|
|
|
|
|
/* Install the bootloader to the boot partition */
|
|
|
|
Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallBootloaderFiles() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create new 'freeldr.ini' */
|
|
|
|
DPRINT("Create new 'freeldr.ini'\n");
|
|
|
|
Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Install FAT12 bootsector */
|
|
|
|
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
|
|
|
|
|
|
|
|
DPRINT1("Install FAT12 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
|
|
|
|
Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat12BootCode);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
GetDeviceInfo_UStr(
|
|
|
|
_In_opt_ PCUNICODE_STRING DeviceName,
|
|
|
|
_In_opt_ HANDLE DeviceHandle,
|
|
|
|
_Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
|
|
|
|
{
|
2016-02-02 01:55:05 +00:00
|
|
|
NTSTATUS Status;
|
2024-08-30 11:40:34 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2014-05-12 14:17:37 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
if (DeviceName && DeviceHandle)
|
|
|
|
return STATUS_INVALID_PARAMETER_MIX;
|
2017-09-03 16:19:59 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Open the device if a name has been given;
|
|
|
|
* otherwise just use the provided handle. */
|
|
|
|
if (DeviceName)
|
2011-10-29 15:10:11 +00:00
|
|
|
{
|
2024-08-30 11:40:34 +00:00
|
|
|
Status = pOpenDeviceEx_UStr(DeviceName, &DeviceHandle,
|
|
|
|
FILE_READ_ATTRIBUTES,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Cannot open device '%wZ' (Status 0x%08lx)\n",
|
|
|
|
DeviceName, Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Query the device */
|
|
|
|
Status = NtQueryVolumeInformationFile(DeviceHandle,
|
|
|
|
&IoStatusBlock,
|
|
|
|
DeviceInfo,
|
|
|
|
sizeof(*DeviceInfo),
|
|
|
|
FileFsDeviceInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
|
|
|
|
|
|
|
|
/* Close the device if we've opened it */
|
|
|
|
if (DeviceName)
|
|
|
|
NtClose(DeviceHandle);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
2019-02-24 16:52:33 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
NTSTATUS
|
|
|
|
GetDeviceInfo(
|
|
|
|
_In_opt_ PCWSTR DeviceName,
|
|
|
|
_In_opt_ HANDLE DeviceHandle,
|
|
|
|
_Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
|
|
|
|
{
|
|
|
|
UNICODE_STRING DeviceNameU;
|
|
|
|
|
|
|
|
if (DeviceName && DeviceHandle)
|
|
|
|
return STATUS_INVALID_PARAMETER_MIX;
|
|
|
|
|
|
|
|
if (DeviceName)
|
|
|
|
RtlInitUnicodeString(&DeviceNameU, DeviceName);
|
|
|
|
|
|
|
|
return GetDeviceInfo_UStr(DeviceName ? &DeviceNameU : NULL,
|
|
|
|
DeviceName ? NULL : DeviceHandle,
|
|
|
|
DeviceInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Installs FreeLoader on the system and configure the boot entries.
|
|
|
|
*
|
|
|
|
* @todo
|
|
|
|
* Split this function into just the InstallBootManager, and a separate one
|
|
|
|
* for just the boot entries.
|
|
|
|
*
|
|
|
|
* @param[in] ArchType
|
|
|
|
* The target architecture.
|
|
|
|
*
|
|
|
|
* @param[in] SystemRootPath
|
|
|
|
* The system partition path, where the FreeLdr boot manager and its
|
|
|
|
* settings are saved to.
|
|
|
|
*
|
|
|
|
* @param[in] SourceRootPath
|
|
|
|
* The installation source, where to copy the FreeLdr boot manager from.
|
|
|
|
*
|
|
|
|
* @param[in] DestinationArcPath
|
|
|
|
* The ReactOS installation path in ARC format.
|
|
|
|
*
|
|
|
|
* @param[in] Options
|
|
|
|
* For BIOS-based PCs:
|
|
|
|
* LOBYTE:
|
|
|
|
* 0: Install only on VBR;
|
|
|
|
* 1: Install on both VBR and MBR.
|
|
|
|
* 2: Install on removable disk.
|
|
|
|
*
|
|
|
|
* @return An NTSTATUS code indicating success or failure.
|
|
|
|
**/
|
|
|
|
NTSTATUS
|
2024-11-22 20:45:06 +00:00
|
|
|
NTAPI
|
2024-08-30 11:40:34 +00:00
|
|
|
InstallBootManagerAndBootEntries(
|
|
|
|
_In_ ARCHITECTURE_TYPE ArchType,
|
|
|
|
_In_ PCUNICODE_STRING SystemRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath,
|
|
|
|
_In_ ULONG_PTR Options)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE DeviceHandle;
|
|
|
|
FILE_FS_DEVICE_INFORMATION DeviceInfo;
|
|
|
|
ULONG DiskNumber;
|
|
|
|
PARTITION_STYLE PartitionStyle;
|
|
|
|
BOOLEAN IsSuperFloppy;
|
|
|
|
WCHAR FileSystem[MAX_PATH+1];
|
|
|
|
|
|
|
|
/* Remove any trailing backslash if needed */
|
|
|
|
UNICODE_STRING RootPartition = *SystemRootPath;
|
|
|
|
TrimTrailingPathSeparators_UStr(&RootPartition);
|
|
|
|
|
|
|
|
/* Open the volume */
|
|
|
|
Status = pOpenDeviceEx_UStr(&RootPartition, &DeviceHandle,
|
|
|
|
GENERIC_READ,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Cannot open %wZ for bootloader installation (Status 0x%08lx)\n",
|
|
|
|
&RootPartition, Status);
|
2011-10-29 15:10:11 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2004-06-23 14:09:55 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Retrieve the volume file system (it will also be mounted) */
|
|
|
|
Status = GetFileSystemName_UStr(NULL, DeviceHandle,
|
|
|
|
FileSystem, sizeof(FileSystem));
|
|
|
|
if (!NT_SUCCESS(Status) || !*FileSystem)
|
|
|
|
{
|
|
|
|
DPRINT1("GetFileSystemName() failed (Status 0x%08lx)\n", Status);
|
|
|
|
goto Quit;
|
|
|
|
}
|
2004-06-23 14:09:55 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Retrieve the device type and characteristics */
|
|
|
|
Status = GetDeviceInfo_UStr(NULL, DeviceHandle, &DeviceInfo);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-06-23 14:09:55 +00:00
|
|
|
{
|
2024-08-30 11:40:34 +00:00
|
|
|
DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ignore volumes that are NOT on usual disks */
|
|
|
|
if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
|
|
|
|
DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
|
|
|
|
{
|
|
|
|
DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check whether this is a floppy or a partitionable device */
|
|
|
|
if (DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE)
|
|
|
|
{
|
|
|
|
/* Floppies don't have partitions */
|
|
|
|
// NOTE: See ntoskrnl/io/iomgr/rawfs.c!RawQueryFsSizeInfo()
|
|
|
|
DiskNumber = ULONG_MAX;
|
|
|
|
PartitionStyle = PARTITION_STYLE_MBR;
|
|
|
|
IsSuperFloppy = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
STORAGE_DEVICE_NUMBER DeviceNumber;
|
|
|
|
|
|
|
|
/* The maximum information a DISK_GEOMETRY_EX dynamic structure can contain */
|
|
|
|
typedef struct _DISK_GEOMETRY_EX_INTERNAL
|
|
|
|
{
|
|
|
|
DISK_GEOMETRY Geometry;
|
|
|
|
LARGE_INTEGER DiskSize;
|
|
|
|
DISK_PARTITION_INFO Partition;
|
|
|
|
/* Followed by: DISK_DETECTION_INFO Detection; unused here */
|
|
|
|
} DISK_GEOMETRY_EX_INTERNAL, *PDISK_GEOMETRY_EX_INTERNAL;
|
|
|
|
|
|
|
|
DISK_GEOMETRY_EX_INTERNAL DiskGeoEx;
|
|
|
|
PARTITION_INFORMATION PartitionInfo;
|
|
|
|
|
|
|
|
/* Retrieve the disk number. NOTE: Fails for floppy disks. */
|
|
|
|
Status = NtDeviceIoControlFile(DeviceHandle,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
&IoStatusBlock,
|
|
|
|
IOCTL_STORAGE_GET_DEVICE_NUMBER,
|
|
|
|
NULL, 0,
|
|
|
|
&DeviceNumber, sizeof(DeviceNumber));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto Quit; /* This may be a dynamic volume, which is unsupported */
|
|
|
|
ASSERT(DeviceNumber.DeviceType == DeviceInfo.DeviceType);
|
|
|
|
if (DeviceNumber.DeviceNumber == ULONG_MAX)
|
|
|
|
{
|
|
|
|
DPRINT1("Invalid disk number reported, bail out\n");
|
|
|
|
Status = STATUS_NOT_FOUND;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Retrieve the drive geometry. NOTE: Fails for floppy disks;
|
|
|
|
* use IOCTL_DISK_GET_DRIVE_GEOMETRY instead. */
|
|
|
|
Status = NtDeviceIoControlFile(DeviceHandle,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
&IoStatusBlock,
|
|
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
|
|
|
NULL, 0,
|
|
|
|
&DiskGeoEx,
|
|
|
|
sizeof(DiskGeoEx));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed (Status 0x%08lx)\n", Status);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve the volume's partition information.
|
|
|
|
* NOTE: Fails for floppy disks.
|
|
|
|
*
|
|
|
|
* NOTE: We can use the non-EX IOCTL because the super-floppy test will
|
|
|
|
* fail anyway if the disk is NOT MBR-partitioned. (If the disk is GPT,
|
|
|
|
* the IOCTL would return only the MBR protective partition, but the
|
|
|
|
* super-floppy test would fail due to the wrong partitioning style.)
|
|
|
|
*/
|
|
|
|
Status = NtDeviceIoControlFile(DeviceHandle,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
&IoStatusBlock,
|
|
|
|
IOCTL_DISK_GET_PARTITION_INFO,
|
|
|
|
NULL, 0,
|
|
|
|
&PartitionInfo,
|
|
|
|
sizeof(PartitionInfo));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IOCTL_DISK_GET_PARTITION_INFO failed (Status 0x%08lx)\n", Status);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskNumber = DeviceNumber.DeviceNumber;
|
|
|
|
PartitionStyle = DiskGeoEx.Partition.PartitionStyle;
|
|
|
|
IsSuperFloppy = IsDiskSuperFloppy2(&DiskGeoEx.Partition,
|
|
|
|
(PULONGLONG)&DiskGeoEx.DiskSize.QuadPart,
|
|
|
|
&PartitionInfo);
|
2004-06-23 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
Status = InstallBootManagerAndBootEntriesWorker(
|
|
|
|
ArchType, SystemRootPath,
|
|
|
|
DiskNumber, PartitionStyle, IsSuperFloppy, FileSystem,
|
|
|
|
SourceRootPath, DestinationArcPath, Options);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
NtClose(DeviceHandle);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2024-11-22 20:45:06 +00:00
|
|
|
NTAPI
|
2024-08-30 11:40:34 +00:00
|
|
|
InstallBootcodeToRemovable(
|
|
|
|
_In_ ARCHITECTURE_TYPE ArchType,
|
|
|
|
_In_ PCUNICODE_STRING RemovableRootPath,
|
|
|
|
_In_ PCUNICODE_STRING SourceRootPath,
|
|
|
|
_In_ PCUNICODE_STRING DestinationArcPath)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
FILE_FS_DEVICE_INFORMATION DeviceInfo;
|
|
|
|
PCWSTR FileSystemName;
|
|
|
|
BOOLEAN IsFloppy;
|
|
|
|
|
|
|
|
/* Remove any trailing backslash if needed */
|
|
|
|
UNICODE_STRING RootDrive = *RemovableRootPath;
|
|
|
|
TrimTrailingPathSeparators_UStr(&RootDrive);
|
|
|
|
|
|
|
|
/* Verify that the removable disk is accessible */
|
|
|
|
if (!DoesDirExist(NULL, RemovableRootPath->Buffer))
|
|
|
|
return STATUS_DEVICE_NOT_READY;
|
|
|
|
|
|
|
|
/* Retrieve the device type and characteristics */
|
|
|
|
Status = GetDeviceInfo_UStr(&RootDrive, NULL, &DeviceInfo);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-06-23 14:09:55 +00:00
|
|
|
{
|
2024-08-30 11:40:34 +00:00
|
|
|
static const UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
|
|
|
|
|
|
|
|
DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
|
|
|
|
|
|
|
|
/* Definitively fail if the device is not a floppy */
|
|
|
|
if (!RtlPrefixUnicodeString(&DeviceFloppy, &RootDrive, TRUE))
|
|
|
|
return Status; /* We cannot cope with a failure */
|
|
|
|
|
|
|
|
/* Try to fall back to something "sane" if the device may be a floppy */
|
|
|
|
DeviceInfo.DeviceType = FILE_DEVICE_DISK;
|
|
|
|
DeviceInfo.Characteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ignore volumes that are NOT on usual disks */
|
|
|
|
if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
|
|
|
|
DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
|
|
|
|
{
|
|
|
|
DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
|
|
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
2004-06-23 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Fail if the disk is not removable */
|
|
|
|
if (!(DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA))
|
|
|
|
{
|
|
|
|
DPRINT1("Device is NOT removable!\n");
|
|
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check whether this is a floppy or another removable device */
|
|
|
|
IsFloppy = !!(DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE);
|
2004-06-23 14:09:55 +00:00
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Use FAT32, unless the device is a floppy disk */
|
|
|
|
FileSystemName = (IsFloppy ? L"FAT" : L"FAT32");
|
|
|
|
|
|
|
|
/* Format the removable disk */
|
|
|
|
Status = FormatFileSystem_UStr(&RootDrive,
|
|
|
|
FileSystemName,
|
|
|
|
(IsFloppy ? FMIFS_FLOPPY : FMIFS_REMOVABLE),
|
|
|
|
NULL,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
NULL);
|
2011-07-20 17:54:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-06-23 14:09:55 +00:00
|
|
|
{
|
2024-08-30 11:40:34 +00:00
|
|
|
if (Status == STATUS_NOT_SUPPORTED)
|
|
|
|
DPRINT1("%s FS non-existent on this system!\n", FileSystemName);
|
|
|
|
else
|
|
|
|
DPRINT1("FormatFileSystem(%s) failed (Status 0x%08lx)\n", FileSystemName, Status);
|
2011-07-20 17:54:28 +00:00
|
|
|
return Status;
|
2004-06-23 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-30 11:40:34 +00:00
|
|
|
/* Copy FreeLoader to the removable disk and save the boot entries */
|
|
|
|
Status = InstallBootManagerAndBootEntries(ArchType,
|
|
|
|
RemovableRootPath,
|
|
|
|
SourceRootPath,
|
|
|
|
DestinationArcPath,
|
|
|
|
2 /* Install on removable media */);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
DPRINT1("InstallBootManagerAndBootEntries() failed (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
2004-06-23 14:09:55 +00:00
|
|
|
}
|
|
|
|
|
2003-01-30 17:37:13 +00:00
|
|
|
/* EOF */
|