ReactOS  0.4.15-dev-2979-gfd8baca
bootsup.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Setup Library
4  * FILE: base/setup/lib/bootsup.c
5  * PURPOSE: Bootloader support functions
6  * PROGRAMMERS: ...
7  * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include "precomp.h"
13 
14 #include "bldrsup.h"
15 #include "filesup.h"
16 #include "partlist.h"
17 #include "bootcode.h"
18 #include "fsutil.h"
19 
20 #include "setuplib.h" // HAXX for IsUnattendedSetup!!
21 
22 #include "bootsup.h"
23 
24 #define NDEBUG
25 #include <debug.h>
26 
27 /*
28  * BIG FIXME!!
29  * ===========
30  *
31  * bootsup.c can deal with MBR code (actually it'll have at some point
32  * to share or give it to partlist.c, because when we'll support GPT disks,
33  * things will change a bit).
34  * And, bootsup.c can manage initializing / adding boot entries into NTLDR
35  * and FREELDR, and installing the latter, and saving the old MBR / boot
36  * sectors in files.
37  */
38 
39 /* FUNCTIONS ****************************************************************/
40 
41 static VOID
44 {
45  while (UnicodeString->Length >= sizeof(WCHAR) &&
46  UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
47  {
48  UnicodeString->Length -= sizeof(WCHAR);
49  }
50 }
51 
52 
53 static VOID
55  IN PVOID BootStoreHandle,
56  IN PCWSTR ArcPath)
57 {
58  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
59  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
60  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
62 
63  BootEntry->Version = FreeLdr;
64  BootEntry->BootFilePath = NULL;
65 
66  BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
67  RtlCopyMemory(Options->Signature,
70 
71  Options->OsLoadPath = ArcPath;
72 
73  /* ReactOS */
74  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
75  BootEntry->FriendlyName = L"\"ReactOS\"";
76  Options->OsLoadOptions = NULL; // L"";
77  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
78 
79  /* ReactOS_Debug */
80  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
81  BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
82  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
83  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
84 
85 #ifdef _WINKD_
86  /* ReactOS_VBoxDebug */
87  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
88  BootEntry->FriendlyName = L"\"ReactOS (VBoxDebug)\"";
89  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
90  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
91 #endif
92 #if DBG
93 #ifndef _WINKD_
94  /* ReactOS_KdSerial */
95  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
96  BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\"";
97  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
98  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
99 #endif
100 
101  /* ReactOS_Screen */
102  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
103  BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
104  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
105  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
106 
107  /* ReactOS_LogFile */
108  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
109  BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
110  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
111  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
112 
113  /* ReactOS_Ram */
114  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
115  BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\"";
116  Options->OsLoadPath = L"ramdisk(0)\\ReactOS";
117  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
118  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
119 
120  /* ReactOS_EMS */
121  // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
122  BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\"";
123  Options->OsLoadPath = ArcPath;
124  Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
125  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
126 #endif
127 
128 
129 #if DBG
130  if (IsUnattendedSetup)
131  {
132  /* DefaultOS=ReactOS */
133 #ifndef _WINKD_
134  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
135 #else
136  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
137 #endif
138  }
139  else
140 #endif
141  {
142  /* DefaultOS=ReactOS */
143  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS");
144  }
145 
146 #if DBG
147  if (IsUnattendedSetup)
148 #endif
149  {
150  /* Timeout=0 for unattended or non debug */
151  BootOptions.Timeout = 0;
152  }
153 #if DBG
154  else
155  {
156  /* Timeout=10 */
157  BootOptions.Timeout = 10;
158  }
159 #endif
160 
161  BootOptions.Version = FreeLdr;
162  SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1);
163 }
164 
165 static NTSTATUS
167  IN PCWSTR IniPath,
168  IN PCWSTR ArcPath)
169 {
171  PVOID BootStoreHandle;
172 
173  /* Initialize the INI file and create the common FreeLdr sections */
174  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
175  if (!NT_SUCCESS(Status))
176  return Status;
177 
178  /* Add the ReactOS entries */
179  CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
180 
181  /* Close the INI file */
182  CloseBootStore(BootStoreHandle);
183  return STATUS_SUCCESS;
184 }
185 
186 static NTSTATUS
188  IN PCWSTR IniPath,
189  IN PCWSTR ArcPath,
190  IN PCWSTR Section,
192  IN PCWSTR BootDrive,
193  IN PCWSTR BootPartition,
195 {
197  PVOID BootStoreHandle;
198  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)];
199  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
200  PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
201 
202  /* Initialize the INI file and create the common FreeLdr sections */
203  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
204  if (!NT_SUCCESS(Status))
205  return Status;
206 
207  /* Add the ReactOS entries */
208  CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
209 
210  BootEntry->Version = FreeLdr;
211  BootEntry->BootFilePath = NULL;
212 
213  BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
214  RtlCopyMemory(Options->Signature,
217 
218  Options->Drive = BootDrive;
219  Options->Partition = BootPartition;
220  Options->BootSectorFileName = BootSector;
221 
222  // BootEntry->BootEntryKey = MAKESTRKEY(Section);
223  BootEntry->FriendlyName = Description;
224  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
225 
226  /* Close the INI file */
227  CloseBootStore(BootStoreHandle);
228  return STATUS_SUCCESS;
229 }
230 
231 //
232 // I think this function can be generalizable as:
233 // "find the corresponding 'ReactOS' boot entry in this loader config file
234 // (here abstraction comes there), and if none, add a new one".
235 //
236 
238 {
245 
246 // PENUM_BOOT_ENTRIES_ROUTINE
247 static NTSTATUS
248 NTAPI
251  IN PBOOT_STORE_ENTRY BootEntry,
253 {
256  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
257  WCHAR SystemPath[MAX_PATH];
258 
259  /* We have a boot entry */
260 
261  /* Check for supported boot type "Windows2003" */
262  if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
263  RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
267  {
268  /* This is not a ReactOS entry */
269  // DPRINT(" An installation '%S' of unsupported type '%S'\n",
270  // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
271  DPRINT(" An installation '%S' of unsupported type %lu\n",
272  BootEntry->FriendlyName, BootEntry->OsOptionsLength);
273  /* Continue the enumeration */
274  goto SkipThisEntry;
275  }
276 
277  /* BootType is Windows2003, now check OsLoadPath */
278  if (!Options->OsLoadPath || !*Options->OsLoadPath)
279  {
280  /* Certainly not a ReactOS installation */
281  DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
282  /* Continue the enumeration */
283  goto SkipThisEntry;
284  }
285 
286  if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
287  {
288  /* Not found, retry with a quoted path */
289  Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
290  if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
291  {
292  /*
293  * This entry is a ReactOS entry, but the SystemRoot
294  * does not match the one we are looking for.
295  */
296  /* Continue the enumeration */
297  goto SkipThisEntry;
298  }
299  }
300 
301  DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
302  BootEntry->FriendlyName, Options->OsLoadPath);
303  // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
304  // BootEntry->FriendlyName, Options->OsLoadPath);
305 
306  DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
307 
308  Data->UseExistingEntry = TRUE;
309  RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
310 
311  /* We have found our entry, stop the enumeration now! */
312  return STATUS_NO_MORE_ENTRIES;
313 
314 SkipThisEntry:
315  Data->UseExistingEntry = FALSE;
316  if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
317  {
318  RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
319  L"ReactOS_%lu", Data->i);
320  RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
321  L"\"ReactOS %lu\"", Data->i);
322  Data->i++;
323  }
324  return STATUS_SUCCESS;
325 }
326 
327 static
328 NTSTATUS
330  IN PCWSTR IniPath,
331  IN PCWSTR ArcPath)
332 {
334  PVOID BootStoreHandle;
336  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
337  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
338  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
339 
340  /* Open the INI file */
341  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE);
342  if (!NT_SUCCESS(Status))
343  return Status;
344 
345  /* Find an existing usable or an unused section name */
346  Data.UseExistingEntry = TRUE;
347  Data.i = 1;
348  Data.ArcPath = ArcPath;
349  RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
350  RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
351 
352  //
353  // FIXME: We temporarily use EnumerateBootStoreEntries, until
354  // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
355  //
357 
358  /* Create a new "ReactOS" entry if there is none already existing that suits us */
359  if (!Data.UseExistingEntry)
360  {
361  // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
362  // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
363 
364  BootEntry->Version = FreeLdr;
365  BootEntry->BootFilePath = NULL;
366 
367  BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
368  RtlCopyMemory(Options->Signature,
371 
372  Options->OsLoadPath = ArcPath;
373 
374  // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
375  BootEntry->FriendlyName = Data.OsName;
376  Options->OsLoadOptions = NULL; // L"";
377  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
378  }
379 
380  /* Close the INI file */
381  CloseBootStore(BootStoreHandle);
382  return STATUS_SUCCESS;
383 }
384 
385 static
386 NTSTATUS
388  IN PCWSTR IniPath,
389  IN PCWSTR EntryName, // ~= ArcPath
390  IN PCWSTR EntryValue)
391 {
393  PVOID BootStoreHandle;
395 
396  // NOTE: Technically it would be "BootSector"...
397  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
398  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
399  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
400 
401  /* Open the INI file */
402  Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE);
403  if (!NT_SUCCESS(Status))
404  return Status;
405 
406  /* Find an existing usable or an unused section name */
407  Data.UseExistingEntry = TRUE;
408  // Data.i = 1;
409  Data.ArcPath = EntryName;
410  // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
411  RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
412 
413  //
414  // FIXME: We temporarily use EnumerateBootStoreEntries, until
415  // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
416  //
418 
419  /* If either the key was not found, or contains something else, add a new one */
420  if (!Data.UseExistingEntry /* ||
421  ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
422  {
423  BootEntry->Version = NtLdr;
424  BootEntry->BootFilePath = NULL;
425 
426  BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
427  RtlCopyMemory(Options->Signature,
430 
431  Options->OsLoadPath = EntryName;
432 
433  // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
434  // BootEntry->FriendlyName = Data.OsName;
435  BootEntry->FriendlyName = EntryValue;
436  Options->OsLoadOptions = NULL; // L"";
437  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
438  }
439 
440  /* Close the INI file */
441  CloseBootStore(BootStoreHandle);
442  return STATUS_SUCCESS; // Status;
443 }
444 
445 
446 static
447 BOOLEAN
449  IN PCWSTR RootPath)
450 {
451  /*
452  * We first demand that the bootsector has a valid signature at its end.
453  * We then check the first 3 bytes (as a ULONG) of the bootsector for a
454  * potential "valid" instruction (the BIOS starts execution of the bootsector
455  * at its beginning). Currently this criterium is that this ULONG must be
456  * non-zero. If both these tests pass, then the bootsector is valid; otherwise
457  * it is invalid and certainly needs to be overwritten.
458  */
459 
460  BOOLEAN IsValid = FALSE;
463  BOOTCODE BootSector = {0};
464 
465  /* Allocate and read the root partition bootsector.
466  * Remove any trailing backslash if needed. */
470  if (!NT_SUCCESS(Status))
471  return FALSE;
472 
473  /* Check for the existence of the bootsector signature */
474  IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
475  if (IsValid)
476  {
477  /* Check for the first instruction encoded on three bytes */
478  IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
479  }
480 
481  /* Free the bootsector and return */
483  return IsValid;
484 }
485 
486 static
487 NTSTATUS
489  IN PCWSTR RootPath,
490  IN PCWSTR DstPath,
491  IN ULONG Length)
492 {
498  // LARGE_INTEGER FileOffset;
499  BOOTCODE BootSector = {0};
500 
501  /* Allocate and read the root partition bootsector.
502  * Remove any trailing backslash if needed. */
503  RtlInitUnicodeString(&Name, RootPath);
506  if (!NT_SUCCESS(Status))
507  return Status;
508 
509  /* Write the bootsector to DstPath */
512  &Name,
514  NULL,
515  NULL);
516 
520  &IoStatusBlock,
521  NULL,
523  0,
526  NULL,
527  0);
528  if (!NT_SUCCESS(Status))
529  {
531  return Status;
532  }
533 
535  NULL,
536  NULL,
537  NULL,
538  &IoStatusBlock,
540  BootSector.Length,
541  NULL,
542  NULL);
544 
545  /* Free the bootsector and return */
547  return Status;
548 }
549 
550 
551 static
552 NTSTATUS
554  IN PCWSTR SrcPath,
555  IN PCWSTR RootPath,
556  IN PFS_INSTALL_BOOTCODE InstallBootCode)
557 {
558  NTSTATUS Status, LockStatus;
562  HANDLE PartitionHandle;
563 
564  /*
565  * Open the root partition from which the bootcode (MBR, VBR) parameters
566  * will be obtained; this is also where we will write the updated bootcode.
567  * Remove any trailing backslash if needed.
568  */
569  RtlInitUnicodeString(&Name, RootPath);
571 
573  &Name,
575  NULL,
576  NULL);
577 
578  Status = NtOpenFile(&PartitionHandle,
581  &IoStatusBlock,
583  FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
584  if (!NT_SUCCESS(Status))
585  return Status;
586 
587  /* Lock the volume */
588  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
589  if (!NT_SUCCESS(LockStatus))
590  {
591  DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
592  }
593 
594  /* Install the bootcode (MBR, VBR) */
595  Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
596 
597  /* dismount & Unlock the volume */
598  if (NT_SUCCESS(LockStatus))
599  {
600  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
601  if (!NT_SUCCESS(LockStatus))
602  {
603  DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
604  }
605 
606  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
607  if (!NT_SUCCESS(LockStatus))
608  {
609  DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
610  }
611  }
612 
613  /* Close the partition */
614  NtClose(PartitionHandle);
615 
616  return Status;
617 }
618 
619 static
620 NTSTATUS
622  IN PCWSTR SrcPath,
623  IN PCWSTR DstPath,
624  IN PCWSTR RootPath,
625  IN PFS_INSTALL_BOOTCODE InstallBootCode)
626 {
631  HANDLE PartitionHandle, FileHandle;
632 
633  /*
634  * Open the root partition from which the bootcode (MBR, VBR)
635  * parameters will be obtained.
636  *
637  * FIXME? It might be possible that we need to also open it for writing
638  * access in case we really need to still write the second portion of
639  * the boot sector ????
640  *
641  * Remove any trailing backslash if needed.
642  */
643  RtlInitUnicodeString(&Name, RootPath);
645 
647  &Name,
649  NULL,
650  NULL);
651 
652  Status = NtOpenFile(&PartitionHandle,
655  &IoStatusBlock,
657  FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
658  if (!NT_SUCCESS(Status))
659  return Status;
660 
661  /* Open or create the file where the new bootsector will be saved */
664  &Name,
666  NULL,
667  NULL);
668 
672  &IoStatusBlock,
673  NULL,
675  0,
676  FILE_SUPERSEDE, // FILE_OVERWRITE_IF
678  NULL,
679  0);
680  if (!NT_SUCCESS(Status))
681  {
682  DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
683  NtClose(PartitionHandle);
684  return Status;
685  }
686 
687  /* Install the bootcode (MBR, VBR) */
688  Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
689 
690  /* Close the file and the partition */
692  NtClose(PartitionHandle);
693 
694  return Status;
695 }
696 
697 
698 static
699 NTSTATUS
701  IN PCWSTR SrcPath, // MBR source file (on the installation medium)
702  IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information
703  IN HANDLE DiskHandle) // Disk holding the (old) MBR information
704 {
709  BOOTCODE OrigBootSector = {0};
710  BOOTCODE NewBootSector = {0};
711 
713 
714  /* Allocate and read the current original MBR bootsector */
715  Status = ReadBootCodeByHandle(&OrigBootSector,
716  DiskHandle,
717  sizeof(PARTITION_SECTOR));
718  if (!NT_SUCCESS(Status))
719  return Status;
720 
721  /* Allocate and read the new bootsector from SrcPath */
722  RtlInitUnicodeString(&Name, SrcPath);
723  Status = ReadBootCodeFromFile(&NewBootSector,
724  &Name,
725  sizeof(PARTITION_SECTOR));
726  if (!NT_SUCCESS(Status))
727  {
728  FreeBootCode(&OrigBootSector);
729  return Status;
730  }
731 
732  /*
733  * Copy the disk signature, the reserved fields and
734  * the partition table from the old MBR to the new one.
735  */
736  RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
737  &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
738  sizeof(PARTITION_SECTOR) -
740  /* Length of partition table */);
741 
742  /* Free the original bootsector */
743  FreeBootCode(&OrigBootSector);
744 
745  /* Write the new bootsector to DstPath */
746  FileOffset.QuadPart = 0ULL;
748  NULL,
749  NULL,
750  NULL,
751  &IoStatusBlock,
752  NewBootSector.BootCode,
753  NewBootSector.Length,
754  &FileOffset,
755  NULL);
756 
757  /* Free the new bootsector */
758  FreeBootCode(&NewBootSector);
759 
760  return Status;
761 }
762 
763 NTSTATUS
765  IN PUNICODE_STRING SystemRootPath,
766  IN PUNICODE_STRING SourceRootPath,
767  IN PCWSTR DestinationDevicePathBuffer)
768 {
770  WCHAR SourceMbrPathBuffer[MAX_PATH];
772 
773 #if 0
774  /*
775  * The DestinationDevicePathBuffer parameter has been built with
776  * the following instruction by the caller; I'm not yet sure whether
777  * I actually want this function to build the path instead, hence
778  * I keep this code here but disabled for now...
779  */
780  WCHAR DestinationDevicePathBuffer[MAX_PATH];
781  RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
782  L"\\Device\\Harddisk%d\\Partition0",
783  DiskNumber);
784 #endif
785 
786  CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2,
787  SourceRootPath->Buffer, L"\\loader\\dosmbr.bin");
788 
789  if (IsThereAValidBootSector(DestinationDevicePathBuffer))
790  {
791  /* Save current MBR */
793  SystemRootPath->Buffer, L"mbr.old");
794 
795  DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
796  Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
797  if (!NT_SUCCESS(Status))
798  {
799  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
800  // Don't care if we succeeded or not saving the old MBR, just go ahead.
801  }
802  }
803 
804  DPRINT1("Install MBR bootcode: %S ==> %S\n",
805  SourceMbrPathBuffer, DestinationDevicePathBuffer);
806 
807  /* Install the MBR */
808  return InstallBootCodeToDisk(SourceMbrPathBuffer,
809  DestinationDevicePathBuffer,
811 }
812 
813 
814 static
815 NTSTATUS
817  IN PUNICODE_STRING SystemRootPath,
818  IN PUNICODE_STRING SourceRootPath,
819  IN PUNICODE_STRING DestinationArcPath,
820  IN PCWSTR FileSystemName)
821 {
823  BOOLEAN DoesFreeLdrExist;
824  WCHAR SrcPath[MAX_PATH];
826 
827  /* FAT or FAT32 partition */
828  DPRINT("System path: '%wZ'\n", SystemRootPath);
829 
830  /* Copy FreeLoader to the system partition, always overwriting the older version */
831  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
832  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
833 
834  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
835  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
836  if (!NT_SUCCESS(Status))
837  {
838  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
839  return Status;
840  }
841 
842  /* Prepare for possibly updating 'freeldr.ini' */
843  DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
844  if (DoesFreeLdrExist)
845  {
846  /* Update existing 'freeldr.ini' */
847  DPRINT1("Update existing 'freeldr.ini'\n");
848  Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
849  if (!NT_SUCCESS(Status))
850  {
851  DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
852  return Status;
853  }
854  }
855 
856  /* Check for NT and other bootloaders */
857 
858  // FIXME: Check for Vista+ bootloader!
859  /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
860  /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
861  if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
862  DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
863  {
864  /* Search root directory for 'NTLDR' and 'BOOT.INI' */
865  DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
866 
867  /* Create or update 'freeldr.ini' */
868  if (DoesFreeLdrExist == FALSE)
869  {
870  /* Create new 'freeldr.ini' */
871  DPRINT1("Create new 'freeldr.ini'\n");
872  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
873  if (!NT_SUCCESS(Status))
874  {
875  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
876  return Status;
877  }
878 
879  /* Install new bootcode into a file */
880  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
881 
882  if (wcsicmp(FileSystemName, L"FAT32") == 0)
883  {
884  /* Install FAT32 bootcode */
885  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
886 
887  DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
889  SystemRootPath->Buffer,
891  if (!NT_SUCCESS(Status))
892  {
893  DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
894  return Status;
895  }
896  }
897  else // if (wcsicmp(FileSystemName, L"FAT") == 0)
898  {
899  /* Install FAT16 bootcode */
900  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
901 
902  DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
904  SystemRootPath->Buffer,
906  if (!NT_SUCCESS(Status))
907  {
908  DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
909  return Status;
910  }
911  }
912  }
913 
914  /* Update 'boot.ini' */
915  /* Windows' NTLDR loads an external bootsector file when the specified drive
916  letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
917  DPRINT1("Update 'boot.ini'\n");
918  Status = UpdateBootIni(SystemRootPath->Buffer,
919  L"C:\\bootsect.ros",
920  L"\"ReactOS\"");
921  if (!NT_SUCCESS(Status))
922  {
923  DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
924  return Status;
925  }
926  }
927  else
928  {
929  /* Non-NT bootloaders: install our own bootloader */
930 
931  PCWSTR Section;
933  PCWSTR BootDrive;
934  PCWSTR BootPartition;
936 
937  /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
938  if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
939  DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
940  {
941  DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
942 
943  Section = L"CPQDOS";
944  Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
945  BootDrive = L"hd0";
946  BootPartition = L"1";
947  BootSector = L"BOOTSECT.DOS";
948  }
949  else
950  /* Search for Microsoft DOS or Windows 9x boot loader */
951  if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
952  DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
953  // WINBOOT.SYS
954  {
955  DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
956 
957  Section = L"MSDOS";
958  Description = L"\"MS-DOS/Windows\"";
959  BootDrive = L"hd0";
960  BootPartition = L"1";
961  BootSector = L"BOOTSECT.DOS";
962  }
963  else
964  /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
965  if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
966  DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
967  DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
968  {
969  DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
970 
971  Section = L"IBMDOS";
972  Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
973  BootDrive = L"hd0";
974  BootPartition = L"1";
975  BootSector = L"BOOTSECT.DOS";
976  }
977  else
978  /* Search for DR-DOS 3.x boot loader */
979  if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
980  DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
981  {
982  DPRINT1("Found DR-DOS 3.x\n");
983 
984  Section = L"DRDOS";
985  Description = L"\"DR-DOS 3.x\"";
986  BootDrive = L"hd0";
987  BootPartition = L"1";
988  BootSector = L"BOOTSECT.DOS";
989  }
990  else
991  /* Search for Dell Real-Mode Kernel (DRMK) OS */
992  if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
993  DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
994  {
995  DPRINT1("Found Dell Real-Mode Kernel OS\n");
996 
997  Section = L"DRMK";
998  Description = L"\"Dell Real-Mode Kernel OS\"";
999  BootDrive = L"hd0";
1000  BootPartition = L"1";
1001  BootSector = L"BOOTSECT.DOS";
1002  }
1003  else
1004  /* Search for MS OS/2 1.x */
1005  if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
1006  DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
1007  DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
1008  {
1009  DPRINT1("Found MS OS/2 1.x\n");
1010 
1011  Section = L"MSOS2";
1012  Description = L"\"MS OS/2 1.x\"";
1013  BootDrive = L"hd0";
1014  BootPartition = L"1";
1015  BootSector = L"BOOTSECT.OS2";
1016  }
1017  else
1018  /* Search for MS or IBM OS/2 */
1019  if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
1020  DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
1021  DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
1022  {
1023  DPRINT1("Found MS/IBM OS/2\n");
1024 
1025  Section = L"IBMOS2";
1026  Description = L"\"MS/IBM OS/2\"";
1027  BootDrive = L"hd0";
1028  BootPartition = L"1";
1029  BootSector = L"BOOTSECT.OS2";
1030  }
1031  else
1032  /* Search for FreeDOS boot loader */
1033  if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
1034  {
1035  DPRINT1("Found FreeDOS boot loader\n");
1036 
1037  Section = L"FDOS";
1038  Description = L"\"FreeDOS\"";
1039  BootDrive = L"hd0";
1040  BootPartition = L"1";
1041  BootSector = L"BOOTSECT.DOS";
1042  }
1043  else
1044  {
1045  /* No or unknown boot loader */
1046  DPRINT1("No or unknown boot loader found\n");
1047 
1048  Section = L"Unknown";
1049  Description = L"\"Unknown Operating System\"";
1050  BootDrive = L"hd0";
1051  BootPartition = L"1";
1052  BootSector = L"BOOTSECT.OLD";
1053  }
1054 
1055  /* Create or update 'freeldr.ini' */
1056  if (DoesFreeLdrExist == FALSE)
1057  {
1058  /* Create new 'freeldr.ini' */
1059  DPRINT1("Create new 'freeldr.ini'\n");
1060 
1061  if (IsThereAValidBootSector(SystemRootPath->Buffer))
1062  {
1064  SystemRootPath->Buffer, DestinationArcPath->Buffer,
1065  Section, Description,
1066  BootDrive, BootPartition, BootSector);
1067  if (!NT_SUCCESS(Status))
1068  {
1069  DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1070  return Status;
1071  }
1072 
1073  /* Save current bootsector */
1074  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1075 
1076  DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1077  Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
1078  if (!NT_SUCCESS(Status))
1079  {
1080  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1081  return Status;
1082  }
1083  }
1084  else
1085  {
1086  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1087  if (!NT_SUCCESS(Status))
1088  {
1089  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1090  return Status;
1091  }
1092  }
1093 
1094  /* Install new bootsector on the disk */
1095  if (wcsicmp(FileSystemName, L"FAT32") == 0)
1096  {
1097  /* Install FAT32 bootcode */
1098  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1099 
1100  DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1101  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
1102  DPRINT1("Status: 0x%08X\n", Status);
1103  if (!NT_SUCCESS(Status))
1104  {
1105  DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
1106  return Status;
1107  }
1108  }
1109  else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1110  {
1111  /* Install FAT16 bootcode */
1112  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1113 
1114  DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1115  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
1116  if (!NT_SUCCESS(Status))
1117  {
1118  DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
1119  return Status;
1120  }
1121  }
1122  }
1123  }
1124 
1125  return STATUS_SUCCESS;
1126 }
1127 
1128 static
1129 NTSTATUS
1131  IN PUNICODE_STRING SystemRootPath,
1132  IN PUNICODE_STRING SourceRootPath,
1133  IN PUNICODE_STRING DestinationArcPath)
1134 {
1135  NTSTATUS Status;
1136  BOOLEAN DoesFreeLdrExist;
1137  WCHAR SrcPath[MAX_PATH];
1139 
1140  /* BTRFS partition */
1141  DPRINT("System path: '%wZ'\n", SystemRootPath);
1142 
1143  /* Copy FreeLoader to the system partition, always overwriting the older version */
1144  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1145  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
1146 
1147  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1148  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1149  if (!NT_SUCCESS(Status))
1150  {
1151  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1152  return Status;
1153  }
1154 
1155  /* Prepare for possibly updating 'freeldr.ini' */
1156  DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1157  if (DoesFreeLdrExist)
1158  {
1159  /* Update existing 'freeldr.ini' */
1160  DPRINT1("Update existing 'freeldr.ini'\n");
1161  Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1162  if (!NT_SUCCESS(Status))
1163  {
1164  DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1165  return Status;
1166  }
1167  }
1168 
1169  /* Check for *nix bootloaders */
1170 
1171  /* Create or update 'freeldr.ini' */
1172  if (DoesFreeLdrExist == FALSE)
1173  {
1174  /* Create new 'freeldr.ini' */
1175  DPRINT1("Create new 'freeldr.ini'\n");
1176 
1177  /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1178  DPRINT1("*nix or unknown boot loader found\n");
1179 
1180  if (IsThereAValidBootSector(SystemRootPath->Buffer))
1181  {
1182  PCWSTR BootSector = L"BOOTSECT.OLD";
1183 
1185  SystemRootPath->Buffer, DestinationArcPath->Buffer,
1186  L"Linux", L"\"Linux\"",
1187  L"hd0", L"1", BootSector);
1188  if (!NT_SUCCESS(Status))
1189  {
1190  DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1191  return Status;
1192  }
1193 
1194  /* Save current bootsector */
1195  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1196 
1197  DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1198  Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
1199  if (!NT_SUCCESS(Status))
1200  {
1201  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1202  return Status;
1203  }
1204  }
1205  else
1206  {
1207  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1208  if (!NT_SUCCESS(Status))
1209  {
1210  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1211  return Status;
1212  }
1213  }
1214 
1215  /* Install new bootsector on the disk */
1216  /* Install BTRFS bootcode */
1217  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
1218 
1219  DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1220  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
1221  if (!NT_SUCCESS(Status))
1222  {
1223  DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
1224  return Status;
1225  }
1226  }
1227 
1228  return STATUS_SUCCESS;
1229 }
1230 
1231 
1232 NTSTATUS
1234  IN PUNICODE_STRING SystemRootPath,
1235  IN PUNICODE_STRING SourceRootPath,
1236  IN PUNICODE_STRING DestinationArcPath,
1237  IN PCWSTR FileSystemName)
1238 {
1239  if (wcsicmp(FileSystemName, L"FAT") == 0 ||
1240  wcsicmp(FileSystemName, L"FAT32") == 0)
1241  {
1242  return InstallFatBootcodeToPartition(SystemRootPath,
1243  SourceRootPath,
1244  DestinationArcPath,
1245  FileSystemName);
1246  }
1247  /*
1248  else if (wcsicmp(FileSystemName, L"NTFS") == 0)
1249  {
1250  DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
1251  return STATUS_NOT_SUPPORTED;
1252  }
1253  */
1254  else if (wcsicmp(FileSystemName, L"BTRFS") == 0)
1255  {
1256  return InstallBtrfsBootcodeToPartition(SystemRootPath,
1257  SourceRootPath,
1258  DestinationArcPath);
1259  }
1260  /*
1261  else if (wcsicmp(FileSystemName, L"EXT2") == 0 ||
1262  wcsicmp(FileSystemName, L"EXT3") == 0 ||
1263  wcsicmp(FileSystemName, L"EXT4") == 0 ||
1264  wcsicmp(FileSystemName, L"FFS") == 0 ||
1265  wcsicmp(FileSystemName, L"REISERFS") == 0)
1266  {
1267  return STATUS_NOT_SUPPORTED;
1268  }
1269  */
1270  else
1271  {
1272  /* Unknown file system */
1273  DPRINT1("Unknown file system '%S'\n", FileSystemName);
1274  }
1275 
1276  return STATUS_NOT_SUPPORTED;
1277 }
1278 
1279 
1280 NTSTATUS
1282  IN PUNICODE_STRING SourceRootPath,
1283  IN PUNICODE_STRING DestinationArcPath)
1284 {
1285  static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\";
1286 
1287  NTSTATUS Status;
1288  WCHAR SrcPath[MAX_PATH];
1290 
1291  /* Verify that the floppy disk is accessible */
1293  return STATUS_DEVICE_NOT_READY;
1294 
1295  /* Format the floppy disk */
1296  // FormatPartition(...)
1298  L"FAT",
1299  FMIFS_FLOPPY,
1300  NULL,
1301  TRUE,
1302  0,
1303  NULL);
1304  if (!NT_SUCCESS(Status))
1305  {
1307  DPRINT1("FAT FS non existent on this system?!\n");
1308  else
1309  DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
1310 
1311  return Status;
1312  }
1313 
1314  /* Copy FreeLoader to the boot partition */
1315  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1316  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice, L"freeldr.sys");
1317 
1318  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1319  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1320  if (!NT_SUCCESS(Status))
1321  {
1322  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1323  return Status;
1324  }
1325 
1326  /* Create new 'freeldr.ini' */
1327  DPRINT("Create new 'freeldr.ini'\n");
1328  Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer);
1329  if (!NT_SUCCESS(Status))
1330  {
1331  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1332  return Status;
1333  }
1334 
1335  /* Install FAT12 boosector */
1336  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1338 
1339  DPRINT("Install FAT12 bootcode: %S ==> %S\n", SrcPath, DstPath);
1341  if (!NT_SUCCESS(Status))
1342  {
1343  DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status %lx)\n", Status);
1344  return Status;
1345  }
1346 
1347  return STATUS_SUCCESS;
1348 }
1349 
1350 /* EOF */
#define BOOT_SECTOR_OPTIONS_SIGNATURE
Definition: bldrsup.h:111
#define NTOS_OPTIONS_SIGNATURE
Definition: bldrsup.h:98
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define InstallFat12BootCode
Definition: fsutil.h:84
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:84
static NTSTATUS InstallBootCodeToDisk(IN PCWSTR SrcPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:553
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
return STATUS_NOT_SUPPORTED
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
struct _BOOT_SECTOR_OPTIONS BOOT_SECTOR_OPTIONS
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define MAKESTRKEY(i)
Definition: bldrsup.h:54
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
static NTSTATUS InstallFatBootcodeToPartition(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath, IN PCWSTR FileSystemName)
Definition: bootsup.c:816
BOOLEAN DoesFileExist_2(IN PCWSTR PathName OPTIONAL, IN PCWSTR FileName)
Definition: filesup.c:748
static VOID TrimTrailingPathSeparators_UStr(IN OUT PUNICODE_STRING UnicodeString)
Definition: bootsup.c:42
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
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG _In_opt_ PVOID Data
Definition: wdfdevice.h:4527
#define BTRFS_BOOTSECTOR_SIZE
Definition: fsutil.h:70
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS SetupCopyFile(IN PCWSTR SourceFileName, IN PCWSTR DestinationFileName, IN BOOLEAN FailIfExists)
Definition: filesup.c:240
ULONG Length
Definition: bootcode.h:18
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
static VOID CreateFreeLoaderReactOSEntries(IN PVOID BootStoreHandle, IN PCWSTR ArcPath)
Definition: bootsup.c:54
NTSTATUS EnumerateBootStoreEntries(IN PVOID Handle, IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine, IN PVOID Parameter OPTIONAL)
Definition: bldrsup.c:1559
NTSTATUS ReadBootCodeFromFile(IN OUT PBOOTCODE BootCodeInfo, IN PUNICODE_STRING FilePath, IN ULONG Length OPTIONAL)
Definition: bootcode.c:69
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
NTSTATUS AddBootStoreEntry(IN PVOID Handle, IN PBOOT_STORE_ENTRY BootEntry, IN ULONG_PTR BootEntryKey)
Definition: bldrsup.c:927
static const WCHAR Description[]
Definition: oid.c:1266
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
static NTSTATUS InstallMbrBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE DiskHandle)
Definition: bootsup.c:700
_In_ PVOID Parameter
Definition: ldrtypes.h:241
if(dx==0 &&dy==0)
Definition: linetemp.h:174
NTSTATUS InstallBtrfsBootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE RootPartition)
Definition: fsutil.c:558
NTSTATUS CloseBootStore(IN PVOID Handle)
Definition: bldrsup.c:827
static NTSTATUS SaveBootSector(IN PCWSTR RootPath, IN PCWSTR DstPath, IN ULONG Length)
Definition: bootsup.c:488
struct _BOOT_STORE_ENTRY * PBOOT_STORE_ENTRY
#define FILE_SHARE_READ
Definition: compat.h:136
struct _BootSector BootSector
Definition: vfat.h:108
static NTSTATUS CreateFreeLoaderIniForReactOS(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:166
HANDLE FileHandle
Definition: stats.c:38
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
static NTSTATUS CreateFreeLoaderIniForReactOSAndBootSector(IN PCWSTR IniPath, IN PCWSTR ArcPath, IN PCWSTR Section, IN PCWSTR Description, IN PCWSTR BootDrive, IN PCWSTR BootPartition, IN PCWSTR BootSector)
Definition: bootsup.c:187
IN HANDLE DstPath
Definition: fsutil.h:75
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
BOOLEAN IsUnattendedSetup
Definition: reactos.c:40
#define GENERIC_WRITE
Definition: nt_native.h:90
struct _NTOS_OPTIONS NTOS_OPTIONS
struct NameRec_ * Name
Definition: cdprocs.h:459
unsigned char BOOLEAN
struct _ENUM_REACTOS_ENTRIES_DATA * PENUM_REACTOS_ENTRIES_DATA
#define C_ASSERT(e)
Definition: intsafe.h:73
#define ULL(a, b)
Definition: format_msg.c:27
Definition: bldrsup.h:16
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
Status
Definition: gdiplustypes.h:24
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
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3531
static BOOLEAN IsThereAValidBootSector(IN PCWSTR RootPath)
Definition: bootsup.c:448
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)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static NTSTATUS UpdateBootIni(IN PCWSTR IniPath, IN PCWSTR EntryName, IN PCWSTR EntryValue)
Definition: bootsup.c:387
#define MAX_PATH
Definition: compat.h:34
Type
Definition: Type.h:6
PVOID BootCode
Definition: bootcode.h:17
BYTE BootCode[448]
Definition: fatfs.h:92
NTSTATUS InstallFatBootcodeToFloppy(IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1281
IN HANDLE IN HANDLE RootPartition
Definition: fsutil.h:75
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
#define wcsicmp
Definition: compat.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
#define DoesDirExist(RootDirectory, DirName)
Definition: filesup.h:74
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const WCHAR L[]
Definition: oid.c:1250
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)
NTSTATUS SetBootStoreOptions(IN PVOID Handle, IN PBOOT_STORE_OPTIONS BootOptions, IN ULONG FieldsToChange)
Definition: bldrsup.c:1196
#define GENERIC_READ
Definition: compat.h:135
NTSTATUS InstallMbrBootCodeToDisk(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PCWSTR DestinationDevicePathBuffer)
Definition: bootsup.c:764
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSTATUS FormatFileSystem(IN PCWSTR DriveRoot, IN PCWSTR FileSystemName, IN FMIFS_MEDIA_FLAG MediaFlag, IN PCWSTR Label, IN BOOLEAN QuickFormat, IN ULONG ClusterSize, IN PFMIFSCALLBACK Callback)
Definition: fsutil.c:349
NTSTATUS OpenBootStore(OUT PVOID *Handle, IN PCWSTR SystemPartition, IN BOOT_STORE_TYPE Type, IN BOOLEAN CreateNew)
Definition: bldrsup.c:815
NTSTATUS ReadBootCodeByHandle(IN OUT PBOOTCODE BootCodeInfo, IN HANDLE FileHandle, IN ULONG Length OPTIONAL)
Definition: bootcode.c:21
VOID FreeBootCode(IN OUT PBOOTCODE BootCodeInfo)
Definition: bootcode.c:104
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
static NTSTATUS InstallBootCodeToFile(IN PCWSTR SrcPath, IN PCWSTR DstPath, IN PCWSTR RootPath, IN PFS_INSTALL_BOOTCODE InstallBootCode)
Definition: bootsup.c:621
enum _BOOT_STORE_TYPE BOOT_STORE_TYPE
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
static NTSTATUS NTAPI EnumerateReactOSEntries(IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
Definition: bootsup.c:249
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
NTSTATUS InstallFat32BootCode(IN PCWSTR SrcPath, IN HANDLE DstPath, IN HANDLE RootPartition)
Definition: fsutil.c:437
#define DPRINT1
Definition: precomp.h:8
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
struct _NTOS_OPTIONS * PNTOS_OPTIONS
#define OUT
Definition: typedefs.h:40
struct _BOOT_SECTOR_OPTIONS * PBOOT_SECTOR_OPTIONS
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
unsigned int ULONG
Definition: retypes.h:1
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS InstallVBRToPartition(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath, IN PCWSTR FileSystemName)
Definition: bootsup.c:1233
#define DPRINT
Definition: sndvol32.h:71
#define SECTORSIZE
Definition: bootcode.h:13
static const WCHAR Signature[]
Definition: parser.c:141
struct _ENUM_REACTOS_ENTRIES_DATA ENUM_REACTOS_ENTRIES_DATA
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:681
static NTSTATUS InstallBtrfsBootcodeToPartition(IN PUNICODE_STRING SystemRootPath, IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING DestinationArcPath)
Definition: bootsup.c:1130
unsigned short * PUSHORT
Definition: retypes.h:2
Definition: bldrsup.h:62
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
static NTSTATUS UpdateFreeLoaderIni(IN PCWSTR IniPath, IN PCWSTR ArcPath)
Definition: bootsup.c:329
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define InstallFat16BootCode
Definition: fsutil.h:85
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68