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 *****************************************************************/
20 #include "setuplib.h" // HAXX for IsUnattendedSetup!!
31 * bootsup.c can deal with MBR code (actually it'll have at some point
32 * to share or give it to partlist.c, because when we'll support GPT disks,
33 * things will change a bit).
34 * And, bootsup.c can manage initializing / adding boot entries into NTLDR
35 * and FREELDR, and installing the latter, and saving the old MBR / boot
39 /* FUNCTIONS ****************************************************************/
42 TrimTrailingPathSeparators_UStr(
43 IN OUT PUNICODE_STRING UnicodeString
)
45 while (UnicodeString
->Length
>= sizeof(WCHAR
) &&
46 UnicodeString
->Buffer
[UnicodeString
->Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
48 UnicodeString
->Length
-= sizeof(WCHAR
);
54 CreateFreeLoaderReactOSEntries(
55 IN PVOID BootStoreHandle
,
58 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
59 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
60 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
61 BOOT_STORE_OPTIONS BootOptions
;
63 BootEntry
->Version
= FreeLdr
;
64 BootEntry
->BootFilePath
= NULL
;
66 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
67 RtlCopyMemory(Options
->Signature
,
68 NTOS_OPTIONS_SIGNATURE
,
69 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
71 Options
->OsLoadPath
= ArcPath
;
74 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
75 BootEntry
->FriendlyName
= L
"\"ReactOS\"";
76 Options
->OsLoadOptions
= NULL
; // L"";
77 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS"));
80 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
81 BootEntry
->FriendlyName
= L
"\"ReactOS (Debug)\"";
82 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
83 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Debug"));
86 /* ReactOS_VBoxDebug */
87 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
88 BootEntry
->FriendlyName
= L
"\"ReactOS (VBox Debug)\"";
89 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=VBOX /SOS";
90 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_VBoxDebug"));
94 /* ReactOS_KdSerial */
95 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
96 BootEntry
->FriendlyName
= L
"\"ReactOS (RosDbg)\"";
97 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
98 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_KdSerial"));
102 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
103 BootEntry
->FriendlyName
= L
"\"ReactOS (Screen)\"";
104 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=SCREEN /SOS";
105 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Screen"));
107 /* ReactOS_LogFile */
108 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
109 BootEntry
->FriendlyName
= L
"\"ReactOS (Log file)\"";
110 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=FILE /SOS";
111 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_LogFile"));
114 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
115 BootEntry
->FriendlyName
= L
"\"ReactOS (RAM Disk)\"";
116 Options
->OsLoadPath
= L
"ramdisk(0)\\ReactOS";
117 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
118 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_Ram"));
121 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
122 BootEntry
->FriendlyName
= L
"\"ReactOS (Emergency Management Services)\"";
123 Options
->OsLoadPath
= ArcPath
;
124 Options
->OsLoadOptions
= L
"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
125 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(L
"ReactOS_EMS"));
129 /* DefaultOS=ReactOS */
130 #if DBG && !defined(_WINKD_)
131 if (IsUnattendedSetup
)
133 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_KdSerial");
139 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS_Debug");
141 BootOptions
.CurrentBootEntryKey
= MAKESTRKEY(L
"ReactOS");
146 if (IsUnattendedSetup
)
149 /* Timeout=0 for unattended or non debug */
150 BootOptions
.Timeout
= 0;
156 BootOptions
.Timeout
= 10;
160 BootOptions
.Version
= FreeLdr
;
161 SetBootStoreOptions(BootStoreHandle
, &BootOptions
, 2 | 1);
165 CreateFreeLoaderIniForReactOS(
170 PVOID BootStoreHandle
;
172 /* Initialize the INI file and create the common FreeLdr sections */
173 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
174 if (!NT_SUCCESS(Status
))
177 /* Add the ReactOS entries */
178 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
180 /* Close the INI file */
181 CloseBootStore(BootStoreHandle
);
182 return STATUS_SUCCESS
;
186 CreateFreeLoaderIniForReactOSAndBootSector(
190 IN PCWSTR Description
,
192 IN PCWSTR BootPartition
,
193 IN PCWSTR BootSector
)
196 PVOID BootStoreHandle
;
197 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(BOOT_SECTOR_OPTIONS
)];
198 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
199 PBOOT_SECTOR_OPTIONS Options
= (PBOOT_SECTOR_OPTIONS
)&BootEntry
->OsOptions
;
201 /* Initialize the INI file and create the common FreeLdr sections */
202 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, TRUE
);
203 if (!NT_SUCCESS(Status
))
206 /* Add the ReactOS entries */
207 CreateFreeLoaderReactOSEntries(BootStoreHandle
, ArcPath
);
209 BootEntry
->Version
= FreeLdr
;
210 BootEntry
->BootFilePath
= NULL
;
212 BootEntry
->OsOptionsLength
= sizeof(BOOT_SECTOR_OPTIONS
);
213 RtlCopyMemory(Options
->Signature
,
214 BOOT_SECTOR_OPTIONS_SIGNATURE
,
215 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS
, Signature
));
217 Options
->Drive
= BootDrive
;
218 Options
->Partition
= BootPartition
;
219 Options
->BootSectorFileName
= BootSector
;
221 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
222 BootEntry
->FriendlyName
= Description
;
223 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Section
));
225 /* Close the INI file */
226 CloseBootStore(BootStoreHandle
);
227 return STATUS_SUCCESS
;
231 // I think this function can be generalizable as:
232 // "find the corresponding 'ReactOS' boot entry in this loader config file
233 // (here abstraction comes there), and if none, add a new one".
236 typedef struct _ENUM_REACTOS_ENTRIES_DATA
239 BOOLEAN UseExistingEntry
;
241 WCHAR SectionName
[80];
243 } ENUM_REACTOS_ENTRIES_DATA
, *PENUM_REACTOS_ENTRIES_DATA
;
245 // PENUM_BOOT_ENTRIES_ROUTINE
248 EnumerateReactOSEntries(
249 IN BOOT_STORE_TYPE Type
,
250 IN PBOOT_STORE_ENTRY BootEntry
,
251 IN PVOID Parameter OPTIONAL
)
254 PENUM_REACTOS_ENTRIES_DATA Data
= (PENUM_REACTOS_ENTRIES_DATA
)Parameter
;
255 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
256 WCHAR SystemPath
[MAX_PATH
];
258 /* We have a boot entry */
260 /* Check for supported boot type "Windows2003" */
261 if (BootEntry
->OsOptionsLength
< sizeof(NTOS_OPTIONS
) ||
262 RtlCompareMemory(&BootEntry
->OsOptions
/* Signature */,
263 NTOS_OPTIONS_SIGNATURE
,
264 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
)) !=
265 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
))
267 /* This is not a ReactOS entry */
268 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
269 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
270 DPRINT(" An installation '%S' of unsupported type %lu\n",
271 BootEntry
->FriendlyName
, BootEntry
->OsOptionsLength
);
272 /* Continue the enumeration */
276 /* BootType is Windows2003, now check OsLoadPath */
277 if (!Options
->OsLoadPath
|| !*Options
->OsLoadPath
)
279 /* Certainly not a ReactOS installation */
280 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry
->FriendlyName
);
281 /* Continue the enumeration */
285 if (_wcsicmp(Options
->OsLoadPath
, Data
->ArcPath
) != 0)
287 /* Not found, retry with a quoted path */
288 Status
= RtlStringCchPrintfW(SystemPath
, ARRAYSIZE(SystemPath
), L
"\"%s\"", Data
->ArcPath
);
289 if (!NT_SUCCESS(Status
) || _wcsicmp(Options
->OsLoadPath
, SystemPath
) != 0)
292 * This entry is a ReactOS entry, but the SystemRoot
293 * does not match the one we are looking for.
295 /* Continue the enumeration */
300 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
301 BootEntry
->FriendlyName
, Options
->OsLoadPath
);
302 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
303 // BootEntry->FriendlyName, Options->OsLoadPath);
305 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options
->OsLoadPath
);
307 Data
->UseExistingEntry
= TRUE
;
308 RtlStringCchCopyW(Data
->OsName
, ARRAYSIZE(Data
->OsName
), BootEntry
->FriendlyName
);
310 /* We have found our entry, stop the enumeration now! */
311 return STATUS_NO_MORE_ENTRIES
;
314 Data
->UseExistingEntry
= FALSE
;
315 if (Type
== FreeLdr
&& wcscmp(Data
->SectionName
, (PWSTR
)BootEntry
->BootEntryKey
)== 0)
317 RtlStringCchPrintfW(Data
->SectionName
, ARRAYSIZE(Data
->SectionName
),
318 L
"ReactOS_%lu", Data
->i
);
319 RtlStringCchPrintfW(Data
->OsName
, ARRAYSIZE(Data
->OsName
),
320 L
"\"ReactOS %lu\"", Data
->i
);
323 return STATUS_SUCCESS
;
333 PVOID BootStoreHandle
;
334 ENUM_REACTOS_ENTRIES_DATA Data
;
335 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
336 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
337 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
339 /* Open the INI file */
340 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, FreeLdr
, /*TRUE*/ FALSE
);
341 if (!NT_SUCCESS(Status
))
344 /* Find an existing usable or an unused section name */
345 Data
.UseExistingEntry
= TRUE
;
347 Data
.ArcPath
= ArcPath
;
348 RtlStringCchCopyW(Data
.SectionName
, ARRAYSIZE(Data
.SectionName
), L
"ReactOS");
349 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
352 // FIXME: We temporarily use EnumerateBootStoreEntries, until
353 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
355 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
357 /* Create a new "ReactOS" entry if there is none already existing that suits us */
358 if (!Data
.UseExistingEntry
)
360 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
361 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
363 BootEntry
->Version
= FreeLdr
;
364 BootEntry
->BootFilePath
= NULL
;
366 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
367 RtlCopyMemory(Options
->Signature
,
368 NTOS_OPTIONS_SIGNATURE
,
369 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
371 Options
->OsLoadPath
= ArcPath
;
373 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
374 BootEntry
->FriendlyName
= Data
.OsName
;
375 Options
->OsLoadOptions
= NULL
; // L"";
376 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(Data
.SectionName
));
379 /* Close the INI file */
380 CloseBootStore(BootStoreHandle
);
381 return STATUS_SUCCESS
;
388 IN PCWSTR EntryName
, // ~= ArcPath
389 IN PCWSTR EntryValue
)
392 PVOID BootStoreHandle
;
393 ENUM_REACTOS_ENTRIES_DATA Data
;
395 // NOTE: Technically it would be "BootSector"...
396 UCHAR xxBootEntry
[FIELD_OFFSET(BOOT_STORE_ENTRY
, OsOptions
) + sizeof(NTOS_OPTIONS
)];
397 PBOOT_STORE_ENTRY BootEntry
= (PBOOT_STORE_ENTRY
)&xxBootEntry
;
398 PNTOS_OPTIONS Options
= (PNTOS_OPTIONS
)&BootEntry
->OsOptions
;
400 /* Open the INI file */
401 Status
= OpenBootStore(&BootStoreHandle
, IniPath
, NtLdr
, FALSE
);
402 if (!NT_SUCCESS(Status
))
405 /* Find an existing usable or an unused section name */
406 Data
.UseExistingEntry
= TRUE
;
408 Data
.ArcPath
= EntryName
;
409 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
410 RtlStringCchCopyW(Data
.OsName
, ARRAYSIZE(Data
.OsName
), L
"\"ReactOS\"");
413 // FIXME: We temporarily use EnumerateBootStoreEntries, until
414 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
416 Status
= EnumerateBootStoreEntries(BootStoreHandle
, EnumerateReactOSEntries
, &Data
);
418 /* If either the key was not found, or contains something else, add a new one */
419 if (!Data
.UseExistingEntry
/* ||
420 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
422 BootEntry
->Version
= NtLdr
;
423 BootEntry
->BootFilePath
= NULL
;
425 BootEntry
->OsOptionsLength
= sizeof(NTOS_OPTIONS
);
426 RtlCopyMemory(Options
->Signature
,
427 NTOS_OPTIONS_SIGNATURE
,
428 RTL_FIELD_SIZE(NTOS_OPTIONS
, Signature
));
430 Options
->OsLoadPath
= EntryName
;
432 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
433 // BootEntry->FriendlyName = Data.OsName;
434 BootEntry
->FriendlyName
= EntryValue
;
435 Options
->OsLoadOptions
= NULL
; // L"";
436 AddBootStoreEntry(BootStoreHandle
, BootEntry
, MAKESTRKEY(0 /*Data.SectionName*/));
439 /* Close the INI file */
440 CloseBootStore(BootStoreHandle
);
441 return STATUS_SUCCESS
; // Status;
447 IsThereAValidBootSector(
451 * We first demand that the bootsector has a valid signature at its end.
452 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
453 * potential "valid" instruction (the BIOS starts execution of the bootsector
454 * at its beginning). Currently this criterium is that this ULONG must be
455 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
456 * it is invalid and certainly needs to be overwritten.
459 BOOLEAN IsValid
= FALSE
;
461 UNICODE_STRING RootPartition
;
462 BOOTCODE BootSector
= {0};
464 /* Allocate and read the root partition bootsector.
465 * Remove any trailing backslash if needed. */
466 RtlInitUnicodeString(&RootPartition
, RootPath
);
467 TrimTrailingPathSeparators_UStr(&RootPartition
);
468 Status
= ReadBootCodeFromFile(&BootSector
, &RootPartition
, SECTORSIZE
);
469 if (!NT_SUCCESS(Status
))
472 /* Check for the existence of the bootsector signature */
473 IsValid
= (*(PUSHORT
)((PUCHAR
)BootSector
.BootCode
+ 0x1FE) == 0xAA55);
476 /* Check for the first instruction encoded on three bytes */
477 IsValid
= (((*(PULONG
)BootSector
.BootCode
) & 0x00FFFFFF) != 0x00000000);
480 /* Free the bootsector and return */
481 FreeBootCode(&BootSector
);
494 OBJECT_ATTRIBUTES ObjectAttributes
;
495 IO_STATUS_BLOCK IoStatusBlock
;
497 // LARGE_INTEGER FileOffset;
498 BOOTCODE BootSector
= {0};
500 /* Allocate and read the root partition bootsector.
501 * Remove any trailing backslash if needed. */
502 RtlInitUnicodeString(&Name
, RootPath
);
503 TrimTrailingPathSeparators_UStr(&Name
);
504 Status
= ReadBootCodeFromFile(&BootSector
, &Name
, Length
);
505 if (!NT_SUCCESS(Status
))
508 /* Write the bootsector to DstPath */
509 RtlInitUnicodeString(&Name
, DstPath
);
510 InitializeObjectAttributes(&ObjectAttributes
,
512 OBJ_CASE_INSENSITIVE
,
516 Status
= NtCreateFile(&FileHandle
,
517 GENERIC_WRITE
| SYNCHRONIZE
,
521 FILE_ATTRIBUTE_NORMAL
,
524 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
527 if (!NT_SUCCESS(Status
))
529 FreeBootCode(&BootSector
);
533 Status
= NtWriteFile(FileHandle
,
544 /* Free the bootsector and return */
545 FreeBootCode(&BootSector
);
552 InstallBootCodeToDisk(
555 IN PFS_INSTALL_BOOTCODE InstallBootCode
)
557 NTSTATUS Status
, LockStatus
;
559 OBJECT_ATTRIBUTES ObjectAttributes
;
560 IO_STATUS_BLOCK IoStatusBlock
;
561 HANDLE PartitionHandle
;
564 * Open the root partition from which the bootcode (MBR, VBR) parameters
565 * will be obtained; this is also where we will write the updated bootcode.
566 * Remove any trailing backslash if needed.
568 RtlInitUnicodeString(&Name
, RootPath
);
569 TrimTrailingPathSeparators_UStr(&Name
);
571 InitializeObjectAttributes(&ObjectAttributes
,
573 OBJ_CASE_INSENSITIVE
,
577 Status
= NtOpenFile(&PartitionHandle
,
578 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
581 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
582 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
583 if (!NT_SUCCESS(Status
))
586 /* Lock the volume */
587 LockStatus
= NtFsControlFile(PartitionHandle
, NULL
, NULL
, NULL
, &IoStatusBlock
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0);
588 if (!NT_SUCCESS(LockStatus
))
590 DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus
);
593 /* Install the bootcode (MBR, VBR) */
594 Status
= InstallBootCode(SrcPath
, PartitionHandle
, PartitionHandle
);
596 /* dismount & Unlock the volume */
597 if (NT_SUCCESS(LockStatus
))
599 LockStatus
= NtFsControlFile(PartitionHandle
, NULL
, NULL
, NULL
, &IoStatusBlock
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0);
600 if (!NT_SUCCESS(LockStatus
))
602 DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus
);
605 LockStatus
= NtFsControlFile(PartitionHandle
, NULL
, NULL
, NULL
, &IoStatusBlock
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0);
606 if (!NT_SUCCESS(LockStatus
))
608 DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus
);
612 /* Close the partition */
613 NtClose(PartitionHandle
);
620 InstallBootCodeToFile(
624 IN PFS_INSTALL_BOOTCODE InstallBootCode
)
628 OBJECT_ATTRIBUTES ObjectAttributes
;
629 IO_STATUS_BLOCK IoStatusBlock
;
630 HANDLE PartitionHandle
, FileHandle
;
633 * Open the root partition from which the bootcode (MBR, VBR)
634 * parameters will be obtained.
636 * FIXME? It might be possible that we need to also open it for writing
637 * access in case we really need to still write the second portion of
638 * the boot sector ????
640 * Remove any trailing backslash if needed.
642 RtlInitUnicodeString(&Name
, RootPath
);
643 TrimTrailingPathSeparators_UStr(&Name
);
645 InitializeObjectAttributes(&ObjectAttributes
,
647 OBJ_CASE_INSENSITIVE
,
651 Status
= NtOpenFile(&PartitionHandle
,
652 GENERIC_READ
| SYNCHRONIZE
,
655 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
656 FILE_SYNCHRONOUS_IO_NONALERT
/* | FILE_SEQUENTIAL_ONLY */);
657 if (!NT_SUCCESS(Status
))
660 /* Open or create the file where the new bootsector will be saved */
661 RtlInitUnicodeString(&Name
, DstPath
);
662 InitializeObjectAttributes(&ObjectAttributes
,
664 OBJ_CASE_INSENSITIVE
,
668 Status
= NtCreateFile(&FileHandle
,
669 GENERIC_WRITE
| SYNCHRONIZE
,
673 FILE_ATTRIBUTE_NORMAL
,
675 FILE_SUPERSEDE
, // FILE_OVERWRITE_IF
676 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
679 if (!NT_SUCCESS(Status
))
681 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
682 NtClose(PartitionHandle
);
686 /* Install the bootcode (MBR, VBR) */
687 Status
= InstallBootCode(SrcPath
, FileHandle
, PartitionHandle
);
689 /* Close the file and the partition */
691 NtClose(PartitionHandle
);
700 IN PCWSTR SrcPath
, // MBR source file (on the installation medium)
701 IN HANDLE DstPath
, // Where to save the bootsector built from the source + disk information
702 IN HANDLE DiskHandle
) // Disk holding the (old) MBR information
706 IO_STATUS_BLOCK IoStatusBlock
;
707 LARGE_INTEGER FileOffset
;
708 BOOTCODE OrigBootSector
= {0};
709 BOOTCODE NewBootSector
= {0};
711 C_ASSERT(sizeof(PARTITION_SECTOR
) == SECTORSIZE
);
713 /* Allocate and read the current original MBR bootsector */
714 Status
= ReadBootCodeByHandle(&OrigBootSector
,
716 sizeof(PARTITION_SECTOR
));
717 if (!NT_SUCCESS(Status
))
720 /* Allocate and read the new bootsector from SrcPath */
721 RtlInitUnicodeString(&Name
, SrcPath
);
722 Status
= ReadBootCodeFromFile(&NewBootSector
,
724 sizeof(PARTITION_SECTOR
));
725 if (!NT_SUCCESS(Status
))
727 FreeBootCode(&OrigBootSector
);
732 * Copy the disk signature, the reserved fields and
733 * the partition table from the old MBR to the new one.
735 RtlCopyMemory(&((PPARTITION_SECTOR
)NewBootSector
.BootCode
)->Signature
,
736 &((PPARTITION_SECTOR
)OrigBootSector
.BootCode
)->Signature
,
737 sizeof(PARTITION_SECTOR
) -
738 FIELD_OFFSET(PARTITION_SECTOR
, Signature
)
739 /* Length of partition table */);
741 /* Free the original bootsector */
742 FreeBootCode(&OrigBootSector
);
744 /* Write the new bootsector to DstPath */
745 FileOffset
.QuadPart
= 0ULL;
746 Status
= NtWriteFile(DstPath
,
751 NewBootSector
.BootCode
,
752 NewBootSector
.Length
,
756 /* Free the new bootsector */
757 FreeBootCode(&NewBootSector
);
763 InstallMbrBootCodeToDisk(
764 IN PUNICODE_STRING SystemRootPath
,
765 IN PUNICODE_STRING SourceRootPath
,
766 IN PCWSTR DestinationDevicePathBuffer
)
769 WCHAR SourceMbrPathBuffer
[MAX_PATH
];
770 WCHAR DstPath
[MAX_PATH
];
774 * The DestinationDevicePathBuffer parameter has been built with
775 * the following instruction by the caller; I'm not yet sure whether
776 * I actually want this function to build the path instead, hence
777 * I keep this code here but disabled for now...
779 WCHAR DestinationDevicePathBuffer
[MAX_PATH
];
780 RtlStringCchPrintfW(DestinationDevicePathBuffer
, ARRAYSIZE(DestinationDevicePathBuffer
),
781 L
"\\Device\\Harddisk%d\\Partition0",
785 CombinePaths(SourceMbrPathBuffer
, ARRAYSIZE(SourceMbrPathBuffer
), 2,
786 SourceRootPath
->Buffer
, L
"\\loader\\dosmbr.bin");
788 if (IsThereAValidBootSector(DestinationDevicePathBuffer
))
790 /* Save current MBR */
791 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2,
792 SystemRootPath
->Buffer
, L
"mbr.old");
794 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer
, DstPath
);
795 Status
= SaveBootSector(DestinationDevicePathBuffer
, DstPath
, sizeof(PARTITION_SECTOR
));
796 if (!NT_SUCCESS(Status
))
798 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
799 // Don't care if we succeeded or not saving the old MBR, just go ahead.
803 DPRINT1("Install MBR bootcode: %S ==> %S\n",
804 SourceMbrPathBuffer
, DestinationDevicePathBuffer
);
806 /* Install the MBR */
807 return InstallBootCodeToDisk(SourceMbrPathBuffer
,
808 DestinationDevicePathBuffer
,
815 InstallFatBootcodeToPartition(
816 IN PUNICODE_STRING SystemRootPath
,
817 IN PUNICODE_STRING SourceRootPath
,
818 IN PUNICODE_STRING DestinationArcPath
,
819 IN PCWSTR FileSystemName
)
822 BOOLEAN DoesFreeLdrExist
;
823 WCHAR SrcPath
[MAX_PATH
];
824 WCHAR DstPath
[MAX_PATH
];
826 /* FAT or FAT32 partition */
827 DPRINT("System path: '%wZ'\n", SystemRootPath
);
829 /* Copy FreeLoader to the system partition, always overwriting the older version */
830 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
831 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
833 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
834 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
835 if (!NT_SUCCESS(Status
))
837 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
841 /* Prepare for possibly updating 'freeldr.ini' */
842 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
843 if (DoesFreeLdrExist
)
845 /* Update existing 'freeldr.ini' */
846 DPRINT1("Update existing 'freeldr.ini'\n");
847 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
848 if (!NT_SUCCESS(Status
))
850 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
855 /* Check for NT and other bootloaders */
857 // FIXME: Check for Vista+ bootloader!
858 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
859 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
860 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"NTLDR") == TRUE
||
861 DoesFileExist_2(SystemRootPath
->Buffer
, L
"BOOT.INI") == TRUE
)
863 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
864 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
866 /* Create or update 'freeldr.ini' */
867 if (DoesFreeLdrExist
== FALSE
)
869 /* Create new 'freeldr.ini' */
870 DPRINT1("Create new 'freeldr.ini'\n");
871 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
872 if (!NT_SUCCESS(Status
))
874 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
878 /* Install new bootcode into a file */
879 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"bootsect.ros");
881 if (wcsicmp(FileSystemName
, L
"FAT32") == 0)
883 /* Install FAT32 bootcode */
884 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
886 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
887 Status
= InstallBootCodeToFile(SrcPath
, DstPath
,
888 SystemRootPath
->Buffer
,
889 InstallFat32BootCode
);
890 if (!NT_SUCCESS(Status
))
892 DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status
);
896 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
898 /* Install FAT16 bootcode */
899 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
901 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
902 Status
= InstallBootCodeToFile(SrcPath
, DstPath
,
903 SystemRootPath
->Buffer
,
904 InstallFat16BootCode
);
905 if (!NT_SUCCESS(Status
))
907 DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status
);
913 /* Update 'boot.ini' */
914 /* Windows' NTLDR loads an external bootsector file when the specified drive
915 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
916 DPRINT1("Update 'boot.ini'\n");
917 Status
= UpdateBootIni(SystemRootPath
->Buffer
,
920 if (!NT_SUCCESS(Status
))
922 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status
);
928 /* Non-NT bootloaders: install our own bootloader */
933 PCWSTR BootPartition
;
936 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
937 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IOSYS.COM") == TRUE
||
938 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.COM") == TRUE
)
940 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
943 Description
= L
"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
945 BootPartition
= L
"1";
946 BootSector
= L
"BOOTSECT.DOS";
949 /* Search for Microsoft DOS or Windows 9x boot loader */
950 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IO.SYS") == TRUE
||
951 DoesFileExist_2(SystemRootPath
->Buffer
, L
"MSDOS.SYS") == TRUE
)
954 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
957 Description
= L
"\"MS-DOS/Windows\"";
959 BootPartition
= L
"1";
960 BootSector
= L
"BOOTSECT.DOS";
963 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
964 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMIO.COM" ) == TRUE
|| // Some people refer to this file instead of IBMBIO.COM...
965 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMBIO.COM") == TRUE
||
966 DoesFileExist_2(SystemRootPath
->Buffer
, L
"IBMDOS.COM") == TRUE
)
968 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
971 Description
= L
"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
973 BootPartition
= L
"1";
974 BootSector
= L
"BOOTSECT.DOS";
977 /* Search for DR-DOS 3.x boot loader */
978 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBIOS.SYS") == TRUE
||
979 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DRBDOS.SYS") == TRUE
)
981 DPRINT1("Found DR-DOS 3.x\n");
984 Description
= L
"\"DR-DOS 3.x\"";
986 BootPartition
= L
"1";
987 BootSector
= L
"BOOTSECT.DOS";
990 /* Search for Dell Real-Mode Kernel (DRMK) OS */
991 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLBIO.BIN") == TRUE
||
992 DoesFileExist_2(SystemRootPath
->Buffer
, L
"DELLRMK.BIN") == TRUE
)
994 DPRINT1("Found Dell Real-Mode Kernel OS\n");
997 Description
= L
"\"Dell Real-Mode Kernel OS\"";
999 BootPartition
= L
"1";
1000 BootSector
= L
"BOOTSECT.DOS";
1003 /* Search for MS OS/2 1.x */
1004 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT.COM") == TRUE
||
1005 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BIO.COM" ) == TRUE
||
1006 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2DOS.COM" ) == TRUE
)
1008 DPRINT1("Found MS OS/2 1.x\n");
1011 Description
= L
"\"MS OS/2 1.x\"";
1013 BootPartition
= L
"1";
1014 BootSector
= L
"BOOTSECT.OS2";
1017 /* Search for MS or IBM OS/2 */
1018 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2BOOT") == TRUE
||
1019 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2LDR" ) == TRUE
||
1020 DoesFileExist_2(SystemRootPath
->Buffer
, L
"OS2KRNL") == TRUE
)
1022 DPRINT1("Found MS/IBM OS/2\n");
1024 Section
= L
"IBMOS2";
1025 Description
= L
"\"MS/IBM OS/2\"";
1027 BootPartition
= L
"1";
1028 BootSector
= L
"BOOTSECT.OS2";
1031 /* Search for FreeDOS boot loader */
1032 if (DoesFileExist_2(SystemRootPath
->Buffer
, L
"kernel.sys") == TRUE
)
1034 DPRINT1("Found FreeDOS boot loader\n");
1037 Description
= L
"\"FreeDOS\"";
1039 BootPartition
= L
"1";
1040 BootSector
= L
"BOOTSECT.DOS";
1044 /* No or unknown boot loader */
1045 DPRINT1("No or unknown boot loader found\n");
1047 Section
= L
"Unknown";
1048 Description
= L
"\"Unknown Operating System\"";
1050 BootPartition
= L
"1";
1051 BootSector
= L
"BOOTSECT.OLD";
1054 /* Create or update 'freeldr.ini' */
1055 if (DoesFreeLdrExist
== FALSE
)
1057 /* Create new 'freeldr.ini' */
1058 DPRINT1("Create new 'freeldr.ini'\n");
1060 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
1062 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
1063 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
1064 Section
, Description
,
1065 BootDrive
, BootPartition
, BootSector
);
1066 if (!NT_SUCCESS(Status
))
1068 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
1072 /* Save current bootsector */
1073 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
1075 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
1076 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, SECTORSIZE
);
1077 if (!NT_SUCCESS(Status
))
1079 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
1085 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1086 if (!NT_SUCCESS(Status
))
1088 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1093 /* Install new bootsector on the disk */
1094 if (wcsicmp(FileSystemName
, L
"FAT32") == 0)
1096 /* Install FAT32 bootcode */
1097 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat32.bin");
1099 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
1100 Status
= InstallBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
, InstallFat32BootCode
);
1101 DPRINT1("Status: 0x%08X\n", Status
);
1102 if (!NT_SUCCESS(Status
))
1104 DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status
);
1108 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1110 /* Install FAT16 bootcode */
1111 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
1113 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
1114 Status
= InstallBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
, InstallFat16BootCode
);
1115 if (!NT_SUCCESS(Status
))
1117 DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status
);
1124 return STATUS_SUCCESS
;
1129 InstallBtrfsBootcodeToPartition(
1130 IN PUNICODE_STRING SystemRootPath
,
1131 IN PUNICODE_STRING SourceRootPath
,
1132 IN PUNICODE_STRING DestinationArcPath
)
1135 BOOLEAN DoesFreeLdrExist
;
1136 WCHAR SrcPath
[MAX_PATH
];
1137 WCHAR DstPath
[MAX_PATH
];
1139 /* BTRFS partition */
1140 DPRINT("System path: '%wZ'\n", SystemRootPath
);
1142 /* Copy FreeLoader to the system partition, always overwriting the older version */
1143 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
1144 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, L
"freeldr.sys");
1146 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
1147 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
1148 if (!NT_SUCCESS(Status
))
1150 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1154 /* Prepare for possibly updating 'freeldr.ini' */
1155 DoesFreeLdrExist
= DoesFileExist_2(SystemRootPath
->Buffer
, L
"freeldr.ini");
1156 if (DoesFreeLdrExist
)
1158 /* Update existing 'freeldr.ini' */
1159 DPRINT1("Update existing 'freeldr.ini'\n");
1160 Status
= UpdateFreeLoaderIni(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1161 if (!NT_SUCCESS(Status
))
1163 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status
);
1168 /* Check for *nix bootloaders */
1170 /* Create or update 'freeldr.ini' */
1171 if (DoesFreeLdrExist
== FALSE
)
1173 /* Create new 'freeldr.ini' */
1174 DPRINT1("Create new 'freeldr.ini'\n");
1176 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1177 DPRINT1("*nix or unknown boot loader found\n");
1179 if (IsThereAValidBootSector(SystemRootPath
->Buffer
))
1181 PCWSTR BootSector
= L
"BOOTSECT.OLD";
1183 Status
= CreateFreeLoaderIniForReactOSAndBootSector(
1184 SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
,
1185 L
"Linux", L
"\"Linux\"",
1186 L
"hd0", L
"1", BootSector
);
1187 if (!NT_SUCCESS(Status
))
1189 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status
);
1193 /* Save current bootsector */
1194 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, SystemRootPath
->Buffer
, BootSector
);
1196 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath
->Buffer
, DstPath
);
1197 Status
= SaveBootSector(SystemRootPath
->Buffer
, DstPath
, BTRFS_BOOTSECTOR_SIZE
);
1198 if (!NT_SUCCESS(Status
))
1200 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status
);
1206 Status
= CreateFreeLoaderIniForReactOS(SystemRootPath
->Buffer
, DestinationArcPath
->Buffer
);
1207 if (!NT_SUCCESS(Status
))
1209 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1214 /* Install new bootsector on the disk */
1215 /* Install BTRFS bootcode */
1216 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\btrfs.bin");
1218 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath
, SystemRootPath
->Buffer
);
1219 Status
= InstallBootCodeToDisk(SrcPath
, SystemRootPath
->Buffer
, InstallBtrfsBootCode
);
1220 if (!NT_SUCCESS(Status
))
1222 DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status
);
1227 return STATUS_SUCCESS
;
1232 InstallVBRToPartition(
1233 IN PUNICODE_STRING SystemRootPath
,
1234 IN PUNICODE_STRING SourceRootPath
,
1235 IN PUNICODE_STRING DestinationArcPath
,
1236 IN PCWSTR FileSystemName
)
1238 if (wcsicmp(FileSystemName
, L
"FAT") == 0 ||
1239 wcsicmp(FileSystemName
, L
"FAT32") == 0)
1241 return InstallFatBootcodeToPartition(SystemRootPath
,
1247 else if (wcsicmp(FileSystemName, L"NTFS") == 0)
1249 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
1250 return STATUS_NOT_SUPPORTED;
1253 else if (wcsicmp(FileSystemName
, L
"BTRFS") == 0)
1255 return InstallBtrfsBootcodeToPartition(SystemRootPath
,
1257 DestinationArcPath
);
1260 else if (wcsicmp(FileSystemName, L"EXT2") == 0 ||
1261 wcsicmp(FileSystemName, L"EXT3") == 0 ||
1262 wcsicmp(FileSystemName, L"EXT4") == 0)
1264 return STATUS_NOT_SUPPORTED;
1269 /* Unknown file system */
1270 DPRINT1("Unknown file system '%S'\n", FileSystemName
);
1273 return STATUS_NOT_SUPPORTED
;
1278 InstallFatBootcodeToFloppy(
1279 IN PUNICODE_STRING SourceRootPath
,
1280 IN PUNICODE_STRING DestinationArcPath
)
1282 static const PCWSTR FloppyDevice
= L
"\\Device\\Floppy0\\";
1285 WCHAR SrcPath
[MAX_PATH
];
1286 WCHAR DstPath
[MAX_PATH
];
1288 /* Verify that the floppy disk is accessible */
1289 if (DoesDirExist(NULL
, FloppyDevice
) == FALSE
)
1290 return STATUS_DEVICE_NOT_READY
;
1292 /* Format the floppy disk */
1293 // FormatPartition(...)
1294 Status
= FormatFileSystem(FloppyDevice
,
1301 if (!NT_SUCCESS(Status
))
1303 if (Status
== STATUS_NOT_SUPPORTED
)
1304 DPRINT1("FAT FS non existent on this system?!\n");
1306 DPRINT1("VfatFormat() failed (Status %lx)\n", Status
);
1311 /* Copy FreeLoader to the boot partition */
1312 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\freeldr.sys");
1313 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 2, FloppyDevice
, L
"freeldr.sys");
1315 DPRINT("Copy: %S ==> %S\n", SrcPath
, DstPath
);
1316 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
1317 if (!NT_SUCCESS(Status
))
1319 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1323 /* Create new 'freeldr.ini' */
1324 DPRINT("Create new 'freeldr.ini'\n");
1325 Status
= CreateFreeLoaderIniForReactOS(FloppyDevice
, DestinationArcPath
->Buffer
);
1326 if (!NT_SUCCESS(Status
))
1328 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status
);
1332 /* Install FAT12 boosector */
1333 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 2, SourceRootPath
->Buffer
, L
"\\loader\\fat.bin");
1334 CombinePaths(DstPath
, ARRAYSIZE(DstPath
), 1, FloppyDevice
);
1336 DPRINT("Install FAT12 bootcode: %S ==> %S\n", SrcPath
, DstPath
);
1337 Status
= InstallBootCodeToDisk(SrcPath
, DstPath
, InstallFat12BootCode
);
1338 if (!NT_SUCCESS(Status
))
1340 DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status %lx)\n", Status
);
1344 return STATUS_SUCCESS
;