ReactOS 0.4.16-dev-747-gbc52d5f
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" // HACK for IsUnattendedSetup
23
24#include "bootsup.h"
25
26#define NDEBUG
27#include <debug.h>
28
29/*
30 * BIG FIXME!!
31 * ===========
32 *
33 * bootsup.c can deal with MBR code (actually it'll have at some point
34 * to share or give it to partlist.c, because when we'll support GPT disks,
35 * things will change a bit).
36 * And, bootsup.c can manage initializing / adding boot entries into NTLDR
37 * and FREELDR, and installing the latter, and saving the old MBR / boot
38 * sectors in files.
39 */
40
41/* FUNCTIONS ****************************************************************/
42
43static VOID
46{
47 while (UnicodeString->Length >= sizeof(WCHAR) &&
48 UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
49 {
50 UnicodeString->Length -= sizeof(WCHAR);
51 }
52}
53
54
55static VOID
57 IN PVOID BootStoreHandle,
58 IN PCWSTR ArcPath)
59{
60 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
61 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
62 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
64
65 BootEntry->Version = FreeLdr;
66 BootEntry->BootFilePath = NULL;
67
68 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
69 RtlCopyMemory(Options->Signature,
72
73 Options->OsLoadPath = ArcPath;
74
75 /* ReactOS */
76 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
77 BootEntry->FriendlyName = L"\"ReactOS\"";
78 Options->OsLoadOptions = L"/FASTDETECT";
79 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
80
81 /* ReactOS_Debug */
82 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
83 BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
84 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
85 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
86
87#ifdef _WINKD_
88 /* ReactOS_VBoxDebug */
89 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
90 BootEntry->FriendlyName = L"\"ReactOS (VBox Debug)\"";
91 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
92 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
93#endif
94#if DBG
95#ifndef _WINKD_
96 /* ReactOS_KdSerial */
97 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
98 BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\"";
99 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
100 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
101#endif
102
103 /* ReactOS_Screen */
104 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
105 BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
106 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
107 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
108
109 /* ReactOS_LogFile */
110 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
111 BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
112 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
113 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
114
115 /* ReactOS_Ram */
116 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
117 BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\"";
118 Options->OsLoadPath = L"ramdisk(0)\\ReactOS";
119 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
120 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
121
122 /* ReactOS_EMS */
123 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
124 BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\"";
125 Options->OsLoadPath = ArcPath;
126 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
127 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
128#endif
129
130
131 /* DefaultOS=ReactOS */
132#if DBG && !defined(_WINKD_)
134 {
135 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
136 }
137 else
138#endif
139 {
140#if DBG
141 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
142#else
143 BootOptions.NextBootEntryKey = MAKESTRKEY(L"ReactOS");
144#endif
145 }
146
147#if DBG
149#endif
150 {
151 /* Timeout=0 for unattended or non debug */
152 BootOptions.Timeout = 0;
153 }
154#if DBG
155 else
156 {
157 /* Timeout=10 */
158 BootOptions.Timeout = 10;
159 }
160#endif
161
162 SetBootStoreOptions(BootStoreHandle, &BootOptions,
164}
165
166static NTSTATUS
168 IN PCWSTR IniPath,
169 IN PCWSTR ArcPath)
170{
172 PVOID BootStoreHandle;
173
174 /* Initialize the INI file and create the common FreeLdr sections */
175 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
176 BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
177 if (!NT_SUCCESS(Status))
178 return Status;
179
180 /* Add the ReactOS entries */
181 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
182
183 /* Close the INI file */
184 CloseBootStore(BootStoreHandle);
185 return STATUS_SUCCESS;
186}
187
188static NTSTATUS
190 IN PCWSTR IniPath,
191 IN PCWSTR ArcPath,
192 IN PCWSTR Section,
194 IN PCWSTR BootPath,
196{
198 PVOID BootStoreHandle;
199 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOTSECTOR_OPTIONS)];
200 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
201 PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
202 WCHAR BootPathBuffer[MAX_PATH] = L"";
203
204 /* Since the BootPath given here is in NT format
205 * (not ARC), we need to hack-generate a mapping */
206 ULONG DiskNumber = 0, PartitionNumber = 0;
208
209 /* From the NT path, compute the disk, partition and path components */
210 // NOTE: this function doesn't support stuff like \Device\FloppyX ...
212 {
213 DPRINT1("BootPath = '%S' points to disk #%d, partition #%d, path '%S'\n",
214 BootPath, DiskNumber, PartitionNumber, PathComponent);
215
216 /* HACK-build a possible ARC path:
217 * Hard disk path: multi(0)disk(0)rdisk(x)partition(y)[\path] */
218 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
219 L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
220 DiskNumber, PartitionNumber);
222 (PathComponent[0] != L'\\' || PathComponent[1]))
223 {
224 RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
226 }
227 }
228 else
229 {
230 PCWSTR Path = BootPath;
231
232 if ((_wcsnicmp(Path, L"\\Device\\Floppy", 14) == 0) &&
233 (Path += 14) && iswdigit(*Path))
234 {
235 DiskNumber = wcstoul(Path, (PWSTR*)&PathComponent, 10);
236 if (PathComponent && *PathComponent && *PathComponent != L'\\')
238
239 /* HACK-build a possible ARC path:
240 * Floppy disk path: multi(0)disk(0)fdisk(x)[\path] */
241 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
242 L"multi(0)disk(0)fdisk(%lu)", DiskNumber);
244 (PathComponent[0] != L'\\' || PathComponent[1]))
245 {
246 RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
248 }
249 }
250 else
251 {
252 /* HACK: Just keep the unresolved NT path and hope for the best... */
253
254 /* Remove any trailing backslash if needed */
258
259 /* RootPartition is BootPath without counting any trailing
260 * path separator. Because of this, we need to copy the string
261 * in the buffer, instead of just using a pointer to it. */
262 RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
263 L"%wZ", &RootPartition);
264
265 DPRINT1("Unhandled NT path '%S'\n", BootPath);
266 }
267 }
268
269 /* Initialize the INI file and create the common FreeLdr sections */
270 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
271 BS_CreateAlways /* BS_OpenAlways */, BS_ReadWriteAccess);
272 if (!NT_SUCCESS(Status))
273 return Status;
274
275 /* Add the ReactOS entries */
276 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
277
278 BootEntry->Version = FreeLdr;
279 BootEntry->BootFilePath = NULL;
280
281 BootEntry->OsOptionsLength = sizeof(BOOTSECTOR_OPTIONS);
282 RtlCopyMemory(Options->Signature,
285
286 Options->BootPath = BootPathBuffer;
287 Options->FileName = BootSector;
288
289 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
290 BootEntry->FriendlyName = Description;
291 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
292
293 /* Close the INI file */
294 CloseBootStore(BootStoreHandle);
295 return STATUS_SUCCESS;
296}
297
298//
299// I think this function can be generalizable as:
300// "find the corresponding 'ReactOS' boot entry in this loader config file
301// (here abstraction comes there), and if none, add a new one".
302//
303
305{
312
313// PENUM_BOOT_ENTRIES_ROUTINE
314static NTSTATUS
315NTAPI
318 IN PBOOT_STORE_ENTRY BootEntry,
320{
323 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
324 WCHAR SystemPath[MAX_PATH];
325
326 /* We have a boot entry */
327
328 /* Check for supported boot type "Windows2003" */
329 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
330 RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
334 {
335 /* This is not a ReactOS entry */
336 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
337 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
338 DPRINT(" An installation '%S' of unsupported type %lu\n",
339 BootEntry->FriendlyName, BootEntry->OsOptionsLength);
340 /* Continue the enumeration */
341 goto SkipThisEntry;
342 }
343
344 /* BootType is Windows2003, now check OsLoadPath */
345 if (!Options->OsLoadPath || !*Options->OsLoadPath)
346 {
347 /* Certainly not a ReactOS installation */
348 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
349 /* Continue the enumeration */
350 goto SkipThisEntry;
351 }
352
353 if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
354 {
355 /* Not found, retry with a quoted path */
356 Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
357 if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
358 {
359 /*
360 * This entry is a ReactOS entry, but the SystemRoot
361 * does not match the one we are looking for.
362 */
363 /* Continue the enumeration */
364 goto SkipThisEntry;
365 }
366 }
367
368 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
369 BootEntry->FriendlyName, Options->OsLoadPath);
370 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
371 // BootEntry->FriendlyName, Options->OsLoadPath);
372
373 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
374
375 Data->UseExistingEntry = TRUE;
376 RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
377
378 /* We have found our entry, stop the enumeration now! */
380
381SkipThisEntry:
382 Data->UseExistingEntry = FALSE;
383 if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
384 {
385 RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
386 L"ReactOS_%lu", Data->i);
387 RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
388 L"\"ReactOS %lu\"", Data->i);
389 Data->i++;
390 }
391 return STATUS_SUCCESS;
392}
393
394static
397 IN PCWSTR IniPath,
398 IN PCWSTR ArcPath)
399{
401 PVOID BootStoreHandle;
403 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
404 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
405 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
406
407 /* Open the INI file */
408 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
409 BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
410 if (!NT_SUCCESS(Status))
411 return Status;
412
413 /* Find an existing usable or an unused section name */
414 Data.UseExistingEntry = TRUE;
415 Data.i = 1;
416 Data.ArcPath = ArcPath;
417 RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
418 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
419
420 //
421 // FIXME: We temporarily use EnumerateBootStoreEntries, until
422 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
423 //
425
426 /* Create a new "ReactOS" entry if there is none already existing that suits us */
427 if (!Data.UseExistingEntry)
428 {
429 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
430 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
431
432 BootEntry->Version = FreeLdr;
433 BootEntry->BootFilePath = NULL;
434
435 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
436 RtlCopyMemory(Options->Signature,
439
440 Options->OsLoadPath = ArcPath;
441
442 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
443 BootEntry->FriendlyName = Data.OsName;
444 Options->OsLoadOptions = NULL; // L"";
445 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
446 }
447
448 /* Close the INI file */
449 CloseBootStore(BootStoreHandle);
450 return STATUS_SUCCESS;
451}
452
453static
456 IN PCWSTR IniPath,
457 IN PCWSTR EntryName, // ~= ArcPath
458 IN PCWSTR EntryValue)
459{
461 PVOID BootStoreHandle;
463
464 // NOTE: Technically it would be "BootSector"...
465 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
466 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
467 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
468
469 /* Open the INI file */
470 Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr,
471 BS_OpenExisting /* BS_OpenAlways */, BS_ReadWriteAccess);
472 if (!NT_SUCCESS(Status))
473 return Status;
474
475 /* Find an existing usable or an unused section name */
476 Data.UseExistingEntry = TRUE;
477 // Data.i = 1;
478 Data.ArcPath = EntryName;
479 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
480 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
481
482 //
483 // FIXME: We temporarily use EnumerateBootStoreEntries, until
484 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
485 //
487
488 /* If either the key was not found, or contains something else, add a new one */
489 if (!Data.UseExistingEntry /* ||
490 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
491 {
492 BootEntry->Version = NtLdr;
493 BootEntry->BootFilePath = NULL;
494
495 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
496 RtlCopyMemory(Options->Signature,
499
500 Options->OsLoadPath = EntryName;
501
502 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
503 // BootEntry->FriendlyName = Data.OsName;
504 BootEntry->FriendlyName = EntryValue;
505 Options->OsLoadOptions = NULL; // L"";
506 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
507 }
508
509 /* Close the INI file */
510 CloseBootStore(BootStoreHandle);
511 return STATUS_SUCCESS; // Status;
512}
513
514
515static
518 IN PCWSTR RootPath)
519{
520 /*
521 * We first demand that the bootsector has a valid signature at its end.
522 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
523 * potential "valid" instruction (the BIOS starts execution of the bootsector
524 * at its beginning). Currently this criterium is that this ULONG must be
525 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
526 * it is invalid and certainly needs to be overwritten.
527 */
528
529 BOOLEAN IsValid = FALSE;
532 BOOTCODE BootSector = {0};
533
534 /* Allocate and read the root partition bootsector.
535 * Remove any trailing backslash if needed. */
539 if (!NT_SUCCESS(Status))
540 return FALSE;
541
542 /* Check for the existence of the bootsector signature */
543 IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
544 if (IsValid)
545 {
546 /* Check for the first instruction encoded on three bytes */
547 IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
548 }
549
550 /* Free the bootsector and return */
552 return IsValid;
553}
554
555static
558 IN PCWSTR RootPath,
561{
567 // LARGE_INTEGER FileOffset;
568 BOOTCODE BootSector = {0};
569
570 /* Allocate and read the root partition bootsector.
571 * Remove any trailing backslash if needed. */
572 RtlInitUnicodeString(&Name, RootPath);
575 if (!NT_SUCCESS(Status))
576 return Status;
577
578 /* Write the bootsector to DstPath */
581 &Name,
583 NULL,
584 NULL);
585
590 NULL,
592 0,
595 NULL,
596 0);
597 if (!NT_SUCCESS(Status))
598 {
600 return Status;
601 }
602
604 NULL,
605 NULL,
606 NULL,
609 BootSector.Length,
610 NULL,
611 NULL);
613
614 /* Free the bootsector and return */
616 return Status;
617}
618
619
620static
623 IN PCWSTR SrcPath,
624 IN PCWSTR RootPath,
625 IN PFS_INSTALL_BOOTCODE InstallBootCode)
626{
627 NTSTATUS Status, LockStatus;
631 HANDLE PartitionHandle;
632
633 /*
634 * Open the root partition from which the bootcode (MBR, VBR) parameters
635 * will be obtained; this is also where we will write the updated bootcode.
636 * Remove any trailing backslash if needed.
637 */
638 RtlInitUnicodeString(&Name, RootPath);
640
642 &Name,
644 NULL,
645 NULL);
646
647 Status = NtOpenFile(&PartitionHandle,
652 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
653 if (!NT_SUCCESS(Status))
654 return Status;
655
656 /* Lock the volume */
657 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
658 if (!NT_SUCCESS(LockStatus))
659 {
660 DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
661 }
662
663 /* Install the bootcode (MBR, VBR) */
664 Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
665
666 /* dismount & Unlock the volume */
667 if (NT_SUCCESS(LockStatus))
668 {
669 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
670 if (!NT_SUCCESS(LockStatus))
671 {
672 DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
673 }
674
675 LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
676 if (!NT_SUCCESS(LockStatus))
677 {
678 DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
679 }
680 }
681
682 /* Close the partition */
683 NtClose(PartitionHandle);
684
685 return Status;
686}
687
688static
691 IN PCWSTR SrcPath,
693 IN PCWSTR RootPath,
694 IN PFS_INSTALL_BOOTCODE InstallBootCode)
695{
700 HANDLE PartitionHandle, FileHandle;
701
702 /*
703 * Open the root partition from which the bootcode (MBR, VBR)
704 * parameters will be obtained.
705 *
706 * FIXME? It might be possible that we need to also open it for writing
707 * access in case we really need to still write the second portion of
708 * the boot sector ????
709 *
710 * Remove any trailing backslash if needed.
711 */
712 RtlInitUnicodeString(&Name, RootPath);
714
716 &Name,
718 NULL,
719 NULL);
720
721 Status = NtOpenFile(&PartitionHandle,
726 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
727 if (!NT_SUCCESS(Status))
728 return Status;
729
730 /* Open or create the file where the new bootsector will be saved */
733 &Name,
735 NULL,
736 NULL);
737
742 NULL,
744 0,
745 FILE_SUPERSEDE, // FILE_OVERWRITE_IF
747 NULL,
748 0);
749 if (!NT_SUCCESS(Status))
750 {
751 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
752 NtClose(PartitionHandle);
753 return Status;
754 }
755
756 /* Install the bootcode (MBR, VBR) */
757 Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
758
759 /* Close the file and the partition */
761 NtClose(PartitionHandle);
762
763 return Status;
764}
765
766
767static
770 IN PCWSTR SrcPath, // MBR source file (on the installation medium)
771 IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information
772 IN HANDLE DiskHandle) // Disk holding the (old) MBR information
773{
778 BOOTCODE OrigBootSector = {0};
779 BOOTCODE NewBootSector = {0};
780
782
783 /* Allocate and read the current original MBR bootsector */
784 Status = ReadBootCodeByHandle(&OrigBootSector,
785 DiskHandle,
786 sizeof(PARTITION_SECTOR));
787 if (!NT_SUCCESS(Status))
788 return Status;
789
790 /* Allocate and read the new bootsector from SrcPath */
791 RtlInitUnicodeString(&Name, SrcPath);
792 Status = ReadBootCodeFromFile(&NewBootSector,
793 &Name,
794 sizeof(PARTITION_SECTOR));
795 if (!NT_SUCCESS(Status))
796 {
797 FreeBootCode(&OrigBootSector);
798 return Status;
799 }
800
801 /*
802 * Copy the disk signature, the reserved fields and
803 * the partition table from the old MBR to the new one.
804 */
805 RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
806 &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
807 sizeof(PARTITION_SECTOR) -
809 /* Length of partition table */);
810
811 /* Free the original bootsector */
812 FreeBootCode(&OrigBootSector);
813
814 /* Write the new bootsector to DstPath */
815 FileOffset.QuadPart = 0ULL;
817 NULL,
818 NULL,
819 NULL,
821 NewBootSector.BootCode,
822 NewBootSector.Length,
823 &FileOffset,
824 NULL);
825
826 /* Free the new bootsector */
827 FreeBootCode(&NewBootSector);
828
829 return Status;
830}
831
832static
835 _In_ PCUNICODE_STRING SystemRootPath,
836 _In_ PCUNICODE_STRING SourceRootPath,
837 _In_ PCWSTR DestinationDevicePathBuffer)
838{
840 WCHAR SourceMbrPathBuffer[MAX_PATH];
842
843#if 0
844 /*
845 * The DestinationDevicePathBuffer parameter has been built with
846 * the following instruction by the caller; I'm not yet sure whether
847 * I actually want this function to build the path instead, hence
848 * I keep this code here but disabled for now...
849 */
850 WCHAR DestinationDevicePathBuffer[MAX_PATH];
851 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
852 L"\\Device\\Harddisk%d\\Partition0",
853 DiskNumber);
854#endif
855
856 CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2,
857 SourceRootPath->Buffer, L"\\loader\\dosmbr.bin");
858
859 if (IsThereAValidBootSector(DestinationDevicePathBuffer))
860 {
861 /* Save current MBR */
863 SystemRootPath->Buffer, L"mbr.old");
864
865 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
866 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
867 if (!NT_SUCCESS(Status))
868 {
869 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
870 // Don't care if we succeeded or not saving the old MBR, just go ahead.
871 }
872 }
873
874 DPRINT1("Install MBR bootcode: %S ==> %S\n",
875 SourceMbrPathBuffer, DestinationDevicePathBuffer);
876
877 /* Install the MBR */
878 return InstallBootCodeToDisk(SourceMbrPathBuffer,
879 DestinationDevicePathBuffer,
881}
882
883static
886 _In_ PCUNICODE_STRING SystemRootPath,
887 _In_ PCUNICODE_STRING SourceRootPath)
888{
890 WCHAR SrcPath[MAX_PATH];
892
893 /* Copy FreeLoader to the system partition, always overwriting the older version */
894 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
895 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
896
897 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
898 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
899 if (!NT_SUCCESS(Status))
900 {
901 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
902 return Status;
903 }
904
905 /* Copy rosload to the system partition, always overwriting the older version */
906 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\rosload.exe");
907 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"rosload.exe");
908
909 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
910 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
911 if (!NT_SUCCESS(Status))
912 {
913 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
914 return Status;
915 }
916
917 return STATUS_SUCCESS;
918}
919
920static
923 _In_ PCUNICODE_STRING SystemRootPath,
924 _In_ PCUNICODE_STRING SourceRootPath,
925 _In_ PCUNICODE_STRING DestinationArcPath,
926 _In_ PCWSTR FileSystemName)
927{
929 BOOLEAN DoesFreeLdrExist;
930 WCHAR SrcPath[MAX_PATH];
932
933 /* FAT or FAT32 partition */
934 DPRINT("System path: '%wZ'\n", SystemRootPath);
935
936 /* Install the bootloader */
937 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
938 if (!NT_SUCCESS(Status))
939 {
940 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
941 return Status;
942 }
943
944 /* Prepare for possibly updating 'freeldr.ini' */
945 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
946 if (DoesFreeLdrExist)
947 {
948 /* Update existing 'freeldr.ini' */
949 DPRINT1("Update existing 'freeldr.ini'\n");
950 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
951 if (!NT_SUCCESS(Status))
952 {
953 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
954 return Status;
955 }
956 }
957
958 /* Check for NT and other bootloaders */
959
960 // FIXME: Check for Vista+ bootloader!
961 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
962 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
963 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
964 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
965 {
966 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
967 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
968
969 /* Create or update 'freeldr.ini' */
970 if (DoesFreeLdrExist == FALSE)
971 {
972 /* Create new 'freeldr.ini' */
973 DPRINT1("Create new 'freeldr.ini'\n");
974 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
975 if (!NT_SUCCESS(Status))
976 {
977 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
978 return Status;
979 }
980
981 /* Install new bootcode into a file */
982 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
983
984 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
985 {
986 /* Install FAT32 bootcode */
987 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
988
989 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
991 SystemRootPath->Buffer,
993 if (!NT_SUCCESS(Status))
994 {
995 DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
996 return Status;
997 }
998 }
999 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1000 {
1001 /* Install FAT16 bootcode */
1002 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1003
1004 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
1006 SystemRootPath->Buffer,
1008 if (!NT_SUCCESS(Status))
1009 {
1010 DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
1011 return Status;
1012 }
1013 }
1014 }
1015
1016 /* Update 'boot.ini' */
1017 /* Windows' NTLDR loads an external bootsector file when the specified drive
1018 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1019 DPRINT1("Update 'boot.ini'\n");
1020 Status = UpdateBootIni(SystemRootPath->Buffer,
1021 L"C:\\bootsect.ros",
1022 L"\"ReactOS\"");
1023 if (!NT_SUCCESS(Status))
1024 {
1025 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1026 return Status;
1027 }
1028 }
1029 else
1030 {
1031 /* Non-NT bootloaders: install our own bootloader */
1032
1033 PCWSTR Section;
1036
1037 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1038 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
1039 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
1040 {
1041 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1042
1043 Section = L"CPQDOS";
1044 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1045 BootSector = L"BOOTSECT.DOS";
1046 }
1047 else
1048 /* Search for Microsoft DOS or Windows 9x boot loader */
1049 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
1050 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
1051 // WINBOOT.SYS
1052 {
1053 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1054
1055 Section = L"MSDOS";
1056 Description = L"\"MS-DOS/Windows\"";
1057 BootSector = L"BOOTSECT.DOS";
1058 }
1059 else
1060 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1061 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
1062 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
1063 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
1064 {
1065 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
1066
1067 Section = L"IBMDOS";
1068 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
1069 BootSector = L"BOOTSECT.DOS";
1070 }
1071 else
1072 /* Search for DR-DOS 3.x boot loader */
1073 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
1074 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
1075 {
1076 DPRINT1("Found DR-DOS 3.x\n");
1077
1078 Section = L"DRDOS";
1079 Description = L"\"DR-DOS 3.x\"";
1080 BootSector = L"BOOTSECT.DOS";
1081 }
1082 else
1083 /* Search for Dell Real-Mode Kernel (DRMK) OS */
1084 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
1085 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
1086 {
1087 DPRINT1("Found Dell Real-Mode Kernel OS\n");
1088
1089 Section = L"DRMK";
1090 Description = L"\"Dell Real-Mode Kernel OS\"";
1091 BootSector = L"BOOTSECT.DOS";
1092 }
1093 else
1094 /* Search for MS OS/2 1.x */
1095 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
1096 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
1097 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
1098 {
1099 DPRINT1("Found MS OS/2 1.x\n");
1100
1101 Section = L"MSOS2";
1102 Description = L"\"MS OS/2 1.x\"";
1103 BootSector = L"BOOTSECT.OS2";
1104 }
1105 else
1106 /* Search for MS or IBM OS/2 */
1107 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
1108 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
1109 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
1110 {
1111 DPRINT1("Found MS/IBM OS/2\n");
1112
1113 Section = L"IBMOS2";
1114 Description = L"\"MS/IBM OS/2\"";
1115 BootSector = L"BOOTSECT.OS2";
1116 }
1117 else
1118 /* Search for FreeDOS boot loader */
1119 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
1120 {
1121 DPRINT1("Found FreeDOS boot loader\n");
1122
1123 Section = L"FDOS";
1124 Description = L"\"FreeDOS\"";
1125 BootSector = L"BOOTSECT.DOS";
1126 }
1127 else
1128 {
1129 /* No or unknown boot loader */
1130 DPRINT1("No or unknown boot loader found\n");
1131
1132 Section = L"Unknown";
1133 Description = L"\"Unknown Operating System\"";
1134 BootSector = L"BOOTSECT.OLD";
1135 }
1136
1137 /* Create or update 'freeldr.ini' */
1138 if (DoesFreeLdrExist == FALSE)
1139 {
1140 /* Create new 'freeldr.ini' */
1141 DPRINT1("Create new 'freeldr.ini'\n");
1142
1143 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1144 {
1146 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1147 Section, Description,
1148 SystemRootPath->Buffer, BootSector);
1149 if (!NT_SUCCESS(Status))
1150 {
1151 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1152 return Status;
1153 }
1154
1155 /* Save current bootsector */
1156 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1157
1158 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1159 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
1160 if (!NT_SUCCESS(Status))
1161 {
1162 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1163 return Status;
1164 }
1165 }
1166 else
1167 {
1168 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1169 if (!NT_SUCCESS(Status))
1170 {
1171 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1172 return Status;
1173 }
1174 }
1175
1176 /* Install new bootsector on the disk */
1177 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
1178 {
1179 /* Install FAT32 bootcode */
1180 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1181
1182 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1183 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
1184 DPRINT1("Status: 0x%08X\n", Status);
1185 if (!NT_SUCCESS(Status))
1186 {
1187 DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
1188 return Status;
1189 }
1190 }
1191 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1192 {
1193 /* Install FAT16 bootcode */
1194 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1195
1196 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1197 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
1198 if (!NT_SUCCESS(Status))
1199 {
1200 DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
1201 return Status;
1202 }
1203 }
1204 }
1205 }
1206
1207 return STATUS_SUCCESS;
1208}
1209
1210static
1213 _In_ PCUNICODE_STRING SystemRootPath,
1214 _In_ PCUNICODE_STRING SourceRootPath,
1215 _In_ PCUNICODE_STRING DestinationArcPath)
1216{
1218 BOOLEAN DoesFreeLdrExist;
1219 WCHAR SrcPath[MAX_PATH];
1221
1222 /* BTRFS partition */
1223 DPRINT("System path: '%wZ'\n", SystemRootPath);
1224
1225 /* Install the bootloader */
1226 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1227 if (!NT_SUCCESS(Status))
1228 {
1229 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1230 return Status;
1231 }
1232
1233 /* Prepare for possibly updating 'freeldr.ini' */
1234 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1235 if (DoesFreeLdrExist)
1236 {
1237 /* Update existing 'freeldr.ini' */
1238 DPRINT1("Update existing 'freeldr.ini'\n");
1239 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1240 if (!NT_SUCCESS(Status))
1241 {
1242 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1243 return Status;
1244 }
1245 }
1246
1247 /* Check for *nix bootloaders */
1248
1249 /* Create or update 'freeldr.ini' */
1250 if (DoesFreeLdrExist == FALSE)
1251 {
1252 /* Create new 'freeldr.ini' */
1253 DPRINT1("Create new 'freeldr.ini'\n");
1254
1255 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1256 DPRINT1("*nix or unknown boot loader found\n");
1257
1258 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1259 {
1260 PCWSTR BootSector = L"BOOTSECT.OLD";
1261
1263 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1264 L"Linux", L"\"Linux\"",
1265 SystemRootPath->Buffer, BootSector);
1266 if (!NT_SUCCESS(Status))
1267 {
1268 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1269 return Status;
1270 }
1271
1272 /* Save current bootsector */
1273 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1274
1275 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1276 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
1277 if (!NT_SUCCESS(Status))
1278 {
1279 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1280 return Status;
1281 }
1282 }
1283 else
1284 {
1285 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1286 if (!NT_SUCCESS(Status))
1287 {
1288 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1289 return Status;
1290 }
1291 }
1292
1293 /* Install new bootsector on the disk */
1294 /* Install BTRFS bootcode */
1295 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
1296
1297 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1298 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
1299 if (!NT_SUCCESS(Status))
1300 {
1301 DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
1302 return Status;
1303 }
1304 }
1305
1306 return STATUS_SUCCESS;
1307}
1308
1309static
1312 _In_ PCUNICODE_STRING SystemRootPath,
1313 _In_ PCUNICODE_STRING SourceRootPath,
1314 _In_ PCUNICODE_STRING DestinationArcPath)
1315{
1317 BOOLEAN DoesFreeLdrExist;
1318 WCHAR SrcPath[MAX_PATH];
1320
1321 /* NTFS partition */
1322 DPRINT("System path: '%wZ'\n", SystemRootPath);
1323
1324 /* Install the bootloader */
1325 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1326 if (!NT_SUCCESS(Status))
1327 {
1328 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1329 return Status;
1330 }
1331
1332 /* Prepare for possibly updating 'freeldr.ini' */
1333 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1334 if (DoesFreeLdrExist)
1335 {
1336 /* Update existing 'freeldr.ini' */
1337 DPRINT1("Update existing 'freeldr.ini'\n");
1338 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1339 if (!NT_SUCCESS(Status))
1340 {
1341 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1342 return Status;
1343 }
1344
1345 return STATUS_SUCCESS;
1346 }
1347
1348 /* Check for *nix bootloaders */
1349
1350 DPRINT1("Create new 'freeldr.ini'\n");
1351
1352 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1353 DPRINT1("*nix or unknown boot loader found\n");
1354
1355 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1356 {
1357 PCWSTR BootSector = L"BOOTSECT.OLD";
1358
1360 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1361 L"Linux", L"\"Linux\"",
1362 SystemRootPath->Buffer, BootSector);
1363 if (!NT_SUCCESS(Status))
1364 {
1365 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1366 return Status;
1367 }
1368
1369 /* Save current bootsector */
1370 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1371
1372 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1373 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, NTFS_BOOTSECTOR_SIZE);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1377 return Status;
1378 }
1379 }
1380 else
1381 {
1382 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1383 if (!NT_SUCCESS(Status))
1384 {
1385 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1386 return Status;
1387 }
1388 }
1389
1390 /* Install new bootsector on the disk */
1391
1392 /* Install NTFS bootcode */
1393 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\ntfs.bin");
1394
1395 DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1396 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallNtfsBootCode);
1397 if (!NT_SUCCESS(Status))
1398 {
1399 DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status);
1400 return Status;
1401 }
1402
1403 return STATUS_SUCCESS;
1404}
1405
1406static
1409 _In_ PCUNICODE_STRING SystemRootPath,
1410 _In_ PCUNICODE_STRING SourceRootPath,
1411 _In_ PCUNICODE_STRING DestinationArcPath,
1412 _In_ PCWSTR FileSystemName)
1413{
1414 if (_wcsicmp(FileSystemName, L"FAT") == 0 ||
1415 _wcsicmp(FileSystemName, L"FAT32") == 0)
1416 {
1417 return InstallFatBootcodeToPartition(SystemRootPath,
1418 SourceRootPath,
1419 DestinationArcPath,
1420 FileSystemName);
1421 }
1422 else if (_wcsicmp(FileSystemName, L"NTFS") == 0)
1423 {
1424 return InstallNtfsBootcodeToPartition(SystemRootPath,
1425 SourceRootPath,
1426 DestinationArcPath);
1427 }
1428 else if (_wcsicmp(FileSystemName, L"BTRFS") == 0)
1429 {
1430 return InstallBtrfsBootcodeToPartition(SystemRootPath,
1431 SourceRootPath,
1432 DestinationArcPath);
1433 }
1434 /*
1435 else if (_wcsicmp(FileSystemName, L"EXT2") == 0 ||
1436 _wcsicmp(FileSystemName, L"EXT3") == 0 ||
1437 _wcsicmp(FileSystemName, L"EXT4") == 0)
1438 {
1439 return STATUS_NOT_SUPPORTED;
1440 }
1441 */
1442 else
1443 {
1444 /* Unknown file system */
1445 DPRINT1("Unknown file system '%S'\n", FileSystemName);
1446 }
1447
1448 return STATUS_NOT_SUPPORTED;
1449}
1450
1451
1452/* GENERIC FUNCTIONS *********************************************************/
1453
1481static
1484 _In_ ARCHITECTURE_TYPE ArchType,
1485 _In_ PCUNICODE_STRING SystemRootPath,
1486 _In_ ULONG DiskNumber, // const STORAGE_DEVICE_NUMBER* DeviceNumber,
1487 _In_ PARTITION_STYLE DiskStyle,
1490 _In_ PCUNICODE_STRING SourceRootPath,
1491 _In_ PCUNICODE_STRING DestinationArcPath,
1493{
1495 BOOLEAN IsBIOS = ((ArchType == ARCH_PcAT) || (ArchType == ARCH_NEC98x86));
1496 UCHAR InstallType = (Options & 0x03);
1497
1498 // FIXME: We currently only support BIOS-based PCs
1499 // TODO: Support other platforms
1500 if (!IsBIOS)
1501 return STATUS_NOT_SUPPORTED;
1502
1503 if (InstallType <= 1)
1504 {
1505 /* Step 1: Write the VBR */
1506 Status = InstallVBRToPartition(SystemRootPath,
1507 SourceRootPath,
1508 DestinationArcPath,
1509 FileSystem);
1510 if (!NT_SUCCESS(Status))
1511 {
1512 DPRINT1("InstallVBRToPartition() failed (Status 0x%08lx)\n", Status);
1513 return ERROR_WRITE_BOOT; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1514 }
1515
1516 /* Step 2: Write the MBR if the disk containing the
1517 * system partition is MBR and not a super-floppy */
1518 if ((InstallType == 1) && (DiskStyle == PARTITION_STYLE_MBR) && !IsSuperFloppy)
1519 {
1520 WCHAR SystemDiskPath[MAX_PATH];
1521 RtlStringCchPrintfW(SystemDiskPath, _countof(SystemDiskPath),
1522 L"\\Device\\Harddisk%d\\Partition0",
1523 DiskNumber);
1524 Status = InstallMbrBootCodeToDisk(SystemRootPath,
1525 SourceRootPath,
1526 SystemDiskPath);
1527 if (!NT_SUCCESS(Status))
1528 {
1529 DPRINT1("InstallMbrBootCodeToDisk() failed (Status 0x%08lx)\n", Status);
1530 return ERROR_INSTALL_BOOTCODE; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1531 }
1532 }
1533 }
1534 else if (InstallType == 2)
1535 {
1536 WCHAR SrcPath[MAX_PATH];
1537
1538 // FIXME: We currently only support FAT12 file system.
1539 if (_wcsicmp(FileSystem, L"FAT") != 0)
1540 return STATUS_NOT_SUPPORTED;
1541
1542 // TODO: In the future, we'll be able to use InstallVBRToPartition()
1543 // directly, instead of re-doing manually the copy steps below.
1544
1545 /* Install the bootloader to the boot partition */
1546 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1547 if (!NT_SUCCESS(Status))
1548 {
1549 DPRINT1("InstallBootloaderFiles() failed (Status 0x%08lx)\n", Status);
1550 return Status;
1551 }
1552
1553 /* Create new 'freeldr.ini' */
1554 DPRINT("Create new 'freeldr.ini'\n");
1555 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1556 if (!NT_SUCCESS(Status))
1557 {
1558 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status 0x%08lx)\n", Status);
1559 return Status;
1560 }
1561
1562 /* Install FAT12 bootsector */
1563 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1564
1565 DPRINT1("Install FAT12 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1566 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat12BootCode);
1567 if (!NT_SUCCESS(Status))
1568 {
1569 DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status 0x%08lx)\n", Status);
1570 return Status;
1571 }
1572 }
1573
1574 return Status;
1575}
1576
1577
1583{
1586
1587 if (DeviceName && DeviceHandle)
1589
1590 /* Open the device if a name has been given;
1591 * otherwise just use the provided handle. */
1592 if (DeviceName)
1593 {
1597 if (!NT_SUCCESS(Status))
1598 {
1599 DPRINT1("Cannot open device '%wZ' (Status 0x%08lx)\n",
1601 return Status;
1602 }
1603 }
1604
1605 /* Query the device */
1608 DeviceInfo,
1609 sizeof(*DeviceInfo),
1611 if (!NT_SUCCESS(Status))
1612 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1613
1614 /* Close the device if we've opened it */
1615 if (DeviceName)
1617
1618 return Status;
1619}
1620
1626{
1627 UNICODE_STRING DeviceNameU;
1628
1629 if (DeviceName && DeviceHandle)
1631
1632 if (DeviceName)
1633 RtlInitUnicodeString(&DeviceNameU, DeviceName);
1634
1635 return GetDeviceInfo_UStr(DeviceName ? &DeviceNameU : NULL,
1637 DeviceInfo);
1638}
1639
1640
1672NTAPI
1674 _In_ ARCHITECTURE_TYPE ArchType,
1675 _In_ PCUNICODE_STRING SystemRootPath,
1676 _In_ PCUNICODE_STRING SourceRootPath,
1677 _In_ PCUNICODE_STRING DestinationArcPath,
1679{
1683 ULONG DiskNumber;
1684 PARTITION_STYLE PartitionStyle;
1687
1688 /* Remove any trailing backslash if needed */
1689 UNICODE_STRING RootPartition = *SystemRootPath;
1691
1692 /* Open the volume */
1696 if (!NT_SUCCESS(Status))
1697 {
1698 DPRINT1("Cannot open %wZ for bootloader installation (Status 0x%08lx)\n",
1700 return Status;
1701 }
1702
1703 /* Retrieve the volume file system (it will also be mounted) */
1705 FileSystem, sizeof(FileSystem));
1706 if (!NT_SUCCESS(Status) || !*FileSystem)
1707 {
1708 DPRINT1("GetFileSystemName() failed (Status 0x%08lx)\n", Status);
1709 goto Quit;
1710 }
1711
1712 /* Retrieve the device type and characteristics */
1714 if (!NT_SUCCESS(Status))
1715 {
1716 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1717 goto Quit;
1718 }
1719
1720 /* Ignore volumes that are NOT on usual disks */
1721 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1722 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1723 {
1724 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1726 goto Quit;
1727 }
1728
1729
1730 /* Check whether this is a floppy or a partitionable device */
1731 if (DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE)
1732 {
1733 /* Floppies don't have partitions */
1734 // NOTE: See ntoskrnl/io/iomgr/rawfs.c!RawQueryFsSizeInfo()
1735 DiskNumber = ULONG_MAX;
1736 PartitionStyle = PARTITION_STYLE_MBR;
1738 }
1739 else
1740 {
1743
1744 /* The maximum information a DISK_GEOMETRY_EX dynamic structure can contain */
1745 typedef struct _DISK_GEOMETRY_EX_INTERNAL
1746 {
1749 DISK_PARTITION_INFO Partition;
1750 /* Followed by: DISK_DETECTION_INFO Detection; unused here */
1752
1753 DISK_GEOMETRY_EX_INTERNAL DiskGeoEx;
1755
1756 /* Retrieve the disk number. NOTE: Fails for floppy disks. */
1758 NULL, NULL, NULL,
1761 NULL, 0,
1762 &DeviceNumber, sizeof(DeviceNumber));
1763 if (!NT_SUCCESS(Status))
1764 goto Quit; /* This may be a dynamic volume, which is unsupported */
1765 ASSERT(DeviceNumber.DeviceType == DeviceInfo.DeviceType);
1766 if (DeviceNumber.DeviceNumber == ULONG_MAX)
1767 {
1768 DPRINT1("Invalid disk number reported, bail out\n");
1770 goto Quit;
1771 }
1772
1773 /* Retrieve the drive geometry. NOTE: Fails for floppy disks;
1774 * use IOCTL_DISK_GET_DRIVE_GEOMETRY instead. */
1776 NULL, NULL, NULL,
1779 NULL, 0,
1780 &DiskGeoEx,
1781 sizeof(DiskGeoEx));
1782 if (!NT_SUCCESS(Status))
1783 {
1784 DPRINT1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed (Status 0x%08lx)\n", Status);
1785 goto Quit;
1786 }
1787
1788 /*
1789 * Retrieve the volume's partition information.
1790 * NOTE: Fails for floppy disks.
1791 *
1792 * NOTE: We can use the non-EX IOCTL because the super-floppy test will
1793 * fail anyway if the disk is NOT MBR-partitioned. (If the disk is GPT,
1794 * the IOCTL would return only the MBR protective partition, but the
1795 * super-floppy test would fail due to the wrong partitioning style.)
1796 */
1798 NULL, NULL, NULL,
1801 NULL, 0,
1803 sizeof(PartitionInfo));
1804 if (!NT_SUCCESS(Status))
1805 {
1806 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO failed (Status 0x%08lx)\n", Status);
1807 goto Quit;
1808 }
1809
1810 DiskNumber = DeviceNumber.DeviceNumber;
1811 PartitionStyle = DiskGeoEx.Partition.PartitionStyle;
1813 (PULONGLONG)&DiskGeoEx.DiskSize.QuadPart,
1814 &PartitionInfo);
1815 }
1816
1818 ArchType, SystemRootPath,
1819 DiskNumber, PartitionStyle, IsSuperFloppy, FileSystem,
1820 SourceRootPath, DestinationArcPath, Options);
1821
1822Quit:
1824 return Status;
1825}
1826
1828NTAPI
1830 _In_ ARCHITECTURE_TYPE ArchType,
1831 _In_ PCUNICODE_STRING RemovableRootPath,
1832 _In_ PCUNICODE_STRING SourceRootPath,
1833 _In_ PCUNICODE_STRING DestinationArcPath)
1834{
1837 PCWSTR FileSystemName;
1838 BOOLEAN IsFloppy;
1839
1840 /* Remove any trailing backslash if needed */
1841 UNICODE_STRING RootDrive = *RemovableRootPath;
1843
1844 /* Verify that the removable disk is accessible */
1845 if (!DoesDirExist(NULL, RemovableRootPath->Buffer))
1847
1848 /* Retrieve the device type and characteristics */
1849 Status = GetDeviceInfo_UStr(&RootDrive, NULL, &DeviceInfo);
1850 if (!NT_SUCCESS(Status))
1851 {
1852 static const UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
1853
1854 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1855
1856 /* Definitively fail if the device is not a floppy */
1857 if (!RtlPrefixUnicodeString(&DeviceFloppy, &RootDrive, TRUE))
1858 return Status; /* We cannot cope with a failure */
1859
1860 /* Try to fall back to something "sane" if the device may be a floppy */
1861 DeviceInfo.DeviceType = FILE_DEVICE_DISK;
1863 }
1864
1865 /* Ignore volumes that are NOT on usual disks */
1866 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1867 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1868 {
1869 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1871 }
1872
1873 /* Fail if the disk is not removable */
1874 if (!(DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA))
1875 {
1876 DPRINT1("Device is NOT removable!\n");
1878 }
1879
1880 /* Check whether this is a floppy or another removable device */
1881 IsFloppy = !!(DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE);
1882
1883 /* Use FAT32, unless the device is a floppy disk */
1884 FileSystemName = (IsFloppy ? L"FAT" : L"FAT32");
1885
1886 /* Format the removable disk */
1887 Status = FormatFileSystem_UStr(&RootDrive,
1888 FileSystemName,
1889 (IsFloppy ? FMIFS_FLOPPY : FMIFS_REMOVABLE),
1890 NULL,
1891 TRUE,
1892 0,
1893 NULL);
1894 if (!NT_SUCCESS(Status))
1895 {
1897 DPRINT1("%s FS non-existent on this system!\n", FileSystemName);
1898 else
1899 DPRINT1("FormatFileSystem(%s) failed (Status 0x%08lx)\n", FileSystemName, Status);
1900 return Status;
1901 }
1902
1903 /* Copy FreeLoader to the removable disk and save the boot entries */
1905 RemovableRootPath,
1906 SourceRootPath,
1907 DestinationArcPath,
1908 2 /* Install on removable media */);
1909 if (!NT_SUCCESS(Status))
1910 DPRINT1("InstallBootManagerAndBootEntries() failed (Status 0x%08lx)\n", Status);
1911 return Status;
1912}
1913
1914/* EOF */
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
struct NameRec_ * Name
Definition: cdprocs.h:460
#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:885
static NTSTATUS InstallMbrBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE DiskHandle)
Definition: bootsup.c:769
static NTSTATUS SaveBootSector(IN PCWSTR RootPath, IN PCWSTR DstPath, IN ULONG Length)
Definition: bootsup.c:557
static NTSTATUS InstallFatBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath, _In_ PCWSTR FileSystemName)
Definition: bootsup.c:922
static NTSTATUS UpdateBootIni(IN PCWSTR IniPath, IN PCWSTR EntryName, IN PCWSTR EntryValue)
Definition: bootsup.c:455
static NTSTATUS NTAPI EnumerateReactOSEntries(IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
Definition: bootsup.c:316
static NTSTATUS InstallBtrfsBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1212
static NTSTATUS InstallMbrBootCodeToDisk(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCWSTR DestinationDevicePathBuffer)
Definition: bootsup.c:834
NTSTATUS NTAPI InstallBootcodeToRemovable(_In_ ARCHITECTURE_TYPE ArchType, _In_ PCUNICODE_STRING RemovableRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1829
static NTSTATUS CreateFreeLoaderIniForReactOS(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:167
static NTSTATUS InstallBootCodeToFile(IN PCWSTR SrcPath, IN PCWSTR DstPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:690
static NTSTATUS CreateFreeLoaderIniForReactOSAndBootSector(IN PCWSTR IniPath, IN PCWSTR ArcPath, IN PCWSTR Section, IN PCWSTR Description, IN PCWSTR BootPath, IN PCWSTR BootSector)
Definition: bootsup.c:189
static NTSTATUS InstallNtfsBootcodeToPartition(_In_ PCUNICODE_STRING SystemRootPath, _In_ PCUNICODE_STRING SourceRootPath, _In_ PCUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1311
static BOOLEAN IsThereAValidBootSector(IN PCWSTR RootPath)
Definition: bootsup.c:517
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:1483
NTSTATUS GetDeviceInfo(_In_opt_ PCWSTR DeviceName, _In_opt_ HANDLE DeviceHandle, _Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
Definition: bootsup.c:1622
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:1673
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:1408
static VOID TrimTrailingPathSeparators_UStr(IN OUT PUNICODE_STRING UnicodeString)
Definition: bootsup.c:44
struct _ENUM_REACTOS_ENTRIES_DATA ENUM_REACTOS_ENTRIES_DATA
static NTSTATUS InstallBootCodeToDisk(IN PCWSTR SrcPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:622
NTSTATUS GetDeviceInfo_UStr(_In_opt_ PCUNICODE_STRING DeviceName, _In_opt_ HANDLE DeviceHandle, _Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
Definition: bootsup.c:1579
static NTSTATUS UpdateFreeLoaderIni(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:396
static VOID CreateFreeLoaderReactOSEntries(IN PVOID BootStoreHandle, IN PCWSTR ArcPath)
Definition: bootsup.c:56
_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
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
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
BOOLEAN IsUnattendedSetup
Definition: setuplib.c:26
@ ARCH_NEC98x86
Definition: setuplib.h:57
@ ARCH_PcAT
Definition: setuplib.h:56
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