2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Setup Library
4 * FILE: base/setup/lib/bootsup.c
5 * PURPOSE: Bootloader support functions
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *****************************************************************/
19 #include "setuplib.h" // HAXX for IsUnattendedSetup!!
27 /* TYPEDEFS *****************************************************************/
33 * All that stuff *MUST* go into the fsutil.c module.
34 * Indeed, all that relates to filesystem formatting details and as such
35 * *MUST* be abstracted out from this module (bootsup.c).
36 * However, bootsup.c can still deal with MBR code (actually it'll have
37 * at some point to share or give it to partlist.c, because when we'll
38 * support GPT disks, things will change a bit).
39 * And, bootsup.c can still manage initializing / adding boot entries
40 * into NTLDR and FREELDR, and installing the latter, and saving the old
41 * MBR / boot sectors in files.
43 #define SECTORSIZE 512
46 typedef struct _FAT_BOOTSECTOR
48 UCHAR JumpBoot
[3]; // Jump instruction to boot code
49 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
50 USHORT BytesPerSector
; // Bytes per sector
51 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
52 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
53 UCHAR NumberOfFats
; // Number of FAT tables
54 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
55 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
56 UCHAR MediaDescriptor
; // Media descriptor byte
57 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
58 USHORT SectorsPerTrack
; // Number of sectors in a track
59 USHORT NumberOfHeads
; // Number of heads on the disk
60 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
61 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
62 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
63 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
64 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
65 ULONG VolumeSerialNumber
; // Volume serial number
66 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
67 CHAR FileSystemType
[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
69 UCHAR BootCodeAndData
[448]; // The remainder of the boot sector
71 USHORT BootSectorMagic
; // 0xAA55
73 } FAT_BOOTSECTOR
, *PFAT_BOOTSECTOR
;
75 typedef struct _FAT32_BOOTSECTOR
77 UCHAR JumpBoot
[3]; // Jump instruction to boot code
78 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
79 USHORT BytesPerSector
; // Bytes per sector
80 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
81 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
82 UCHAR NumberOfFats
; // Number of FAT tables
83 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
84 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
85 UCHAR MediaDescriptor
; // Media descriptor byte
86 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
87 USHORT SectorsPerTrack
; // Number of sectors in a track
88 USHORT NumberOfHeads
; // Number of heads on the disk
89 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
90 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
91 ULONG SectorsPerFatBig
; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
92 USHORT ExtendedFlags
; // Extended flags (fat32)
93 USHORT FileSystemVersion
; // File system version (fat32)
94 ULONG RootDirStartCluster
; // Starting cluster of the root directory (fat32)
95 USHORT FsInfo
; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
96 USHORT BackupBootSector
; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
97 UCHAR Reserved
[12]; // Reserved for future expansion
98 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
99 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
100 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
101 ULONG VolumeSerialNumber
; // Volume serial number
102 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
103 CHAR FileSystemType
[8]; // Always set to the string "FAT32 "
105 UCHAR BootCodeAndData
[420]; // The remainder of the boot sector
107 USHORT BootSectorMagic
; // 0xAA55
109 } FAT32_BOOTSECTOR
, *PFAT32_BOOTSECTOR
;
111 typedef struct _BTRFS_BOOTSECTOR
116 ULONGLONG PartitionStartLBA
;
117 UCHAR Fill
[1521]; // 1536 - 15
118 USHORT BootSectorMagic
;
119 } BTRFS_BOOTSECTOR
, *PBTRFS_BOOTSECTOR
;
120 C_ASSERT(sizeof(BTRFS_BOOTSECTOR
) == 3 * 512);
122 // TODO: Add more bootsector structures!
126 /* End of BIG FIXME!! */
129 /* FUNCTIONS ****************************************************************/
132 TrimTrailingPathSeparators_UStr(
133 IN OUT PUNICODE_STRING UnicodeString
)
135 while (UnicodeString
->Length
>= sizeof(WCHAR
) &&
136 UnicodeString
->Buffer
[UnicodeString
->Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
138 UnicodeString
->Length
-= sizeof(WCHAR
);
144 CreateFreeLoaderReactOSEntries(
145 IN PVOID BootStoreHandle
,
148 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
149 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
150 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
151 BOOT_STORE_OPTIONS BootOptions
;
153 BootEntry
->Version
= FreeLdr
;
154 BootEntry
->BootFilePath
= NULL
;
156 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
157 RtlCopyMemory(Options
->Signature
,
158 NTOS_OPTIONS_SIGNATURE
,
159 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
161 Options
->OsLoadPath
= ArcPath
;
164 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
165 BootEntry
->FriendlyName
= L
"\"ReactOS\"";
166 Options
->OsLoadOptions
= NULL
; // L"";
167 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS"));
170 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
171 BootEntry
->FriendlyName
= L
"\"ReactOS (Debug)\"";
172 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
173 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Debug"));
176 /* ReactOS_VBoxDebug */
177 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
178 BootEntry
->FriendlyName
= L
"\"ReactOS (VBoxDebug)\"";
179 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=VBOX /SOS";
180 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_VBoxDebug"));
184 /* ReactOS_KdSerial */
185 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
186 BootEntry
->FriendlyName
= L
"\"ReactOS (RosDbg)\"";
187 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
188 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_KdSerial"));
192 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
193 BootEntry
->FriendlyName
= L
"\"ReactOS (Screen)\"";
194 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=SCREEN /SOS";
195 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Screen"));
197 /* ReactOS_LogFile */
198 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
199 BootEntry
->FriendlyName
= L
"\"ReactOS (Log file)\"";
200 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=FILE /SOS";
201 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_LogFile"));
204 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
205 BootEntry
->FriendlyName
= L
"\"ReactOS (RAM Disk)\"";
206 Options
->OsLoadPath
= L
"ramdisk(0)\\ReactOS";
207 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
208 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Ram"));
211 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
212 BootEntry
->FriendlyName
= L
"\"ReactOS (Emergency Management Services)\"";
213 Options
->OsLoadPath
= ArcPath
;
214 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
215 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_EMS"));
220 if (IsUnattendedSetup
)
222 /* DefaultOS=ReactOS */
224 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_KdSerial");
226 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_Debug");
232 /* DefaultOS=ReactOS */
233 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS");
237 if (IsUnattendedSetup
)
240 /* Timeout=0 for unattended or non debug */
241 BootOptions
.Timeout
= 0;
247 BootOptions
.Timeout
= 10;
251 BootOptions
.Version
= FreeLdr
;
252 SetBootStoreOptions(BootStoreHandle
, &BootOptions
, 2 | 1);
256 CreateFreeLoaderIniForReactOS(
261 PVOID BootStoreHandle
;
263 /* Initialize the INI file and create the common FreeLdr sections */
264 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
265 if (!NT_SUCCESS(Status
))
268 /* Add the ReactOS entries */
269 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
271 /* Close the INI file */
272 CloseBootStore(BootStoreHandle
);
273 return STATUS_SUCCESS
;
277 CreateFreeLoaderIniForReactOSAndBootSector(
281 IN PCWSTR Description
,
283 IN PCWSTR BootPartition
,
284 IN PCWSTR BootSector
)
287 PVOID BootStoreHandle
;
288 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(BOOT_SECTOR_OPTIONS
)];
289 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
290 PBOOT_SECTOR_OPTIONS Options
= (PBOOT_SECTOR_OPTIONS
)&BootEntry
->OsOptions
;
292 /* Initialize the INI file and create the common FreeLdr sections */
293 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
294 if (!NT_SUCCESS(Status
))
297 /* Add the ReactOS entries */
298 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
300 BootEntry
->Version
= FreeLdr
;
301 BootEntry
->BootFilePath
= NULL
;
303 BootEntry
->OsOptionsLength
= sizeof(BOOT_SECTOR_OPTIONS
);
304 RtlCopyMemory(Options
->Signature
,
305 BOOT_SECTOR_OPTIONS_SIGNATURE
,
306 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS
, Signature
));
308 Options
->Drive
= BootDrive
;
309 Options
->Partition
= BootPartition
;
310 Options
->BootSectorFileName
= BootSector
;
312 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
313 BootEntry
->FriendlyName
= Description
;
314 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Section
));
316 /* Close the INI file */
317 CloseBootStore(BootStoreHandle
);
318 return STATUS_SUCCESS
;
322 // I think this function can be generalizable as:
323 // "find the corresponding 'ReactOS' boot entry in this loader config file
324 // (here abstraction comes there), and if none, add a new one".
327 typedef struct _ENUM_REACTOS_ENTRIES_DATA
330 BOOLEAN UseExistingEntry
;
332 WCHAR SectionName
[80];
334 } ENUM_REACTOS_ENTRIES_DATA
, *PENUM_REACTOS_ENTRIES_DATA
;
336 // PENUM_BOOT_ENTRIES_ROUTINE
339 EnumerateReactOSEntries(
340 IN BOOT_STORE_TYPE Type
,
341 IN PBOOT_STORE_ENTRY BootEntry
,
342 IN PVOID Parameter OPTIONAL
)
344 PENUM_REACTOS_ENTRIES_DATA Data
= (PENUM_REACTOS_ENTRIES_DATA
)Parameter
;
345 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
346 WCHAR SystemPath
[MAX_PATH
];
348 /* We have a boot entry */
350 /* Check for supported boot type "Windows2003" */
351 if (BootEntry
->OsOptionsLength
< sizeof(NTOS_OPTIONS
) ||
352 RtlCompareMemory(&BootEntry
->OsOptions
/* Signature */,
353 NTOS_OPTIONS_SIGNATURE
,
354 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
)) !=
355 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
))
357 /* This is not a ReactOS entry */
358 // DPRINT1(" An installation '%S' of unsupported type '%S'\n",
359 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
360 DPRINT1(" An installation '%S' of unsupported type %lu\n",
361 BootEntry
->FriendlyName
, BootEntry
->OsOptionsLength
);
362 /* Continue the enumeration */
366 /* BootType is Windows2003, now check OsLoadPath */
367 if (!Options
->OsLoadPath
|| !*Options
->OsLoadPath
)
369 /* Certainly not a ReactOS installation */
370 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry
->FriendlyName
);
371 /* Continue the enumeration */
375 RtlStringCchPrintfW(SystemPath
, ARRAYSIZE(SystemPath
), L
"\"%s\"", Data
->ArcPath
);
376 if ((_wcsicmp(Options
->OsLoadPath
, Data
->ArcPath
) != 0) &&
377 (_wcsicmp(Options
->OsLoadPath
, SystemPath
) != 0))
380 * This entry is a ReactOS entry, but the SystemRoot
381 * does not match the one we are looking for.
383 /* Continue the enumeration */
387 DPRINT1(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
388 BootEntry
->FriendlyName
, Options
->OsLoadPath
);
389 // DPRINT1(" Found a Win2k3 install '%S' with ARC path '%S'\n",
390 // BootEntry->FriendlyName, Options->OsLoadPath);
392 DPRINT1("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options
->OsLoadPath
);
394 Data
->UseExistingEntry
= TRUE
;
395 RtlStringCchCopyW(Data
->OsName
, ARRAYSIZE(Data
->OsName
), BootEntry
->FriendlyName
);
397 /* We have found our entry, stop the enumeration now! */
398 return STATUS_NO_MORE_ENTRIES
;
401 Data
->UseExistingEntry
= FALSE
;
402 if (Type
== FreeLdr
&& wcscmp(Data
->SectionName
, (PWSTR
)BootEntry
->BootEntryKey
)== 0)
404 RtlStringCchPrintfW(Data
->SectionName
, ARRAYSIZE(Data
->SectionName
),
405 L
"ReactOS_%lu", Data
->i
);
406 RtlStringCchPrintfW(Data
->OsName
, ARRAYSIZE(Data
->OsName
),
407 L
"\"ReactOS %lu\"", Data
->i
);
410 return STATUS_SUCCESS
;
420 PVOID BootStoreHandle
;
421 ENUM_REACTOS_ENTRIES_DATA Data
;
422 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
423 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
424 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
426 /* Open the INI file */
427 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, /*TRUE*/ FALSE
);
428 if (!NT_SUCCESS(Status
))
431 /* Find an existing usable or an unused section name */
432 Data
.UseExistingEntry
= TRUE
;
434 Data
.ArcPath
= ArcPath
;
435 RtlStringCchCopyW(Data
.SectionName
, ARRAYSIZE(Data
.SectionName
), L
"ReactOS");
436 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
439 // FIXME: We temporarily use EnumerateBootStoreEntries, until
440 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
442 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
444 /* Create a new "ReactOS" entry if there is none already existing that suits us */
445 if (!Data
.UseExistingEntry
)
447 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
448 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
450 BootEntry
->Version
= FreeLdr
;
451 BootEntry
->BootFilePath
= NULL
;
453 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
454 RtlCopyMemory(Options
->Signature
,
455 NTOS_OPTIONS_SIGNATURE
,
456 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
458 Options
->OsLoadPath
= ArcPath
;
460 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
461 BootEntry
->FriendlyName
= Data
.OsName
;
462 Options
->OsLoadOptions
= NULL
; // L"";
463 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Data
.SectionName
));
466 /* Close the INI file */
467 CloseBootStore(BootStoreHandle
);
468 return STATUS_SUCCESS
;
475 IN PCWSTR EntryName
, // ~= ArcPath
476 IN PCWSTR EntryValue
)
479 PVOID BootStoreHandle
;
480 ENUM_REACTOS_ENTRIES_DATA Data
;
482 // NOTE: Technically it would be "BootSector"...
483 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
484 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
485 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
487 /* Open the INI file */
488 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, NtLdr
, FALSE
);
489 if (!NT_SUCCESS(Status
))
492 /* Find an existing usable or an unused section name */
493 Data
.UseExistingEntry
= TRUE
;
495 Data
.ArcPath
= EntryName
;
496 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
497 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
500 // FIXME: We temporarily use EnumerateBootStoreEntries, until
501 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
503 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
505 /* If either the key was not found, or contains something else, add a new one */
506 if (!Data
.UseExistingEntry
/* ||
507 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
509 BootEntry
->Version
= NtLdr
;
510 BootEntry
->BootFilePath
= NULL
;
512 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
513 RtlCopyMemory(Options
->Signature
,
514 NTOS_OPTIONS_SIGNATURE
,
515 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
517 Options
->OsLoadPath
= EntryName
;
519 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
520 // BootEntry->FriendlyName = Data.OsName;
521 BootEntry
->FriendlyName
= EntryValue
;
522 Options
->OsLoadOptions
= NULL
; // L"";
523 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(0 /*Data.SectionName*/));
526 /* Close the INI file */
527 CloseBootStore(BootStoreHandle
);
528 return STATUS_SUCCESS
; // Status;
534 IsThereAValidBootSector(
538 * We first demand that the bootsector has a valid signature at its end.
539 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
540 * potential "valid" instruction (the BIOS starts execution of the bootsector
541 * at its beginning). Currently this criterium is that this ULONG must be
542 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
543 * it is invalid and certainly needs to be overwritten.
546 BOOLEAN IsValid
= FALSE
;
548 UNICODE_STRING RootPartition
;
549 OBJECT_ATTRIBUTES ObjectAttributes
;
550 IO_STATUS_BLOCK IoStatusBlock
;
552 LARGE_INTEGER FileOffset
;
556 /* Allocate buffer for bootsector */
557 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
558 if (BootSector
== NULL
)
559 return FALSE
; // STATUS_INSUFFICIENT_RESOURCES;
560 RtlZeroMemory(BootSector
, SECTORSIZE
);
562 /* Open the root partition - Remove any trailing backslash if needed */
563 RtlInitUnicodeString(&RootPartition
, RootPath
);
564 TrimTrailingPathSeparators_UStr(&RootPartition
);
566 InitializeObjectAttributes(&ObjectAttributes
,
568 OBJ_CASE_INSENSITIVE
,
572 Status
= NtOpenFile(&FileHandle
,
573 GENERIC_READ
| SYNCHRONIZE
,
577 FILE_SYNCHRONOUS_IO_NONALERT
);
578 if (!NT_SUCCESS(Status
))
581 /* Read current boot sector into buffer */
582 FileOffset
.QuadPart
= 0ULL;
583 Status
= NtReadFile(FileHandle
,
593 if (!NT_SUCCESS(Status
))
596 /* Check the instruction; we use a ULONG to read three bytes */
597 Instruction
= (*(PULONG
)BootSector
) & 0x00FFFFFF;
598 IsValid
= (Instruction
!= 0x00000000);
600 /* Check the bootsector signature */
601 IsValid
&= (*(PUSHORT
)(BootSector
+ 0x1fe) == 0xaa55);
604 /* Free the boot sector */
605 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
606 return IsValid
; // Status;
618 OBJECT_ATTRIBUTES ObjectAttributes
;
619 IO_STATUS_BLOCK IoStatusBlock
;
621 LARGE_INTEGER FileOffset
;
624 /* Allocate buffer for bootsector */
625 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, Length
);
626 if (BootSector
== NULL
)
627 return STATUS_INSUFFICIENT_RESOURCES
;
629 /* Open the root partition - Remove any trailing backslash if needed */
630 RtlInitUnicodeString(&Name
, RootPath
);
631 TrimTrailingPathSeparators_UStr(&Name
);
633 InitializeObjectAttributes(&ObjectAttributes
,
635 OBJ_CASE_INSENSITIVE
,
639 Status
= NtOpenFile(&FileHandle
,
640 GENERIC_READ
| SYNCHRONIZE
,
644 FILE_SYNCHRONOUS_IO_NONALERT
);
645 if (!NT_SUCCESS(Status
))
647 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
651 /* Read current boot sector into buffer */
652 FileOffset
.QuadPart
= 0ULL;
653 Status
= NtReadFile(FileHandle
,
663 if (!NT_SUCCESS(Status
))
665 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
669 /* Write bootsector to DstPath */
670 RtlInitUnicodeString(&Name
, DstPath
);
672 InitializeObjectAttributes(&ObjectAttributes
,
678 Status
= NtCreateFile(&FileHandle
,
679 GENERIC_WRITE
| SYNCHRONIZE
,
683 FILE_ATTRIBUTE_NORMAL
,
686 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
689 if (!NT_SUCCESS(Status
))
691 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
695 Status
= NtWriteFile(FileHandle
,
706 /* Free the boot sector */
707 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
715 InstallMbrBootCodeToDiskHelper(
721 OBJECT_ATTRIBUTES ObjectAttributes
;
722 IO_STATUS_BLOCK IoStatusBlock
;
724 LARGE_INTEGER FileOffset
;
725 PPARTITION_SECTOR OrigBootSector
;
726 PPARTITION_SECTOR NewBootSector
;
728 /* Allocate buffer for original bootsector */
729 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
730 if (OrigBootSector
== NULL
)
731 return STATUS_INSUFFICIENT_RESOURCES
;
733 /* Open the root partition - Remove any trailing backslash if needed */
734 RtlInitUnicodeString(&Name
, RootPath
);
735 TrimTrailingPathSeparators_UStr(&Name
);
737 InitializeObjectAttributes(&ObjectAttributes
,
739 OBJ_CASE_INSENSITIVE
,
743 Status
= NtOpenFile(&FileHandle
,
744 GENERIC_READ
| SYNCHRONIZE
,
748 FILE_SYNCHRONOUS_IO_NONALERT
);
749 if (!NT_SUCCESS(Status
))
751 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
755 /* Read current boot sector into buffer */
756 FileOffset
.QuadPart
= 0ULL;
757 Status
= NtReadFile(FileHandle
,
763 sizeof(PARTITION_SECTOR
),
767 if (!NT_SUCCESS(Status
))
769 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
773 /* Allocate buffer for new bootsector */
774 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
775 if (NewBootSector
== NULL
)
777 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
778 return STATUS_INSUFFICIENT_RESOURCES
;
781 /* Read new bootsector from SrcPath */
782 RtlInitUnicodeString(&Name
, SrcPath
);
784 InitializeObjectAttributes(&ObjectAttributes
,
786 OBJ_CASE_INSENSITIVE
,
790 Status
= NtOpenFile(&FileHandle
,
791 GENERIC_READ
| SYNCHRONIZE
,
795 FILE_SYNCHRONOUS_IO_NONALERT
);
796 if (!NT_SUCCESS(Status
))
798 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
799 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
803 Status
= NtReadFile(FileHandle
,
809 sizeof(PARTITION_SECTOR
),
813 if (!NT_SUCCESS(Status
))
815 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
816 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
821 * Copy the disk signature, the reserved fields and
822 * the partition table from the old MBR to the new one.
824 RtlCopyMemory(&NewBootSector
->Signature
,
825 &OrigBootSector
->Signature
,
826 sizeof(PARTITION_SECTOR
) - offsetof(PARTITION_SECTOR
, Signature
)
827 /* Length of partition table */);
829 /* Free the original boot sector */
830 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
832 /* Open the root partition - Remove any trailing backslash if needed */
833 RtlInitUnicodeString(&Name
, RootPath
);
834 TrimTrailingPathSeparators_UStr(&Name
);
836 InitializeObjectAttributes(&ObjectAttributes
,
842 Status
= NtOpenFile(&FileHandle
,
843 GENERIC_WRITE
| SYNCHRONIZE
,
847 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
848 if (!NT_SUCCESS(Status
))
850 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
851 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
855 /* Write new bootsector to RootPath */
856 FileOffset
.QuadPart
= 0ULL;
857 Status
= NtWriteFile(FileHandle
,
863 sizeof(PARTITION_SECTOR
),
868 /* Free the new boot sector */
869 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
875 InstallMbrBootCodeToDisk(
876 IN PUNICODE_STRING SystemRootPath
,
877 IN PUNICODE_STRING SourceRootPath
,
878 IN PCWSTR DestinationDevicePathBuffer
)
881 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
882 WCHAR DstPath
[MAX_PATH
];
885 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
886 StringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
887 L
"\\Device\\Harddisk%d\\Partition0",
891 CombinePaths(SourceMbrPathBuffer
, ARRAYSIZE(SourceMbrPathBuffer
), 2,
892 SourceRootPath
->Buffer
, L
"\\loader\\dosmbr.bin");
894 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
896 /* Save current MBR */
897 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2,
898 SystemRootPath
->Buffer
, L
"mbr.old");
900 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
901 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
902 if (!NT_SUCCESS(Status
))
904 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
905 // Don't care if we succeeded or not saving the old MBR, just go ahead.
909 DPRINT1("Install MBR bootcode: %S ==> %S\n",
910 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
912 return InstallMbrBootCodeToDiskHelper(SourceMbrPathBuffer
,
913 DestinationDevicePathBuffer
);
919 InstallFat12BootCodeToFloppy(
925 OBJECT_ATTRIBUTES ObjectAttributes
;
926 IO_STATUS_BLOCK IoStatusBlock
;
928 LARGE_INTEGER FileOffset
;
929 PFAT_BOOTSECTOR OrigBootSector
;
930 PFAT_BOOTSECTOR NewBootSector
;
932 /* Allocate buffer for original bootsector */
933 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
934 if (OrigBootSector
== NULL
)
935 return STATUS_INSUFFICIENT_RESOURCES
;
937 /* Open the root partition - Remove any trailing backslash if needed */
938 RtlInitUnicodeString(&Name
, RootPath
);
939 TrimTrailingPathSeparators_UStr(&Name
);
941 InitializeObjectAttributes(&ObjectAttributes
,
943 OBJ_CASE_INSENSITIVE
,
947 Status
= NtOpenFile(&FileHandle
,
948 GENERIC_READ
| SYNCHRONIZE
,
952 FILE_SYNCHRONOUS_IO_NONALERT
);
953 if (!NT_SUCCESS(Status
))
955 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
959 /* Read current boot sector into buffer */
960 FileOffset
.QuadPart
= 0ULL;
961 Status
= NtReadFile(FileHandle
,
971 if (!NT_SUCCESS(Status
))
973 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
977 /* Allocate buffer for new bootsector */
978 NewBootSector
= RtlAllocateHeap(ProcessHeap
,
981 if (NewBootSector
== NULL
)
983 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
984 return STATUS_INSUFFICIENT_RESOURCES
;
987 /* Read new bootsector from SrcPath */
988 RtlInitUnicodeString(&Name
, SrcPath
);
990 InitializeObjectAttributes(&ObjectAttributes
,
992 OBJ_CASE_INSENSITIVE
,
996 Status
= NtOpenFile(&FileHandle
,
997 GENERIC_READ
| SYNCHRONIZE
,
1001 FILE_SYNCHRONOUS_IO_NONALERT
);
1002 if (!NT_SUCCESS(Status
))
1004 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1005 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1009 Status
= NtReadFile(FileHandle
,
1018 NtClose(FileHandle
);
1019 if (!NT_SUCCESS(Status
))
1021 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1022 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1026 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1027 memcpy(&NewBootSector
->OemName
,
1028 &OrigBootSector
->OemName
,
1029 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
1030 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
1032 /* Free the original boot sector */
1033 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1035 /* Open the root partition - Remove any trailing backslash if needed */
1036 RtlInitUnicodeString(&Name
, RootPath
);
1037 TrimTrailingPathSeparators_UStr(&Name
);
1039 InitializeObjectAttributes(&ObjectAttributes
,
1045 Status
= NtOpenFile(&FileHandle
,
1046 GENERIC_WRITE
| SYNCHRONIZE
,
1050 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1051 if (!NT_SUCCESS(Status
))
1053 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1054 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1058 /* Write new bootsector to RootPath */
1059 FileOffset
.QuadPart
= 0ULL;
1060 Status
= NtWriteFile(FileHandle
,
1069 NtClose(FileHandle
);
1071 /* Free the new boot sector */
1072 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1079 InstallFat16BootCode(
1080 IN PCWSTR SrcPath
, // FAT16 bootsector source file (on the installation medium)
1081 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1082 IN HANDLE RootPartition
) // Partition holding the (old) FAT16 information
1085 UNICODE_STRING Name
;
1086 OBJECT_ATTRIBUTES ObjectAttributes
;
1087 IO_STATUS_BLOCK IoStatusBlock
;
1089 LARGE_INTEGER FileOffset
;
1090 PFAT_BOOTSECTOR OrigBootSector
;
1091 PFAT_BOOTSECTOR NewBootSector
;
1093 /* Allocate a buffer for the original bootsector */
1094 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1095 if (OrigBootSector
== NULL
)
1096 return STATUS_INSUFFICIENT_RESOURCES
;
1098 /* Read the current partition boot sector into the buffer */
1099 FileOffset
.QuadPart
= 0ULL;
1100 Status
= NtReadFile(RootPartition
,
1109 if (!NT_SUCCESS(Status
))
1111 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1115 /* Allocate a buffer for the new bootsector */
1116 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1117 if (NewBootSector
== NULL
)
1119 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1120 return STATUS_INSUFFICIENT_RESOURCES
;
1123 /* Read the new bootsector from SrcPath */
1124 RtlInitUnicodeString(&Name
, SrcPath
);
1125 InitializeObjectAttributes(&ObjectAttributes
,
1127 OBJ_CASE_INSENSITIVE
,
1130 Status
= NtOpenFile(&FileHandle
,
1131 GENERIC_READ
| SYNCHRONIZE
,
1135 FILE_SYNCHRONOUS_IO_NONALERT
);
1136 if (!NT_SUCCESS(Status
))
1138 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1139 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1143 FileOffset
.QuadPart
= 0ULL;
1144 Status
= NtReadFile(FileHandle
,
1153 NtClose(FileHandle
);
1154 if (!NT_SUCCESS(Status
))
1156 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1157 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1161 /* Adjust the bootsector (copy a part of the FAT16 BPB) */
1162 memcpy(&NewBootSector
->OemName
,
1163 &OrigBootSector
->OemName
,
1164 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
1165 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
1167 /* Free the original boot sector */
1168 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1170 /* Write the new bootsector to DstPath */
1171 FileOffset
.QuadPart
= 0ULL;
1172 Status
= NtWriteFile(DstPath
,
1182 /* Free the new boot sector */
1183 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1190 InstallFat16BootCodeToFile(
1196 UNICODE_STRING Name
;
1197 OBJECT_ATTRIBUTES ObjectAttributes
;
1198 IO_STATUS_BLOCK IoStatusBlock
;
1199 HANDLE PartitionHandle
, FileHandle
;
1202 * Open the root partition from which the boot sector
1203 * parameters will be obtained.
1204 * Remove any trailing backslash if needed.
1206 RtlInitUnicodeString(&Name
, RootPath
);
1207 TrimTrailingPathSeparators_UStr(&Name
);
1209 InitializeObjectAttributes(&ObjectAttributes
,
1211 OBJ_CASE_INSENSITIVE
,
1214 Status
= NtOpenFile(&PartitionHandle
,
1215 GENERIC_READ
| SYNCHRONIZE
,
1219 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1220 if (!NT_SUCCESS(Status
))
1223 /* Open or create the file where the new bootsector will be saved */
1224 RtlInitUnicodeString(&Name
, DstPath
);
1225 InitializeObjectAttributes(&ObjectAttributes
,
1227 0, // OBJ_CASE_INSENSITIVE,
1230 Status
= NtCreateFile(&FileHandle
,
1231 GENERIC_WRITE
| SYNCHRONIZE
,
1235 FILE_ATTRIBUTE_NORMAL
,
1238 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1241 if (!NT_SUCCESS(Status
))
1243 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1244 NtClose(PartitionHandle
);
1248 /* Install the FAT16 boot sector */
1249 Status
= InstallFat16BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1251 /* Close the file and the partition */
1252 NtClose(FileHandle
);
1253 NtClose(PartitionHandle
);
1260 InstallFat16BootCodeToDisk(
1265 UNICODE_STRING Name
;
1266 OBJECT_ATTRIBUTES ObjectAttributes
;
1267 IO_STATUS_BLOCK IoStatusBlock
;
1268 HANDLE PartitionHandle
;
1271 * Open the root partition from which the boot sector parameters will be
1272 * obtained; this is also where we will write the updated boot sector.
1273 * Remove any trailing backslash if needed.
1275 RtlInitUnicodeString(&Name
, RootPath
);
1276 TrimTrailingPathSeparators_UStr(&Name
);
1278 InitializeObjectAttributes(&ObjectAttributes
,
1280 OBJ_CASE_INSENSITIVE
,
1283 Status
= NtOpenFile(&PartitionHandle
,
1284 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1288 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1289 if (!NT_SUCCESS(Status
))
1292 /* Install the FAT16 boot sector */
1293 Status
= InstallFat16BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1295 /* Close the partition */
1296 NtClose(PartitionHandle
);
1304 InstallFat32BootCode(
1305 IN PCWSTR SrcPath
, // FAT32 bootsector source file (on the installation medium)
1306 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1307 IN HANDLE RootPartition
) // Partition holding the (old) FAT32 information
1310 UNICODE_STRING Name
;
1311 OBJECT_ATTRIBUTES ObjectAttributes
;
1312 IO_STATUS_BLOCK IoStatusBlock
;
1314 LARGE_INTEGER FileOffset
;
1315 PFAT32_BOOTSECTOR OrigBootSector
;
1316 PFAT32_BOOTSECTOR NewBootSector
;
1317 USHORT BackupBootSector
;
1319 /* Allocate a buffer for the original bootsector */
1320 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1321 if (OrigBootSector
== NULL
)
1322 return STATUS_INSUFFICIENT_RESOURCES
;
1324 /* Read the current boot sector into the buffer */
1325 FileOffset
.QuadPart
= 0ULL;
1326 Status
= NtReadFile(RootPartition
,
1335 if (!NT_SUCCESS(Status
))
1337 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1341 /* Allocate a buffer for the new bootsector (2 sectors) */
1342 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, 2 * SECTORSIZE
);
1343 if (NewBootSector
== NULL
)
1345 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1346 return STATUS_INSUFFICIENT_RESOURCES
;
1349 /* Read the new bootsector from SrcPath */
1350 RtlInitUnicodeString(&Name
, SrcPath
);
1351 InitializeObjectAttributes(&ObjectAttributes
,
1353 OBJ_CASE_INSENSITIVE
,
1356 Status
= NtOpenFile(&FileHandle
,
1357 GENERIC_READ
| SYNCHRONIZE
,
1361 FILE_SYNCHRONOUS_IO_NONALERT
);
1362 if (!NT_SUCCESS(Status
))
1364 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1365 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1369 FileOffset
.QuadPart
= 0ULL;
1370 Status
= NtReadFile(FileHandle
,
1379 NtClose(FileHandle
);
1380 if (!NT_SUCCESS(Status
))
1382 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1383 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1387 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
1388 memcpy(&NewBootSector
->OemName
,
1389 &OrigBootSector
->OemName
,
1390 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1391 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1394 * We know we copy the boot code to a file only when DstPath != RootPartition,
1395 * otherwise the boot code is copied to the specified root partition.
1397 if (DstPath
!= RootPartition
)
1399 /* Copy to a file: Disable the backup boot sector */
1400 NewBootSector
->BackupBootSector
= 0;
1404 /* Copy to a disk: Get the location of the backup boot sector */
1405 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1408 /* Free the original boot sector */
1409 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1411 /* Write the first sector of the new bootcode to DstPath sector 0 */
1412 FileOffset
.QuadPart
= 0ULL;
1413 Status
= NtWriteFile(DstPath
,
1422 if (!NT_SUCCESS(Status
))
1424 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1425 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1429 if (DstPath
== RootPartition
)
1431 /* Copy to a disk: Write the backup boot sector */
1432 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1434 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1435 Status
= NtWriteFile(DstPath
,
1444 if (!NT_SUCCESS(Status
))
1446 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1447 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1453 /* Write the second sector of the new bootcode to boot disk sector 14 */
1454 // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1455 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1456 Status
= NtWriteFile(DstPath
, // or really RootPartition ???
1461 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1465 if (!NT_SUCCESS(Status
))
1467 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1470 /* Free the new boot sector */
1471 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1478 InstallFat32BootCodeToFile(
1484 UNICODE_STRING Name
;
1485 OBJECT_ATTRIBUTES ObjectAttributes
;
1486 IO_STATUS_BLOCK IoStatusBlock
;
1487 HANDLE PartitionHandle
, FileHandle
;
1490 * Open the root partition from which the boot sector parameters
1492 * FIXME? It might be possible that we need to also open it for writing
1493 * access in case we really need to still write the second portion of
1494 * the boot sector ????
1496 * Remove any trailing backslash if needed.
1498 RtlInitUnicodeString(&Name
, RootPath
);
1499 TrimTrailingPathSeparators_UStr(&Name
);
1501 InitializeObjectAttributes(&ObjectAttributes
,
1503 OBJ_CASE_INSENSITIVE
,
1506 Status
= NtOpenFile(&PartitionHandle
,
1507 GENERIC_READ
| SYNCHRONIZE
,
1511 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1512 if (!NT_SUCCESS(Status
))
1515 /* Open or create the file where (the first sector of ????) the new bootsector will be saved */
1516 RtlInitUnicodeString(&Name
, DstPath
);
1517 InitializeObjectAttributes(&ObjectAttributes
,
1519 0, // OBJ_CASE_INSENSITIVE,
1522 Status
= NtCreateFile(&FileHandle
,
1523 GENERIC_WRITE
| SYNCHRONIZE
,
1527 FILE_ATTRIBUTE_NORMAL
,
1529 FILE_SUPERSEDE
, // FILE_OVERWRITE_IF, <- is used for FAT16
1530 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1533 if (!NT_SUCCESS(Status
))
1535 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1536 NtClose(PartitionHandle
);
1540 /* Install the FAT32 boot sector */
1541 Status
= InstallFat32BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1543 /* Close the file and the partition */
1544 NtClose(FileHandle
);
1545 NtClose(PartitionHandle
);
1552 InstallFat32BootCodeToDisk(
1557 UNICODE_STRING Name
;
1558 OBJECT_ATTRIBUTES ObjectAttributes
;
1559 IO_STATUS_BLOCK IoStatusBlock
;
1560 HANDLE PartitionHandle
;
1563 * Open the root partition from which the boot sector parameters will be
1564 * obtained; this is also where we will write the updated boot sector.
1565 * Remove any trailing backslash if needed.
1567 RtlInitUnicodeString(&Name
, RootPath
);
1568 TrimTrailingPathSeparators_UStr(&Name
);
1570 InitializeObjectAttributes(&ObjectAttributes
,
1572 OBJ_CASE_INSENSITIVE
,
1575 Status
= NtOpenFile(&PartitionHandle
,
1576 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1580 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1581 if (!NT_SUCCESS(Status
))
1584 /* Install the FAT32 boot sector */
1585 Status
= InstallFat32BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1587 /* Close the partition */
1588 NtClose(PartitionHandle
);
1595 InstallBtrfsBootCodeToDisk(
1600 UNICODE_STRING Name
;
1601 OBJECT_ATTRIBUTES ObjectAttributes
;
1602 IO_STATUS_BLOCK IoStatusBlock
;
1604 LARGE_INTEGER FileOffset
;
1605 // PEXT2_BOOTSECTOR OrigBootSector;
1606 PBTRFS_BOOTSECTOR NewBootSector
;
1607 // USHORT BackupBootSector;
1608 PARTITION_INFORMATION_EX PartInfo
;
1611 /* Allocate buffer for original bootsector */
1612 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1613 if (OrigBootSector
== NULL
)
1614 return STATUS_INSUFFICIENT_RESOURCES
;
1616 /* Open the root partition - Remove any trailing backslash if needed */
1617 RtlInitUnicodeString(&Name
, RootPath
);
1618 TrimTrailingPathSeparators_UStr(&Name
);
1620 InitializeObjectAttributes(&ObjectAttributes
,
1622 OBJ_CASE_INSENSITIVE
,
1626 Status
= NtOpenFile(&FileHandle
,
1627 GENERIC_READ
| SYNCHRONIZE
,
1631 FILE_SYNCHRONOUS_IO_NONALERT
);
1632 if (!NT_SUCCESS(Status
))
1634 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1638 /* Read current boot sector into buffer */
1639 FileOffset
.QuadPart
= 0ULL;
1640 Status
= NtReadFile(FileHandle
,
1649 NtClose(FileHandle
);
1650 if (!NT_SUCCESS(Status
))
1652 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1657 /* Allocate buffer for new bootsector */
1658 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(BTRFS_BOOTSECTOR
));
1659 if (NewBootSector
== NULL
)
1661 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1662 return STATUS_INSUFFICIENT_RESOURCES
;
1665 /* Read new bootsector from SrcPath */
1666 RtlInitUnicodeString(&Name
, SrcPath
);
1668 InitializeObjectAttributes(&ObjectAttributes
,
1670 OBJ_CASE_INSENSITIVE
,
1674 Status
= NtOpenFile(&FileHandle
,
1675 GENERIC_READ
| SYNCHRONIZE
,
1679 FILE_SYNCHRONOUS_IO_NONALERT
);
1680 if (!NT_SUCCESS(Status
))
1682 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1683 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1687 Status
= NtReadFile(FileHandle
,
1693 sizeof(BTRFS_BOOTSECTOR
),
1696 NtClose(FileHandle
);
1697 if (!NT_SUCCESS(Status
))
1699 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1700 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1705 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1706 memcpy(&NewBootSector
->OemName
,
1707 &OrigBootSector
->OemName
,
1708 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1709 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1711 /* Get the location of the backup boot sector */
1712 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1714 /* Free the original boot sector */
1715 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1718 /* Open the root partition - Remove any trailing backslash if needed */
1719 RtlInitUnicodeString(&Name
, RootPath
);
1720 TrimTrailingPathSeparators_UStr(&Name
);
1722 InitializeObjectAttributes(&ObjectAttributes
,
1728 Status
= NtOpenFile(&FileHandle
,
1729 GENERIC_WRITE
| SYNCHRONIZE
,
1733 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1734 if (!NT_SUCCESS(Status
))
1736 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1737 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1741 /* Obtaining partition info and writing it to bootsector */
1742 Status
= NtDeviceIoControlFile(FileHandle
,
1747 IOCTL_DISK_GET_PARTITION_INFO_EX
,
1752 if (!NT_SUCCESS(Status
))
1754 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status
);
1755 NtClose(FileHandle
);
1756 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1760 /* Write new bootsector to RootPath */
1762 NewBootSector
->PartitionStartLBA
= PartInfo
.StartingOffset
.QuadPart
/ SECTORSIZE
;
1764 /* Write sector 0 */
1765 FileOffset
.QuadPart
= 0ULL;
1766 Status
= NtWriteFile(FileHandle
,
1772 sizeof(BTRFS_BOOTSECTOR
),
1776 if (!NT_SUCCESS(Status
))
1778 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1779 NtClose(FileHandle
);
1780 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1784 /* Write backup boot sector */
1785 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1787 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1788 Status
= NtWriteFile(FileHandle
,
1797 if (!NT_SUCCESS(Status
))
1799 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1800 NtClose(FileHandle
);
1801 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1806 /* Write sector 14 */
1807 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1808 Status
= NtWriteFile(FileHandle
,
1813 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1817 if (!NT_SUCCESS(Status
))
1819 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1822 NtClose(FileHandle
);
1824 /* Free the new boot sector */
1825 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1833 InstallFatBootcodeToPartition(
1834 IN PUNICODE_STRING SystemRootPath
,
1835 IN PUNICODE_STRING SourceRootPath
,
1836 IN PUNICODE_STRING DestinationArcPath
,
1837 IN UCHAR PartitionType
)
1840 BOOLEAN DoesFreeLdrExist
;
1841 WCHAR SrcPath
[MAX_PATH
];
1842 WCHAR DstPath
[MAX_PATH
];
1844 /* FAT or FAT32 partition */
1845 DPRINT("System path: '%wZ'\n", SystemRootPath
);
1847 /* Copy FreeLoader to the system partition, always overwriting the older version */
1848 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
1849 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
1851 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
1852 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
1853 if (!NT_SUCCESS(Status
))
1855 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1859 /* Prepare for possibly updating 'freeldr.ini' */
1860 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
1861 if (DoesFreeLdrExist
)
1863 /* Update existing 'freeldr.ini' */
1864 DPRINT1("Update existing 'freeldr.ini'\n");
1865 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1866 if (!NT_SUCCESS(Status
))
1868 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
1873 /* Check for NT and other bootloaders */
1875 // FIXME: Check for Vista+ bootloader!
1876 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
1877 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
1878 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"NTLDR") == TRUE
||
1879 DoesFileExist_2(SystemRootPath
->Buffer
, L
"BOOT.INI") == TRUE
)
1881 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
1882 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1884 /* Create or update 'freeldr.ini' */
1885 if (DoesFreeLdrExist
== FALSE
)
1887 /* Create new 'freeldr.ini' */
1888 DPRINT1("Create new 'freeldr.ini'\n");
1889 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1890 if (!NT_SUCCESS(Status
))
1892 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1896 /* Install new bootcode into a file */
1897 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"bootsect.ros");
1899 if (PartitionType
== PARTITION_FAT32
||
1900 PartitionType
== PARTITION_FAT32_XINT13
)
1902 /* Install FAT32 bootcode */
1903 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
1905 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1906 Status
= InstallFat32BootCodeToFile(SrcPath
, DstPath
,
1907 SystemRootPath
->Buffer
);
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status
);
1916 /* Install FAT16 bootcode */
1917 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
1919 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1920 Status
= InstallFat16BootCodeToFile(SrcPath
, DstPath
,
1921 SystemRootPath
->Buffer
);
1922 if (!NT_SUCCESS(Status
))
1924 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status
);
1930 /* Update 'boot.ini' */
1931 /* Windows' NTLDR loads an external bootsector file when the specified drive
1932 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1933 DPRINT1("Update 'boot.ini'\n");
1934 Status
= UpdateBootIni(SystemRootPath
->Buffer
,
1935 L
"C:\\bootsect.ros",
1937 if (!NT_SUCCESS(Status
))
1939 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status
);
1945 /* Non-NT bootloaders: install our own bootloader */
1950 PCWSTR BootPartition
;
1953 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1954 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IOSYS.COM") == TRUE
||
1955 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.COM") == TRUE
)
1957 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1959 Section
= L
"CPQDOS";
1960 Description
= L
"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1962 BootPartition
= L
"1";
1963 BootSector
= L
"BOOTSECT.DOS";
1966 /* Search for Microsoft DOS or Windows 9x boot loader */
1967 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IO.SYS") == TRUE
||
1968 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.SYS") == TRUE
)
1971 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1974 Description
= L
"\"MS-DOS/Windows\"";
1976 BootPartition
= L
"1";
1977 BootSector
= L
"BOOTSECT.DOS";
1980 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1981 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMIO.COM" ) == TRUE
|| // Some people refer to this file instead of IBMBIO.COM...
1982 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMBIO.COM") == TRUE
||
1983 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMDOS.COM") == TRUE
)
1985 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
1987 Section
= L
"IBMDOS";
1988 Description
= L
"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
1990 BootPartition
= L
"1";
1991 BootSector
= L
"BOOTSECT.DOS";
1994 /* Search for DR-DOS 3.x boot loader */
1995 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBIOS.SYS") == TRUE
||
1996 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBDOS.SYS") == TRUE
)
1998 DPRINT1("Found DR-DOS 3.x\n");
2001 Description
= L
"\"DR-DOS 3.x\"";
2003 BootPartition
= L
"1";
2004 BootSector
= L
"BOOTSECT.DOS";
2007 /* Search for Dell Real-Mode Kernel (DRMK) OS */
2008 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLBIO.BIN") == TRUE
||
2009 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLRMK.BIN") == TRUE
)
2011 DPRINT1("Found Dell Real-Mode Kernel OS\n");
2014 Description
= L
"\"Dell Real-Mode Kernel OS\"";
2016 BootPartition
= L
"1";
2017 BootSector
= L
"BOOTSECT.DOS";
2020 /* Search for MS OS/2 1.x */
2021 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT.COM") == TRUE
||
2022 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BIO.COM" ) == TRUE
||
2023 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2DOS.COM" ) == TRUE
)
2025 DPRINT1("Found MS OS/2 1.x\n");
2028 Description
= L
"\"MS OS/2 1.x\"";
2030 BootPartition
= L
"1";
2031 BootSector
= L
"BOOTSECT.OS2";
2034 /* Search for MS or IBM OS/2 */
2035 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT") == TRUE
||
2036 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2LDR" ) == TRUE
||
2037 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2KRNL") == TRUE
)
2039 DPRINT1("Found MS/IBM OS/2\n");
2041 Section
= L
"IBMOS2";
2042 Description
= L
"\"MS/IBM OS/2\"";
2044 BootPartition
= L
"1";
2045 BootSector
= L
"BOOTSECT.OS2";
2048 /* Search for FreeDOS boot loader */
2049 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"kernel.sys") == TRUE
)
2051 DPRINT1("Found FreeDOS boot loader\n");
2054 Description
= L
"\"FreeDOS\"";
2056 BootPartition
= L
"1";
2057 BootSector
= L
"BOOTSECT.DOS";
2061 /* No or unknown boot loader */
2062 DPRINT1("No or unknown boot loader found\n");
2064 Section
= L
"Unknown";
2065 Description
= L
"\"Unknown Operating System\"";
2067 BootPartition
= L
"1";
2068 BootSector
= L
"BOOTSECT.OLD";
2071 /* Create or update 'freeldr.ini' */
2072 if (DoesFreeLdrExist
== FALSE
)
2074 /* Create new 'freeldr.ini' */
2075 DPRINT1("Create new 'freeldr.ini'\n");
2077 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2079 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2080 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2081 Section
, Description
,
2082 BootDrive
, BootPartition
, BootSector
);
2083 if (!NT_SUCCESS(Status
))
2085 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2089 /* Save current bootsector */
2090 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2092 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2093 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, SECTORSIZE
);
2094 if (!NT_SUCCESS(Status
))
2096 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2102 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2103 if (!NT_SUCCESS(Status
))
2105 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2110 /* Install new bootsector on the disk */
2111 if (PartitionType
== PARTITION_FAT32
||
2112 PartitionType
== PARTITION_FAT32_XINT13
)
2114 /* Install FAT32 bootcode */
2115 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
2117 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2118 Status
= InstallFat32BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2119 if (!NT_SUCCESS(Status
))
2121 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status
);
2127 /* Install FAT16 bootcode */
2128 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2130 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2131 Status
= InstallFat16BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2132 if (!NT_SUCCESS(Status
))
2134 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status
);
2141 return STATUS_SUCCESS
;
2146 InstallBtrfsBootcodeToPartition(
2147 IN PUNICODE_STRING SystemRootPath
,
2148 IN PUNICODE_STRING SourceRootPath
,
2149 IN PUNICODE_STRING DestinationArcPath
,
2150 IN UCHAR PartitionType
)
2153 BOOLEAN DoesFreeLdrExist
;
2154 WCHAR SrcPath
[MAX_PATH
];
2155 WCHAR DstPath
[MAX_PATH
];
2157 /* BTRFS partition */
2158 DPRINT("System path: '%wZ'\n", SystemRootPath
);
2160 /* Copy FreeLoader to the system partition, always overwriting the older version */
2161 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2162 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
2164 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2165 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
2166 if (!NT_SUCCESS(Status
))
2168 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2172 /* Prepare for possibly updating 'freeldr.ini' */
2173 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
2174 if (DoesFreeLdrExist
)
2176 /* Update existing 'freeldr.ini' */
2177 DPRINT1("Update existing 'freeldr.ini'\n");
2178 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2179 if (!NT_SUCCESS(Status
))
2181 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2186 /* Check for *nix bootloaders */
2188 /* Create or update 'freeldr.ini' */
2189 if (DoesFreeLdrExist
== FALSE
)
2191 /* Create new 'freeldr.ini' */
2192 DPRINT1("Create new 'freeldr.ini'\n");
2194 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2195 DPRINT1("*nix or unknown boot loader found\n");
2197 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2199 PCWSTR BootSector
= L
"BOOTSECT.OLD";
2201 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2202 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2203 L
"Linux", L
"\"Linux\"",
2204 L
"hd0", L
"1", BootSector
);
2205 if (!NT_SUCCESS(Status
))
2207 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2211 /* Save current bootsector */
2212 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2214 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2215 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, sizeof(BTRFS_BOOTSECTOR
));
2216 if (!NT_SUCCESS(Status
))
2218 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2224 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2225 if (!NT_SUCCESS(Status
))
2227 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2232 /* Install new bootsector on the disk */
2233 // if (PartitionType == PARTITION_EXT2)
2235 /* Install BTRFS bootcode */
2236 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\btrfs.bin");
2238 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2239 Status
= InstallBtrfsBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2240 if (!NT_SUCCESS(Status
))
2242 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status
);
2248 return STATUS_SUCCESS
;
2253 InstallVBRToPartition(
2254 IN PUNICODE_STRING SystemRootPath
,
2255 IN PUNICODE_STRING SourceRootPath
,
2256 IN PUNICODE_STRING DestinationArcPath
,
2257 IN UCHAR PartitionType
)
2259 switch (PartitionType
)
2261 case PARTITION_FAT_12
:
2262 case PARTITION_FAT_16
:
2263 case PARTITION_HUGE
:
2264 case PARTITION_XINT13
:
2265 case PARTITION_FAT32
:
2266 case PARTITION_FAT32_XINT13
:
2268 return InstallFatBootcodeToPartition(SystemRootPath
,
2274 case PARTITION_LINUX
:
2276 return InstallBtrfsBootcodeToPartition(SystemRootPath
,
2283 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2287 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType
);
2291 return STATUS_UNSUCCESSFUL
;
2296 InstallFatBootcodeToFloppy(
2297 IN PUNICODE_STRING SourceRootPath
,
2298 IN PUNICODE_STRING DestinationArcPath
)
2302 UNICODE_STRING FloppyDevice
= RTL_CONSTANT_STRING(L
"\\Device\\Floppy0\\");
2303 WCHAR SrcPath
[MAX_PATH
];
2304 WCHAR DstPath
[MAX_PATH
];
2306 /* Verify that the floppy disk is accessible */
2307 if (DoesDirExist(NULL
, FloppyDevice
.Buffer
) == FALSE
)
2308 return STATUS_DEVICE_NOT_READY
;
2310 /* Format the floppy disk */
2311 FatFS
= GetFileSystemByName(L
"FAT");
2314 DPRINT1("FAT FS non existent on this system?!\n");
2315 return STATUS_NOT_SUPPORTED
;
2317 Status
= FatFS
->FormatFunc(&FloppyDevice
,
2323 if (!NT_SUCCESS(Status
))
2325 DPRINT1("VfatFormat() failed (Status %lx)\n", Status
);
2329 /* Copy FreeLoader to the boot partition */
2330 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2331 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, FloppyDevice
.Buffer
, L
"freeldr.sys");
2333 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2334 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
2335 if (!NT_SUCCESS(Status
))
2337 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2341 /* Create new 'freeldr.ini' */
2342 DPRINT("Create new 'freeldr.ini'\n");
2343 Status
= CreateFreeLoaderIniForReactOS(FloppyDevice
.Buffer
, DestinationArcPath
->Buffer
);
2344 if (!NT_SUCCESS(Status
))
2346 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2350 /* Install FAT12 boosector */
2351 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2352 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 1, FloppyDevice
.Buffer
);
2354 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
2355 Status
= InstallFat12BootCodeToFloppy(SrcPath
, DstPath
);
2356 if (!NT_SUCCESS(Status
))
2358 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status
);
2362 return STATUS_SUCCESS
;