ReactOS 0.4.17-dev-1190-g4c812f4
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) &&
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;
64 BOOT_STORE_OPTIONS BootOptions;
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,
609 BootSector.BootCode,
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{
890 /* Set the SYSTEM, HIDDEN and READONLY attributes to the FreeLoader files */
891 static const ULONG ProtectAttribs =
893
895 WCHAR SrcPath[MAX_PATH];
897
898 /* Copy FreeLoader to the system partition, always overwriting the older version */
899 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
900 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
901
902 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
903 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
904 if (!NT_SUCCESS(Status))
905 {
906 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
907 return Status;
908 }
909
910 /* Protect freeldr.sys (this is optional, so any potential errors are ignored) */
911 SetupSetFileAttributes(DstPath, ProtectAttribs);
912
913 /* Copy rosload to the system partition, always overwriting the older version */
914 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\rosload.exe");
915 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"rosload.exe");
916
917 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
918 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
919 if (!NT_SUCCESS(Status))
920 {
921 DPRINT1("SetupCopyFile() failed (Status 0x%08lx)\n", Status);
922 return Status;
923 }
924
925 /* Protect rosload.exe (this is optional, so any potential errors are ignored) */
926 SetupSetFileAttributes(DstPath, ProtectAttribs);
927
928 return STATUS_SUCCESS;
929}
930
931static
934 _In_ PCUNICODE_STRING SystemRootPath,
935 _In_ PCUNICODE_STRING SourceRootPath,
936 _In_ PCUNICODE_STRING DestinationArcPath,
937 _In_ PCWSTR FileSystemName)
938{
940 BOOLEAN DoesFreeLdrExist;
941 WCHAR SrcPath[MAX_PATH];
943
944 /* FAT or FAT32 partition */
945 DPRINT("System path: '%wZ'\n", SystemRootPath);
946
947 /* Install the bootloader */
948 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
949 if (!NT_SUCCESS(Status))
950 {
951 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
952 return Status;
953 }
954
955 /* Prepare for possibly updating 'freeldr.ini' */
956 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
957 if (DoesFreeLdrExist)
958 {
959 /* Update existing 'freeldr.ini' */
960 DPRINT1("Update existing 'freeldr.ini'\n");
961 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
962 if (!NT_SUCCESS(Status))
963 {
964 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
965 return Status;
966 }
967 }
968
969 /* Check for NT and other bootloaders */
970
971 // FIXME: Check for Vista+ bootloader!
972 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
973 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
974 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
975 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
976 {
977 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
978 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
979
980 /* Create or update 'freeldr.ini' */
981 if (DoesFreeLdrExist == FALSE)
982 {
983 /* Create new 'freeldr.ini' */
984 DPRINT1("Create new 'freeldr.ini'\n");
985 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
986 if (!NT_SUCCESS(Status))
987 {
988 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
989 return Status;
990 }
991
992 /* Install new bootcode into a file */
993 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
994
995 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
996 {
997 /* Install FAT32 bootcode */
998 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
999
1000 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1002 SystemRootPath->Buffer,
1004 if (!NT_SUCCESS(Status))
1005 {
1006 DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
1007 return Status;
1008 }
1009 }
1010 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1011 {
1012 /* Install FAT16 bootcode */
1013 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1014
1015 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
1017 SystemRootPath->Buffer,
1019 if (!NT_SUCCESS(Status))
1020 {
1021 DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
1022 return Status;
1023 }
1024 }
1025 }
1026
1027 /* Update 'boot.ini' */
1028 /* Windows' NTLDR loads an external bootsector file when the specified drive
1029 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1030 DPRINT1("Update 'boot.ini'\n");
1031 Status = UpdateBootIni(SystemRootPath->Buffer,
1032 L"C:\\bootsect.ros",
1033 L"\"ReactOS\"");
1034 if (!NT_SUCCESS(Status))
1035 {
1036 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1037 return Status;
1038 }
1039 }
1040 else
1041 {
1042 /* Non-NT bootloaders: install our own bootloader */
1043
1044 PCWSTR Section;
1047
1048 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1049 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
1050 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
1051 {
1052 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1053
1054 Section = L"CPQDOS";
1055 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1056 BootSector = L"BOOTSECT.DOS";
1057 }
1058 else
1059 /* Search for Microsoft DOS or Windows 9x boot loader */
1060 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
1061 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
1062 // WINBOOT.SYS
1063 {
1064 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1065
1066 Section = L"MSDOS";
1067 Description = L"\"MS-DOS/Windows\"";
1068 BootSector = L"BOOTSECT.DOS";
1069 }
1070 else
1071 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1072 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
1073 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
1074 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
1075 {
1076 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
1077
1078 Section = L"IBMDOS";
1079 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
1080 BootSector = L"BOOTSECT.DOS";
1081 }
1082 else
1083 /* Search for DR-DOS 3.x boot loader */
1084 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
1085 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
1086 {
1087 DPRINT1("Found DR-DOS 3.x\n");
1088
1089 Section = L"DRDOS";
1090 Description = L"\"DR-DOS 3.x\"";
1091 BootSector = L"BOOTSECT.DOS";
1092 }
1093 else
1094 /* Search for Dell Real-Mode Kernel (DRMK) OS */
1095 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
1096 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
1097 {
1098 DPRINT1("Found Dell Real-Mode Kernel OS\n");
1099
1100 Section = L"DRMK";
1101 Description = L"\"Dell Real-Mode Kernel OS\"";
1102 BootSector = L"BOOTSECT.DOS";
1103 }
1104 else
1105 /* Search for MS OS/2 1.x */
1106 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
1107 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
1108 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
1109 {
1110 DPRINT1("Found MS OS/2 1.x\n");
1111
1112 Section = L"MSOS2";
1113 Description = L"\"MS OS/2 1.x\"";
1114 BootSector = L"BOOTSECT.OS2";
1115 }
1116 else
1117 /* Search for MS or IBM OS/2 */
1118 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
1119 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
1120 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
1121 {
1122 DPRINT1("Found MS/IBM OS/2\n");
1123
1124 Section = L"IBMOS2";
1125 Description = L"\"MS/IBM OS/2\"";
1126 BootSector = L"BOOTSECT.OS2";
1127 }
1128 else
1129 /* Search for FreeDOS boot loader */
1130 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
1131 {
1132 DPRINT1("Found FreeDOS boot loader\n");
1133
1134 Section = L"FDOS";
1135 Description = L"\"FreeDOS\"";
1136 BootSector = L"BOOTSECT.DOS";
1137 }
1138 else
1139 {
1140 /* No or unknown boot loader */
1141 DPRINT1("No or unknown boot loader found\n");
1142
1143 Section = L"Unknown";
1144 Description = L"\"Unknown Operating System\"";
1145 BootSector = L"BOOTSECT.OLD";
1146 }
1147
1148 /* Create or update 'freeldr.ini' */
1149 if (DoesFreeLdrExist == FALSE)
1150 {
1151 /* Create new 'freeldr.ini' */
1152 DPRINT1("Create new 'freeldr.ini'\n");
1153
1154 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1155 {
1157 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1158 Section, Description,
1159 SystemRootPath->Buffer, BootSector);
1160 if (!NT_SUCCESS(Status))
1161 {
1162 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1163 return Status;
1164 }
1165
1166 /* Save current bootsector */
1167 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1168
1169 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1170 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
1171 if (!NT_SUCCESS(Status))
1172 {
1173 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1174 return Status;
1175 }
1176 }
1177 else
1178 {
1179 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1180 if (!NT_SUCCESS(Status))
1181 {
1182 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1183 return Status;
1184 }
1185 }
1186
1187 /* Install new bootsector on the disk */
1188 if (_wcsicmp(FileSystemName, L"FAT32") == 0)
1189 {
1190 /* Install FAT32 bootcode */
1191 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1192
1193 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1194 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
1195 DPRINT1("Status: 0x%08X\n", Status);
1196 if (!NT_SUCCESS(Status))
1197 {
1198 DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
1199 return Status;
1200 }
1201 }
1202 else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1203 {
1204 /* Install FAT16 bootcode */
1205 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1206
1207 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1208 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
1209 if (!NT_SUCCESS(Status))
1210 {
1211 DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
1212 return Status;
1213 }
1214 }
1215 }
1216 }
1217
1218 return STATUS_SUCCESS;
1219}
1220
1221static
1224 _In_ PCUNICODE_STRING SystemRootPath,
1225 _In_ PCUNICODE_STRING SourceRootPath,
1226 _In_ PCUNICODE_STRING DestinationArcPath)
1227{
1229 BOOLEAN DoesFreeLdrExist;
1230 WCHAR SrcPath[MAX_PATH];
1232
1233 /* BTRFS partition */
1234 DPRINT("System path: '%wZ'\n", SystemRootPath);
1235
1236 /* Install the bootloader */
1237 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1238 if (!NT_SUCCESS(Status))
1239 {
1240 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1241 return Status;
1242 }
1243
1244 /* Prepare for possibly updating 'freeldr.ini' */
1245 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1246 if (DoesFreeLdrExist)
1247 {
1248 /* Update existing 'freeldr.ini' */
1249 DPRINT1("Update existing 'freeldr.ini'\n");
1250 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1254 return Status;
1255 }
1256 }
1257
1258 /* Check for *nix bootloaders */
1259
1260 /* Create or update 'freeldr.ini' */
1261 if (DoesFreeLdrExist == FALSE)
1262 {
1263 /* Create new 'freeldr.ini' */
1264 DPRINT1("Create new 'freeldr.ini'\n");
1265
1266 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1267 DPRINT1("*nix or unknown boot loader found\n");
1268
1269 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1270 {
1271 PCWSTR BootSector = L"BOOTSECT.OLD";
1272
1274 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1275 L"Linux", L"\"Linux\"",
1276 SystemRootPath->Buffer, BootSector);
1277 if (!NT_SUCCESS(Status))
1278 {
1279 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1280 return Status;
1281 }
1282
1283 /* Save current bootsector */
1284 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1285
1286 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1287 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
1288 if (!NT_SUCCESS(Status))
1289 {
1290 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1291 return Status;
1292 }
1293 }
1294 else
1295 {
1296 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1297 if (!NT_SUCCESS(Status))
1298 {
1299 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1300 return Status;
1301 }
1302 }
1303
1304 /* Install new bootsector on the disk */
1305 /* Install BTRFS bootcode */
1306 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
1307
1308 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1309 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
1310 if (!NT_SUCCESS(Status))
1311 {
1312 DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
1313 return Status;
1314 }
1315 }
1316
1317 return STATUS_SUCCESS;
1318}
1319
1320static
1323 _In_ PCUNICODE_STRING SystemRootPath,
1324 _In_ PCUNICODE_STRING SourceRootPath,
1325 _In_ PCUNICODE_STRING DestinationArcPath)
1326{
1328 BOOLEAN DoesFreeLdrExist;
1329 WCHAR SrcPath[MAX_PATH];
1331
1332 /* NTFS partition */
1333 DPRINT("System path: '%wZ'\n", SystemRootPath);
1334
1335 /* Install the bootloader */
1336 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1337 if (!NT_SUCCESS(Status))
1338 {
1339 DPRINT1("InstallBootloaderFiles() failed (Status %lx)\n", Status);
1340 return Status;
1341 }
1342
1343 /* Prepare for possibly updating 'freeldr.ini' */
1344 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1345 if (DoesFreeLdrExist)
1346 {
1347 /* Update existing 'freeldr.ini' */
1348 DPRINT1("Update existing 'freeldr.ini'\n");
1349 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1350 if (!NT_SUCCESS(Status))
1351 {
1352 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1353 return Status;
1354 }
1355
1356 return STATUS_SUCCESS;
1357 }
1358
1359 /* Check for *nix bootloaders */
1360
1361 DPRINT1("Create new 'freeldr.ini'\n");
1362
1363 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1364 DPRINT1("*nix or unknown boot loader found\n");
1365
1366 if (IsThereAValidBootSector(SystemRootPath->Buffer))
1367 {
1368 PCWSTR BootSector = L"BOOTSECT.OLD";
1369
1371 SystemRootPath->Buffer, DestinationArcPath->Buffer,
1372 L"Linux", L"\"Linux\"",
1373 SystemRootPath->Buffer, BootSector);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1377 return Status;
1378 }
1379
1380 /* Save current bootsector */
1381 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1382
1383 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1384 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, NTFS_BOOTSECTOR_SIZE);
1385 if (!NT_SUCCESS(Status))
1386 {
1387 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1388 return Status;
1389 }
1390 }
1391 else
1392 {
1393 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1394 if (!NT_SUCCESS(Status))
1395 {
1396 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1397 return Status;
1398 }
1399 }
1400
1401 /* Install new bootsector on the disk */
1402
1403 /* Install NTFS bootcode */
1404 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\ntfs.bin");
1405
1406 DPRINT1("Install NTFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1407 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallNtfsBootCode);
1408 if (!NT_SUCCESS(Status))
1409 {
1410 DPRINT1("InstallBootCodeToDisk(NTFS) failed (Status %lx)\n", Status);
1411 return Status;
1412 }
1413
1414 return STATUS_SUCCESS;
1415}
1416
1417static
1420 _In_ PCUNICODE_STRING SystemRootPath,
1421 _In_ PCUNICODE_STRING SourceRootPath,
1422 _In_ PCUNICODE_STRING DestinationArcPath,
1423 _In_ PCWSTR FileSystemName)
1424{
1425 if (_wcsicmp(FileSystemName, L"FAT") == 0 ||
1426 _wcsicmp(FileSystemName, L"FAT32") == 0)
1427 {
1428 return InstallFatBootcodeToPartition(SystemRootPath,
1429 SourceRootPath,
1430 DestinationArcPath,
1431 FileSystemName);
1432 }
1433 else if (_wcsicmp(FileSystemName, L"NTFS") == 0)
1434 {
1435 return InstallNtfsBootcodeToPartition(SystemRootPath,
1436 SourceRootPath,
1437 DestinationArcPath);
1438 }
1439 else if (_wcsicmp(FileSystemName, L"BTRFS") == 0)
1440 {
1441 return InstallBtrfsBootcodeToPartition(SystemRootPath,
1442 SourceRootPath,
1443 DestinationArcPath);
1444 }
1445 /*
1446 else if (_wcsicmp(FileSystemName, L"EXT2") == 0 ||
1447 _wcsicmp(FileSystemName, L"EXT3") == 0 ||
1448 _wcsicmp(FileSystemName, L"EXT4") == 0)
1449 {
1450 return STATUS_NOT_SUPPORTED;
1451 }
1452 */
1453 else
1454 {
1455 /* Unknown file system */
1456 DPRINT1("Unknown file system '%S'\n", FileSystemName);
1457 }
1458
1459 return STATUS_NOT_SUPPORTED;
1460}
1461
1462
1463/* GENERIC FUNCTIONS *********************************************************/
1464
1492static
1495 _In_ ARCHITECTURE_TYPE ArchType,
1496 _In_ PCUNICODE_STRING SystemRootPath,
1497 _In_ ULONG DiskNumber, // const STORAGE_DEVICE_NUMBER* DeviceNumber,
1498 _In_ PARTITION_STYLE DiskStyle,
1501 _In_ PCUNICODE_STRING SourceRootPath,
1502 _In_ PCUNICODE_STRING DestinationArcPath,
1504{
1506 BOOLEAN IsBIOS = ((ArchType == ARCH_PcAT) || (ArchType == ARCH_NEC98x86));
1507 UCHAR InstallType = (Options & 0x03);
1508
1509 // FIXME: We currently only support BIOS-based PCs
1510 // TODO: Support other platforms
1511 if (!IsBIOS)
1512 return STATUS_NOT_SUPPORTED;
1513
1514 if (InstallType <= 1)
1515 {
1516 /* Step 1: Write the VBR */
1517 Status = InstallVBRToPartition(SystemRootPath,
1518 SourceRootPath,
1519 DestinationArcPath,
1520 FileSystem);
1521 if (!NT_SUCCESS(Status))
1522 {
1523 DPRINT1("InstallVBRToPartition() failed (Status 0x%08lx)\n", Status);
1524 return ERROR_WRITE_BOOT; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1525 }
1526
1527 /* Step 2: Write the MBR if the disk containing the
1528 * system partition is MBR and not a super-floppy */
1529 if ((InstallType == 1) && (DiskStyle == PARTITION_STYLE_MBR) && !IsSuperFloppy)
1530 {
1531 WCHAR SystemDiskPath[MAX_PATH];
1532 RtlStringCchPrintfW(SystemDiskPath, _countof(SystemDiskPath),
1533 L"\\Device\\Harddisk%d\\Partition0",
1534 DiskNumber);
1535 Status = InstallMbrBootCodeToDisk(SystemRootPath,
1536 SourceRootPath,
1537 SystemDiskPath);
1538 if (!NT_SUCCESS(Status))
1539 {
1540 DPRINT1("InstallMbrBootCodeToDisk() failed (Status 0x%08lx)\n", Status);
1541 return ERROR_INSTALL_BOOTCODE; // Status; STATUS_BAD_MASTER_BOOT_RECORD;
1542 }
1543 }
1544 }
1545 else if (InstallType == 2)
1546 {
1547 WCHAR SrcPath[MAX_PATH];
1548
1549 // FIXME: We currently only support FAT12 file system.
1550 if (_wcsicmp(FileSystem, L"FAT") != 0)
1551 return STATUS_NOT_SUPPORTED;
1552
1553 // TODO: In the future, we'll be able to use InstallVBRToPartition()
1554 // directly, instead of re-doing manually the copy steps below.
1555
1556 /* Install the bootloader to the boot partition */
1557 Status = InstallBootloaderFiles(SystemRootPath, SourceRootPath);
1558 if (!NT_SUCCESS(Status))
1559 {
1560 DPRINT1("InstallBootloaderFiles() failed (Status 0x%08lx)\n", Status);
1561 return Status;
1562 }
1563
1564 /* Create new 'freeldr.ini' */
1565 DPRINT("Create new 'freeldr.ini'\n");
1566 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1567 if (!NT_SUCCESS(Status))
1568 {
1569 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status 0x%08lx)\n", Status);
1570 return Status;
1571 }
1572
1573 /* Install FAT12 bootsector */
1574 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1575
1576 DPRINT1("Install FAT12 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1577 Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat12BootCode);
1578 if (!NT_SUCCESS(Status))
1579 {
1580 DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status 0x%08lx)\n", Status);
1581 return Status;
1582 }
1583 }
1584
1585 return Status;
1586}
1587
1588
1594{
1597
1598 if (DeviceName && DeviceHandle)
1600
1601 /* Open the device if a name has been given;
1602 * otherwise just use the provided handle. */
1603 if (DeviceName)
1604 {
1608 if (!NT_SUCCESS(Status))
1609 {
1610 DPRINT1("Cannot open device '%wZ' (Status 0x%08lx)\n",
1612 return Status;
1613 }
1614 }
1615
1616 /* Query the device */
1619 DeviceInfo,
1620 sizeof(*DeviceInfo),
1622 if (!NT_SUCCESS(Status))
1623 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1624
1625 /* Close the device if we've opened it */
1626 if (DeviceName)
1628
1629 return Status;
1630}
1631
1637{
1638 UNICODE_STRING DeviceNameU;
1639
1640 if (DeviceName && DeviceHandle)
1642
1643 if (DeviceName)
1644 RtlInitUnicodeString(&DeviceNameU, DeviceName);
1645
1646 return GetDeviceInfo_UStr(DeviceName ? &DeviceNameU : NULL,
1648 DeviceInfo);
1649}
1650
1651
1683NTAPI
1685 _In_ ARCHITECTURE_TYPE ArchType,
1686 _In_ PCUNICODE_STRING SystemRootPath,
1687 _In_ PCUNICODE_STRING SourceRootPath,
1688 _In_ PCUNICODE_STRING DestinationArcPath,
1690{
1694 ULONG DiskNumber;
1695 PARTITION_STYLE PartitionStyle;
1698
1699 /* Remove any trailing backslash if needed */
1700 UNICODE_STRING RootPartition = *SystemRootPath;
1702
1703 /* Open the volume */
1707 if (!NT_SUCCESS(Status))
1708 {
1709 DPRINT1("Cannot open %wZ for bootloader installation (Status 0x%08lx)\n",
1711 return Status;
1712 }
1713
1714 /* Retrieve the volume file system (it will also be mounted) */
1716 FileSystem, sizeof(FileSystem));
1717 if (!NT_SUCCESS(Status) || !*FileSystem)
1718 {
1719 DPRINT1("GetFileSystemName() failed (Status 0x%08lx)\n", Status);
1720 goto Quit;
1721 }
1722
1723 /* Retrieve the device type and characteristics */
1725 if (!NT_SUCCESS(Status))
1726 {
1727 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1728 goto Quit;
1729 }
1730
1731 /* Ignore volumes that are NOT on usual disks */
1732 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1733 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1734 {
1735 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1737 goto Quit;
1738 }
1739
1740
1741 /* Check whether this is a floppy or a partitionable device */
1742 if (DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE)
1743 {
1744 /* Floppies don't have partitions */
1745 // NOTE: See ntoskrnl/io/iomgr/rawfs.c!RawQueryFsSizeInfo()
1746 DiskNumber = ULONG_MAX;
1747 PartitionStyle = PARTITION_STYLE_MBR;
1749 }
1750 else
1751 {
1754
1755 /* The maximum information a DISK_GEOMETRY_EX dynamic structure can contain */
1756 typedef struct _DISK_GEOMETRY_EX_INTERNAL
1757 {
1760 DISK_PARTITION_INFO Partition;
1761 /* Followed by: DISK_DETECTION_INFO Detection; unused here */
1763
1764 DISK_GEOMETRY_EX_INTERNAL DiskGeoEx;
1766
1767 /* Retrieve the disk number. NOTE: Fails for floppy disks. */
1769 NULL, NULL, NULL,
1772 NULL, 0,
1773 &DeviceNumber, sizeof(DeviceNumber));
1774 if (!NT_SUCCESS(Status))
1775 goto Quit; /* This may be a dynamic volume, which is unsupported */
1776 ASSERT(DeviceNumber.DeviceType == DeviceInfo.DeviceType);
1777 if (DeviceNumber.DeviceNumber == ULONG_MAX)
1778 {
1779 DPRINT1("Invalid disk number reported, bail out\n");
1781 goto Quit;
1782 }
1783
1784 /* Retrieve the drive geometry. NOTE: Fails for floppy disks;
1785 * use IOCTL_DISK_GET_DRIVE_GEOMETRY instead. */
1787 NULL, NULL, NULL,
1790 NULL, 0,
1791 &DiskGeoEx,
1792 sizeof(DiskGeoEx));
1793 if (!NT_SUCCESS(Status))
1794 {
1795 DPRINT1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed (Status 0x%08lx)\n", Status);
1796 goto Quit;
1797 }
1798
1799 /*
1800 * Retrieve the volume's partition information.
1801 * NOTE: Fails for floppy disks.
1802 *
1803 * NOTE: We can use the non-EX IOCTL because the super-floppy test will
1804 * fail anyway if the disk is NOT MBR-partitioned. (If the disk is GPT,
1805 * the IOCTL would return only the MBR protective partition, but the
1806 * super-floppy test would fail due to the wrong partitioning style.)
1807 */
1809 NULL, NULL, NULL,
1812 NULL, 0,
1814 sizeof(PartitionInfo));
1815 if (!NT_SUCCESS(Status))
1816 {
1817 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO failed (Status 0x%08lx)\n", Status);
1818 goto Quit;
1819 }
1820
1821 DiskNumber = DeviceNumber.DeviceNumber;
1822 PartitionStyle = DiskGeoEx.Partition.PartitionStyle;
1824 (PULONGLONG)&DiskGeoEx.DiskSize.QuadPart,
1825 &PartitionInfo);
1826 }
1827
1829 ArchType, SystemRootPath,
1830 DiskNumber, PartitionStyle, IsSuperFloppy, FileSystem,
1831 SourceRootPath, DestinationArcPath, Options);
1832
1833Quit:
1835 return Status;
1836}
1837
1839NTAPI
1841 _In_ ARCHITECTURE_TYPE ArchType,
1842 _In_ PCUNICODE_STRING RemovableRootPath,
1843 _In_ PCUNICODE_STRING SourceRootPath,
1844 _In_ PCUNICODE_STRING DestinationArcPath)
1845{
1848 PCWSTR FileSystemName;
1850
1851 /* Remove any trailing backslash if needed */
1852 UNICODE_STRING RootDrive = *RemovableRootPath;
1854
1855 /* Verify that the removable disk is accessible */
1856 if (!DoesDirExist(NULL, RemovableRootPath->Buffer))
1858
1859 /* Retrieve the device type and characteristics */
1860 Status = GetDeviceInfo_UStr(&RootDrive, NULL, &DeviceInfo);
1861 if (!NT_SUCCESS(Status))
1862 {
1863 static const UNICODE_STRING DeviceFloppy = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
1864
1865 DPRINT1("FileFsDeviceInformation failed (Status 0x%08lx)\n", Status);
1866
1867 /* Definitively fail if the device is not a floppy */
1868 if (!RtlPrefixUnicodeString(&DeviceFloppy, &RootDrive, TRUE))
1869 return Status; /* We cannot cope with a failure */
1870
1871 /* Try to fall back to something "sane" if the device may be a floppy */
1872 DeviceInfo.DeviceType = FILE_DEVICE_DISK;
1874 }
1875
1876 /* Ignore volumes that are NOT on usual disks */
1877 if (DeviceInfo.DeviceType != FILE_DEVICE_DISK /*&&
1878 DeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK*/)
1879 {
1880 DPRINT1("Invalid volume; device type %lu\n", DeviceInfo.DeviceType);
1882 }
1883
1884 /* Fail if the disk is not removable */
1885 if (!(DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA))
1886 {
1887 DPRINT1("Device is NOT removable!\n");
1889 }
1890
1891 /* Check whether this is a floppy or another removable device */
1892 IsFloppy = !!(DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE);
1893
1894 /* Use FAT32, unless the device is a floppy disk */
1895 FileSystemName = (IsFloppy ? L"FAT" : L"FAT32");
1896
1897 /* Format the removable disk */
1898 Status = FormatFileSystem_UStr(&RootDrive,
1899 FileSystemName,
1901 NULL,
1902 TRUE,
1903 0,
1904 NULL);
1905 if (!NT_SUCCESS(Status))
1906 {
1908 DPRINT1("%s FS non-existent on this system!\n", FileSystemName);
1909 else
1910 DPRINT1("FormatFileSystem(%s) failed (Status 0x%08lx)\n", FileSystemName, Status);
1911 return Status;
1912 }
1913
1914 /* Copy FreeLoader to the removable disk and save the boot entries */
1916 RemovableRootPath,
1917 SourceRootPath,
1918 DestinationArcPath,
1919 2 /* Install on removable media */);
1920 if (!NT_SUCCESS(Status))
1921 DPRINT1("InstallBootManagerAndBootEntries() failed (Status 0x%08lx)\n", Status);
1922 return Status;
1923}
1924
1925/* EOF */
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
#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:71
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:933
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:1223
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:1840
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:1322
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:1494
NTSTATUS GetDeviceInfo(_In_opt_ PCWSTR DeviceName, _In_opt_ HANDLE DeviceHandle, _Out_ PFILE_FS_DEVICE_INFORMATION DeviceInfo)
Definition: bootsup.c:1633
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:1684
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:1419
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:27
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:1590
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
#define ARRAYSIZE(a)
Definition: cat.c:25
_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
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
#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 RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#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
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2917
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:164
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:200
#define ULONG_MAX
Definition: limits.h:31
static const WCHAR Signature[]
Definition: parser.c:141
static BOOL IsFloppy(PCWSTR pszDrive)
Definition: drive.cpp:48
#define L(x)
Definition: resources.c:13
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:665
BOOLEAN DoesFileExist_2(IN PCWSTR PathName OPTIONAL, IN PCWSTR FileName)
Definition: filesup.c:741
BOOLEAN NtPathToDiskPartComponents(IN PCWSTR NtPath, OUT PULONG pDiskNumber, OUT PULONG pPartNumber, OUT PCWSTR *PathComponent OPTIONAL)
Definition: filesup.c:764
NTSTATUS SetupSetFileAttributes(_In_ PCWSTR Path, _In_ ULONG FileAttributes)
Definition: filesup.c:1153
NTSTATUS SetupCopyFile(IN PCWSTR SourceFileName, IN PCWSTR DestinationFileName, IN BOOLEAN FailIfExists)
Definition: filesup.c:224
#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:62
@ FMIFS_REMOVABLE
Definition: fmifs.h:65
#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:24
#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
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
_In_ PIOMMU_DEVICE_PATH _In_ PIOMMU_SVM_CAPABILITIES _Out_ PVOID * DeviceHandle
Definition: haltypes.h:1894
#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:3951
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#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
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
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:3434
#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:395
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_INVALID_PARAMETER_MIX
Definition: ntstatus.h:378
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:285
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
_Must_inspect_result_ _In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_opt_ LPGUID _In_opt_ HANDLE _In_opt_ ULONG _In_opt_ ULONG _In_opt_ ULONG _In_opt_ PLARGE_INTEGER _In_opt_ PUNICODE_STRING Description
Definition: nttmapi.h:425
short WCHAR
Definition: pedump.c:58
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define iswdigit(_c)
Definition: ctype.h:667
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:493
BOOLEAN IsSuperFloppy(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:602
@ 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
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
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
#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
struct _BootSector BootSector
Definition: vfat.h:108
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3540
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3281
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_opt_ PCUNICODE_STRING UnicodeString
Definition: wdfstring.h:64
_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