* PROGRAMMER: Eric Kohl
*/
-#include <ddk/ntddk.h>
-#include <ntdll/rtl.h>
+#include <usetup.h>
-#include "usetup.h"
-#include "inicache.h"
-#include "bootsup.h"
+#define NDEBUG
+#include <debug.h>
+#define SECTORSIZE 512
/* FUNCTIONS ****************************************************************/
IniSection = IniCacheAppendSection(IniCache,
L"FREELOADER");
-#if 0
-MessageLine=Welcome to FreeLoader!
-MessageLine=Copyright (c) 2002 by Brian Palmer <brianp@sginet.com>
-MessageLine=
-MessageBox=Edit your FREELDR.INI file to change your boot settings.
-#endif
-
/* DefaultOS=ReactOS */
IniCacheInsertKey(IniSection,
NULL,
L"TimeOut",
L"10");
-
/* Create "Display" section */
IniSection = IniCacheAppendSection(IniCache,
L"Display");
- /* DisplayMode=NORMAL_VGA */
- IniCacheInsertKey(IniSection,
- NULL,
- INSERT_LAST,
- L"DisplayMode",
- L"NORMAL_VGA");
-
- /* TitleText=Boot Menu */
+ /* TitleText=ReactOS Boot Manager */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
L"TitleText",
- L"Boot Menu");
+ L"ReactOS Boot Manager");
/* StatusBarColor=Cyan */
IniCacheInsertKey(IniSection,
NTSTATUS
CreateFreeLoaderIniForDos(PWCHAR IniPath,
- PWCHAR SystemPath)
+ PWCHAR ArcPath)
{
PINICACHE IniCache;
PINICACHESECTION IniSection;
CreateCommonFreeLoaderSections(IniCache);
- /* Create "OperatingSystems" section */
+ /* Create "Operating Systems" section */
IniSection = IniCacheAppendSection(IniCache,
- L"OperatingSystems");
+ L"Operating Systems");
/* REACTOS=ReactOS */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
- L"REACTOS",
- L"ReactOS");
+ 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");
+ L"\"DOS/Windows\"");
- /* Create "REACTOS" section */
+ /* Create "ReactOS" section */
IniSection = IniCacheAppendSection(IniCache,
- L"REACTOS");
+ L"ReactOS");
/* BootType=ReactOS */
IniCacheInsertKey(IniSection,
L"BootType",
L"ReactOS");
- /* SystemPath=multi(0)disk(0)rdisk(0)partition(1)\reactos */
+ /* SystemPath=<ArcPath> */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
L"SystemPath",
- SystemPath);
+ ArcPath);
+
+ /* Create "ReactOS_Debug" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"ReactOS_Debug");
- /* Options=/DEBUGPORT=SCREEN */
+ /* BootType=ReactOS */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
- L"Options",
- L"/DEBUGPORT=SCREEN");
-
+ L"BootType",
+ L"ReactOS");
- /* Kernel=\REACTOS\SYSTEM32\NTOSKRNL.EXE */
-#if 0
+ /* SystemPath=<ArcPath> */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
- L"Options",
- L"/DEBUGPORT=SCREEN");
-#endif
+ L"SystemPath",
+ ArcPath);
- /* Hal=\REACTOS\SYSTEM32\HAL.DLL */
-#if 0
+ /* Options=/DEBUGPORT=SCREEN /NOGUIBOOT */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
- L"Hal",
- L"/DEBUGPORT=SCREEN");
-#endif
+ L"Options",
+ L"/DEBUGPORT=SCREEN /NOGUIBOOT");
/* Create "DOS" section */
IniSection = IniCacheAppendSection(IniCache,
L"BootType",
L"BootSector");
- /* BootSector=BOOTDOS.BIN */
+ /* 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
+CreateFreeLoaderIniForReactos(PWCHAR IniPath,
+ PWCHAR 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)\"");
+
+ /* 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=/DEBUGPORT=SCREEN /NOGUIBOOT */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"Options",
+ L"/DEBUGPORT=SCREEN /NOGUIBOOT");
+
+ /* Save the ini file */
+ IniCacheSave(IniCache, IniPath);
+ IniCacheDestroy(IniCache);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+UpdateFreeLoaderIni(PWCHAR IniPath,
+ PWCHAR 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);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ /* Get "Operating Systems" section */
+ IniSection = IniCacheGetSection(IniCache,
+ L"Operating Systems");
+ if (IniSection == NULL)
+ {
+ IniCacheDestroy(IniCache);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* 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;
+
+ /* 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);
+ }
+
+ OsIniSection = IniCacheGetSection(IniCache,
+ SectionName2);
+ if (OsIniSection != NULL)
+ {
+ BOOLEAN UseExistingEntry = TRUE;
+
+ /* 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;
+ }
+
+ 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;
+ }
+ }
+
+ if (UseExistingEntry)
+ {
+ IniCacheDestroy(IniCache);
+ return(STATUS_SUCCESS);
+ }
+ }
+
+ swprintf(SectionName, L"ReactOS_%lu", i);
+ swprintf(OsName, L"\"ReactOS %lu\"", i);
+ i++;
+ }
+
+ /* <SectionName>=<OsName> */
IniCacheInsertKey(IniSection,
NULL,
INSERT_LAST,
- L"BootSector",
- L"BOOTDOS.BIN");
+ SectionName,
+ OsName);
+
+ /* Create <SectionName> section */
+ IniSection = IniCacheAppendSection(IniCache,
+ SectionName);
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
IniCacheSave(IniCache, IniPath);
IniCacheDestroy(IniCache);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+SaveCurrentBootSector(PWSTR RootPath,
+ PWSTR DstPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR BootSector;
+
+ /* Allocate buffer for bootsector */
+ BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (BootSector == 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,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return(Status);
+ }
+
+ /* Write bootsector to DstPath */
+ RtlInitUnicodeString(&Name,
+ DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE,
+ &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, BootSector);
+ return(Status);
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)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,
+ &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);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ 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);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT BPB) */
+ memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to DstPath */
+ RtlInitUnicodeString(&Name,
+ DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(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);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+ LARGE_INTEGER FileOffset;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)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,
+ &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);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy((NewBootSector + 3),
+ (OrigBootSector + 3),
+ 87); /* FAT32 BPB length */
+
+ /* Disable the backup boot sector */
+ NewBootSector[0x32] = 0x00;
+ NewBootSector[0x33] = 0x00;
+
+ /* 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,
+ &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 */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ (NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallMbrBootCodeToDisk (PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PPARTITION_SECTOR OrigBootSector;
+ PPARTITION_SECTOR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(PARTITION_SECTOR));
+ 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,
+ &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);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(PARTITION_SECTOR));
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ sizeof(PARTITION_SECTOR),
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ 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 */);
+
+ /* 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,
+ &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);
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)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,
+ &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);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ 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);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT16 BPB) */
+ memcpy((NewBootSector + 3),
+ (OrigBootSector + 3),
+ 59); /* FAT16 BPB length*/
+
+ /* 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,
+ &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
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+ LARGE_INTEGER FileOffset;
+ USHORT BackupBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)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,
+ &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);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy((NewBootSector + 3),
+ (OrigBootSector + 3),
+ 87); /* FAT32 BPB length */
+
+ /* Get the location of the backup boot sector */
+ BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x32];
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE,
+ &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);
+ }
+
+ /* Write sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Write backup boot sector */
+ if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
+ {
+ FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+ }
+
+ /* Write sector 14 */
+ FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ (NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+UnprotectBootIni(PWSTR FileName,
+ PULONG 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,
+ &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,
+ &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;
+
+ 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);
+ }
+
+ IniCacheInsertKey(Section,
+ NULL,
+ INSERT_LAST,
+ EntryName,
+ EntryValue);
+
+ Status = UnprotectBootIni(BootIniPath,
+ &FileAttribute);
+ if (!NT_SUCCESS(Status))
+ {
+ IniCacheDestroy(Cache);
+ return(Status);
+ }
+
+ Status = IniCacheSave(Cache,
+ BootIniPath);
+ if (!NT_SUCCESS(Status))
+ {
+ IniCacheDestroy(Cache);
+ 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)
+{
+ 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;
+ }
+
+ return FALSE;
+}
+
+
+NTSTATUS
+InstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath,
+ PUNICODE_STRING SourceRootPath,
+ PUNICODE_STRING DestinationArcPath,
+ UCHAR PartitionType)
+{
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
+ NTSTATUS Status;
+
+ /* FAT or FAT32 partition */
+ DPRINT1("System path: '%wZ'\n", SystemRootPath);
+
+ if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
+ DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
+ {
+ /* 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);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Create or update freeldr.ini */
+ if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == 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);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Install new bootcode */
+ if (PartitionType == PARTITION_FAT32 ||
+ 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");
+
+ DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
+ Status = InstallFat32BootCodeToFile(SrcPath,
+ DstPath,
+ SystemRootPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+ }
+ else
+ {
+ /* Install FAT16 bootcode */
+ wcscpy(SrcPath, SourceRootPath->Buffer);
+ wcscat(SrcPath, L"\\loader\\fat.bin");
+ wcscpy(DstPath, SystemRootPath->Buffer);
+ wcscat(DstPath, L"\\bootsect.ros");
+
+ DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
+ Status = InstallFat16BootCodeToFile(SrcPath,
+ DstPath,
+ SystemRootPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallFat16BootCodeToFile() 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,
+ L"C:\\bootsect.ros",
+ L"\"ReactOS\"");
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
+ return 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;
+ }
+ }
+ }
+ else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
+ DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
+ {
+ /* Search for root directory for 'io.sys' and 'msdos.sys'. */
+ DPRINT1("Found Microsoft DOS or Windows 9x 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);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Create or update 'freeldr.ini' */
+ if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == 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))
+ {
+ DPRINT1("CreateFreeLoaderIniForDos() 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");
+
+ DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
+ Status = SaveCurrentBootSector(SrcPath,
+ DstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SaveCurrentBootSector() 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");
+
+ DPRINT1("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
+ {
+ wcscpy(SrcPath, SourceRootPath->Buffer);
+ wcscat(SrcPath, L"\\loader\\fat.bin");
+
+ DPRINT1("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;
+ }
+ }
+ }
+ 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");
+
+ DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = SetupCopyFile(SrcPath, DstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /* Create or update 'freeldr.ini' */
+ if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
+ {
+ /* Create new freeldr.ini */
+ wcscpy(DstPath, SystemRootPath->Buffer);
+ wcscat(DstPath, L"\\freeldr.ini");
+
+ DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
+ Status = CreateFreeLoaderIniForReactos(DstPath,
+ DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CreateFreeLoaderIniForReactos() 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");
+
+ DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
+ Status = SaveCurrentBootSector(SrcPath,
+ DstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SaveCurrentBootSector() 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
+ {
+ 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;
+ }
+ }
+ }
+ 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;
+ }
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+InstallFatBootcodeToFloppy(PUNICODE_STRING SourceRootPath,
+ PUNICODE_STRING DestinationArcPath)
+{
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
+ NTSTATUS Status;
+
+ /* Copy FreeLoader to the boot partition */
+ wcscpy(SrcPath, SourceRootPath->Buffer);
+ wcscat(SrcPath, L"\\loader\\freeldr.sys");
+
+ wcscpy(DstPath, L"\\Device\\Floppy0\\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;
+ }
+
+ /* Create new 'freeldr.ini' */
+ wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
+
+ DPRINT("Create new 'freeldr.ini'\n");
+ Status = CreateFreeLoaderIniForReactos(DstPath,
+ DestinationArcPath->Buffer);
+ if (!NT_SUCCESS(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");
+
+ DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
+ Status = InstallFat16BootCodeToDisk(SrcPath,
+ DstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ return STATUS_SUCCESS;
}
-/* EOF */
\ No newline at end of file
+/* EOF */