2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: base/setup/usetup/bootsup.c
5 * PURPOSE: Bootloader support functions
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
19 * All that stuff *MUST* go into the fsutil.c module.
20 * Indeed, all that relates to filesystem formatting details and as such
21 * *MUST* be abstracted out from this module (bootsup.c).
22 * However, bootsup.c can still deal with MBR code (actually it'll have
23 * at some point to share or give it to partlist.c, because when we'll
24 * support GPT disks, things will change a bit).
25 * And, bootsup.c can still manage initializing / adding boot entries
26 * into NTLDR and FREELDR, and installing the latter, and saving the old
27 * MBR / boot sectors in files.
29 #define SECTORSIZE 512
32 typedef struct _FAT_BOOTSECTOR
34 UCHAR JumpBoot
[3]; // Jump instruction to boot code
35 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
36 USHORT BytesPerSector
; // Bytes per sector
37 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
38 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
39 UCHAR NumberOfFats
; // Number of FAT tables
40 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
41 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
42 UCHAR MediaDescriptor
; // Media descriptor byte
43 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
44 USHORT SectorsPerTrack
; // Number of sectors in a track
45 USHORT NumberOfHeads
; // Number of heads on the disk
46 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
47 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
48 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
49 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
50 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
51 ULONG VolumeSerialNumber
; // Volume serial number
52 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
53 CHAR FileSystemType
[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
55 UCHAR BootCodeAndData
[448]; // The remainder of the boot sector
57 USHORT BootSectorMagic
; // 0xAA55
59 } FAT_BOOTSECTOR
, *PFAT_BOOTSECTOR
;
61 typedef struct _FAT32_BOOTSECTOR
63 UCHAR JumpBoot
[3]; // Jump instruction to boot code
64 CHAR OemName
[8]; // "MSWIN4.1" for MS formatted volumes
65 USHORT BytesPerSector
; // Bytes per sector
66 UCHAR SectorsPerCluster
; // Number of sectors in a cluster
67 USHORT ReservedSectors
; // Reserved sectors, usually 1 (the bootsector)
68 UCHAR NumberOfFats
; // Number of FAT tables
69 USHORT RootDirEntries
; // Number of root directory entries (fat12/16)
70 USHORT TotalSectors
; // Number of total sectors on the drive, 16-bit
71 UCHAR MediaDescriptor
; // Media descriptor byte
72 USHORT SectorsPerFat
; // Sectors per FAT table (fat12/16)
73 USHORT SectorsPerTrack
; // Number of sectors in a track
74 USHORT NumberOfHeads
; // Number of heads on the disk
75 ULONG HiddenSectors
; // Hidden sectors (sectors before the partition start like the partition table)
76 ULONG TotalSectorsBig
; // This field is the new 32-bit total count of sectors on the volume
77 ULONG SectorsPerFatBig
; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
78 USHORT ExtendedFlags
; // Extended flags (fat32)
79 USHORT FileSystemVersion
; // File system version (fat32)
80 ULONG RootDirStartCluster
; // Starting cluster of the root directory (fat32)
81 USHORT FsInfo
; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
82 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.
83 UCHAR Reserved
[12]; // Reserved for future expansion
84 UCHAR DriveNumber
; // Int 0x13 drive number (e.g. 0x80)
85 UCHAR Reserved1
; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
86 UCHAR BootSignature
; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
87 ULONG VolumeSerialNumber
; // Volume serial number
88 CHAR VolumeLabel
[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
89 CHAR FileSystemType
[8]; // Always set to the string "FAT32 "
91 UCHAR BootCodeAndData
[420]; // The remainder of the boot sector
93 USHORT BootSectorMagic
; // 0xAA55
95 } FAT32_BOOTSECTOR
, *PFAT32_BOOTSECTOR
;
97 typedef struct _BTRFS_BOOTSECTOR
102 ULONGLONG PartitionStartLBA
;
103 UCHAR Fill
[1521]; // 1536 - 15
104 USHORT BootSectorMagic
;
105 } BTRFS_BOOTSECTOR
, *PBTRFS_BOOTSECTOR
;
106 C_ASSERT(sizeof(BTRFS_BOOTSECTOR
) == 3 * 512);
108 // TODO: Add more bootsector structures!
112 /* End of BIG FIXME!! */
115 /* FUNCTIONS ****************************************************************/
118 TrimTrailingPathSeparators_UStr(
119 IN OUT PUNICODE_STRING UnicodeString
)
121 while (UnicodeString
->Length
>= sizeof(WCHAR
) &&
122 UnicodeString
->Buffer
[UnicodeString
->Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
124 UnicodeString
->Length
-= sizeof(WCHAR
);
130 CreateFreeLoaderReactOSEntries(
131 IN PVOID BootStoreHandle
,
134 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
135 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
136 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
137 BOOT_STORE_OPTIONS BootOptions
;
139 BootEntry
->Version
= FreeLdr
;
140 BootEntry
->BootFilePath
= NULL
;
142 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
143 RtlCopyMemory(Options
->Signature
,
144 NTOS_OPTIONS_SIGNATURE
,
145 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
147 Options
->OsLoadPath
= ArcPath
;
150 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
151 BootEntry
->FriendlyName
= L
"\"ReactOS\"";
152 Options
->OsLoadOptions
= NULL
; // L"";
153 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS"));
156 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
157 BootEntry
->FriendlyName
= L
"\"ReactOS (Debug)\"";
158 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
159 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Debug"));
162 /* ReactOS_VBoxDebug */
163 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
164 BootEntry
->FriendlyName
= L
"\"ReactOS (VBoxDebug)\"";
165 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=VBOX /SOS";
166 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_VBoxDebug"));
170 /* ReactOS_KdSerial */
171 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
172 BootEntry
->FriendlyName
= L
"\"ReactOS (RosDbg)\"";
173 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
174 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_KdSerial"));
178 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
179 BootEntry
->FriendlyName
= L
"\"ReactOS (Screen)\"";
180 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=SCREEN /SOS";
181 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Screen"));
183 /* ReactOS_LogFile */
184 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
185 BootEntry
->FriendlyName
= L
"\"ReactOS (Log file)\"";
186 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=FILE /SOS";
187 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_LogFile"));
190 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
191 BootEntry
->FriendlyName
= L
"\"ReactOS (RAM Disk)\"";
192 Options
->OsLoadPath
= L
"ramdisk(0)\\ReactOS";
193 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
194 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Ram"));
197 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
198 BootEntry
->FriendlyName
= L
"\"ReactOS (Emergency Management Services)\"";
199 Options
->OsLoadPath
= ArcPath
;
200 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
201 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_EMS"));
206 if (IsUnattendedSetup
)
208 /* DefaultOS=ReactOS */
210 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_KdSerial");
212 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_Debug");
218 /* DefaultOS=ReactOS */
219 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS");
223 if (IsUnattendedSetup
)
226 /* Timeout=0 for unattended or non debug */
227 BootOptions
.Timeout
= 0;
233 BootOptions
.Timeout
= 10;
237 BootOptions
.Version
= FreeLdr
;
238 SetBootStoreOptions(BootStoreHandle
, &BootOptions
, 2 | 1);
242 CreateFreeLoaderIniForReactOS(
247 PVOID BootStoreHandle
;
249 /* Initialize the INI file and create the common FreeLdr sections */
250 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
251 if (!NT_SUCCESS(Status
))
254 /* Add the ReactOS entries */
255 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
257 /* Close the INI file */
258 CloseBootStore(BootStoreHandle
);
259 return STATUS_SUCCESS
;
263 CreateFreeLoaderIniForReactOSAndBootSector(
267 IN PCWSTR Description
,
269 IN PCWSTR BootPartition
,
270 IN PCWSTR BootSector
)
273 PVOID BootStoreHandle
;
274 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(BOOT_SECTOR_OPTIONS
)];
275 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
276 PBOOT_SECTOR_OPTIONS Options
= (PBOOT_SECTOR_OPTIONS
)&BootEntry
->OsOptions
;
278 /* Initialize the INI file and create the common FreeLdr sections */
279 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
280 if (!NT_SUCCESS(Status
))
283 /* Add the ReactOS entries */
284 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
286 BootEntry
->Version
= FreeLdr
;
287 BootEntry
->BootFilePath
= NULL
;
289 BootEntry
->OsOptionsLength
= sizeof(BOOT_SECTOR_OPTIONS
);
290 RtlCopyMemory(Options
->Signature
,
291 BOOT_SECTOR_OPTIONS_SIGNATURE
,
292 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS
, Signature
));
294 Options
->Drive
= BootDrive
;
295 Options
->Partition
= BootPartition
;
296 Options
->BootSectorFileName
= BootSector
;
298 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
299 BootEntry
->FriendlyName
= Description
;
300 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Section
));
302 /* Close the INI file */
303 CloseBootStore(BootStoreHandle
);
304 return STATUS_SUCCESS
;
308 // I think this function can be generalizable as:
309 // "find the corresponding 'ReactOS' boot entry in this loader config file
310 // (here abstraction comes there), and if none, add a new one".
313 typedef struct _ENUM_REACTOS_ENTRIES_DATA
316 BOOLEAN UseExistingEntry
;
318 WCHAR SectionName
[80];
320 } ENUM_REACTOS_ENTRIES_DATA
, *PENUM_REACTOS_ENTRIES_DATA
;
322 // PENUM_BOOT_ENTRIES_ROUTINE
325 EnumerateReactOSEntries(
326 IN BOOT_STORE_TYPE Type
,
327 IN PBOOT_STORE_ENTRY BootEntry
,
328 IN PVOID Parameter OPTIONAL
)
330 PENUM_REACTOS_ENTRIES_DATA Data
= (PENUM_REACTOS_ENTRIES_DATA
)Parameter
;
331 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
332 WCHAR SystemPath
[MAX_PATH
];
334 /* We have a boot entry */
336 /* Check for supported boot type "Windows2003" */
337 if (BootEntry
->OsOptionsLength
< sizeof(NTOS_OPTIONS
) ||
338 RtlCompareMemory(&BootEntry
->OsOptions
/* Signature */,
339 NTOS_OPTIONS_SIGNATURE
,
340 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
)) !=
341 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
))
343 /* This is not a ReactOS entry */
344 // DPRINT1(" An installation '%S' of unsupported type '%S'\n",
345 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
346 DPRINT1(" An installation '%S' of unsupported type %lu\n",
347 BootEntry
->FriendlyName
, BootEntry
->OsOptionsLength
);
348 /* Continue the enumeration */
352 /* BootType is Windows2003, now check OsLoadPath */
353 if (!Options
->OsLoadPath
|| !*Options
->OsLoadPath
)
355 /* Certainly not a ReactOS installation */
356 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry
->FriendlyName
);
357 /* Continue the enumeration */
361 RtlStringCchPrintfW(SystemPath
, ARRAYSIZE(SystemPath
), L
"\"%s\"", Data
->ArcPath
);
362 if ((_wcsicmp(Options
->OsLoadPath
, Data
->ArcPath
) != 0) &&
363 (_wcsicmp(Options
->OsLoadPath
, SystemPath
) != 0))
366 * This entry is a ReactOS entry, but the SystemRoot
367 * does not match the one we are looking for.
369 /* Continue the enumeration */
373 DPRINT1(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
374 BootEntry
->FriendlyName
, Options
->OsLoadPath
);
375 // DPRINT1(" Found a Win2k3 install '%S' with ARC path '%S'\n",
376 // BootEntry->FriendlyName, Options->OsLoadPath);
378 DPRINT1("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options
->OsLoadPath
);
380 Data
->UseExistingEntry
= TRUE
;
381 RtlStringCchCopyW(Data
->OsName
, ARRAYSIZE(Data
->OsName
), BootEntry
->FriendlyName
);
383 /* We have found our entry, stop the enumeration now! */
384 return STATUS_NO_MORE_ENTRIES
;
387 Data
->UseExistingEntry
= FALSE
;
388 if (Type
== FreeLdr
&& wcscmp(Data
->SectionName
, (PWSTR
)BootEntry
->BootEntryKey
)== 0)
390 RtlStringCchPrintfW(Data
->SectionName
, ARRAYSIZE(Data
->SectionName
),
391 L
"ReactOS_%lu", Data
->i
);
392 RtlStringCchPrintfW(Data
->OsName
, ARRAYSIZE(Data
->OsName
),
393 L
"\"ReactOS %lu\"", Data
->i
);
396 return STATUS_SUCCESS
;
406 PVOID BootStoreHandle
;
407 ENUM_REACTOS_ENTRIES_DATA Data
;
408 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
409 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
410 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
412 /* Open the INI file */
413 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, /*TRUE*/ FALSE
);
414 if (!NT_SUCCESS(Status
))
417 /* Find an existing usable or an unused section name */
418 Data
.UseExistingEntry
= TRUE
;
420 Data
.ArcPath
= ArcPath
;
421 RtlStringCchCopyW(Data
.SectionName
, ARRAYSIZE(Data
.SectionName
), L
"ReactOS");
422 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
425 // FIXME: We temporarily use EnumerateBootStoreEntries, until
426 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
428 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
430 /* Create a new "ReactOS" entry if there is none already existing that suits us */
431 if (!Data
.UseExistingEntry
)
433 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
434 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
436 BootEntry
->Version
= FreeLdr
;
437 BootEntry
->BootFilePath
= NULL
;
439 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
440 RtlCopyMemory(Options
->Signature
,
441 NTOS_OPTIONS_SIGNATURE
,
442 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
444 Options
->OsLoadPath
= ArcPath
;
446 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
447 BootEntry
->FriendlyName
= Data
.OsName
;
448 Options
->OsLoadOptions
= NULL
; // L"";
449 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Data
.SectionName
));
452 /* Close the INI file */
453 CloseBootStore(BootStoreHandle
);
454 return STATUS_SUCCESS
;
461 IN PCWSTR EntryName
, // ~= ArcPath
462 IN PCWSTR EntryValue
)
465 PVOID BootStoreHandle
;
466 ENUM_REACTOS_ENTRIES_DATA Data
;
468 // NOTE: Technically it would be "BootSector"...
469 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
470 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
471 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
473 /* Open the INI file */
474 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, NtLdr
, FALSE
);
475 if (!NT_SUCCESS(Status
))
478 /* Find an existing usable or an unused section name */
479 Data
.UseExistingEntry
= TRUE
;
481 Data
.ArcPath
= EntryName
;
482 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
483 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
486 // FIXME: We temporarily use EnumerateBootStoreEntries, until
487 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
489 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
491 /* If either the key was not found, or contains something else, add a new one */
492 if (!Data
.UseExistingEntry
/* ||
493 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
495 BootEntry
->Version
= NtLdr
;
496 BootEntry
->BootFilePath
= NULL
;
498 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
499 RtlCopyMemory(Options
->Signature
,
500 NTOS_OPTIONS_SIGNATURE
,
501 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
503 Options
->OsLoadPath
= EntryName
;
505 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
506 // BootEntry->FriendlyName = Data.OsName;
507 BootEntry
->FriendlyName
= EntryValue
;
508 Options
->OsLoadOptions
= NULL
; // L"";
509 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(0 /*Data.SectionName*/));
512 /* Close the INI file */
513 CloseBootStore(BootStoreHandle
);
514 return STATUS_SUCCESS
; // Status;
519 IsThereAValidBootSector(
523 * We first demand that the bootsector has a valid signature at its end.
524 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
525 * potential "valid" instruction (the BIOS starts execution of the bootsector
526 * at its beginning). Currently this criterium is that this ULONG must be
527 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
528 * it is invalid and certainly needs to be overwritten.
531 BOOLEAN IsValid
= FALSE
;
533 UNICODE_STRING RootPartition
;
534 OBJECT_ATTRIBUTES ObjectAttributes
;
535 IO_STATUS_BLOCK IoStatusBlock
;
537 LARGE_INTEGER FileOffset
;
541 /* Allocate buffer for bootsector */
542 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
543 if (BootSector
== NULL
)
544 return FALSE
; // STATUS_INSUFFICIENT_RESOURCES;
545 RtlZeroMemory(BootSector
, SECTORSIZE
);
547 /* Open the root partition - Remove any trailing backslash if needed */
548 RtlInitUnicodeString(&RootPartition
, RootPath
);
549 TrimTrailingPathSeparators_UStr(&RootPartition
);
551 InitializeObjectAttributes(&ObjectAttributes
,
553 OBJ_CASE_INSENSITIVE
,
557 Status
= NtOpenFile(&FileHandle
,
558 GENERIC_READ
| SYNCHRONIZE
,
562 FILE_SYNCHRONOUS_IO_NONALERT
);
563 if (!NT_SUCCESS(Status
))
566 /* Read current boot sector into buffer */
567 FileOffset
.QuadPart
= 0ULL;
568 Status
= NtReadFile(FileHandle
,
578 if (!NT_SUCCESS(Status
))
581 /* Check the instruction; we use a ULONG to read three bytes */
582 Instruction
= (*(PULONG
)BootSector
) & 0x00FFFFFF;
583 IsValid
= (Instruction
!= 0x00000000);
585 /* Check the bootsector signature */
586 IsValid
&= (*(PUSHORT
)(BootSector
+ 0x1fe) == 0xaa55);
589 /* Free the boot sector */
590 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
591 return IsValid
; // Status;
602 OBJECT_ATTRIBUTES ObjectAttributes
;
603 IO_STATUS_BLOCK IoStatusBlock
;
605 LARGE_INTEGER FileOffset
;
608 /* Allocate buffer for bootsector */
609 BootSector
= RtlAllocateHeap(ProcessHeap
, 0, Length
);
610 if (BootSector
== NULL
)
611 return STATUS_INSUFFICIENT_RESOURCES
;
613 /* Open the root partition - Remove any trailing backslash if needed */
614 RtlInitUnicodeString(&Name
, RootPath
);
615 TrimTrailingPathSeparators_UStr(&Name
);
617 InitializeObjectAttributes(&ObjectAttributes
,
619 OBJ_CASE_INSENSITIVE
,
623 Status
= NtOpenFile(&FileHandle
,
624 GENERIC_READ
| SYNCHRONIZE
,
628 FILE_SYNCHRONOUS_IO_NONALERT
);
629 if (!NT_SUCCESS(Status
))
631 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
635 /* Read current boot sector into buffer */
636 FileOffset
.QuadPart
= 0ULL;
637 Status
= NtReadFile(FileHandle
,
647 if (!NT_SUCCESS(Status
))
649 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
653 /* Write bootsector to DstPath */
654 RtlInitUnicodeString(&Name
, DstPath
);
656 InitializeObjectAttributes(&ObjectAttributes
,
662 Status
= NtCreateFile(&FileHandle
,
663 GENERIC_WRITE
| SYNCHRONIZE
,
667 FILE_ATTRIBUTE_NORMAL
,
670 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
673 if (!NT_SUCCESS(Status
))
675 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
679 Status
= NtWriteFile(FileHandle
,
690 /* Free the boot sector */
691 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
697 InstallMbrBootCodeToDisk(
703 OBJECT_ATTRIBUTES ObjectAttributes
;
704 IO_STATUS_BLOCK IoStatusBlock
;
706 LARGE_INTEGER FileOffset
;
707 PPARTITION_SECTOR OrigBootSector
;
708 PPARTITION_SECTOR NewBootSector
;
710 /* Allocate buffer for original bootsector */
711 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
712 if (OrigBootSector
== NULL
)
713 return STATUS_INSUFFICIENT_RESOURCES
;
715 /* Open the root partition - Remove any trailing backslash if needed */
716 RtlInitUnicodeString(&Name
, RootPath
);
717 TrimTrailingPathSeparators_UStr(&Name
);
719 InitializeObjectAttributes(&ObjectAttributes
,
721 OBJ_CASE_INSENSITIVE
,
725 Status
= NtOpenFile(&FileHandle
,
726 GENERIC_READ
| SYNCHRONIZE
,
730 FILE_SYNCHRONOUS_IO_NONALERT
);
731 if (!NT_SUCCESS(Status
))
733 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
737 /* Read current boot sector into buffer */
738 FileOffset
.QuadPart
= 0ULL;
739 Status
= NtReadFile(FileHandle
,
745 sizeof(PARTITION_SECTOR
),
749 if (!NT_SUCCESS(Status
))
751 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
755 /* Allocate buffer for new bootsector */
756 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTITION_SECTOR
));
757 if (NewBootSector
== NULL
)
759 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
760 return STATUS_INSUFFICIENT_RESOURCES
;
763 /* Read new bootsector from SrcPath */
764 RtlInitUnicodeString(&Name
, SrcPath
);
766 InitializeObjectAttributes(&ObjectAttributes
,
768 OBJ_CASE_INSENSITIVE
,
772 Status
= NtOpenFile(&FileHandle
,
773 GENERIC_READ
| SYNCHRONIZE
,
777 FILE_SYNCHRONOUS_IO_NONALERT
);
778 if (!NT_SUCCESS(Status
))
780 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
781 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
785 Status
= NtReadFile(FileHandle
,
791 sizeof(PARTITION_SECTOR
),
795 if (!NT_SUCCESS(Status
))
797 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
798 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
803 * Copy the disk signature, the reserved fields and
804 * the partition table from the old MBR to the new one.
806 RtlCopyMemory(&NewBootSector
->Signature
,
807 &OrigBootSector
->Signature
,
808 sizeof(PARTITION_SECTOR
) - offsetof(PARTITION_SECTOR
, Signature
)
809 /* Length of partition table */);
811 /* Free the original boot sector */
812 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
814 /* Write new bootsector to RootPath */
815 RtlInitUnicodeString(&Name
, RootPath
);
817 InitializeObjectAttributes(&ObjectAttributes
,
823 Status
= NtOpenFile(&FileHandle
,
824 GENERIC_WRITE
| SYNCHRONIZE
,
828 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
829 if (!NT_SUCCESS(Status
))
831 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
832 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
836 FileOffset
.QuadPart
= 0ULL;
837 Status
= NtWriteFile(FileHandle
,
843 sizeof(PARTITION_SECTOR
),
848 /* Free the new boot sector */
849 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
857 InstallFat12BootCodeToFloppy(
863 OBJECT_ATTRIBUTES ObjectAttributes
;
864 IO_STATUS_BLOCK IoStatusBlock
;
866 LARGE_INTEGER FileOffset
;
867 PFAT_BOOTSECTOR OrigBootSector
;
868 PFAT_BOOTSECTOR NewBootSector
;
870 /* Allocate buffer for original bootsector */
871 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
872 if (OrigBootSector
== NULL
)
873 return STATUS_INSUFFICIENT_RESOURCES
;
875 /* Open the root partition - Remove any trailing backslash if needed */
876 RtlInitUnicodeString(&Name
, RootPath
);
877 TrimTrailingPathSeparators_UStr(&Name
);
879 InitializeObjectAttributes(&ObjectAttributes
,
881 OBJ_CASE_INSENSITIVE
,
885 Status
= NtOpenFile(&FileHandle
,
886 GENERIC_READ
| SYNCHRONIZE
,
890 FILE_SYNCHRONOUS_IO_NONALERT
);
891 if (!NT_SUCCESS(Status
))
893 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
897 /* Read current boot sector into buffer */
898 FileOffset
.QuadPart
= 0ULL;
899 Status
= NtReadFile(FileHandle
,
909 if (!NT_SUCCESS(Status
))
911 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
915 /* Allocate buffer for new bootsector */
916 NewBootSector
= RtlAllocateHeap(ProcessHeap
,
919 if (NewBootSector
== NULL
)
921 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
922 return STATUS_INSUFFICIENT_RESOURCES
;
925 /* Read new bootsector from SrcPath */
926 RtlInitUnicodeString(&Name
, SrcPath
);
928 InitializeObjectAttributes(&ObjectAttributes
,
930 OBJ_CASE_INSENSITIVE
,
934 Status
= NtOpenFile(&FileHandle
,
935 GENERIC_READ
| SYNCHRONIZE
,
939 FILE_SYNCHRONOUS_IO_NONALERT
);
940 if (!NT_SUCCESS(Status
))
942 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
943 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
947 Status
= NtReadFile(FileHandle
,
957 if (!NT_SUCCESS(Status
))
959 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
960 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
964 /* Adjust bootsector (copy a part of the FAT16 BPB) */
965 memcpy(&NewBootSector
->OemName
,
966 &OrigBootSector
->OemName
,
967 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
968 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
970 /* Free the original boot sector */
971 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
973 /* Write new bootsector to RootPath */
974 RtlInitUnicodeString(&Name
, RootPath
);
976 InitializeObjectAttributes(&ObjectAttributes
,
982 Status
= NtOpenFile(&FileHandle
,
983 GENERIC_WRITE
| SYNCHRONIZE
,
987 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
988 if (!NT_SUCCESS(Status
))
990 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
991 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
995 FileOffset
.QuadPart
= 0ULL;
996 Status
= NtWriteFile(FileHandle
,
1005 NtClose(FileHandle
);
1007 /* Free the new boot sector */
1008 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1015 InstallFat16BootCode(
1016 IN PCWSTR SrcPath
, // FAT16 bootsector source file (on the installation medium)
1017 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1018 IN HANDLE RootPartition
) // Partition holding the (old) FAT16 information
1021 UNICODE_STRING Name
;
1022 OBJECT_ATTRIBUTES ObjectAttributes
;
1023 IO_STATUS_BLOCK IoStatusBlock
;
1025 LARGE_INTEGER FileOffset
;
1026 PFAT_BOOTSECTOR OrigBootSector
;
1027 PFAT_BOOTSECTOR NewBootSector
;
1029 /* Allocate a buffer for the original bootsector */
1030 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1031 if (OrigBootSector
== NULL
)
1032 return STATUS_INSUFFICIENT_RESOURCES
;
1034 /* Read the current partition boot sector into the buffer */
1035 FileOffset
.QuadPart
= 0ULL;
1036 Status
= NtReadFile(RootPartition
,
1045 if (!NT_SUCCESS(Status
))
1047 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1051 /* Allocate a buffer for the new bootsector */
1052 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1053 if (NewBootSector
== NULL
)
1055 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1056 return STATUS_INSUFFICIENT_RESOURCES
;
1059 /* Read the new bootsector from SrcPath */
1060 RtlInitUnicodeString(&Name
, SrcPath
);
1061 InitializeObjectAttributes(&ObjectAttributes
,
1063 OBJ_CASE_INSENSITIVE
,
1066 Status
= NtOpenFile(&FileHandle
,
1067 GENERIC_READ
| SYNCHRONIZE
,
1071 FILE_SYNCHRONOUS_IO_NONALERT
);
1072 if (!NT_SUCCESS(Status
))
1074 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1075 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1079 FileOffset
.QuadPart
= 0ULL;
1080 Status
= NtReadFile(FileHandle
,
1089 NtClose(FileHandle
);
1090 if (!NT_SUCCESS(Status
))
1092 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1093 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1097 /* Adjust the bootsector (copy a part of the FAT16 BPB) */
1098 memcpy(&NewBootSector
->OemName
,
1099 &OrigBootSector
->OemName
,
1100 FIELD_OFFSET(FAT_BOOTSECTOR
, BootCodeAndData
) -
1101 FIELD_OFFSET(FAT_BOOTSECTOR
, OemName
));
1103 /* Free the original boot sector */
1104 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1106 /* Write the new bootsector to DstPath */
1107 FileOffset
.QuadPart
= 0ULL;
1108 Status
= NtWriteFile(DstPath
,
1118 /* Free the new boot sector */
1119 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1126 InstallFat16BootCodeToFile(
1132 UNICODE_STRING Name
;
1133 OBJECT_ATTRIBUTES ObjectAttributes
;
1134 IO_STATUS_BLOCK IoStatusBlock
;
1135 HANDLE PartitionHandle
, FileHandle
;
1138 * Open the root partition from which the boot sector
1139 * parameters will be obtained.
1140 * Remove any trailing backslash if needed.
1142 RtlInitUnicodeString(&Name
, RootPath
);
1143 TrimTrailingPathSeparators_UStr(&Name
);
1145 InitializeObjectAttributes(&ObjectAttributes
,
1147 OBJ_CASE_INSENSITIVE
,
1150 Status
= NtOpenFile(&PartitionHandle
,
1151 GENERIC_READ
| SYNCHRONIZE
,
1155 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1156 if (!NT_SUCCESS(Status
))
1159 /* Open or create the file where the new bootsector will be saved */
1160 RtlInitUnicodeString(&Name
, DstPath
);
1161 InitializeObjectAttributes(&ObjectAttributes
,
1163 0, // OBJ_CASE_INSENSITIVE,
1166 Status
= NtCreateFile(&FileHandle
,
1167 GENERIC_WRITE
| SYNCHRONIZE
,
1171 FILE_ATTRIBUTE_NORMAL
,
1174 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1177 if (!NT_SUCCESS(Status
))
1179 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1180 NtClose(PartitionHandle
);
1184 /* Install the FAT16 boot sector */
1185 Status
= InstallFat16BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1187 /* Close the file and the partition */
1188 NtClose(FileHandle
);
1189 NtClose(PartitionHandle
);
1196 InstallFat16BootCodeToDisk(
1201 UNICODE_STRING Name
;
1202 OBJECT_ATTRIBUTES ObjectAttributes
;
1203 IO_STATUS_BLOCK IoStatusBlock
;
1204 HANDLE PartitionHandle
;
1207 * Open the root partition from which the boot sector parameters will be
1208 * obtained; this is also where we will write the updated boot sector.
1209 * Remove any trailing backslash if needed.
1211 RtlInitUnicodeString(&Name
, RootPath
);
1212 TrimTrailingPathSeparators_UStr(&Name
);
1214 InitializeObjectAttributes(&ObjectAttributes
,
1216 OBJ_CASE_INSENSITIVE
,
1219 Status
= NtOpenFile(&PartitionHandle
,
1220 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1224 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1225 if (!NT_SUCCESS(Status
))
1228 /* Install the FAT16 boot sector */
1229 Status
= InstallFat16BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1231 /* Close the partition */
1232 NtClose(PartitionHandle
);
1240 InstallFat32BootCode(
1241 IN PCWSTR SrcPath
, // FAT32 bootsector source file (on the installation medium)
1242 IN HANDLE DstPath
, // Where to save the bootsector built from the source + partition information
1243 IN HANDLE RootPartition
) // Partition holding the (old) FAT32 information
1246 UNICODE_STRING Name
;
1247 OBJECT_ATTRIBUTES ObjectAttributes
;
1248 IO_STATUS_BLOCK IoStatusBlock
;
1250 LARGE_INTEGER FileOffset
;
1251 PFAT32_BOOTSECTOR OrigBootSector
;
1252 PFAT32_BOOTSECTOR NewBootSector
;
1253 USHORT BackupBootSector
;
1255 /* Allocate a buffer for the original bootsector */
1256 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1257 if (OrigBootSector
== NULL
)
1258 return STATUS_INSUFFICIENT_RESOURCES
;
1260 /* Read the current boot sector into the buffer */
1261 FileOffset
.QuadPart
= 0ULL;
1262 Status
= NtReadFile(RootPartition
,
1271 if (!NT_SUCCESS(Status
))
1273 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1277 /* Allocate a buffer for the new bootsector (2 sectors) */
1278 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, 2 * SECTORSIZE
);
1279 if (NewBootSector
== NULL
)
1281 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1282 return STATUS_INSUFFICIENT_RESOURCES
;
1285 /* Read the new bootsector from SrcPath */
1286 RtlInitUnicodeString(&Name
, SrcPath
);
1287 InitializeObjectAttributes(&ObjectAttributes
,
1289 OBJ_CASE_INSENSITIVE
,
1292 Status
= NtOpenFile(&FileHandle
,
1293 GENERIC_READ
| SYNCHRONIZE
,
1297 FILE_SYNCHRONOUS_IO_NONALERT
);
1298 if (!NT_SUCCESS(Status
))
1300 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1301 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1305 FileOffset
.QuadPart
= 0ULL;
1306 Status
= NtReadFile(FileHandle
,
1315 NtClose(FileHandle
);
1316 if (!NT_SUCCESS(Status
))
1318 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1319 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1323 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
1324 memcpy(&NewBootSector
->OemName
,
1325 &OrigBootSector
->OemName
,
1326 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1327 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1330 * We know we copy the boot code to a file only when DstPath != RootPartition,
1331 * otherwise the boot code is copied to the specified root partition.
1333 if (DstPath
!= RootPartition
)
1335 /* Copy to a file: Disable the backup boot sector */
1336 NewBootSector
->BackupBootSector
= 0;
1340 /* Copy to a disk: Get the location of the backup boot sector */
1341 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1344 /* Free the original boot sector */
1345 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1347 /* Write the first sector of the new bootcode to DstPath sector 0 */
1348 FileOffset
.QuadPart
= 0ULL;
1349 Status
= NtWriteFile(DstPath
,
1358 if (!NT_SUCCESS(Status
))
1360 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1361 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1365 if (DstPath
== RootPartition
)
1367 /* Copy to a disk: Write the backup boot sector */
1368 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1370 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1371 Status
= NtWriteFile(DstPath
,
1380 if (!NT_SUCCESS(Status
))
1382 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1383 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1389 /* Write the second sector of the new bootcode to boot disk sector 14 */
1390 // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1391 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1392 Status
= NtWriteFile(DstPath
, // or really RootPartition ???
1397 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1401 if (!NT_SUCCESS(Status
))
1403 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1406 /* Free the new boot sector */
1407 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1414 InstallFat32BootCodeToFile(
1420 UNICODE_STRING Name
;
1421 OBJECT_ATTRIBUTES ObjectAttributes
;
1422 IO_STATUS_BLOCK IoStatusBlock
;
1423 HANDLE PartitionHandle
, FileHandle
;
1426 * Open the root partition from which the boot sector parameters
1428 * FIXME? It might be possible that we need to also open it for writing
1429 * access in case we really need to still write the second portion of
1430 * the boot sector ????
1432 * Remove any trailing backslash if needed.
1434 RtlInitUnicodeString(&Name
, RootPath
);
1435 TrimTrailingPathSeparators_UStr(&Name
);
1437 InitializeObjectAttributes(&ObjectAttributes
,
1439 OBJ_CASE_INSENSITIVE
,
1442 Status
= NtOpenFile(&PartitionHandle
,
1443 GENERIC_READ
| SYNCHRONIZE
,
1447 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1448 if (!NT_SUCCESS(Status
))
1451 /* Open or create the file where (the first sector of ????) the new bootsector will be saved */
1452 RtlInitUnicodeString(&Name
, DstPath
);
1453 InitializeObjectAttributes(&ObjectAttributes
,
1455 0, // OBJ_CASE_INSENSITIVE,
1458 Status
= NtCreateFile(&FileHandle
,
1459 GENERIC_WRITE
| SYNCHRONIZE
,
1463 FILE_ATTRIBUTE_NORMAL
,
1465 FILE_SUPERSEDE
, // FILE_OVERWRITE_IF, <- is used for FAT16
1466 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1469 if (!NT_SUCCESS(Status
))
1471 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
1472 NtClose(PartitionHandle
);
1476 /* Install the FAT32 boot sector */
1477 Status
= InstallFat32BootCode(SrcPath
, FileHandle
, PartitionHandle
);
1479 /* Close the file and the partition */
1480 NtClose(FileHandle
);
1481 NtClose(PartitionHandle
);
1488 InstallFat32BootCodeToDisk(
1493 UNICODE_STRING Name
;
1494 OBJECT_ATTRIBUTES ObjectAttributes
;
1495 IO_STATUS_BLOCK IoStatusBlock
;
1496 HANDLE PartitionHandle
;
1499 * Open the root partition from which the boot sector parameters will be
1500 * obtained; this is also where we will write the updated boot sector.
1501 * Remove any trailing backslash if needed.
1503 RtlInitUnicodeString(&Name
, RootPath
);
1504 TrimTrailingPathSeparators_UStr(&Name
);
1506 InitializeObjectAttributes(&ObjectAttributes
,
1508 OBJ_CASE_INSENSITIVE
,
1511 Status
= NtOpenFile(&PartitionHandle
,
1512 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1516 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
1517 if (!NT_SUCCESS(Status
))
1520 /* Install the FAT32 boot sector */
1521 Status
= InstallFat32BootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
1523 /* Close the partition */
1524 NtClose(PartitionHandle
);
1531 InstallBtrfsBootCodeToDisk(
1536 UNICODE_STRING Name
;
1537 OBJECT_ATTRIBUTES ObjectAttributes
;
1538 IO_STATUS_BLOCK IoStatusBlock
;
1540 LARGE_INTEGER FileOffset
;
1541 // PEXT2_BOOTSECTOR OrigBootSector;
1542 PBTRFS_BOOTSECTOR NewBootSector
;
1543 // USHORT BackupBootSector;
1544 PARTITION_INFORMATION_EX PartInfo
;
1547 /* Allocate buffer for original bootsector */
1548 OrigBootSector
= RtlAllocateHeap(ProcessHeap
, 0, SECTORSIZE
);
1549 if (OrigBootSector
== NULL
)
1550 return STATUS_INSUFFICIENT_RESOURCES
;
1552 /* Open the root partition - Remove any trailing backslash if needed */
1553 RtlInitUnicodeString(&Name
, RootPath
);
1554 TrimTrailingPathSeparators_UStr(&Name
);
1556 InitializeObjectAttributes(&ObjectAttributes
,
1558 OBJ_CASE_INSENSITIVE
,
1562 Status
= NtOpenFile(&FileHandle
,
1563 GENERIC_READ
| SYNCHRONIZE
,
1567 FILE_SYNCHRONOUS_IO_NONALERT
);
1568 if (!NT_SUCCESS(Status
))
1570 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1574 /* Read current boot sector into buffer */
1575 FileOffset
.QuadPart
= 0ULL;
1576 Status
= NtReadFile(FileHandle
,
1585 NtClose(FileHandle
);
1586 if (!NT_SUCCESS(Status
))
1588 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1593 /* Allocate buffer for new bootsector */
1594 NewBootSector
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(BTRFS_BOOTSECTOR
));
1595 if (NewBootSector
== NULL
)
1597 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1598 return STATUS_INSUFFICIENT_RESOURCES
;
1601 /* Read new bootsector from SrcPath */
1602 RtlInitUnicodeString(&Name
, SrcPath
);
1604 InitializeObjectAttributes(&ObjectAttributes
,
1606 OBJ_CASE_INSENSITIVE
,
1610 Status
= NtOpenFile(&FileHandle
,
1611 GENERIC_READ
| SYNCHRONIZE
,
1615 FILE_SYNCHRONOUS_IO_NONALERT
);
1616 if (!NT_SUCCESS(Status
))
1618 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1619 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1623 Status
= NtReadFile(FileHandle
,
1629 sizeof(BTRFS_BOOTSECTOR
),
1632 NtClose(FileHandle
);
1633 if (!NT_SUCCESS(Status
))
1635 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1636 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1641 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1642 memcpy(&NewBootSector
->OemName
,
1643 &OrigBootSector
->OemName
,
1644 FIELD_OFFSET(FAT32_BOOTSECTOR
, BootCodeAndData
) -
1645 FIELD_OFFSET(FAT32_BOOTSECTOR
, OemName
));
1647 /* Get the location of the backup boot sector */
1648 BackupBootSector
= OrigBootSector
->BackupBootSector
;
1650 /* Free the original boot sector */
1651 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1654 /* Write new bootsector to RootPath */
1655 RtlInitUnicodeString(&Name
, RootPath
);
1657 InitializeObjectAttributes(&ObjectAttributes
,
1663 Status
= NtOpenFile(&FileHandle
,
1664 GENERIC_WRITE
| SYNCHRONIZE
,
1668 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1669 if (!NT_SUCCESS(Status
))
1671 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1672 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1676 /* Obtaining partition info and writing it to bootsector */
1677 Status
= NtDeviceIoControlFile(FileHandle
,
1682 IOCTL_DISK_GET_PARTITION_INFO_EX
,
1688 if (!NT_SUCCESS(Status
))
1690 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status
);
1691 NtClose(FileHandle
);
1692 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1696 NewBootSector
->PartitionStartLBA
= PartInfo
.StartingOffset
.QuadPart
/ SECTORSIZE
;
1698 /* Write sector 0 */
1699 FileOffset
.QuadPart
= 0ULL;
1700 Status
= NtWriteFile(FileHandle
,
1706 sizeof(BTRFS_BOOTSECTOR
),
1710 if (!NT_SUCCESS(Status
))
1712 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1713 NtClose(FileHandle
);
1714 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1718 /* Write backup boot sector */
1719 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1721 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1722 Status
= NtWriteFile(FileHandle
,
1731 if (!NT_SUCCESS(Status
))
1733 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1734 NtClose(FileHandle
);
1735 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1740 /* Write sector 14 */
1741 FileOffset
.QuadPart
= 14 * SECTORSIZE
;
1742 Status
= NtWriteFile(FileHandle
,
1747 ((PUCHAR
)NewBootSector
+ SECTORSIZE
),
1751 if (!NT_SUCCESS(Status
))
1753 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1756 NtClose(FileHandle
);
1758 /* Free the new boot sector */
1759 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1766 InstallFatBootcodeToPartition(
1767 PUNICODE_STRING SystemRootPath
,
1768 PUNICODE_STRING SourceRootPath
,
1769 PUNICODE_STRING DestinationArcPath
,
1770 UCHAR PartitionType
)
1773 BOOLEAN DoesFreeLdrExist
;
1774 WCHAR SrcPath
[MAX_PATH
];
1775 WCHAR DstPath
[MAX_PATH
];
1777 /* FAT or FAT32 partition */
1778 DPRINT("System path: '%wZ'\n", SystemRootPath
);
1780 /* Copy FreeLoader to the system partition, always overwriting the older version */
1781 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
1782 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
1784 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
1785 Status
= SetupCopyFile(SrcPath
, DstPath
);
1786 if (!NT_SUCCESS(Status
))
1788 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1792 /* Prepare for possibly updating 'freeldr.ini' */
1793 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
1794 if (DoesFreeLdrExist
)
1796 /* Update existing 'freeldr.ini' */
1797 DPRINT1("Update existing 'freeldr.ini'\n");
1798 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1799 if (!NT_SUCCESS(Status
))
1801 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
1806 /* Check for NT and other bootloaders */
1808 // FIXME: Check for Vista+ bootloader!
1809 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
1810 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
1811 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"NTLDR") == TRUE
||
1812 DoesFileExist_2(SystemRootPath
->Buffer
, L
"BOOT.INI") == TRUE
)
1814 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
1815 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1817 /* Create or update 'freeldr.ini' */
1818 if (DoesFreeLdrExist
== FALSE
)
1820 /* Create new 'freeldr.ini' */
1821 DPRINT1("Create new 'freeldr.ini'\n");
1822 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1823 if (!NT_SUCCESS(Status
))
1825 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1829 /* Install new bootcode into a file */
1830 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"bootsect.ros");
1832 if (PartitionType
== PARTITION_FAT32
||
1833 PartitionType
== PARTITION_FAT32_XINT13
)
1835 /* Install FAT32 bootcode */
1836 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
1838 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1839 Status
= InstallFat32BootCodeToFile(SrcPath
, DstPath
,
1840 SystemRootPath
->Buffer
);
1841 if (!NT_SUCCESS(Status
))
1843 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status
);
1849 /* Install FAT16 bootcode */
1850 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
1852 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1853 Status
= InstallFat16BootCodeToFile(SrcPath
, DstPath
,
1854 SystemRootPath
->Buffer
);
1855 if (!NT_SUCCESS(Status
))
1857 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status
);
1863 /* Update 'boot.ini' */
1864 /* Windows' NTLDR loads an external bootsector file when the specified drive
1865 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1866 DPRINT1("Update 'boot.ini'\n");
1867 Status
= UpdateBootIni(SystemRootPath
->Buffer
,
1868 L
"C:\\bootsect.ros",
1870 if (!NT_SUCCESS(Status
))
1872 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status
);
1878 /* Non-NT bootloaders: install our own bootloader */
1883 PCWSTR BootPartition
;
1886 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1887 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IOSYS.COM") == TRUE
||
1888 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.COM") == TRUE
)
1890 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1892 Section
= L
"CPQDOS";
1893 Description
= L
"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1895 BootPartition
= L
"1";
1896 BootSector
= L
"BOOTSECT.DOS";
1899 /* Search for Microsoft DOS or Windows 9x boot loader */
1900 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IO.SYS") == TRUE
||
1901 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.SYS") == TRUE
)
1904 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1907 Description
= L
"\"MS-DOS/Windows\"";
1909 BootPartition
= L
"1";
1910 BootSector
= L
"BOOTSECT.DOS";
1913 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1914 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMIO.COM" ) == TRUE
|| // Some people refer to this file instead of IBMBIO.COM...
1915 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMBIO.COM") == TRUE
||
1916 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMDOS.COM") == TRUE
)
1918 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
1920 Section
= L
"IBMDOS";
1921 Description
= L
"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
1923 BootPartition
= L
"1";
1924 BootSector
= L
"BOOTSECT.DOS";
1927 /* Search for DR-DOS 3.x boot loader */
1928 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBIOS.SYS") == TRUE
||
1929 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBDOS.SYS") == TRUE
)
1931 DPRINT1("Found DR-DOS 3.x\n");
1934 Description
= L
"\"DR-DOS 3.x\"";
1936 BootPartition
= L
"1";
1937 BootSector
= L
"BOOTSECT.DOS";
1940 /* Search for Dell Real-Mode Kernel (DRMK) OS */
1941 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLBIO.BIN") == TRUE
||
1942 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLRMK.BIN") == TRUE
)
1944 DPRINT1("Found Dell Real-Mode Kernel OS\n");
1947 Description
= L
"\"Dell Real-Mode Kernel OS\"";
1949 BootPartition
= L
"1";
1950 BootSector
= L
"BOOTSECT.DOS";
1953 /* Search for MS OS/2 1.x */
1954 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT.COM") == TRUE
||
1955 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BIO.COM" ) == TRUE
||
1956 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2DOS.COM" ) == TRUE
)
1958 DPRINT1("Found MS OS/2 1.x\n");
1961 Description
= L
"\"MS OS/2 1.x\"";
1963 BootPartition
= L
"1";
1964 BootSector
= L
"BOOTSECT.OS2";
1967 /* Search for MS or IBM OS/2 */
1968 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT") == TRUE
||
1969 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2LDR" ) == TRUE
||
1970 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2KRNL") == TRUE
)
1972 DPRINT1("Found MS/IBM OS/2\n");
1974 Section
= L
"IBMOS2";
1975 Description
= L
"\"MS/IBM OS/2\"";
1977 BootPartition
= L
"1";
1978 BootSector
= L
"BOOTSECT.OS2";
1981 /* Search for FreeDOS boot loader */
1982 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"kernel.sys") == TRUE
)
1984 DPRINT1("Found FreeDOS boot loader\n");
1987 Description
= L
"\"FreeDOS\"";
1989 BootPartition
= L
"1";
1990 BootSector
= L
"BOOTSECT.DOS";
1994 /* No or unknown boot loader */
1995 DPRINT1("No or unknown boot loader found\n");
1997 Section
= L
"Unknown";
1998 Description
= L
"\"Unknown Operating System\"";
2000 BootPartition
= L
"1";
2001 BootSector
= L
"BOOTSECT.OLD";
2004 /* Create or update 'freeldr.ini' */
2005 if (DoesFreeLdrExist
== FALSE
)
2007 /* Create new 'freeldr.ini' */
2008 DPRINT1("Create new 'freeldr.ini'\n");
2010 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2012 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2013 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2014 Section
, Description
,
2015 BootDrive
, BootPartition
, BootSector
);
2016 if (!NT_SUCCESS(Status
))
2018 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2022 /* Save current bootsector */
2023 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2025 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2026 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, SECTORSIZE
);
2027 if (!NT_SUCCESS(Status
))
2029 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2035 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2036 if (!NT_SUCCESS(Status
))
2038 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2043 /* Install new bootsector on the disk */
2044 if (PartitionType
== PARTITION_FAT32
||
2045 PartitionType
== PARTITION_FAT32_XINT13
)
2047 /* Install FAT32 bootcode */
2048 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
2050 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2051 Status
= InstallFat32BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2052 if (!NT_SUCCESS(Status
))
2054 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status
);
2060 /* Install FAT16 bootcode */
2061 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2063 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2064 Status
= InstallFat16BootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2065 if (!NT_SUCCESS(Status
))
2067 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status
);
2074 return STATUS_SUCCESS
;
2079 InstallBtrfsBootcodeToPartition(
2080 PUNICODE_STRING SystemRootPath
,
2081 PUNICODE_STRING SourceRootPath
,
2082 PUNICODE_STRING DestinationArcPath
,
2083 UCHAR PartitionType
)
2086 BOOLEAN DoesFreeLdrExist
;
2087 WCHAR SrcPath
[MAX_PATH
];
2088 WCHAR DstPath
[MAX_PATH
];
2090 /* BTRFS partition */
2091 DPRINT("System path: '%wZ'\n", SystemRootPath
);
2093 /* Copy FreeLoader to the system partition, always overwriting the older version */
2094 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2095 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
2097 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2098 Status
= SetupCopyFile(SrcPath
, DstPath
);
2099 if (!NT_SUCCESS(Status
))
2101 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2105 /* Prepare for possibly updating 'freeldr.ini' */
2106 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
2107 if (DoesFreeLdrExist
)
2109 /* Update existing 'freeldr.ini' */
2110 DPRINT1("Update existing 'freeldr.ini'\n");
2111 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2112 if (!NT_SUCCESS(Status
))
2114 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
2119 /* Check for *nix bootloaders */
2121 /* Create or update 'freeldr.ini' */
2122 if (DoesFreeLdrExist
== FALSE
)
2124 /* Create new 'freeldr.ini' */
2125 DPRINT1("Create new 'freeldr.ini'\n");
2127 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2128 DPRINT1("*nix or unknown boot loader found\n");
2130 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
2132 PCWSTR BootSector
= L
"BOOTSECT.OLD";
2134 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
2135 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
2136 L
"Linux", L
"\"Linux\"",
2137 L
"hd0", L
"1", BootSector
);
2138 if (!NT_SUCCESS(Status
))
2140 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
2144 /* Save current bootsector */
2145 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
2147 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
2148 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, sizeof(BTRFS_BOOTSECTOR
));
2149 if (!NT_SUCCESS(Status
))
2151 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
2157 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
2158 if (!NT_SUCCESS(Status
))
2160 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2165 /* Install new bootsector on the disk */
2166 // if (PartitionType == PARTITION_EXT2)
2168 /* Install BTRFS bootcode */
2169 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\btrfs.bin");
2171 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
2172 Status
= InstallBtrfsBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
);
2173 if (!NT_SUCCESS(Status
))
2175 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status
);
2181 return STATUS_SUCCESS
;
2186 InstallVBRToPartition(
2187 PUNICODE_STRING SystemRootPath
,
2188 PUNICODE_STRING SourceRootPath
,
2189 PUNICODE_STRING DestinationArcPath
,
2190 UCHAR PartitionType
)
2192 switch (PartitionType
)
2194 case PARTITION_FAT_12
:
2195 case PARTITION_FAT_16
:
2196 case PARTITION_HUGE
:
2197 case PARTITION_XINT13
:
2198 case PARTITION_FAT32
:
2199 case PARTITION_FAT32_XINT13
:
2201 return InstallFatBootcodeToPartition(SystemRootPath
,
2207 case PARTITION_LINUX
:
2209 return InstallBtrfsBootcodeToPartition(SystemRootPath
,
2216 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2220 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType
);
2224 return STATUS_UNSUCCESSFUL
;
2229 InstallFatBootcodeToFloppy(
2230 PUNICODE_STRING SourceRootPath
,
2231 PUNICODE_STRING DestinationArcPath
)
2235 UNICODE_STRING FloppyDevice
= RTL_CONSTANT_STRING(L
"\\Device\\Floppy0\\");
2236 WCHAR SrcPath
[MAX_PATH
];
2237 WCHAR DstPath
[MAX_PATH
];
2239 /* Format the floppy first */
2240 FatFS
= GetFileSystemByName(L
"FAT");
2243 DPRINT1("FAT FS non existent on this system?!\n");
2244 return STATUS_NOT_SUPPORTED
;
2246 Status
= FatFS
->FormatFunc(&FloppyDevice
,
2252 if (!NT_SUCCESS(Status
))
2254 DPRINT1("VfatFormat() failed (Status %lx)\n", Status
);
2258 /* Copy FreeLoader to the boot partition */
2259 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
2260 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, FloppyDevice
.Buffer
, L
"freeldr.sys");
2262 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
2263 Status
= SetupCopyFile(SrcPath
, DstPath
);
2264 if (!NT_SUCCESS(Status
))
2266 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
2270 /* Create new 'freeldr.ini' */
2271 DPRINT("Create new 'freeldr.ini'\n");
2272 Status
= CreateFreeLoaderIniForReactOS(FloppyDevice
.Buffer
, DestinationArcPath
->Buffer
);
2273 if (!NT_SUCCESS(Status
))
2275 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
2279 /* Install FAT12 boosector */
2280 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
2281 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 1, FloppyDevice
.Buffer
);
2283 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath
, DstPath
);
2284 Status
= InstallFat12BootCodeToFloppy(SrcPath
, DstPath
);
2285 if (!NT_SUCCESS(Status
))
2287 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status
);
2291 return STATUS_SUCCESS
;