ReactOS 0.4.16-dev-981-g80eb313
bootsup.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Bootloader support functions
5 * COPYRIGHT: ...
6 * Copyright 2017-2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include "precomp.h"
12
13#include <ntddstor.h> // For STORAGE_DEVICE_NUMBER
14
15#include "bldrsup.h"
16#include "devutils.h"
17#include "filesup.h"
18#include "partlist.h"
19#include "bootcode.h"
20#include "fsutil.h"
21
22#include "setuplib.h"
23extern BOOLEAN IsUnattendedSetup; // HACK
24
25#include "bootsup.h"
26
27#define NDEBUG
28#include <debug.h>
29
30/*
31 * BIG FIXME!!
32 * ===========
33 *
34 * bootsup.c can deal with MBR code (actually it'll have at some point
35 * to share or give it to partlist.c, because when we'll support GPT disks,
36 * things will change a bit).
37 * And, bootsup.c can manage initializing / adding boot entries into NTLDR
38 * and FREELDR, and installing the latter, and saving the old MBR / boot
39 * sectors in files.
40 */
41
42/* FUNCTIONS ****************************************************************/
43
44static VOID
47{
48 while (UnicodeString->Length >= sizeof(WCHAR) &&
49 UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
50 {
51 UnicodeString->Length -= sizeof(WCHAR);
52 }
53}
54
55
56static VOID
58 IN PVOID BootStoreHandle,
59 IN PCWSTR ArcPath)
60{
61 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
62 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
63 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
65
66 BootEntry->Version = FreeLdr;
67 BootEntry->BootFilePath = NULL;
68
69 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
70 RtlCopyMemory(Options->Signature,
73
74 Options->OsLoadPath = ArcPath;
75
76 /* ReactOS */
77 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
78 BootEntry->FriendlyName = L"\"ReactOS\"";
79 Options->OsLoadOptions = L"/FASTDETECT";
80 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
81
82 /* ReactOS_Debug */
83 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
84 BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
85 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
86 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
87
88#ifdef _WINKD_
89 /* ReactOS_VBoxDebug */
90 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
91 BootEntry->FriendlyName = L"\"ReactOS (VBox Debug)\"";
92 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
93 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
94#endif
95#if DBG
96#ifndef _WINKD_
97 /* ReactOS_KdSerial */
98 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
99 BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\"";
100 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
101 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
102#endif
103
104 /* ReactOS_Screen */
105 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
106 BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
107 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
108 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
109
110 /* ReactOS_LogFile */
111 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
112 BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
113 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
114 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
115
116 /* ReactOS_Ram */
117 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
118 BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\"";
119 Options->OsLoadPath = L"ramdisk(0)\\ReactOS";
120 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
121 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
122
123 /* ReactOS_EMS */
124 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
125 BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\"";
126 Options->OsLoadPath = ArcPath;
127 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
128 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
129#endif
130
131
132 /* DefaultOS=ReactOS */
133#if DBG && !defined(_WINKD_)
135 {
136 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
137 }
138 else
139#endif
140 {
141#if DBG
142 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
143#else
144 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS");
145#endif
146 }
147
148#if DBG
150#endif
151 {
152 /* Timeout=0 for unattended or non debug */
153 BootOptions.Timeout = 0;
154 }
155#if DBG
156 else
157 {
158 /* Timeout=10 */
159 BootOptions.Timeout = 10;
160 }
161#endif
162
163 SetBootStoreOptions(BootStoreHandle, &BootOptions,
165}
166
167static NTSTATUS
169 IN PCWSTR IniPath,
170 IN PCWSTR ArcPath)
171{
173 PVOID BootStoreHandle;
174
175 /* Initialize the INI file and create the common FreeLdr sections */
176 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
177 BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
178 if (!NT_SUCCESS(Status))
179 return Status;
180
181 /* Add the ReactOS entries */
182 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
183
184 /* Close the INI file */
185 CloseBootStore(BootStoreHandle);
186 return STATUS_SUCCESS;
187}
188
189static NTSTATUS
191 IN PCWSTR IniPath,
192 IN PCWSTR ArcPath,
193 IN PCWSTR Section,
195 IN PCWSTR BootPath,
197{
199 PVOID BootStoreHandle;
200 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOTSECTOR_OPTIONS)];
201 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
202 PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
203 WCHAR BootPathBuffer[MAX_PATH] = L"";
204
205 /* Since the BootPath given here is in NT format
206 * (not ARC), we need to hack-generate a mapping */
207 ULONG DiskNumber = 0, PartitionNumber = 0;
209
210 /* From the NT path, compute the disk, partition and path components */
211 // NOTE: this function doesn't support stuff like \Device\FloppyX ...
213 {
214 DPRINT1("BootPath = '%S' points to disk #%d, partition #%d, path '%S'\n",
215 BootPath, DiskNumber, PartitionNumber, PathComponent);
216
217 /* HACK-build a possible ARC path:
218 * Hard disk path: multi(0)disk(0)rdisk(x)partition(y)[\path] */
219 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
220 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
221 DiskNumber, PartitionNumber);
223 (PathComponent[0] != L'\\' || PathComponent[1]))
224 {
225 RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
227 }
228 }
229 else
230 {
231 PCWSTR Path = BootPath;
232
233 if ((_wcsnicmp(Path, L"\\Device\\Floppy", 14) == 0) &&
234 (Path += 14) && iswdigit(*Path))
235 {
236 DiskNumber = wcstoul(Path, (PWSTR*)&PathComponent, 10);
237 if (PathComponent && *PathComponent && *PathComponent != L'\\')
239
240 /* HACK-build a possible ARC path:
241 * Floppy disk path: multi(0)disk(0)fdisk(x)[\path] */
242 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
243 L"multi(0)disk(0)fdisk(%lu)", DiskNumber);
245 (PathComponent[0] != L'\\' || PathComponent[1]))
246 {
247 RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
249 }
250 }
251 else
252 {
253 /* HACK: Just keep the unresolved NT path and hope for the best... */
254
255 /* Remove any trailing backslash if needed */
259
260 /* RootPartition is BootPath without counting any trailing
261 * path separator. Because of this, we need to copy the string
262 * in the buffer, instead of just using a pointer to it. */
263 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
264 L"%wZ", &RootPartition);
265
266 DPRINT1("Unhandled NT path '%S'\n", BootPath);
267 }
268 }
269
270 /* Initialize the INI file and create the common FreeLdr sections */
271 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
272 BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
273 if (!NT_SUCCESS(Status))
274 return Status;
275
276 /* Add the ReactOS entries */
277 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
278
279 BootEntry->Version = FreeLdr;
280 BootEntry->BootFilePath = NULL;
281
282 BootEntry->OsOptionsLength = sizeof(BOOTSECTOR_OPTIONS);
283 RtlCopyMemory(Options->Signature,
286
287 Options->BootPath = BootPathBuffer;
288 Options->FileName = BootSector;
289
290 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
291 BootEntry->FriendlyName = Description;
292 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
293
294 /* Close the INI file */
295 CloseBootStore(BootStoreHandle);
296 return STATUS_SUCCESS;
297}
298
299//
300// I think this function can be generalizable as:
301// "find the corresponding 'ReactOS' boot entry in this loader config file
302// (here abstraction comes there), and if none, add a new one".
303//
304
306{
313
314// PENUM_BOOT_ENTRIES_ROUTINE
315static NTSTATUS
316NTAPI
319 IN PBOOT_STORE_ENTRY BootEntry,
321{
324 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
325 WCHAR SystemPath[MAX_PATH];
326
327 /* We have a boot entry */
328
329 /* Check for supported boot type "Windows2003" */
330 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
331 RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
335 {
336 /* This is not a ReactOS entry */
337 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
338 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
339 DPRINT(" An installation '%S' of unsupported type %lu\n",
340 BootEntry->FriendlyName, BootEntry->OsOptionsLength);
341 /* Continue the enumeration */
342 goto SkipThisEntry;
343 }
344
345 /* BootType is Windows2003, now check OsLoadPath */
346 if (!Options->OsLoadPath || !*Options->OsLoadPath)
347 {
348 /* Certainly not a ReactOS installation */
349 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
350 /* Continue the enumeration */
351 goto SkipThisEntry;
352 }
353
354 if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
355 {
356 /* Not found, retry with a quoted path */
357 Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
358 if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
359 {
360 /*
361 * This entry is a ReactOS entry, but the SystemRoot
362 * does not match the one we are looking for.
363 */
364 /* Continue the enumeration */
365 goto SkipThisEntry;
366 }
367 }
368
369 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
370 BootEntry->FriendlyName, Options->OsLoadPath);
371 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
372 // BootEntry->FriendlyName, Options->OsLoadPath);
373
374 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
375
376 Data->UseExistingEntry = TRUE;
377 RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
378
379 /* We have found our entry, stop the enumeration now! */
381
382SkipThisEntry:
383 Data->UseExistingEntry = FALSE;
384 if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
385 {
386 RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
387 L"ReactOS_%lu", Data->i);
388 RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
389 L"\"ReactOS %lu\"", Data->i);
390 Data->i++;
391 }
392 return STATUS_SUCCESS;
393}
394
395static
398 IN PCWSTR IniPath,
399 IN PCWSTR ArcPath)
400{
402 PVOID BootStoreHandle;
404 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
405 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
406 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
407
408 /* Open the INI file */
409 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
410 BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
411 if (!NT_SUCCESS(Status))
412 return Status;
413
414 /* Find an existing usable or an unused section name */
415 Data.UseExistingEntry = TRUE;
416 Data.i = 1;
417 Data.ArcPath = ArcPath;
418 RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
419 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
420
421 //
422 // FIXME: We temporarily use EnumerateBootStoreEntries, until
423 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
424 //
426
427 /* Create a new "ReactOS" entry if there is none already existing that suits us */
428 if (!Data.UseExistingEntry)
429 {
430 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
431 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
432
433 BootEntry->Version = FreeLdr;
434 BootEntry->BootFilePath = NULL;
435
436 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
437 RtlCopyMemory(Options->Signature,
440
441 Options->OsLoadPath = ArcPath;
442
443 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
444 BootEntry->FriendlyName = Data.OsName;
445 Options->OsLoadOptions = NULL; // L"";
446 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
447 }
448
449 /* Close the INI file */
450 CloseBootStore(BootStoreHandle);
451 return STATUS_SUCCESS;
452}
453
454static
457 IN PCWSTR IniPath,
458 IN PCWSTR EntryName, // ~= ArcPath
459 IN PCWSTR EntryValue)
460{
462 PVOID BootStoreHandle;
464
465 // NOTE: Technically it would be "BootSector"...
466 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
467 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
468 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
469
470 /* Open the INI file */
471 Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr,
472 BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
473 if (!NT_SUCCESS(Status))
474 return Status;
475
476 /* Find an existing usable or an unused section name */
477 Data.UseExistingEntry = TRUE;
478 // Data.i = 1;
479 Data.ArcPath = EntryName;
480 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
481 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
482
483 //
484 // FIXME: We temporarily use EnumerateBootStoreEntries, until
485 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
486 //
488
489 /* If either the key was not found, or contains something else, add a new one */
490 if (!Data.UseExistingEntry /* ||
491 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
492 {
493 BootEntry->Version = NtLdr;
494 BootEntry->BootFilePath = NULL;
495
496 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
497 RtlCopyMemory(Options->Signature,
500
501 Options->OsLoadPath = EntryName;
502
503 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
504 // BootEntry->FriendlyName = Data.OsName;
505 BootEntry->FriendlyName = EntryValue;
506 Options->OsLoadOptions = NULL; // L"";
507 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
508 }
509
510 /* Close the INI file */
511 CloseBootStore(BootStoreHandle);
512 return STATUS_SUCCESS; // Status;
513}
514
515
516static
519 IN PCWSTR RootPath)
520{
521 /*
522 * We first demand that the bootsector has a valid signature at its end.
523 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
524 * potential "valid" instruction (the BIOS starts execution of the bootsector
525 * at its beginning). Currently this criterium is that this ULONG must be
526 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
527 * it is invalid and certainly needs to be overwritten.
528 */
529
530 BOOLEAN IsValid = FALSE;
533 BOOTCODE BootSector = {0};
534
535 /* Allocate and read the root partition bootsector.
536 * Remove any trailing backslash if needed. */
540 if (!NT_SUCCESS(Status))
541 return FALSE;
542
543 /* Check for the existence of the bootsector signature */
544 IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
545 if (IsValid)
546 {
547 /* Check for the first instruction encoded on three bytes */
548 IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
549 }
550
551 /* Free the bootsector and return */
553 return IsValid;
554}
555
556static
559 IN PCWSTR RootPath,
562{
568 // LARGE_INTEGER FileOffset;
569 BOOTCODE BootSector = {0};
570
571 /* Allocate and read the root partition bootsector.
572 * Remove any trailing backslash if needed. */
573 RtlInitUnicodeString(&Name, RootPath);
576 if (!NT_SUCCESS(Status))
577 return Status;
578
579 /* Write the bootsector to DstPath */
582 &Name,
584 NULL,
585 NULL);
586
591 NULL,
593 0,
596 NULL,
597 0);
598 if (!NT_SUCCESS(Status))
599 {
601 return Status;
602 }
603
605 NULL,
606 NULL,
607 NULL,
610 BootSector.Length,
611 NULL,
612 NULL);
614
615 /* Free the bootsector and return */
617 return Status;
618}
619
620
621static
624 IN PCWSTR SrcPath,
625 IN PCWSTR RootPath,
626 IN PFS_INSTALL_BOOTCODE InstallBootCode)
627{
628 NTSTATUS Status, LockStatus;
632 HANDLE PartitionHandle;
633
634 /*
635 * Open the root partition from which the bootcode (MBR, VBR) parameters
636 * will be obtained; this is also where we will write the updated bootcode.
637 * Remove any trailing backslash if needed.
638 */
639 RtlInitUnicodeString(&Name, RootPath);
641
643 &Name,
645 NULL,
646 NULL);
647
648 Status = NtOpenFile(&PartitionHandle,
653 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
654 if (!NT_SUCCESS(Status))
655 return Status;
656
657 /* Lock the volume */
658 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
659 if (!NT_SUCCESS(LockStatus))
660 {
661 DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
662 }
663
664 /* Install the bootcode (MBR, VBR) */
665 Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
666
667 /* dismount & Unlock the volume */
668 if (NT_SUCCESS(LockStatus))
669 {
670 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
671 if (!NT_SUCCESS(LockStatus))
672 {
673 DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
674 }
675
676 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
677 if (!NT_SUCCESS(LockStatus))
678 {
679 DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
680 }
681 }
682
683 /* Close the partition */
684 NtClose(PartitionHandle);
685
686 return Status;
687}
688
689static
692 IN PCWSTR SrcPath,
694 IN PCWSTR RootPath,
695 IN PFS_INSTALL_BOOTCODE InstallBootCode)
696{
701 HANDLE PartitionHandle, FileHandle;
702
703 /*
704 * Open the root partition from which the bootcode (MBR, VBR)
705 * parameters will be obtained.
706 *
707 * FIXME? It might be possible that we need to also open it for writing
708 * access in case we really need to still write the second portion of
709 * the boot sector ????
710 *
711 * Remove any trailing backslash if needed.
712 */
713 RtlInitUnicodeString(&Name, RootPath);
715
717 &Name,
719 NULL,
720 NULL);
721
722 Status = NtOpenFile(&PartitionHandle,
727 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
728 if (!NT_SUCCESS(Status))
729 return Status;
730
731 /* Open or create the file where the new bootsector will be saved */
734 &Name,
736 NULL,
737 NULL);
738
743 NULL,
745 0,
746 FILE_SUPERSEDE, // FILE_OVERWRITE_IF
748 NULL,
749 0);
750 if (!NT_SUCCESS(Status))
751 {
752 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
753 NtClose(PartitionHandle);
754 return Status;
755 }
756
757 /* Install the bootcode (MBR, VBR) */
758 Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
759
760 /* Close the file and the partition */
762 NtClose(PartitionHandle);
763
764 return Status;
765}
766
767
768static
771 IN PCWSTR SrcPath, // MBR source file (on the installation medium)
772 IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information
773 IN HANDLE DiskHandle) // Disk holding the (old) MBR information
774{
779 BOOTCODE OrigBootSector = {0};
780 BOOTCODE NewBootSector = {0};
781
783
784 /* Allocate and read the current original MBR bootsector */
785 Status = ReadBootCodeByHandle(&OrigBootSector,
786 DiskHandle,
787 sizeof(PARTITION_SECTOR));
788 if (!NT_SUCCESS(Status))
789 return Status;
790
791 /* Allocate and read the new bootsector from SrcPath */
792 RtlInitUnicodeString(&Name, SrcPath);
793 Status = ReadBootCodeFromFile(&NewBootSector,
794 &Name,
795 sizeof(PARTITION_SECTOR));
796 if (!NT_SUCCESS(Status))
797 {
798 FreeBootCode(&OrigBootSector);
799 return Status;
800 }
801
802 /*
803 * Copy the disk signature, the reserved fields and
804 * the partition table from the old MBR to the new one.
805 */
806 RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
807 &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
808 sizeof(PARTITION_SECTOR) -
810 /* Length of partition table */);
811
812 /* Free the original bootsector */
813 FreeBootCode(&OrigBootSector);
814
815 /* Write the new bootsector to DstPath */
816 FileOffset.QuadPart = 0ULL;
818 NULL,
819 NULL,
820 NULL,
822 NewBootSector.BootCode,
823 NewBootSector.Length,
824 &FileOffset,
825 NULL);
826
827 /* Free the new bootsector */
828 FreeBootCode(&NewBootSector);
829
830 return Status;
831}
832
833static
836 _In_ PCUNICODE_STRING SystemRootPath,
837 _In_ PCUNICODE_STRING SourceRootPath,
838 _In_ PCWSTR DestinationDevicePathBuffer)
839{
841 WCHAR SourceMbrPathBuffer[MAX_PATH];
843
844#if 0
845 /*
846 * The DestinationDevicePathBuffer parameter has been built with
847 * the following instruction by the caller; I'm not yet sure whether
848 * I actually want this function to build the path instead, hence
849 * I keep this code here but disabled for now...
850 */
851 WCHAR DestinationDevicePathBuffer[MAX_PATH];
852 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
853 L"\\Device\\Harddisk%d\\Partition0",
854 DiskNumber);
855#endif
856
857 CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2,
858 SourceRootPath->Buffer, L"\\loader\\dosmbr.bin");
859
860 if (IsThereAValidBootSector(DestinationDevicePathBuffer))
861 {
862 /* Save current MBR */
864 SystemRootPath->Buffer, L"mbr.old");
865
866 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
867 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
868 if (!NT_SUCCESS(Status))
869 {
870 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
871 // Don't care if we succeeded or not saving the old MBR, just go ahead.
872 }
873 }
874
875 DPRINT1("Install MBR bootcode: %S ==> %S\n",
876 SourceMbrPathBuffer, DestinationDevicePathBuffer);
877
878 /* Install the MBR */
879 return InstallBootCodeToDisk(SourceMbrPathBuffer,
880 DestinationDevicePathBuffer,
882}
883
884static
887 _In_ PCUNICODE_STRING SystemRootPath,
888 _In_ PCUNICODE_STRING SourceRootPath)
889{
891 WCHAR SrcPath[MAX_PATH];
893
894 /* Copy FreeLoader to the system partition, always overwriting the older version */
895 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
896 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
897
898 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
899 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
900 if (!NT_SUCCESS(Status))
901 {
902 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
903 return Status;
904 }
905
906 /* Copy rosload to the system partition, always overwriting the older version */
907 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\rosload.exe");
908 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"rosload.exe");
909
910 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
911 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
912 if (!NT_SUCCESS(Status))
913 {
914 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
915 return Status;
916 }
917
918 return STATUS_SUCCESS;
919}
920
921static
924 _In_ PCUNICODE_STRING SystemRootPath,
925 _In_ PCUNICODE_STRING SourceRootPath,
926 _In_ PCUNICODE_STRING DestinationArcPath,
927 _In_ PCWSTR FileSystemName)
928{
930 BOOLEAN DoesFreeLdrExist;
931 WCHAR SrcPath[MAX_PATH];
933
934 /* FAT or FAT32 partition */
935 DPRINT("System path: '%wZ'\n", SystemRootPath);
936
937 /* Install the bootloader */
938 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
939 if (!NT_SUCCESS(Status))
940 {
941 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
942 return Status;
943 }
944
945 /* Prepare for possibly updating 'freeldr.ini' */
946 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
947 if (DoesFreeLdrExist)
948 {
949 /* Update existing 'freeldr.ini' */
950 DPRINT1("Update existing 'freeldr.ini'\n");
951 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
952 if (!NT_SUCCESS(Status))
953 {
954 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
955 return Status;
956 }
957 }
958
959 /* Check for NT and other bootloaders */
960
961 // FIXME: Check for Vista+ bootloader!
962 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
963 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
964 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
965 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
966 {
967 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
968 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
969
970 /* Create or update 'freeldr.ini' */
971 if (DoesFreeLdrExist == FALSE)
972 {
973 /* Create new 'freeldr.ini' */
974 DPRINT1("Create new 'freeldr.ini'\n");
975 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
976 if (!NT_SUCCESS(Status))
977 {
978 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
979 return Status;
980 }
981
982 /* Install new bootcode into a file */
983 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
984
985 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
986 {
987 /* Install FAT32 bootcode */
988 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
989
990 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
992 SystemRootPath->Buffer,
994 if (!NT_SUCCESS(Status))
995 {
996 DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
997 return Status;
998 }
999 }
1000 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1001 {
1002 /* Install FAT16 bootcode */
1003 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1004
1005 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
1007 SystemRootPath->Buffer,
1009 if (!NT_SUCCESS(Status))
1010 {
1011 DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
1012 return Status;
1013 }
1014 }
1015 }
1016
1017 /* Update 'boot.ini' */
1018 /* Windows' NTLDR loads an external bootsector file when the specified drive
1019 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1020 DPRINT1("Update 'boot.ini'\n");
1021 Status = UpdateBootIni(SystemRootPath->Buffer,
1022 L"C:\\bootsect.ros",
1023 L"\"ReactOS\"");
1024 if (!NT_SUCCESS(Status))
1025 {
1026 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1027 return Status;
1028 }
1029 }
1030 else
1031 {
1032 /* Non-NT bootloaders: install our own bootloader */
1033
1034 PCWSTR Section;
1037
1038 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1039 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
1040 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
1041 {
1042 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1043
1044 Section = L"CPQDOS";
1045 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1046 BootSector = L"BOOTSECT.DOS";
1047 }
1048 else
1049 /* Search for Microsoft DOS or Windows 9x boot loader */
1050 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
1051 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
1052 // WINBOOT.SYS
1053 {
1054 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1055
1056 Section = L"MSDOS";
1057 Description = L"\"MS-DOS/Windows\"";
1058 BootSector = L"BOOTSECT.DOS";
1059 }
1060 else
1061 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1062 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
1063 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
1064 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
1065 {
1066 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
1067
1068 Section = L"IBMDOS";
1069 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
1070 BootSector = L"BOOTSECT.DOS";
1071 }
1072 else
1073 /* Search for DR-DOS 3.x boot loader */
1074 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
1075 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
1076 {
1077 DPRINT1("Found DR-DOS 3.x\n");
1078
1079 Section = L"DRDOS";
1080 Description = L"\"DR-DOS 3.x\"";
1081 BootSector = L"BOOTSECT.DOS";
1082 }
1083 else
1084 /* Search for Dell Real-Mode Kernel (DRMK) OS */
1085 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
1086 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
1087 {
1088 DPRINT1("Found Dell Real-Mode Kernel OS\n");
1089
1090 Section = L"DRMK";
1091 Description = L"\"Dell Real-Mode Kernel OS\"";
1092 BootSector = L"BOOTSECT.DOS";
1093 }
1094 else
1095 /* Search for MS OS/2 1.x */
1096 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
1097 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
1098 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
1099 {
1100 DPRINT1("Found MS OS/2 1.x\n");
1101
1102 Section = L"MSOS2";
1103 Description = L"\"MS OS/2 1.x\"";
1104 BootSector = L"BOOTSECT.OS2";
1105 }
1106 else
1107 /* Search for MS or IBM OS/2 */
1108 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
1109 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
1110 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
1111 {
1112 DPRINT1("Found MS/IBM OS/2\n");
1113
1114 Section = L"IBMOS2";
1115 Description = L"\"MS/IBM OS/2\"";
1116 BootSector = L"BOOTSECT.OS2";
1117 }
1118 else
1119 /* Search for FreeDOS boot loader */
1120 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
1121 {
1122 DPRINT1("Found FreeDOS boot loader\n");
1123
1124 Section = L"FDOS";
1125 Description = L"\"FreeDOS\"";
1126 BootSector = L"BOOTSECT.DOS";
1127 }
1128 else
1129 {
1130 /* No or unknown boot loader */
1131 DPRINT1("No or unknown boot loader found\n");
1132
1133 Section = L"Unknown";
1134 Description = L"\"Unknown Operating System\"";
1135 BootSector = L"BOOTSECT.OLD";
1136 }
1137
1138 /* Create or update 'freeldr.ini' */
1139 if (DoesFreeLdrExist == FALSE)
1140 {
1141 /* Create new 'freeldr.ini' */
1142 DPRINT1("Create new 'freeldr.ini'\n");
1143
1144 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1145 {
1147 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1148 Section, Description,
1149 SystemRootPath->Buffer, BootSector);
1150 if (!NT_SUCCESS(Status))
1151 {
1152 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1153 return Status;
1154 }
1155
1156 /* Save current bootsector */
1157 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1158
1159 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1160 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
1161 if (!NT_SUCCESS(Status))
1162 {
1163 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1164 return Status;
1165 }
1166 }
1167 else
1168 {
1169 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1170 if (!NT_SUCCESS(Status))
1171 {
1172 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1173 return Status;
1174 }
1175 }
1176
1177 /* Install new bootsector on the disk */
1178 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
1179 {
1180 /* Install FAT32 bootcode */
1181 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1182
1183 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1184 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
1185 DPRINT1("Status: 0x%08X\n", Status);
1186 if (!NT_SUCCESS(Status))
1187 {
1188 DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
1189 return Status;
1190 }
1191 }
1192 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1193 {
1194 /* Install FAT16 bootcode */
1195 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1196
1197 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1198 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
1199 if (!NT_SUCCESS(Status))
1200 {
1201 DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
1202 return Status;
1203 }
1204 }
1205 }
1206 }
1207
1208 return STATUS_SUCCESS;
1209}
1210
1211static
1214 _In_ PCUNICODE_STRING SystemRootPath,
1215 _In_ PCUNICODE_STRING SourceRootPath,
1216 _In_ PCUNICODE_STRING DestinationArcPath)
1217{
1219 BOOLEAN DoesFreeLdrExist;
1220 WCHAR SrcPath[MAX_PATH];
1222
1223 /* BTRFS partition */
1224 DPRINT("System path: '%wZ'\n", SystemRootPath);
1225
1226 /* Install the bootloader */
1227 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1228 if (!NT_SUCCESS(Status))
1229 {
1230 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1231 return Status;
1232 }
1233
1234 /* Prepare for possibly updating 'freeldr.ini' */
1235 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1236 if (DoesFreeLdrExist)
1237 {
1238 /* Update existing 'freeldr.ini' */
1239 DPRINT1("Update existing 'freeldr.ini'\n");
1240 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1241 if (!NT_SUCCESS(Status))
1242 {
1243 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1244 return Status;
1245 }
1246 }
1247
1248 /* Check for *nix bootloaders */
1249
1250 /* Create or update 'freeldr.ini' */
1251 if (DoesFreeLdrExist == FALSE)
1252 {
1253 /* Create new 'freeldr.ini' */
1254 DPRINT1("Create new 'freeldr.ini'\n");
1255
1256 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1257 DPRINT1("*nix or unknown boot loader found\n");
1258
1259 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1260 {
1261 PCWSTR BootSector = L"BOOTSECT.OLD";
1262
1264 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1265 L"Linux", L"\"Linux\"",
1266 SystemRootPath->Buffer, BootSector);
1267 if (!NT_SUCCESS(Status))
1268 {
1269 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1270 return Status;
1271 }
1272
1273 /* Save current bootsector */
1274 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1275
1276 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1277 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
1278 if (!NT_SUCCESS(Status))
1279 {
1280 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1281 return Status;
1282 }
1283 }
1284 else
1285 {
1286 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1287 if (!NT_SUCCESS(Status))
1288 {
1289 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1290 return Status;
1291 }
1292 }
1293
1294 /* Install new bootsector on the disk */
1295 /* Install BTRFS bootcode */
1296 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
1297
1298 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1299 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
1300 if (!NT_SUCCESS(Status))
1301 {
1302 DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
1303 return Status;
1304 }
1305 }
1306
1307 return STATUS_SUCCESS;
1308}
1309
1310static
1313 _In_ PCUNICODE_STRING SystemRootPath,
1314 _In_ PCUNICODE_STRING SourceRootPath,
1315 _In_ PCUNICODE_STRING DestinationArcPath)
1316{
1318 BOOLEAN DoesFreeLdrExist;
1319 WCHAR SrcPath[MAX_PATH];
1321
1322 /* NTFS partition */
1323 DPRINT("System path: '%wZ'\n", SystemRootPath);
1324
1325 /* Install the bootloader */
1326 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1327 if (!NT_SUCCESS(Status))
1328 {
1329 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1330 return Status;
1331 }
1332
1333 /* Prepare for possibly updating 'freeldr.ini' */
1334 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1335 if (DoesFreeLdrExist)
1336 {
1337 /* Update existing 'freeldr.ini' */
1338 DPRINT1("Update existing 'freeldr.ini'\n");
1339 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1340 if (!NT_SUCCESS(Status))
1341 {
1342 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1343 return Status;
1344 }
1345
1346 return STATUS_SUCCESS;
1347 }
1348
1349 /* Check for *nix bootloaders */
1350
1351 DPRINT1("Create new 'freeldr.ini'\n");
1352
1353 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1354 DPRINT1("*nix or unknown boot loader found\n");
1355
1356 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1357 {
1358 PCWSTR BootSector = L"BOOTSECT.OLD";
1359
1361 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1362 L"Linux", L"\"Linux\"",
1363 SystemRootPath->Buffer, BootSector);
1364 if (!NT_SUCCESS(Status))
1365 {
1366 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1367 return Status;
1368 }
1369
1370 /* Save current bootsector */
1371 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1372
1373 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1374 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, NTFS_BOOTSECTOR_SIZE);
1375 if (!NT_SUCCESS(Status))
1376 {
1377 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1378 return Status;
1379 }
1380 }
1381 else
1382 {
1383 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1384 if (!NT_SUCCESS(Status))
1385 {
1386 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1387 return Status;
1388 }
1389 }
1390
1391 /* Install new bootsector on the disk */
1392
1393 /* Install NTFS bootcode */
1394 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\ntfs.bin");
1395
1396 DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1397 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallNtfsBootCode);
1398 if (!NT_SUCCESS(Status))
1399 {
1400 DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status);
1401 return Status;
1402 }
1403
1404 return STATUS_SUCCESS;
1405}
1406
1407static
1410 _In_ PCUNICODE_STRING SystemRootPath,
1411 _In_ PCUNICODE_STRING SourceRootPath,
1412 _In_ PCUNICODE_STRING DestinationArcPath,
1413 _In_ PCWSTR FileSystemName)
1414{
1415 if (_wcsicmp(FileSystemName, L"FAT") == 0 ||
1416 _wcsicmp(FileSystemName, L"FAT32") == 0)
1417 {
1418 return InstallFatBootcodeToPartition(SystemRootPath,
1419 SourceRootPath,
1420 DestinationArcPath,
1421 FileSystemName);
1422 }
1423 else if (_wcsicmp(FileSystemName, L"NTFS") == 0)
1424 {
1425 return InstallNtfsBootcodeToPartition(SystemRootPath,
1426 SourceRootPath,
1427 DestinationArcPath);
1428 }
1429 else if (_wcsicmp(FileSystemName, L"BTRFS") == 0)
1430 {
1431 return InstallBtrfsBootcodeToPartition(SystemRootPath,
1432 SourceRootPath,
1433 DestinationArcPath);
1434 }
1435 /*
1436 else if (_wcsicmp(FileSystemName, L"EXT2") == 0 ||
1437 _wcsicmp(FileSystemName, L"EXT3") == 0 ||
1438 _wcsicmp(FileSystemName, L"EXT4") == 0)
1439 {
1440 return STATUS_NOT_SUPPORTED;
1441 }
1442 */
1443 else
1444 {
1445 /* Unknown file system */
1446 DPRINT1("Unknown file system '%S'\n", FileSystemName);
1447 }
1448
1449 return STATUS_NOT_SUPPORTED;
1450}
1451
1452
1453/* GENERIC FUNCTIONS *********************************************************/
1454
1482static
1485 _In_ ARCHITECTURE_TYPE ArchType,
1486 _In_ PCUNICODE_STRING SystemRootPath,
1487 _In_ ULONG DiskNumber, // const STORAGE_DEVICE_NUMBER* DeviceNumber,
1488 _In_ PARTITION_STYLE DiskStyle,
1491 _In_ PCUNICODE_STRING SourceRootPath,
1492 _In_ PCUNICODE_STRING DestinationArcPath,
1494{
1496 BOOLEAN IsBIOS = ((ArchType == ARCH_PcAT) || (ArchType == ARCH_NEC98x86));
1497 UCHAR InstallType = (Options & 0x03);
1498
1499 // FIXME: We currently only support BIOS-based PCs
1500 // TODO: Support other platforms
1501 if (!IsBIOS)
1502 return STATUS_NOT_SUPPORTED;
1503
1504 if (InstallType <= 1)
1505 {
1506 /* Step 1: Write the VBR */
1507 Status = InstallVBRToPartition(SystemRootPath,
1508 SourceRootPath,
1509 DestinationArcPath,
1510 FileSystem);
1511 if (!NT_SUCCESS(Status))
1512 {
1513 DPRINT1("InstallVBRToPartition() failed (Status 0x%08lx)\n", Status);
1514 return ERROR_WRITE_BOOT; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1515 }
1516
1517 /* Step 2: Write the MBR if the disk containing the
1518 * system partition is MBR and not a super-floppy */
1519 if ((InstallType == 1) && (DiskStyle == PARTITION_STYLE_MBR) && !IsSuperFloppy)
1520 {
1521 WCHAR SystemDiskPath[MAX_PATH];
1522 RtlStringCchPrintfW(SystemDiskPath, _countof(SystemDiskPath),
1523 L"\\Device\\Harddisk%d\\Partition0",
1524 DiskNumber);
1525 Status = InstallMbrBootCodeToDisk(SystemRootPath,
1526 SourceRootPath,
1527 SystemDiskPath);
1528 if (!NT_SUCCESS(Status))
1529 {
1530 DPRINT1("InstallMbrBootCodeToDisk() failed (Status 0x%08lx)\n", Status);
1531 return ERROR_INSTALL_BOOTCODE; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1532 }
1533 }
1534 }
1535 else if (InstallType == 2)
1536 {
1537 WCHAR SrcPath[MAX_PATH];
1538
1539 // FIXME: We currently only support FAT12 file system.
1540 if (_wcsicmp(FileSystem, L"FAT") != 0)
1541 return STATUS_NOT_SUPPORTED;
1542
1543 // TODO: In the future, we'll be able to use InstallVBRToPartition()
1544 // directly, instead of re-doing manually the copy steps below.
1545
1546 /* Install the bootloader to the boot partition */
1547 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1548 if (!NT_SUCCESS(Status))
1549 {
1550 DPRINT1("InstallBootloaderFiles() failed (Status 0x%08lx)\n", Status);
1551 return Status;
1552 }
1553
1554 /* Create new 'freeldr.ini' */
1555 DPRINT("Create new 'freeldr.ini'\n");
1556 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1557 if (!NT_SUCCESS(Status))
1558 {
1559 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status 0x%08lx)\n", Status);
1560 return Status;
1561 }
1562
1563 /* Install FAT12 bootsector */
1564 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1565
1566 DPRINT1("Install FAT12 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1567 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat12BootCode);
1568 if (!NT_SUCCESS(Status))
1569 {
1570 DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status 0x%08lx)\n", Status);
1571 return Status;
1572 }
1573 }
1574
1575 return Status;
1576}
1577
1578
1584{
1587
1588 if (DeviceName && DeviceHandle)
1590
1591 /* Open the device if a name has been given;
1592 * otherwise just use the provided handle. */
1593 if (DeviceName)
1594 {
1598 if (!NT_SUCCESS(Status))
1599 {
1600 DPRINT1("Cannot open device '%wZ' (Status 0x%08lx)\n",
1602 return Status;
1603 }
1604 }
1605
1606 /* Query the device */
1609 DeviceInfo,
1610 sizeof(*DeviceInfo),
1612 if (!NT_SUCCESS(Status))
1613 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1614
1615 /* Close the device if we've opened it */
1616 if (DeviceName)
1618
1619 return Status;
1620}
1621
1627{
1628 UNICODE_STRING DeviceNameU;
1629
1630 if (DeviceName && DeviceHandle)
1632
1633 if (DeviceName)
1634 RtlInitUnicodeString(&DeviceNameU, DeviceName);
1635
1636 return GetDeviceInfo_UStr(DeviceName ? &DeviceNameU : NULL,
1638 DeviceInfo);
1639}
1640
1641
1673NTAPI
1675 _In_ ARCHITECTURE_TYPE ArchType,
1676 _In_ PCUNICODE_STRING SystemRootPath,
1677 _In_ PCUNICODE_STRING SourceRootPath,
1678 _In_ PCUNICODE_STRING DestinationArcPath,
1680{
1684 ULONG DiskNumber;
1685 PARTITION_STYLE PartitionStyle;
1688
1689 /* Remove any trailing backslash if needed */
1690 UNICODE_STRING RootPartition = *SystemRootPath;
1692
1693 /* Open the volume */
1697 if (!NT_SUCCESS(Status))
1698 {
1699 DPRINT1("Cannot open %wZ for bootloader installation (Status 0x%08lx)\n",
1701 return Status;
1702 }
1703
1704 /* Retrieve the volume file system (it will also be mounted) */
1706 FileSystem, sizeof(FileSystem));
1707 if (!NT_SUCCESS(Status) || !*FileSystem)
1708 {
1709 DPRINT1("GetFileSystemName() failed (Status 0x%08lx)\n", Status);
1710 goto Quit;
1711 }
1712
1713 /* Retrieve the device type and characteristics */
1715 if (!NT_SUCCESS(Status))
1716 {
1717 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1718 goto Quit;
1719 }
1720
1721 /* Ignore volumes that are NOT on usual disks */
1722 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1723 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1724 {
1725 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1727 goto Quit;
1728 }
1729
1730
1731 /* Check whether this is a floppy or a partitionable device */
1732 if (DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE)
1733 {
1734 /* Floppies don't have partitions */
1735 // NOTE: See ntoskrnl/io/iomgr/rawfs.c!RawQueryFsSizeInfo()
1736 DiskNumber = ULONG_MAX;
1737 PartitionStyle = PARTITION_STYLE_MBR;
1739 }
1740 else
1741 {
1744
1745 /* The maximum information a DISK_GEOMETRY_EX dynamic structure can contain */
1746 typedef struct _DISK_GEOMETRY_EX_INTERNAL
1747 {
1750 DISK_PARTITION_INFO Partition;
1751 /* Followed by: DISK_DETECTION_INFO Detection; unused here */
1753
1754 DISK_GEOMETRY_EX_INTERNAL DiskGeoEx;
1756
1757 /* Retrieve the disk number. NOTE: Fails for floppy disks. */
1759 NULL, NULL, NULL,
1762 NULL, 0,
1763 &DeviceNumber, sizeof(DeviceNumber));
1764 if (!NT_SUCCESS(Status))
1765 goto Quit; /* This may be a dynamic volume, which is unsupported */
1766 ASSERT(DeviceNumber.DeviceType == DeviceInfo.DeviceType);
1767 if (DeviceNumber.DeviceNumber == ULONG_MAX)
1768 {
1769 DPRINT1("Invalid disk number reported, bail out\n");
1771 goto Quit;
1772 }
1773
1774 /* Retrieve the drive geometry. NOTE: Fails for floppy disks;
1775 * use IOCTL_DISK_GET_DRIVE_GEOMETRY instead. */
1777 NULL, NULL, NULL,
1780 NULL, 0,
1781 &DiskGeoEx,
1782 sizeof(DiskGeoEx));
1783 if (!NT_SUCCESS(Status))
1784 {
1785 DPRINT1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed (Status 0x%08lx)\n", Status);
1786 goto Quit;
1787 }
1788
1789 /*
1790 * Retrieve the volume's partition information.
1791 * NOTE: Fails for floppy disks.
1792 *
1793 * NOTE: We can use the non-EX IOCTL because the super-floppy test will
1794 * fail anyway if the disk is NOT MBR-partitioned. (If the disk is GPT,
1795 * the IOCTL would return only the MBR protective partition, but the
1796 * super-floppy test would fail due to the wrong partitioning style.)
1797 */
1799 NULL, NULL, NULL,
1802 NULL, 0,
1804 sizeof(PartitionInfo));
1805 if (!NT_SUCCESS(Status))
1806 {
1807 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO failed (Status 0x%08lx)\n", Status);
1808 goto Quit;
1809 }
1810
1811 DiskNumber = DeviceNumber.DeviceNumber;
1812 PartitionStyle = DiskGeoEx.Partition.PartitionStyle;
1814 (PULONGLONG)&DiskGeoEx.DiskSize.QuadPart,
1815 &PartitionInfo);
1816 }
1817
1819 ArchType, SystemRootPath,
1820 DiskNumber, PartitionStyle, IsSuperFloppy, FileSystem,
1821 SourceRootPath, DestinationArcPath, Options);
1822
1823Quit:
1825 return Status;
1826}
1827
1829NTAPI
1831 _In_ ARCHITECTURE_TYPE ArchType,
1832 _In_ PCUNICODE_STRING RemovableRootPath,
1833 _In_ PCUNICODE_STRING SourceRootPath,
1834 _In_ PCUNICODE_STRING DestinationArcPath)
1835{
1838 PCWSTR FileSystemName;
1840
1841 /* Remove any trailing backslash if needed */
1842 UNICODE_STRING RootDrive = *RemovableRootPath;
1844
1845 /* Verify that the removable disk is accessible */
1846 if (!DoesDirExist(NULL, RemovableRootPath->Buffer))
1848
1849 /* Retrieve the device type and characteristics */
1850 Status = GetDeviceInfo_UStr(&RootDrive, NULL, &DeviceInfo);
1851 if (!NT_SUCCESS(Status))
1852 {
1853 static const UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
1854
1855 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1856
1857 /* Definitively fail if the device is not a floppy */
1858 if (!RtlPrefixUnicodeString(&DeviceFloppy, &RootDrive, TRUE))
1859 return Status; /* We cannot cope with a failure */
1860
1861 /* Try to fall back to something "sane" if the device may be a floppy */
1862 DeviceInfo.DeviceType = FILE_DEVICE_DISK;
1864 }
1865
1866 /* Ignore volumes that are NOT on usual disks */
1867 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1868 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1869 {
1870 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1872 }
1873
1874 /* Fail if the disk is not removable */
1875 if (!(DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA))
1876 {
1877 DPRINT1("Device is NOT removable!\n");
1879 }
1880
1881 /* Check whether this is a floppy or another removable device */
1882 IsFloppy = !!(DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE);
1883
1884 /* Use FAT32, unless the device is a floppy disk */
1885 FileSystemName = (IsFloppy ? L"FAT" : L"FAT32");
1886
1887 /* Format the removable disk */
1888 Status = FormatFileSystem_UStr(&RootDrive,
1889 FileSystemName,
1891 NULL,
1892 TRUE,
1893 0,
1894 NULL);
1895 if (!NT_SUCCESS(Status))
1896 {
1898 DPRINT1("%s FS non-existent on this system!\n", FileSystemName);
1899 else
1900 DPRINT1("FormatFileSystem(%s) failed (Status 0x%08lx)\n", FileSystemName, Status);
1901 return Status;
1902 }
1903
1904 /* Copy FreeLoader to the removable disk and save the boot entries */
1906 RemovableRootPath,
1907 SourceRootPath,
1908 DestinationArcPath,
1909 2 /* Install on removable media */);
1910 if (!NT_SUCCESS(Status))
1911 DPRINT1("InstallBootManagerAndBootEntries() failed (Status 0x%08lx)\n", Status);
1912 return Status;
1913}
1914
1915/* EOF */
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PWCHAR FileSystem
Definition: format.c:72
@ BootOptions
Definition: bl.h:898
NTSTATUS OpenBootStore(_Out_ PVOID *Handle, _In_ PCWSTR SystemPartition, _In_ BOOT_STORE_TYPE Type, _In_ BOOT_STORE_OPENMODE OpenMode, _In_ BOOT_STORE_ACCESS Access)
Definition: bldrsup.c:997
NTSTATUS SetBootStoreOptions(IN PVOID Handle, IN PBOOT_STORE_OPTIONS BootOptions, IN ULONG FieldsToChange)
Definition: bldrsup.c:1356
NTSTATUS AddBootStoreEntry(IN PVOID Handle, IN PBOOT_STORE_ENTRY BootEntry, IN ULONG_PTR BootEntryKey)
Definition: bldrsup.c:1094
NTSTATUS CloseBootStore(_In_ PVOID Handle)
Definition: bldrsup.c:1014
NTSTATUS EnumerateBootStoreEntries(IN PVOID Handle, IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine, IN PVOID Parameter OPTIONAL)
Definition: bldrsup.c:1703
@ BS_ReadWriteAccess
Definition: bldrsup.h:146
struct _BOOTSECTOR_OPTIONS BOOTSECTOR_OPTIONS
#define BOOTSECTOR_OPTIONS_SIGNATURE
Definition: bldrsup.h:114
struct _NTOS_OPTIONS NTOS_OPTIONS
#define BOOT_OPTIONS_NEXT_BOOTENTRY_KEY
Definition: bldrsup.h:42
#define BOOT_OPTIONS_TIMEOUT
Definition: bldrsup.h:41
@ NtLdr
Definition: bldrsup.h:16
@ FreeLdr
Definition: bldrsup.h:15
#define MAKESTRKEY(i)
Definition: bldrsup.h:58
struct _NTOS_OPTIONS * PNTOS_OPTIONS
@ BS_OpenExisting
Definition: bldrsup.h:135
@ BS_CreateAlways
Definition: bldrsup.h:138
struct _BOOT_STORE_ENTRY * PBOOT_STORE_ENTRY
#define NTOS_OPTIONS_SIGNATURE
Definition: bldrsup.h:102
struct _BOOTSECTOR_OPTIONS * PBOOTSECTOR_OPTIONS
enum _BOOT_STORE_TYPE BOOT_STORE_TYPE
VOID FreeBootCode(IN OUT PBOOTCODE BootCodeInfo)
Definition: bootcode.c:104
NTSTATUS ReadBootCodeByHandle(IN OUT PBOOTCODE BootCodeInfo, IN HANDLE FileHandle, IN ULONG Length OPTIONAL)
Definition: bootcode.c:21
NTSTATUS ReadBootCodeFromFile(IN OUT PBOOTCODE BootCodeInfo, IN PUNICODE_STRING FilePath, IN ULONG Length OPTIONAL)
Definition: bootcode.c:69
#define SECTORSIZE
Definition: bootcode.h:13
static NTSTATUS InstallBootloaderFiles(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath)
Definition: bootsup.c:886
static NTSTATUS InstallMbrBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE DiskHandle)
Definition: bootsup.c:770
static NTSTATUS SaveBootSector(IN PCWSTR RootPath, IN PCWSTR DstPath, IN ULONG Length)
Definition: bootsup.c:558
static NTSTATUS InstallFatBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath, _In_ PCWSTR FileSystemName)
Definition: bootsup.c:923
static NTSTATUS UpdateBootIni(IN PCWSTR IniPath, IN PCWSTR EntryName, IN PCWSTR EntryValue)
Definition: bootsup.c:456
static NTSTATUS NTAPI EnumerateReactOSEntries(IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
Definition: bootsup.c:317
static NTSTATUS InstallBtrfsBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1213
static NTSTATUS InstallMbrBootCodeToDisk(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCWSTR DestinationDevicePathBuffer)
Definition: bootsup.c:835
NTSTATUS NTAPI InstallBootcodeToRemovable(_In_ ARCHITECTURE_TYPE ArchType, _In_ PCUNICODE_STRING RemovableRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1830
static NTSTATUS CreateFreeLoaderIniForReactOS(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:168
static NTSTATUS InstallBootCodeToFile(IN PCWSTR SrcPath, IN PCWSTR DstPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:691
static NTSTATUS CreateFreeLoaderIniForReactOSAndBootSector(IN PCWSTR IniPath, IN PCWSTR ArcPath, IN PCWSTR Section, IN PCWSTR Description, IN PCWSTR BootPath, IN PCWSTR BootSector)
Definition: bootsup.c:190
static NTSTATUS InstallNtfsBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1312
static BOOLEAN IsThereAValidBootSector(IN PCWSTR RootPath)
Definition: bootsup.c:518
static NTSTATUS InstallBootManagerAndBootEntriesWorker(_In_ ARCHITECTURE_TYPE ArchType, _In_ PCUNICODE_STRING SystemRootPath, _In_ ULONG DiskNumber, _In_ PARTITION_STYLE DiskStyle, _In_ BOOLEAN IsSuperFloppy, _In_ PCWSTR FileSystem, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath, _In_ ULONG_PTR Options)
Helper for InstallBootManagerAndBootEntries().
Definition: bootsup.c:1484
NTSTATUS GetDeviceInfo(_In_opt_ PCWSTR DeviceName, _In_opt_ HANDLE DeviceHandle, _Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
Definition: bootsup.c:1623
NTSTATUS NTAPI InstallBootManagerAndBootEntries(_In_ ARCHITECTURE_TYPE ArchType, _In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath, _In_ ULONG_PTR Options)
Installs FreeLoader on the system and configure the boot entries.
Definition: bootsup.c:1674
struct _ENUM_REACTOS_ENTRIES_DATA * PENUM_REACTOS_ENTRIES_DATA
static NTSTATUS InstallVBRToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath, _In_ PCWSTR FileSystemName)
Definition: bootsup.c:1409
static VOID TrimTrailingPathSeparators_UStr(IN OUT PUNICODE_STRING UnicodeString)
Definition: bootsup.c:45
struct _ENUM_REACTOS_ENTRIES_DATA ENUM_REACTOS_ENTRIES_DATA
BOOLEAN IsUnattendedSetup
Definition: setuplib.c:26
static NTSTATUS InstallBootCodeToDisk(IN PCWSTR SrcPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:623
NTSTATUS GetDeviceInfo_UStr(_In_opt_ PCUNICODE_STRING DeviceName, _In_opt_ HANDLE DeviceHandle, _Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
Definition: bootsup.c:1580
static NTSTATUS UpdateFreeLoaderIni(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:397
static VOID CreateFreeLoaderReactOSEntries(IN PVOID BootStoreHandle, IN PCWSTR ArcPath)
Definition: bootsup.c:57
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
LPWSTR Name
Definition: desk.c:124
NTSTATUS pOpenDeviceEx_UStr(_In_ PCUNICODE_STRING DevicePath, _Out_ PHANDLE DeviceHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG ShareAccess)
Open an existing device given by its NT-style path, which is assumed to be for a disk device or a par...
Definition: devutils.c:38
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
static const WCHAR Description[]
Definition: oid.c:1266
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR Signature[]
Definition: parser.c:141
static BOOL IsFloppy(PCWSTR pszDrive)
Definition: drive.cpp:48
struct _DISK_GEOMETRY_EX_INTERNAL * PDISK_GEOMETRY_EX_INTERNAL
struct _DISK_GEOMETRY_EX_INTERNAL DISK_GEOMETRY_EX_INTERNAL
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
@ ERROR_WRITE_BOOT
Definition: errorcode.h:28
@ ERROR_INSTALL_BOOTCODE
Definition: errorcode.h:35
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:664
BOOLEAN DoesFileExist_2(IN PCWSTR PathName OPTIONAL, IN PCWSTR FileName)
Definition: filesup.c:740
BOOLEAN NtPathToDiskPartComponents(IN PCWSTR NtPath, OUT PULONG pDiskNumber, OUT PULONG pPartNumber, OUT PCWSTR *PathComponent OPTIONAL)
Definition: filesup.c:763
NTSTATUS SetupCopyFile(IN PCWSTR SourceFileName, IN PCWSTR DestinationFileName, IN BOOLEAN FailIfExists)
Definition: filesup.c:223
#define DoesDirExist(RootDirectory, DirName)
Definition: filesup.h:80
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FMIFS_FLOPPY
Definition: fmifs.h:61
@ FMIFS_REMOVABLE
Definition: fmifs.h:64
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
NTSTATUS GetFileSystemName_UStr(IN PUNICODE_STRING PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:55
Status
Definition: gdiplustypes.h:25
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
#define iswdigit(_c)
Definition: ctype.h:667
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define ULONG_MAX
Definition: intsafe.h:155
#define C_ASSERT(e)
Definition: intsafe.h:73
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:86
if(dx< 0)
Definition: linetemp.h:194
UNICODE_STRING DeviceFloppy
Definition: symlink.c:43
#define ASSERT(a)
Definition: mode.c:44
enum _PARTITION_STYLE PARTITION_STYLE
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define ULL(a, b)
Definition: format_msg.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3953
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define STATUS_INVALID_PARAMETER_MIX
Definition: ntstatus.h:285
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
NTSTRSAFEAPI RtlStringCchCatW(_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:601
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
#define L(x)
Definition: ntvdm.h:50
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
NTSTATUS InstallFat32BootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE RootPartition)
Definition: fsutil.c:469
NTSTATUS NTAPI FormatFileSystem_UStr(_In_ PUNICODE_STRING DriveRoot, _In_ PCWSTR FileSystemName, _In_ FMIFS_MEDIA_FLAG MediaFlag, _In_opt_ PUNICODE_STRING Label, _In_ BOOLEAN QuickFormat, _In_ ULONG ClusterSize, _In_opt_ PFMIFSCALLBACK Callback)
Definition: fsutil.c:315
NTSTATUS InstallBtrfsBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE RootPartition)
Definition: fsutil.c:590
NTSTATUS InstallNtfsBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE RootPartition)
Definition: fsutil.c:697
IN HANDLE IN HANDLE RootPartition
Definition: fsutil.h:82
#define NTFS_BOOTSECTOR_SIZE
Definition: fsutil.h:76
#define InstallFat16BootCode
Definition: fsutil.h:91
#define InstallFat12BootCode
Definition: fsutil.h:90
#define BTRFS_BOOTSECTOR_SIZE
Definition: fsutil.h:75
IN HANDLE DstPath
Definition: fsutil.h:81
BOOLEAN IsDiskSuperFloppy2(_In_ const DISK_PARTITION_INFO *DiskInfo, _In_opt_ const ULONGLONG *DiskSize, _In_ const PARTITION_INFORMATION *PartitionInfo)
Definition: partlist.c:491
BOOLEAN IsSuperFloppy(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:600
@ ARCH_NEC98x86
Definition: setuplib.h:55
@ ARCH_PcAT
Definition: setuplib.h:54
enum _ARCHITECTURE_TYPE ARCHITECTURE_TYPE
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:73
#define _countof(array)
Definition: sndvol32.h:70
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
BYTE BootCode[448]
Definition: fatfs.h:92
ULONG Length
Definition: bootcode.h:18
PVOID BootCode
Definition: bootcode.h:17
Definition: bldrsup.h:67
LARGE_INTEGER DiskSize
Definition: disk.c:3666
DISK_PARTITION_INFO Partition
Definition: disk.c:3667
DISK_GEOMETRY Geometry
Definition: disk.c:3665
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180