/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
- * FILE: subsys/system/usetup/bootsup.c
+ * FILE: base/setup/usetup/bootsup.c
* PURPOSE: Bootloader support functions
- * PROGRAMMER: Eric Kohl
+ * PROGRAMMERS: ...
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
+/*
+ * BIG FIXME!!
+ * ===========
+ *
+ * All that stuff *MUST* go into the fsutil.c module.
+ * Indeed, all that relates to filesystem formatting details and as such
+ * *MUST* be abstracted out from this module (bootsup.c).
+ * However, bootsup.c can still 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 still manage initializing / adding boot entries
+ * into NTLDR and FREELDR, and installing the latter, and saving the old
+ * MBR / boot sectors in files.
+ */
#define SECTORSIZE 512
#include <pshpack1.h>
USHORT BootSectorMagic; // 0xAA55
} FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
+
+typedef struct _BTRFS_BOOTSECTOR
+{
+ UCHAR JumpBoot[3];
+ UCHAR ChunkMapSize;
+ UCHAR BootDrive;
+ ULONGLONG PartitionStartLBA;
+ UCHAR Fill[1521]; // 1536 - 15
+ USHORT BootSectorMagic;
+} BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
+C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == 3 * 512);
+
+// TODO: Add more bootsector structures!
+
#include <poppack.h>
-extern PPARTLIST PartitionList;
+/* End of BIG FIXME!! */
+
/* FUNCTIONS ****************************************************************/
+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);
+ }
+}
+
-static
-VOID
-CreateCommonFreeLoaderSections(
- PINICACHE IniCache)
+static VOID
+CreateFreeLoaderReactOSEntries(
+ IN PVOID BootStoreHandle,
+ IN PCWSTR ArcPath)
{
- PINICACHESECTION IniSection;
+ UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
+ PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
+ PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
+ BOOT_STORE_OPTIONS BootOptions;
+
+ BootEntry->Version = FreeLdr;
+ 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\"";
+ Options->OsLoadOptions = NULL; // L"";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
+
+ /* ReactOS_Debug */
+ // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
+ BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
+ Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
+
+#ifdef _WINKD_
+ /* ReactOS_VBoxDebug */
+ // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
+ BootEntry->FriendlyName = L"\"ReactOS (VBoxDebug)\"";
+ Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
+#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";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
+#endif
+
+ /* ReactOS_Screen */
+ // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
+ BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
+ Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
+
+ /* ReactOS_LogFile */
+ // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
+ BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
+ Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
+
+ /* 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";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
+
+ /* 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";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
+#endif
- /* Create "FREELOADER" section */
- IniSection = IniCacheAppendSection(IniCache,
- L"FREELOADER");
#if DBG
if (IsUnattendedSetup)
{
/* DefaultOS=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"DefaultOS",
#ifndef _WINKD_
- L"ReactOS_KdSerial");
+ BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
#else
- L"ReactOS_Debug");
+ BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
#endif
}
else
#endif
{
/* DefaultOS=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"DefaultOS",
- L"ReactOS");
+ BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS");
}
#if DBG
if (IsUnattendedSetup)
#endif
{
- /* Timeout=0 for unattended or non debug*/
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TimeOut",
- L"0");
+ /* Timeout=0 for unattended or non debug */
+ BootOptions.Timeout = 0;
}
#if DBG
else
{
- /* Timeout=0 or 10 */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TimeOut",
- L"10");
+ /* Timeout=10 */
+ BootOptions.Timeout = 10;
}
#endif
- /* Create "Display" section */
- IniSection = IniCacheAppendSection(IniCache, L"Display");
-
- /* TitleText=ReactOS Boot Manager */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TitleText",
- L"ReactOS Boot Manager");
-
- /* StatusBarColor=Cyan */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"StatusBarColor",
- L"Cyan");
-
- /* StatusBarTextColor=Black */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"StatusBarTextColor",
- L"Black");
-
- /* BackdropTextColor=White */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BackdropTextColor",
- L"White");
-
- /* BackdropColor=Blue */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BackdropColor",
- L"Blue");
-
- /* BackdropFillStyle=Medium */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BackdropFillStyle",
- L"Medium");
-
- /* TitleBoxTextColor=White */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TitleBoxTextColor",
- L"White");
-
- /* TitleBoxColor=Red */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TitleBoxColor",
- L"Red");
-
- /* MessageBoxTextColor=White */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MessageBoxTextColor",
- L"White");
-
- /* MessageBoxColor=Blue */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MessageBoxColor",
- L"Blue");
-
- /* MenuTextColor=White */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MenuTextColor",
- L"Gray");
-
- /* MenuColor=Blue */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MenuColor",
- L"Black");
-
- /* TextColor=Yellow */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TextColor",
- L"Gray");
-
- /* SelectedTextColor=Black */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SelectedTextColor",
- L"Black");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SelectedColor",
- L"Gray");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"ShowTime",
- L"No");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MenuBox",
- L"No");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"CenterMenu",
- L"No");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"MinimalUI",
- L"Yes");
-
- /* SelectedColor=Gray */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"TimeText",
- L"Seconds until highlighted choice will be started automatically: ");
+ BootOptions.Version = FreeLdr;
+ SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1);
}
-
-NTSTATUS
-CreateFreeLoaderIniForDos(
- PWCHAR IniPath,
- PWCHAR ArcPath)
+static NTSTATUS
+CreateFreeLoaderIniForReactOS(
+ IN PCWSTR IniPath,
+ IN PCWSTR ArcPath)
{
- PINICACHE IniCache;
- PINICACHESECTION IniSection;
-
- IniCache = IniCacheCreate();
-
- CreateCommonFreeLoaderSections(IniCache);
-
- /* Create "Operating Systems" section */
- IniSection = IniCacheAppendSection(IniCache, L"Operating Systems");
-
- /* REACTOS=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"ReactOS",
- L"\"ReactOS\"");
-
- /* ReactOS_Debug="ReactOS (Debug)" */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"ReactOS_Debug",
- L"\"ReactOS (Debug)\"");
-
- /* DOS=Dos/Windows */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"DOS",
- L"\"DOS/Windows\"");
-
- /* Create "ReactOS" section */
- IniSection = IniCacheAppendSection(IniCache, L"ReactOS");
-
- /* BootType=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootType",
- L"ReactOS");
-
- /* SystemPath=<ArcPath> */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SystemPath",
- ArcPath);
-
- /* Create "ReactOS_Debug" section */
- IniSection = IniCacheAppendSection(IniCache, L"ReactOS_Debug");
-
- /* BootType=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootType",
- L"ReactOS");
-
- /* SystemPath=<ArcPath> */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SystemPath",
- ArcPath);
-
- /* Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"Options",
- L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS");
-
- /* Create "DOS" section */
- IniSection = IniCacheAppendSection(IniCache,
- L"DOS");
-
- /* BootType=BootSector */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootType",
- L"BootSector");
-
- /* BootDrive=hd0 */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootDrive",
- L"hd0");
-
- /* BootPartition=1 */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootPartition",
- L"1");
-
- /* BootSector=BOOTSECT.DOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootSectorFile",
- L"BOOTSECT.DOS");
-
- IniCacheSave(IniCache, IniPath);
- IniCacheDestroy(IniCache);
-
- return STATUS_SUCCESS;
-}
+ NTSTATUS Status;
+ PVOID BootStoreHandle;
+ /* Initialize the INI file and create the common FreeLdr sections */
+ Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
+ if (!NT_SUCCESS(Status))
+ return Status;
-NTSTATUS
-CreateFreeLoaderEntry(
- PINICACHE IniCache,
- PINICACHESECTION OSSection,
- PWCHAR Section,
- PWCHAR Description,
- PWCHAR BootType,
- PWCHAR ArcPath,
- PWCHAR Options)
-{
- PINICACHESECTION IniSection;
-
- /* Insert entry into "Operating Systems" section */
- IniCacheInsertKey(OSSection,
- NULL,
- INSERT_LAST,
- Section,
- Description);
-
- /* Create new section */
- IniSection = IniCacheAppendSection(IniCache, Section);
-
- /* BootType= */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootType",
- BootType);
-
- /* SystemPath= */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SystemPath",
- ArcPath);
-
- /* Options=*/
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"Options",
- Options);
+ /* Add the ReactOS entries */
+ CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
+ /* Close the INI file */
+ CloseBootStore(BootStoreHandle);
return STATUS_SUCCESS;
}
-NTSTATUS
-CreateFreeLoaderIniForReactos(
- PWCHAR IniPath,
- PWCHAR ArcPath)
+static NTSTATUS
+CreateFreeLoaderIniForReactOSAndBootSector(
+ IN PCWSTR IniPath,
+ IN PCWSTR ArcPath,
+ IN PCWSTR Section,
+ IN PCWSTR Description,
+ IN PCWSTR BootDrive,
+ IN PCWSTR BootPartition,
+ IN PCWSTR BootSector)
{
- PINICACHE IniCache;
- PINICACHESECTION IniSection;
+ NTSTATUS Status;
+ PVOID BootStoreHandle;
+ UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)];
+ PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
+ PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
- IniCache = IniCacheCreate();
+ /* Initialize the INI file and create the common FreeLdr sections */
+ Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
+ if (!NT_SUCCESS(Status))
+ return Status;
- CreateCommonFreeLoaderSections(IniCache);
+ /* Add the ReactOS entries */
+ CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
- /* Create "Operating Systems" section */
- IniSection = IniCacheAppendSection(IniCache, L"Operating Systems");
+ BootEntry->Version = FreeLdr;
+ BootEntry->BootFilePath = NULL;
- /* ReactOS */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS", L"\"ReactOS\"",
- L"Windows2003", ArcPath,
- L"");
+ BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
+ RtlCopyMemory(Options->Signature,
+ BOOT_SECTOR_OPTIONS_SIGNATURE,
+ RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature));
- /* ReactOS_Debug */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_Debug", L"\"ReactOS (Debug)\"",
- L"Windows2003", ArcPath,
- L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS");
+ Options->Drive = BootDrive;
+ Options->Partition = BootPartition;
+ Options->BootSectorFileName = BootSector;
-#if DBG
-#ifndef _WINKD_
- /* ReactOS_KdSerial */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_KdSerial", L"\"ReactOS (RosDbg)\"",
- L"Windows2003", ArcPath,
- L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL");
-#endif
+ // BootEntry->BootEntryKey = MAKESTRKEY(Section);
+ BootEntry->FriendlyName = Description;
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
- /* ReactOS_Screen */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_Screen", L"\"ReactOS (Screen)\"",
- L"Windows2003", ArcPath,
- L"/DEBUG /DEBUGPORT=SCREEN /SOS");
+ /* Close the INI file */
+ CloseBootStore(BootStoreHandle);
+ return STATUS_SUCCESS;
+}
- /* ReactOS_LogFile */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_LogFile", L"\"ReactOS (Log file)\"",
- L"Windows2003", ArcPath,
- L"/DEBUG /DEBUGPORT=FILE /SOS");
+//
+// 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".
+//
- /* ReactOS_Ram */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_Ram", L"\"ReactOS (RAM Disk)\"",
- L"Windows2003", L"ramdisk(0)\\ReactOS",
- L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDIMAGEPATH=reactos.img /RDIMAGEOFFSET=32256");
+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(
+ IN BOOT_STORE_TYPE Type,
+ IN PBOOT_STORE_ENTRY BootEntry,
+ IN PVOID Parameter OPTIONAL)
+{
+ PENUM_REACTOS_ENTRIES_DATA Data = (PENUM_REACTOS_ENTRIES_DATA)Parameter;
+ PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
+ WCHAR SystemPath[MAX_PATH];
- /* ReactOS_EMS */
- CreateFreeLoaderEntry(IniCache, IniSection,
- L"ReactOS_EMS", L"\"ReactOS (Emergency Management Services)\"",
- L"Windows2003", ArcPath,
- L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200");
-#endif
+ /* We have a boot entry */
+
+ /* 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))
+ {
+ /* This is not a ReactOS entry */
+ // DPRINT1(" An installation '%S' of unsupported type '%S'\n",
+ // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
+ DPRINT1(" An installation '%S' of unsupported type %lu\n",
+ BootEntry->FriendlyName, BootEntry->OsOptionsLength);
+ /* Continue the enumeration */
+ goto SkipThisEntry;
+ }
+
+ /* BootType is Windows2003, now check OsLoadPath */
+ if (!Options->OsLoadPath || !*Options->OsLoadPath)
+ {
+ /* Certainly not a ReactOS installation */
+ DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
+ /* Continue the enumeration */
+ goto SkipThisEntry;
+ }
+
+ RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
+ if ((_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0) &&
+ (_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;
+ }
+
+ DPRINT1(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
+ BootEntry->FriendlyName, Options->OsLoadPath);
+ // DPRINT1(" Found a Win2k3 install '%S' with ARC path '%S'\n",
+ // BootEntry->FriendlyName, Options->OsLoadPath);
+
+ DPRINT1("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
- /* Save the ini file */
- IniCacheSave(IniCache, IniPath);
- IniCacheDestroy(IniCache);
+ 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)
+ {
+ RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
+ L"ReactOS_%lu", Data->i);
+ RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
+ L"\"ReactOS %lu\"", Data->i);
+ Data->i++;
+ }
return STATUS_SUCCESS;
}
-
+static
NTSTATUS
UpdateFreeLoaderIni(
- PWCHAR IniPath,
- PWCHAR ArcPath)
+ IN PCWSTR IniPath,
+ IN PCWSTR ArcPath)
{
- UNICODE_STRING Name;
- PINICACHE IniCache;
- PINICACHESECTION IniSection;
- PINICACHESECTION OsIniSection;
- WCHAR SectionName[80];
- WCHAR OsName[80];
- WCHAR SystemPath[200];
- WCHAR SectionName2[200];
- PWCHAR KeyData;
- ULONG i,j;
NTSTATUS Status;
-
- RtlInitUnicodeString(&Name, IniPath);
-
- Status = IniCacheLoad(&IniCache, &Name, FALSE);
+ PVOID BootStoreHandle;
+ ENUM_REACTOS_ENTRIES_DATA Data;
+ UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
+ PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
+ PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
+
+ /* Open the INI file */
+ Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE);
if (!NT_SUCCESS(Status))
return Status;
- /* Get "Operating Systems" section */
- IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
- if (IniSection == NULL)
+ /* 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\"");
+
+ //
+ // FIXME: We temporarily use EnumerateBootStoreEntries, until
+ // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
+ //
+ Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
+
+ /* Create a new "ReactOS" entry if there is none already existing that suits us */
+ if (!Data.UseExistingEntry)
{
- IniCacheDestroy(IniCache);
- return STATUS_UNSUCCESSFUL;
+ // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
+ // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
+
+ BootEntry->Version = FreeLdr;
+ BootEntry->BootFilePath = NULL;
+
+ BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
+ RtlCopyMemory(Options->Signature,
+ NTOS_OPTIONS_SIGNATURE,
+ RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
+
+ Options->OsLoadPath = ArcPath;
+
+ // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
+ BootEntry->FriendlyName = Data.OsName;
+ Options->OsLoadOptions = NULL; // L"";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
}
- /* Find an existing usable or an unused section name */
- i = 1;
- wcscpy(SectionName, L"ReactOS");
- wcscpy(OsName, L"\"ReactOS\"");
- while(TRUE)
- {
- Status = IniCacheGetKey(IniSection, SectionName, &KeyData);
- if (!NT_SUCCESS(Status))
- break;
+ /* Close the INI file */
+ CloseBootStore(BootStoreHandle);
+ return STATUS_SUCCESS;
+}
- /* Get operation system section */
- if (KeyData[0] == '"')
- {
- wcscpy(SectionName2, &KeyData[1]);
- j = wcslen(SectionName2);
- if (j > 0)
- {
- SectionName2[j-1] = 0;
- }
- }
- else
- {
- wcscpy(SectionName2, KeyData);
- }
+static
+NTSTATUS
+UpdateBootIni(
+ IN PCWSTR IniPath,
+ IN PCWSTR EntryName, // ~= ArcPath
+ IN PCWSTR EntryValue)
+{
+ NTSTATUS Status;
+ PVOID BootStoreHandle;
+ ENUM_REACTOS_ENTRIES_DATA Data;
- OsIniSection = IniCacheGetSection(IniCache, SectionName2);
- if (OsIniSection != NULL)
- {
- BOOLEAN UseExistingEntry = TRUE;
+ // NOTE: Technically it would be "BootSector"...
+ UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
+ PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
+ PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
- /* Check BootType */
- Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
- if (NT_SUCCESS(Status))
- {
- if ((KeyData == NULL) ||
- ( (_wcsicmp(KeyData, L"ReactOS") != 0) &&
- (_wcsicmp(KeyData, L"\"ReactOS\"") != 0) ))
- {
- /* This is not a ReactOS entry */
- UseExistingEntry = FALSE;
- }
- }
- else
- {
- UseExistingEntry = FALSE;
- }
+ /* Open the INI file */
+ Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE);
+ if (!NT_SUCCESS(Status))
+ return Status;
- if (UseExistingEntry)
- {
- /* BootType is ReactOS. Now check SystemPath */
- Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
- if (NT_SUCCESS(Status))
- {
- swprintf(SystemPath, L"\"%S\"", ArcPath);
- if ((KeyData == NULL) ||
- ((_wcsicmp(KeyData, ArcPath) != 0) &&
- (_wcsicmp(KeyData, SystemPath) != 0) ))
- {
- /* This entry is a ReactOS entry, but the SystemRoot does not
- match the one we are looking for */
- UseExistingEntry = FALSE;
- }
- }
- else
- {
- UseExistingEntry = FALSE;
- }
- }
+ /* 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\"");
+
+ //
+ // FIXME: We temporarily use EnumerateBootStoreEntries, until
+ // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
+ //
+ Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
+
+ /* 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) ) */)
+ {
+ BootEntry->Version = NtLdr;
+ 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"";
+ AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
+ }
+
+ /* Close the INI file */
+ CloseBootStore(BootStoreHandle);
+ return STATUS_SUCCESS; // Status;
+}
- if (UseExistingEntry)
- {
- IniCacheDestroy(IniCache);
- return STATUS_SUCCESS;
- }
- }
- swprintf(SectionName, L"ReactOS_%lu", i);
- swprintf(OsName, L"\"ReactOS %lu\"", i);
- i++;
- }
+BOOLEAN
+IsThereAValidBootSector(
+ IN PCWSTR RootPath)
+{
+ /*
+ * 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.
+ */
+
+ BOOLEAN IsValid = FALSE;
+ NTSTATUS Status;
+ UNICODE_STRING RootPartition;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ LARGE_INTEGER FileOffset;
+ PUCHAR BootSector;
+ ULONG Instruction;
+
+ /* Allocate buffer for bootsector */
+ BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (BootSector == NULL)
+ return FALSE; // STATUS_INSUFFICIENT_RESOURCES;
+ RtlZeroMemory(BootSector, SECTORSIZE);
+
+ /* Open the root partition - Remove any trailing backslash if needed */
+ RtlInitUnicodeString(&RootPartition, RootPath);
+ TrimTrailingPathSeparators_UStr(&RootPartition);
- /* <SectionName>=<OsName> */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- SectionName,
- OsName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RootPartition,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
- /* Create <SectionName> section */
- IniSection = IniCacheAppendSection(IniCache, SectionName);
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ goto Quit;
- /* BootType=ReactOS */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"BootType",
- L"ReactOS");
+ /* Read current boot sector into buffer */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ goto Quit;
- /* SystemPath=<ArcPath> */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"SystemPath",
- ArcPath);
+ /* Check the instruction; we use a ULONG to read three bytes */
+ Instruction = (*(PULONG)BootSector) & 0x00FFFFFF;
+ IsValid = (Instruction != 0x00000000);
- IniCacheSave(IniCache, IniPath);
- IniCacheDestroy(IniCache);
+ /* Check the bootsector signature */
+ IsValid &= (*(PUSHORT)(BootSector + 0x1fe) == 0xaa55);
- return STATUS_SUCCESS;
+Quit:
+ /* Free the boot sector */
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return IsValid; // Status;
}
-
NTSTATUS
-SaveCurrentBootSector(
- PWSTR RootPath,
- PWSTR DstPath)
+SaveBootSector(
+ IN PCWSTR RootPath,
+ IN PCWSTR DstPath,
+ IN ULONG Length)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
HANDLE FileHandle;
- NTSTATUS Status;
+ LARGE_INTEGER FileOffset;
PUCHAR BootSector;
/* Allocate buffer for bootsector */
- BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ BootSector = RtlAllocateHeap(ProcessHeap, 0, Length);
if (BootSector == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
- /* Read current boot sector into buffer */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
return Status;
}
+ /* Read current boot sector into buffer */
+ FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
BootSector,
- SECTORSIZE,
- NULL,
+ Length,
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
NULL,
&IoStatusBlock,
BootSector,
- SECTORSIZE,
+ Length,
NULL,
NULL);
NtClose(FileHandle);
- /* Free the new boot sector */
+ /* Free the boot sector */
RtlFreeHeap(ProcessHeap, 0, BootSector);
return Status;
}
-
NTSTATUS
-InstallFat16BootCodeToFile(
- PWSTR SrcPath,
- PWSTR DstPath,
- PWSTR RootPath)
+InstallMbrBootCodeToDisk(
+ IN PCWSTR SrcPath,
+ IN PCWSTR RootPath)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
HANDLE FileHandle;
- NTSTATUS Status;
- PFAT_BOOTSECTOR OrigBootSector;
- PFAT_BOOTSECTOR NewBootSector;
+ LARGE_INTEGER FileOffset;
+ PPARTITION_SECTOR OrigBootSector;
+ PPARTITION_SECTOR NewBootSector;
/* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES ;
+ return STATUS_INSUFFICIENT_RESOURCES;
- /* Read current boot sector into buffer */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
return Status;
}
+ /* Read current boot sector into buffer */
+ FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
OrigBootSector,
- SECTORSIZE,
- NULL,
+ sizeof(PARTITION_SECTOR),
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
}
/* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
if (NewBootSector == NULL)
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
NULL,
&IoStatusBlock,
NewBootSector,
- SECTORSIZE,
+ sizeof(PARTITION_SECTOR),
NULL,
NULL);
NtClose(FileHandle);
return Status;
}
- /* Adjust bootsector (copy a part of the FAT BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+ /*
+ * Copy the disk signature, the reserved fields and
+ * the partition table from the old MBR to the new one.
+ */
+ RtlCopyMemory(&NewBootSector->Signature,
+ &OrigBootSector->Signature,
+ sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature)
+ /* Length of partition table */);
/* Free the original boot sector */
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- /* Write new bootsector to DstPath */
- RtlInitUnicodeString(&Name, DstPath);
+ /* Open the root partition - Remove any trailing backslash if needed */
+ RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- 0,
- FILE_OVERWRITE_IF,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
- NULL,
- 0);
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
-#if 0
- FilePosition.QuadPart = 0;
-#endif
+ /* Write new bootsector to RootPath */
+ FileOffset.QuadPart = 0ULL;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
NewBootSector,
- SECTORSIZE,
- NULL,
+ sizeof(PARTITION_SECTOR),
+ &FileOffset,
NULL);
NtClose(FileHandle);
}
+static
NTSTATUS
-InstallFat32BootCodeToFile(
- PWSTR SrcPath,
- PWSTR DstPath,
- PWSTR RootPath)
+InstallFat12BootCodeToFloppy(
+ IN PCWSTR SrcPath,
+ IN PCWSTR RootPath)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
HANDLE FileHandle;
- NTSTATUS Status;
- PFAT32_BOOTSECTOR OrigBootSector;
- PFAT32_BOOTSECTOR NewBootSector;
LARGE_INTEGER FileOffset;
+ PFAT_BOOTSECTOR OrigBootSector;
+ PFAT_BOOTSECTOR NewBootSector;
/* Allocate buffer for original bootsector */
OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
if (OrigBootSector == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
- /* Read current boot sector into buffer */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
return Status;
}
- Status = NtReadFile(FileHandle,
+ /* Read current boot sector into buffer */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
OrigBootSector,
SECTORSIZE,
- NULL,
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
return Status;
}
- /* Allocate buffer for new bootsector (2 sectors) */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
+ /* Allocate buffer for new bootsector */
+ NewBootSector = RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
if (NewBootSector == NULL)
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
NULL,
&IoStatusBlock,
NewBootSector,
- 2 * SECTORSIZE,
+ SECTORSIZE,
NULL,
NULL);
NtClose(FileHandle);
return Status;
}
- /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ /* Adjust bootsector (copy a part of the FAT16 BPB) */
memcpy(&NewBootSector->OemName,
&OrigBootSector->OemName,
- FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
-
- /* Disable the backup boot sector */
- NewBootSector->BackupBootSector = 0;
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
/* Free the original boot sector */
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- /* Write the first sector of the new bootcode to DstPath */
- RtlInitUnicodeString(&Name, DstPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
-
- Status = NtCreateFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- 0,
- FILE_SUPERSEDE,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
-
- /* Write the second sector of the new bootcode to boot disk sector 14 */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
&ObjectAttributes,
&IoStatusBlock,
0,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
- FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ /* Write new bootsector to RootPath */
+ FileOffset.QuadPart = 0ULL;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
- ((PUCHAR)NewBootSector + SECTORSIZE),
+ NewBootSector,
SECTORSIZE,
&FileOffset,
NULL);
- if (!NT_SUCCESS(Status))
- {
- }
NtClose(FileHandle);
/* Free the new boot sector */
return Status;
}
-
+static
NTSTATUS
-InstallMbrBootCodeToDisk(
- PWSTR SrcPath,
- PWSTR RootPath)
+InstallFat16BootCode(
+ IN PCWSTR SrcPath, // FAT16 bootsector source file (on the installation medium)
+ IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information
+ IN HANDLE RootPartition) // Partition holding the (old) FAT16 information
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
HANDLE FileHandle;
- NTSTATUS Status;
- PPARTITION_SECTOR OrigBootSector;
- PPARTITION_SECTOR NewBootSector;
+ LARGE_INTEGER FileOffset;
+ PFAT_BOOTSECTOR OrigBootSector;
+ PFAT_BOOTSECTOR NewBootSector;
- /* Allocate buffer for original bootsector */
- OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(PARTITION_SECTOR));
+ /* Allocate a buffer for the original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
if (OrigBootSector == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
- /* Read current boot sector into buffer */
- RtlInitUnicodeString(&Name,
- RootPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-
- Status = NtReadFile(FileHandle,
+ /* Read the current partition boot sector into the buffer */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(RootPartition,
NULL,
NULL,
NULL,
&IoStatusBlock,
OrigBootSector,
SECTORSIZE,
- NULL,
+ &FileOffset,
NULL);
- NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
}
- /* Allocate buffer for new bootsector */
- NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(PARTITION_SECTOR));
+ /* Allocate a buffer for the new bootsector */
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
if (NewBootSector == NULL)
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return STATUS_INSUFFICIENT_RESOURCES;
}
- /* Read new bootsector from SrcPath */
+ /* Read the new bootsector from SrcPath */
RtlInitUnicodeString(&Name, SrcPath);
-
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
Status = NtOpenFile(&FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
return Status;
}
+ FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
NewBootSector,
- sizeof(PARTITION_SECTOR),
- NULL,
+ SECTORSIZE,
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
return Status;
}
- /* Copy partition table from old MBR to new */
- RtlCopyMemory (&NewBootSector->Signature,
- &OrigBootSector->Signature,
- sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */);
+ /* Adjust the bootsector (copy a part of the FAT16 BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
/* Free the original boot sector */
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- /* Write new bootsector to RootPath */
+ /* Write the new bootsector to DstPath */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+static
+NTSTATUS
+InstallFat16BootCodeToFile(
+ IN PCWSTR SrcPath,
+ IN PCWSTR DstPath,
+ IN PCWSTR RootPath)
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE PartitionHandle, FileHandle;
+
+ /*
+ * Open the root partition from which the boot sector
+ * parameters will be obtained.
+ * Remove any trailing backslash if needed.
+ */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
+ Status = NtOpenFile(&PartitionHandle,
+ GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Open or create the file where the new bootsector will be saved */
+ RtlInitUnicodeString(&Name, DstPath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0, // OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ NtClose(PartitionHandle);
return Status;
}
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
+ /* Install the FAT16 boot sector */
+ Status = InstallFat16BootCode(SrcPath, FileHandle, PartitionHandle);
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ /* Close the file and the partition */
+ NtClose(FileHandle);
+ NtClose(PartitionHandle);
return Status;
}
-
+static
NTSTATUS
-InstallFat12BootCodeToFloppy(
- PWSTR SrcPath,
- PWSTR RootPath)
+InstallFat16BootCodeToDisk(
+ IN PCWSTR SrcPath,
+ IN PCWSTR RootPath)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
- HANDLE FileHandle;
- NTSTATUS Status;
- PFAT_BOOTSECTOR OrigBootSector;
- PFAT_BOOTSECTOR NewBootSector;
-
- /* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
+ HANDLE PartitionHandle;
- /* Read current boot sector into buffer */
+ /*
+ * Open the root partition from which the boot sector parameters will be
+ * obtained; this is also where we will write the updated boot sector.
+ * Remove any trailing backslash if needed.
+ */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
+ Status = NtOpenFile(&PartitionHandle,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
- }
- Status = NtReadFile(FileHandle,
+ /* Install the FAT16 boot sector */
+ Status = InstallFat16BootCode(SrcPath, PartitionHandle, PartitionHandle);
+
+ /* Close the partition */
+ NtClose(PartitionHandle);
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+InstallFat32BootCode(
+ IN PCWSTR SrcPath, // FAT32 bootsector source file (on the installation medium)
+ IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information
+ IN HANDLE RootPartition) // Partition holding the (old) FAT32 information
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ LARGE_INTEGER FileOffset;
+ PFAT32_BOOTSECTOR OrigBootSector;
+ PFAT32_BOOTSECTOR NewBootSector;
+ USHORT BackupBootSector;
+
+ /* Allocate a buffer for the original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read the current boot sector into the buffer */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(RootPartition,
NULL,
NULL,
NULL,
&IoStatusBlock,
OrigBootSector,
SECTORSIZE,
- NULL,
+ &FileOffset,
NULL);
- NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
}
- /* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap,
- 0,
- SECTORSIZE);
+ /* Allocate a buffer for the new bootsector (2 sectors) */
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
if (NewBootSector == NULL)
{
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return STATUS_INSUFFICIENT_RESOURCES;
}
- /* Read new bootsector from SrcPath */
+ /* Read the new bootsector from SrcPath */
RtlInitUnicodeString(&Name, SrcPath);
-
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
Status = NtOpenFile(&FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
return Status;
}
+ FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
NewBootSector,
- SECTORSIZE,
- NULL,
+ 2 * SECTORSIZE,
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
return Status;
}
- /* Adjust bootsector (copy a part of the FAT16 BPB) */
+ /* Adjust the bootsector (copy a part of the FAT32 BPB) */
memcpy(&NewBootSector->OemName,
&OrigBootSector->OemName,
- FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+ FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
+
+ /*
+ * We know we copy the boot code to a file only when DstPath != RootPartition,
+ * otherwise the boot code is copied to the specified root partition.
+ */
+ if (DstPath != RootPartition)
+ {
+ /* Copy to a file: Disable the backup boot sector */
+ NewBootSector->BackupBootSector = 0;
+ }
+ else
+ {
+ /* Copy to a disk: Get the location of the backup boot sector */
+ BackupBootSector = OrigBootSector->BackupBootSector;
+ }
/* Free the original boot sector */
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- /* Write new bootsector to RootPath */
- RtlInitUnicodeString(&Name, RootPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ /* Write the first sector of the new bootcode to DstPath sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
-#if 0
- FilePosition.QuadPart = 0;
-#endif
- Status = NtWriteFile(FileHandle,
+ if (DstPath == RootPartition)
+ {
+ /* Copy to a disk: Write the backup boot sector */
+ if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
+ {
+ FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
+ Status = NtWriteFile(DstPath,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+ }
+ }
+
+ /* Write the second sector of the new bootcode to boot disk sector 14 */
+ // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ FileOffset.QuadPart = 14 * SECTORSIZE;
+ Status = NtWriteFile(DstPath, // or really RootPartition ???
NULL,
NULL,
NULL,
&IoStatusBlock,
- NewBootSector,
+ ((PUCHAR)NewBootSector + SECTORSIZE),
SECTORSIZE,
- NULL,
+ &FileOffset,
NULL);
- NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ }
/* Free the new boot sector */
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
-
+static
NTSTATUS
-InstallFat16BootCodeToDisk(
- PWSTR SrcPath,
- PWSTR RootPath)
+InstallFat32BootCodeToFile(
+ IN PCWSTR SrcPath,
+ IN PCWSTR DstPath,
+ IN PCWSTR RootPath)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
- HANDLE FileHandle;
- NTSTATUS Status;
- PFAT_BOOTSECTOR OrigBootSector;
- PFAT_BOOTSECTOR NewBootSector;
-
- /* Allocate buffer for original bootsector */
- OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
- if (OrigBootSector == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- /* Read current boot sector into buffer */
+ HANDLE PartitionHandle, FileHandle;
+
+ /*
+ * Open the root partition from which the boot sector 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);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
- Status = NtOpenFile(&FileHandle,
+ Status = NtOpenFile(&PartitionHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return Status;
- }
-
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- OrigBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
+ FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
- }
-
- /* Allocate buffer for new bootsector */
- NewBootSector = RtlAllocateHeap(ProcessHeap,
- 0,
- SECTORSIZE);
- if (NewBootSector == NULL)
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Read new bootsector from SrcPath */
- RtlInitUnicodeString(&Name, SrcPath);
+ /* Open or create the file where (the first sector of ????) the new bootsector will be saved */
+ RtlInitUnicodeString(&Name, DstPath);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
- OBJ_CASE_INSENSITIVE,
+ 0, // OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE, // FILE_OVERWRITE_IF, <- is used for FAT16
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+ NtClose(PartitionHandle);
return Status;
}
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
- return Status;
- }
+ /* Install the FAT32 boot sector */
+ Status = InstallFat32BootCode(SrcPath, FileHandle, PartitionHandle);
- /* Adjust bootsector (copy a part of the FAT16 BPB) */
- memcpy(&NewBootSector->OemName,
- &OrigBootSector->OemName,
- FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
- FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+ /* Close the file and the partition */
+ NtClose(FileHandle);
+ NtClose(PartitionHandle);
- NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
+ return Status;
+}
- /* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+static
+NTSTATUS
+InstallFat32BootCodeToDisk(
+ IN PCWSTR SrcPath,
+ IN PCWSTR RootPath)
+{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE PartitionHandle;
- /* Write new bootsector to RootPath */
+ /*
+ * Open the root partition from which the boot sector parameters will be
+ * obtained; this is also where we will write the updated boot sector.
+ * Remove any trailing backslash if needed.
+ */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
- 0,
+ OBJ_CASE_INSENSITIVE,
NULL,
NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_WRITE | SYNCHRONIZE,
+ Status = NtOpenFile(&PartitionHandle,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
- FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
- }
-#if 0
- FilePosition.QuadPart = 0;
-#endif
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- NewBootSector,
- SECTORSIZE,
- NULL,
- NULL);
- NtClose(FileHandle);
+ /* Install the FAT32 boot sector */
+ Status = InstallFat32BootCode(SrcPath, PartitionHandle, PartitionHandle);
- /* Free the new boot sector */
- RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ /* Close the partition */
+ NtClose(PartitionHandle);
return Status;
}
-
+static
NTSTATUS
-InstallFat32BootCodeToDisk(
- PWSTR SrcPath,
- PWSTR RootPath)
+InstallBtrfsBootCodeToDisk(
+ IN PCWSTR SrcPath,
+ IN PCWSTR RootPath)
{
+ NTSTATUS Status;
+ UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING Name;
HANDLE FileHandle;
- NTSTATUS Status;
- PFAT32_BOOTSECTOR OrigBootSector;
- PFAT32_BOOTSECTOR NewBootSector;
LARGE_INTEGER FileOffset;
- USHORT BackupBootSector;
+// PEXT2_BOOTSECTOR OrigBootSector;
+ PBTRFS_BOOTSECTOR NewBootSector;
+ // USHORT BackupBootSector;
+ PARTITION_INFORMATION_EX PartInfo;
+#if 0
/* Allocate buffer for original bootsector */
OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
if (OrigBootSector == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
- /* Read current boot sector into buffer */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
return Status;
}
+ /* Read current boot sector into buffer */
+ FileOffset.QuadPart = 0ULL;
Status = NtReadFile(FileHandle,
NULL,
NULL,
&IoStatusBlock,
OrigBootSector,
SECTORSIZE,
- NULL,
+ &FileOffset,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
}
+#endif
-
- /* Allocate buffer for new bootsector (2 sectors) */
- NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
+ /* Allocate buffer for new bootsector */
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR));
if (NewBootSector == NULL)
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return STATUS_INSUFFICIENT_RESOURCES;
}
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
NULL,
&IoStatusBlock,
NewBootSector,
- 2 * SECTORSIZE,
+ sizeof(BTRFS_BOOTSECTOR),
NULL,
NULL);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
+#if 0
/* Adjust bootsector (copy a part of the FAT32 BPB) */
memcpy(&NewBootSector->OemName,
&OrigBootSector->OemName,
FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
- NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
-
/* Get the location of the backup boot sector */
BackupBootSector = OrigBootSector->BackupBootSector;
/* Free the original boot sector */
- RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+#endif
- /* Write the first sector of the new bootcode to DstPath */
+ /* Open the root partition - Remove any trailing backslash if needed */
RtlInitUnicodeString(&Name, RootPath);
+ TrimTrailingPathSeparators_UStr(&Name);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
return Status;
}
+ /* Obtaining partition info and writing it to bootsector */
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_DISK_GET_PARTITION_INFO_EX,
+ NULL,
+ 0,
+ &PartInfo,
+ sizeof(PartInfo));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Write new bootsector to RootPath */
+
+ NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE;
+
/* Write sector 0 */
FileOffset.QuadPart = 0ULL;
Status = NtWriteFile(FileHandle,
NULL,
&IoStatusBlock,
NewBootSector,
- SECTORSIZE,
+ sizeof(BTRFS_BOOTSECTOR),
&FileOffset,
NULL);
+#if 0
if (!NT_SUCCESS(Status))
{
DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
{
DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
}
+#endif
NtClose(FileHandle);
/* Free the new boot sector */
return Status;
}
-
static
NTSTATUS
-UnprotectBootIni(
- PWSTR FileName,
- PULONG Attributes)
+InstallFatBootcodeToPartition(
+ PUNICODE_STRING SystemRootPath,
+ PUNICODE_STRING SourceRootPath,
+ PUNICODE_STRING DestinationArcPath,
+ UCHAR PartitionType)
{
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- FILE_BASIC_INFORMATION FileInfo;
- HANDLE FileHandle;
NTSTATUS Status;
+ BOOLEAN DoesFreeLdrExist;
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
- RtlInitUnicodeString(&Name, FileName);
+ /* FAT or FAT32 partition */
+ DPRINT("System path: '%wZ'\n", SystemRootPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
+ /* 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");
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (Status == STATUS_NO_SUCH_FILE)
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- *Attributes = 0;
- return STATUS_SUCCESS;
- }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- return Status;
- }
-
- Status = NtQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInfo,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
- return Status;
- }
-
- *Attributes = FileInfo.FileAttributes;
-
- /* Delete attributes SYSTEM, HIDDEN and READONLY */
- FileInfo.FileAttributes = FileInfo.FileAttributes &
- ~(FILE_ATTRIBUTE_SYSTEM |
- FILE_ATTRIBUTE_HIDDEN |
- FILE_ATTRIBUTE_READONLY);
-
- Status = NtSetInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInfo,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
- }
-
- NtClose(FileHandle);
- return Status;
-}
-
-
-static
-NTSTATUS
-ProtectBootIni(
- PWSTR FileName,
- ULONG Attributes)
-{
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- FILE_BASIC_INFORMATION FileInfo;
- HANDLE FileHandle;
- NTSTATUS Status;
-
- RtlInitUnicodeString(&Name, FileName);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- return Status;
- }
-
- Status = NtQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInfo,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
- return Status;
- }
-
- FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
-
- Status = NtSetInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInfo,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
- }
-
- NtClose(FileHandle);
- return Status;
-}
-
-
-NTSTATUS
-UpdateBootIni(
- PWSTR BootIniPath,
- PWSTR EntryName,
- PWSTR EntryValue)
-{
- UNICODE_STRING Name;
- PINICACHE Cache = NULL;
- PINICACHESECTION Section = NULL;
- NTSTATUS Status;
- ULONG FileAttribute;
- PWCHAR OldValue = NULL;
-
- RtlInitUnicodeString(&Name, BootIniPath);
-
- Status = IniCacheLoad(&Cache, &Name, FALSE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Section = IniCacheGetSection(Cache,
- L"operating systems");
- if (Section == NULL)
- {
- IniCacheDestroy(Cache);
- return STATUS_UNSUCCESSFUL;
- }
-
- /* Check - maybe record already exists */
- Status = IniCacheGetKey(Section, EntryName, &OldValue);
-
- /* If either key was not found, or contains something else - add new one */
- if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
- {
- IniCacheInsertKey(Section,
- NULL,
- INSERT_LAST,
- EntryName,
- EntryValue);
- }
-
- Status = UnprotectBootIni(BootIniPath,
- &FileAttribute);
- if (!NT_SUCCESS(Status))
- {
- IniCacheDestroy(Cache);
- return Status;
- }
-
- Status = IniCacheSave(Cache, BootIniPath);
+ DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = SetupCopyFile(SrcPath, DstPath);
if (!NT_SUCCESS(Status))
{
- IniCacheDestroy(Cache);
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
return Status;
}
- FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
- Status = ProtectBootIni(BootIniPath, FileAttribute);
-
- IniCacheDestroy(Cache);
-
- return Status;
-}
-
-
-BOOLEAN
-CheckInstallFatBootcodeToPartition(
- PUNICODE_STRING SystemRootPath)
-{
-#ifdef __REACTOS__
- if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") ||
- DoesFileExist(SystemRootPath->Buffer, L"boot.ini"))
- {
- return TRUE;
- }
- else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") ||
- DoesFileExist(SystemRootPath->Buffer, L"msdos.sys"))
- {
- return TRUE;
- }
-#endif
-
- return FALSE;
-}
-
-
-NTSTATUS
-InstallFatBootcodeToPartition(
- PUNICODE_STRING SystemRootPath,
- PUNICODE_STRING SourceRootPath,
- PUNICODE_STRING DestinationArcPath,
- UCHAR PartitionType)
-{
-#ifdef __REACTOS__
- WCHAR SrcPath[MAX_PATH];
- WCHAR DstPath[MAX_PATH];
- NTSTATUS Status;
-
- /* FAT or FAT32 partition */
- DPRINT("System path: '%wZ'\n", SystemRootPath);
-
- if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
- DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
+ /* Prepare for possibly updating 'freeldr.ini' */
+ DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
+ if (DoesFreeLdrExist)
{
- /* Search root directory for 'ntldr' and 'boot.ini'. */
- DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n");
-
- /* Copy FreeLoader to the boot partition */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\freeldr.sys");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.sys");
-
- DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
- Status = SetupCopyFile(SrcPath, DstPath);
+ /* Update existing 'freeldr.ini' */
+ DPRINT1("Update existing 'freeldr.ini'\n");
+ Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
if (!NT_SUCCESS(Status))
{
- DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
return Status;
}
+ }
+
+ /* Check for NT and other bootloaders */
- /* Create or update freeldr.ini */
- if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
+ // 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)
+ {
+ /* Search root directory for 'NTLDR' and 'BOOT.INI' */
+ DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
+
+ /* Create or update 'freeldr.ini' */
+ if (DoesFreeLdrExist == FALSE)
{
/* Create new 'freeldr.ini' */
DPRINT1("Create new 'freeldr.ini'\n");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
-
- Status = CreateFreeLoaderIniForReactos(DstPath,
- DestinationArcPath->Buffer);
+ Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
+ DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
return Status;
}
- /* Install new bootcode */
+ /* Install new bootcode into a file */
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
+
if (PartitionType == PARTITION_FAT32 ||
- PartitionType == PARTITION_FAT32_XINT13)
+ PartitionType == PARTITION_FAT32_XINT13)
{
/* Install FAT32 bootcode */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat32.bin");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\bootsect.ros");
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
- Status = InstallFat32BootCodeToFile(SrcPath,
- DstPath,
+ Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
SystemRootPath->Buffer);
if (!NT_SUCCESS(Status))
{
else
{
/* Install FAT16 bootcode */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat.bin");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\bootsect.ros");
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
- Status = InstallFat16BootCodeToFile(SrcPath,
- DstPath,
+ Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
SystemRootPath->Buffer);
if (!NT_SUCCESS(Status))
{
}
}
}
- else
- {
- /* Update existing 'freeldr.ini' */
- DPRINT1("Update existing 'freeldr.ini'\n");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
-
- Status = UpdateFreeLoaderIni(DstPath,
- DestinationArcPath->Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
- return Status;
- }
- }
/* Update 'boot.ini' */
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\boot.ini");
-
- DPRINT1("Update 'boot.ini': %S\n", DstPath);
- Status = UpdateBootIni(DstPath,
+ /* 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. */
+ DPRINT1("Update 'boot.ini'\n");
+ Status = UpdateBootIni(SystemRootPath->Buffer,
L"C:\\bootsect.ros",
L"\"ReactOS\"");
if (!NT_SUCCESS(Status))
return Status;
}
}
- else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
- DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
+ else
{
- /* Search for root directory for 'io.sys' and 'msdos.sys'. */
- DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
+ /* Non-NT bootloaders: install our own bootloader */
- /* Copy FreeLoader to the boot partition */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\freeldr.sys");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.sys");
+ PCWSTR Section;
+ PCWSTR Description;
+ PCWSTR BootDrive;
+ PCWSTR BootPartition;
+ PCWSTR BootSector;
- DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
- Status = SetupCopyFile(SrcPath, DstPath);
- if (!NT_SUCCESS(Status))
+ /* 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("SetupCopyFile() failed (Status %lx)\n", Status);
- return Status;
+ DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
+
+ Section = L"CPQDOS";
+ Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ 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
+ {
+ DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
+
+ Section = L"MSDOS";
+ Description = L"\"MS-DOS/Windows\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ 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");
+
+ Section = L"IBMDOS";
+ Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ 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");
+
+ Section = L"DRDOS";
+ Description = L"\"DR-DOS 3.x\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ else
+ /* 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");
+
+ Section = L"DRMK";
+ Description = L"\"Dell Real-Mode Kernel OS\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ else
+ /* 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");
+
+ Section = L"MSOS2";
+ Description = L"\"MS OS/2 1.x\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.OS2";
+ }
+ 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");
+
+ Section = L"IBMOS2";
+ Description = L"\"MS/IBM OS/2\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.OS2";
+ }
+ else
+ /* Search for FreeDOS boot loader */
+ if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
+ {
+ DPRINT1("Found FreeDOS boot loader\n");
+
+ Section = L"FDOS";
+ Description = L"\"FreeDOS\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.DOS";
+ }
+ else
+ {
+ /* No or unknown boot loader */
+ DPRINT1("No or unknown boot loader found\n");
+
+ Section = L"Unknown";
+ Description = L"\"Unknown Operating System\"";
+ BootDrive = L"hd0";
+ BootPartition = L"1";
+ BootSector = L"BOOTSECT.OLD";
}
/* Create or update 'freeldr.ini' */
- if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
+ if (DoesFreeLdrExist == FALSE)
{
/* Create new 'freeldr.ini' */
DPRINT1("Create new 'freeldr.ini'\n");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
- Status = CreateFreeLoaderIniForDos(DstPath,
- DestinationArcPath->Buffer);
- if (!NT_SUCCESS(Status))
+ if (IsThereAValidBootSector(SystemRootPath->Buffer))
{
- DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
- return Status;
- }
+ Status = CreateFreeLoaderIniForReactOSAndBootSector(
+ SystemRootPath->Buffer, DestinationArcPath->Buffer,
+ Section, Description,
+ BootDrive, BootPartition, BootSector);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
+ return Status;
+ }
- /* Save current bootsector as 'BOOTSECT.DOS' */
- wcscpy(SrcPath, SystemRootPath->Buffer);
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\bootsect.dos");
+ /* Save current bootsector */
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
- DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
- Status = SaveCurrentBootSector(SrcPath,
- DstPath);
- if (!NT_SUCCESS(Status))
+ DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
+ Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ }
+ else
{
- DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
- return Status;
+ Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
+ return Status;
+ }
}
- /* Install new bootsector */
+ /* Install new bootsector on the disk */
if (PartitionType == PARTITION_FAT32 ||
- PartitionType == PARTITION_FAT32_XINT13)
+ PartitionType == PARTITION_FAT32_XINT13)
{
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat32.bin");
+ /* Install FAT32 bootcode */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
- Status = InstallFat32BootCodeToDisk(SrcPath,
- SystemRootPath->Buffer);
+ Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
}
else
{
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat.bin");
+ /* Install FAT16 bootcode */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
- DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
- Status = InstallFat16BootCodeToDisk(SrcPath,
- SystemRootPath->Buffer);
+ DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
+ Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
}
}
}
- else
- {
- /* Update existing 'freeldr.ini' */
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
-
- Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
- return Status;
- }
- }
}
- else
- {
- /* No or unknown boot loader */
- DPRINT1("No or unknown boot loader found\n");
- /* Copy FreeLoader to the boot partition */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\freeldr.sys");
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.sys");
+ return STATUS_SUCCESS;
+}
- DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
- Status = SetupCopyFile(SrcPath, DstPath);
+static
+NTSTATUS
+InstallBtrfsBootcodeToPartition(
+ PUNICODE_STRING SystemRootPath,
+ PUNICODE_STRING SourceRootPath,
+ PUNICODE_STRING DestinationArcPath,
+ UCHAR PartitionType)
+{
+ NTSTATUS Status;
+ BOOLEAN DoesFreeLdrExist;
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
+
+ /* BTRFS partition */
+ DPRINT("System path: '%wZ'\n", SystemRootPath);
+
+ /* 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");
+
+ DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = SetupCopyFile(SrcPath, DstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ 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("SetupCopyFile() failed (Status %lx)\n", Status);
+ DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
return Status;
}
+ }
- /* Create or update 'freeldr.ini' */
- if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
+ /* 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");
+
+ if (IsThereAValidBootSector(SystemRootPath->Buffer))
{
- /* Create new freeldr.ini */
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
+ PCWSTR BootSector = L"BOOTSECT.OLD";
- DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
- Status = CreateFreeLoaderIniForReactos(DstPath,
- DestinationArcPath->Buffer);
+ Status = CreateFreeLoaderIniForReactOSAndBootSector(
+ SystemRootPath->Buffer, DestinationArcPath->Buffer,
+ L"Linux", L"\"Linux\"",
+ L"hd0", L"1", BootSector);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
+ DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
return Status;
}
- /* Save current bootsector as 'BOOTSECT.OLD' */
- wcscpy(SrcPath, SystemRootPath->Buffer);
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\bootsect.old");
+ /* Save current bootsector */
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
- DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
- Status = SaveCurrentBootSector(SrcPath,
- DstPath);
+ DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
+ Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(BTRFS_BOOTSECTOR));
if (!NT_SUCCESS(Status))
{
- DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
+ DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
return Status;
}
-
- /* Install new bootsector */
- if ((PartitionType == PARTITION_FAT32) ||
- (PartitionType == PARTITION_FAT32_XINT13))
- {
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat32.bin");
-
- DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
- Status = InstallFat32BootCodeToDisk(SrcPath,
- SystemRootPath->Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
- return Status;
- }
- }
- else
+ }
+ else
+ {
+ Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(Status))
{
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat.bin");
-
- DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
- Status = InstallFat16BootCodeToDisk(SrcPath,
- SystemRootPath->Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
- return Status;
- }
+ DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
+ return Status;
}
}
- else
+
+ /* Install new bootsector on the disk */
+ // if (PartitionType == PARTITION_EXT2)
{
- /* Update existing 'freeldr.ini' */
- wcscpy(DstPath, SystemRootPath->Buffer);
- wcscat(DstPath, L"\\freeldr.ini");
+ /* Install BTRFS bootcode */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
- Status = UpdateFreeLoaderIni(DstPath,
- DestinationArcPath->Buffer);
+ DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
+ Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer);
if (!NT_SUCCESS(Status))
{
- DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
+ DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status);
return Status;
}
}
}
return STATUS_SUCCESS;
-#else
- return STATUS_NOT_IMPLEMENTED;
-#endif
}
PUNICODE_STRING DestinationArcPath,
UCHAR PartitionType)
{
- if ((PartitionType == PARTITION_FAT_12) ||
- (PartitionType == PARTITION_FAT_16) ||
- (PartitionType == PARTITION_HUGE) ||
- (PartitionType == PARTITION_XINT13) ||
- (PartitionType == PARTITION_FAT32) ||
- (PartitionType == PARTITION_FAT32_XINT13))
- {
- return InstallFatBootcodeToPartition(SystemRootPath,
- SourceRootPath,
- DestinationArcPath,
- PartitionType);
+ switch (PartitionType)
+ {
+ case PARTITION_FAT_12:
+ case PARTITION_FAT_16:
+ case PARTITION_HUGE:
+ case PARTITION_XINT13:
+ case PARTITION_FAT32:
+ case PARTITION_FAT32_XINT13:
+ {
+ return InstallFatBootcodeToPartition(SystemRootPath,
+ SourceRootPath,
+ DestinationArcPath,
+ PartitionType);
+ }
+
+ case PARTITION_LINUX:
+ {
+ return InstallBtrfsBootcodeToPartition(SystemRootPath,
+ SourceRootPath,
+ DestinationArcPath,
+ PartitionType);
+ }
+
+ case PARTITION_IFS:
+ DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
+ break;
+
+ default:
+ DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
+ break;
}
return STATUS_UNSUCCESSFUL;
PUNICODE_STRING SourceRootPath,
PUNICODE_STRING DestinationArcPath)
{
-#ifdef __REACTOS__
- UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0");
+ NTSTATUS Status;
+ PFILE_SYSTEM FatFS;
+ UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
WCHAR SrcPath[MAX_PATH];
WCHAR DstPath[MAX_PATH];
- NTSTATUS Status;
/* Format the floppy first */
- Status = VfatFormat(&FloppyDevice,
- FMIFS_FLOPPY,
- NULL,
- TRUE,
- 0,
- NULL);
+ FatFS = GetFileSystemByName(L"FAT");
+ if (!FatFS)
+ {
+ DPRINT1("FAT FS non existent on this system?!\n");
+ return STATUS_NOT_SUPPORTED;
+ }
+ Status = FatFS->FormatFunc(&FloppyDevice,
+ FMIFS_FLOPPY,
+ NULL,
+ TRUE,
+ 0,
+ NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
}
/* Copy FreeLoader to the boot partition */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\freeldr.sys");
-
- wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.sys");
DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
Status = SetupCopyFile(SrcPath, DstPath);
}
/* Create new 'freeldr.ini' */
- wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
-
DPRINT("Create new 'freeldr.ini'\n");
- Status = CreateFreeLoaderIniForReactos(DstPath, DestinationArcPath->Buffer);
+ Status = CreateFreeLoaderIniForReactOS(FloppyDevice.Buffer, DestinationArcPath->Buffer);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
+ DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
return Status;
}
- /* Install FAT12/16 boosector */
- wcscpy(SrcPath, SourceRootPath->Buffer);
- wcscat(SrcPath, L"\\loader\\fat.bin");
-
- wcscpy(DstPath, L"\\Device\\Floppy0");
+ /* Install FAT12 boosector */
+ CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
+ CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice.Buffer);
DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
if (!NT_SUCCESS(Status))
{
- DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
+ DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status);
return Status;
}
return STATUS_SUCCESS;
-#else
- return STATUS_NOT_IMPLEMENTED;
-#endif
}
/* EOF */