ReactOS  0.4.15-dev-3326-ga91f5e8
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 (VBox Debug)\"";
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  /* DefaultOS=ReactOS */
130 #if DBG && !defined(_WINKD_)
131  if (IsUnattendedSetup)
132  {
133  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
134  }
135  else
136 #endif
137  {
138 #if DBG
139  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
140 #else
141  BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS");
142 #endif
143  }
144 
145 #if DBG
146  if (IsUnattendedSetup)
147 #endif
148  {
149  /* Timeout=0 for unattended or non debug */
150  BootOptions.Timeout = 0;
151  }
152 #if DBG
153  else
154  {
155  /* Timeout=10 */
156  BootOptions.Timeout = 10;
157  }
158 #endif
159 
160  BootOptions.Version = FreeLdr;
161  SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1);
162 }
163 
164 static NTSTATUS
166  IN PCWSTR IniPath,
167  IN PCWSTR ArcPath)
168 {
170  PVOID BootStoreHandle;
171 
172  /* Initialize the INI file and create the common FreeLdr sections */
173  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
174  if (!NT_SUCCESS(Status))
175  return Status;
176 
177  /* Add the ReactOS entries */
178  CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
179 
180  /* Close the INI file */
181  CloseBootStore(BootStoreHandle);
182  return STATUS_SUCCESS;
183 }
184 
185 static NTSTATUS
187  IN PCWSTR IniPath,
188  IN PCWSTR ArcPath,
189  IN PCWSTR Section,
191  IN PCWSTR BootDrive,
192  IN PCWSTR BootPartition,
194 {
196  PVOID BootStoreHandle;
197  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)];
198  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
199  PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
200 
201  /* Initialize the INI file and create the common FreeLdr sections */
202  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
203  if (!NT_SUCCESS(Status))
204  return Status;
205 
206  /* Add the ReactOS entries */
207  CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
208 
209  BootEntry->Version = FreeLdr;
210  BootEntry->BootFilePath = NULL;
211 
212  BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
213  RtlCopyMemory(Options->Signature,
216 
217  Options->Drive = BootDrive;
218  Options->Partition = BootPartition;
219  Options->BootSectorFileName = BootSector;
220 
221  // BootEntry->BootEntryKey = MAKESTRKEY(Section);
222  BootEntry->FriendlyName = Description;
223  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
224 
225  /* Close the INI file */
226  CloseBootStore(BootStoreHandle);
227  return STATUS_SUCCESS;
228 }
229 
230 //
231 // I think this function can be generalizable as:
232 // "find the corresponding 'ReactOS' boot entry in this loader config file
233 // (here abstraction comes there), and if none, add a new one".
234 //
235 
237 {
244 
245 // PENUM_BOOT_ENTRIES_ROUTINE
246 static NTSTATUS
247 NTAPI
250  IN PBOOT_STORE_ENTRY BootEntry,
252 {
255  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
256  WCHAR SystemPath[MAX_PATH];
257 
258  /* We have a boot entry */
259 
260  /* Check for supported boot type "Windows2003" */
261  if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
262  RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
266  {
267  /* This is not a ReactOS entry */
268  // DPRINT(" An installation '%S' of unsupported type '%S'\n",
269  // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
270  DPRINT(" An installation '%S' of unsupported type %lu\n",
271  BootEntry->FriendlyName, BootEntry->OsOptionsLength);
272  /* Continue the enumeration */
273  goto SkipThisEntry;
274  }
275 
276  /* BootType is Windows2003, now check OsLoadPath */
277  if (!Options->OsLoadPath || !*Options->OsLoadPath)
278  {
279  /* Certainly not a ReactOS installation */
280  DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
281  /* Continue the enumeration */
282  goto SkipThisEntry;
283  }
284 
285  if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
286  {
287  /* Not found, retry with a quoted path */
288  Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
289  if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
290  {
291  /*
292  * This entry is a ReactOS entry, but the SystemRoot
293  * does not match the one we are looking for.
294  */
295  /* Continue the enumeration */
296  goto SkipThisEntry;
297  }
298  }
299 
300  DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
301  BootEntry->FriendlyName, Options->OsLoadPath);
302  // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
303  // BootEntry->FriendlyName, Options->OsLoadPath);
304 
305  DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
306 
307  Data->UseExistingEntry = TRUE;
308  RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
309 
310  /* We have found our entry, stop the enumeration now! */
311  return STATUS_NO_MORE_ENTRIES;
312 
313 SkipThisEntry:
314  Data->UseExistingEntry = FALSE;
315  if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
316  {
317  RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
318  L"ReactOS_%lu", Data->i);
319  RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
320  L"\"ReactOS %lu\"", Data->i);
321  Data->i++;
322  }
323  return STATUS_SUCCESS;
324 }
325 
326 static
327 NTSTATUS
329  IN PCWSTR IniPath,
330  IN PCWSTR ArcPath)
331 {
333  PVOID BootStoreHandle;
335  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
336  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
337  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
338 
339  /* Open the INI file */
340  Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE);
341  if (!NT_SUCCESS(Status))
342  return Status;
343 
344  /* Find an existing usable or an unused section name */
345  Data.UseExistingEntry = TRUE;
346  Data.i = 1;
347  Data.ArcPath = ArcPath;
348  RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
349  RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
350 
351  //
352  // FIXME: We temporarily use EnumerateBootStoreEntries, until
353  // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
354  //
356 
357  /* Create a new "ReactOS" entry if there is none already existing that suits us */
358  if (!Data.UseExistingEntry)
359  {
360  // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
361  // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
362 
363  BootEntry->Version = FreeLdr;
364  BootEntry->BootFilePath = NULL;
365 
366  BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
367  RtlCopyMemory(Options->Signature,
370 
371  Options->OsLoadPath = ArcPath;
372 
373  // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
374  BootEntry->FriendlyName = Data.OsName;
375  Options->OsLoadOptions = NULL; // L"";
376  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
377  }
378 
379  /* Close the INI file */
380  CloseBootStore(BootStoreHandle);
381  return STATUS_SUCCESS;
382 }
383 
384 static
385 NTSTATUS
387  IN PCWSTR IniPath,
388  IN PCWSTR EntryName, // ~= ArcPath
389  IN PCWSTR EntryValue)
390 {
392  PVOID BootStoreHandle;
394 
395  // NOTE: Technically it would be "BootSector"...
396  UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
397  PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
398  PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
399 
400  /* Open the INI file */
401  Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE);
402  if (!NT_SUCCESS(Status))
403  return Status;
404 
405  /* Find an existing usable or an unused section name */
406  Data.UseExistingEntry = TRUE;
407  // Data.i = 1;
408  Data.ArcPath = EntryName;
409  // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
410  RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
411 
412  //
413  // FIXME: We temporarily use EnumerateBootStoreEntries, until
414  // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
415  //
417 
418  /* If either the key was not found, or contains something else, add a new one */
419  if (!Data.UseExistingEntry /* ||
420  ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
421  {
422  BootEntry->Version = NtLdr;
423  BootEntry->BootFilePath = NULL;
424 
425  BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
426  RtlCopyMemory(Options->Signature,
429 
430  Options->OsLoadPath = EntryName;
431 
432  // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
433  // BootEntry->FriendlyName = Data.OsName;
434  BootEntry->FriendlyName = EntryValue;
435  Options->OsLoadOptions = NULL; // L"";
436  AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
437  }
438 
439  /* Close the INI file */
440  CloseBootStore(BootStoreHandle);
441  return STATUS_SUCCESS; // Status;
442 }
443 
444 
445 static
446 BOOLEAN
448  IN PCWSTR RootPath)
449 {
450  /*
451  * We first demand that the bootsector has a valid signature at its end.
452  * We then check the first 3 bytes (as a ULONG) of the bootsector for a
453  * potential "valid" instruction (the BIOS starts execution of the bootsector
454  * at its beginning). Currently this criterium is that this ULONG must be
455  * non-zero. If both these tests pass, then the bootsector is valid; otherwise
456  * it is invalid and certainly needs to be overwritten.
457  */
458 
459  BOOLEAN IsValid = FALSE;
462  BOOTCODE BootSector = {0};
463 
464  /* Allocate and read the root partition bootsector.
465  * Remove any trailing backslash if needed. */
469  if (!NT_SUCCESS(Status))
470  return FALSE;
471 
472  /* Check for the existence of the bootsector signature */
473  IsValid = (*(PUSHORT)((PUCHAR)BootSector.BootCode + 0x1FE) == 0xAA55);
474  if (IsValid)
475  {
476  /* Check for the first instruction encoded on three bytes */
477  IsValid = (((*(PULONG)BootSector.BootCode) & 0x00FFFFFF) != 0x00000000);
478  }
479 
480  /* Free the bootsector and return */
482  return IsValid;
483 }
484 
485 static
486 NTSTATUS
488  IN PCWSTR RootPath,
489  IN PCWSTR DstPath,
490  IN ULONG Length)
491 {
497  // LARGE_INTEGER FileOffset;
498  BOOTCODE BootSector = {0};
499 
500  /* Allocate and read the root partition bootsector.
501  * Remove any trailing backslash if needed. */
502  RtlInitUnicodeString(&Name, RootPath);
505  if (!NT_SUCCESS(Status))
506  return Status;
507 
508  /* Write the bootsector to DstPath */
511  &Name,
513  NULL,
514  NULL);
515 
519  &IoStatusBlock,
520  NULL,
522  0,
525  NULL,
526  0);
527  if (!NT_SUCCESS(Status))
528  {
530  return Status;
531  }
532 
534  NULL,
535  NULL,
536  NULL,
537  &IoStatusBlock,
539  BootSector.Length,
540  NULL,
541  NULL);
543 
544  /* Free the bootsector and return */
546  return Status;
547 }
548 
549 
550 static
551 NTSTATUS
553  IN PCWSTR SrcPath,
554  IN PCWSTR RootPath,
555  IN PFS_INSTALL_BOOTCODE InstallBootCode)
556 {
557  NTSTATUS Status, LockStatus;
561  HANDLE PartitionHandle;
562 
563  /*
564  * Open the root partition from which the bootcode (MBR, VBR) parameters
565  * will be obtained; this is also where we will write the updated bootcode.
566  * Remove any trailing backslash if needed.
567  */
568  RtlInitUnicodeString(&Name, RootPath);
570 
572  &Name,
574  NULL,
575  NULL);
576 
577  Status = NtOpenFile(&PartitionHandle,
580  &IoStatusBlock,
582  FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
583  if (!NT_SUCCESS(Status))
584  return Status;
585 
586  /* Lock the volume */
587  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
588  if (!NT_SUCCESS(LockStatus))
589  {
590  DPRINT1("Unable to lock the volume before installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
591  }
592 
593  /* Install the bootcode (MBR, VBR) */
594  Status = InstallBootCode(SrcPath, PartitionHandle, PartitionHandle);
595 
596  /* dismount & Unlock the volume */
597  if (NT_SUCCESS(LockStatus))
598  {
599  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
600  if (!NT_SUCCESS(LockStatus))
601  {
602  DPRINT1("Unable to dismount the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
603  }
604 
605  LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
606  if (!NT_SUCCESS(LockStatus))
607  {
608  DPRINT1("Unable to unlock the volume after installing boot code. Status 0x%08x. Expect problems.\n", LockStatus);
609  }
610  }
611 
612  /* Close the partition */
613  NtClose(PartitionHandle);
614 
615  return Status;
616 }
617 
618 static
619 NTSTATUS
621  IN PCWSTR SrcPath,
622  IN PCWSTR DstPath,
623  IN PCWSTR RootPath,
624  IN PFS_INSTALL_BOOTCODE InstallBootCode)
625 {
630  HANDLE PartitionHandle, FileHandle;
631 
632  /*
633  * Open the root partition from which the bootcode (MBR, VBR)
634  * parameters will be obtained.
635  *
636  * FIXME? It might be possible that we need to also open it for writing
637  * access in case we really need to still write the second portion of
638  * the boot sector ????
639  *
640  * Remove any trailing backslash if needed.
641  */
642  RtlInitUnicodeString(&Name, RootPath);
644 
646  &Name,
648  NULL,
649  NULL);
650 
651  Status = NtOpenFile(&PartitionHandle,
654  &IoStatusBlock,
656  FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
657  if (!NT_SUCCESS(Status))
658  return Status;
659 
660  /* Open or create the file where the new bootsector will be saved */
663  &Name,
665  NULL,
666  NULL);
667 
671  &IoStatusBlock,
672  NULL,
674  0,
675  FILE_SUPERSEDE, // FILE_OVERWRITE_IF
677  NULL,
678  0);
679  if (!NT_SUCCESS(Status))
680  {
681  DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
682  NtClose(PartitionHandle);
683  return Status;
684  }
685 
686  /* Install the bootcode (MBR, VBR) */
687  Status = InstallBootCode(SrcPath, FileHandle, PartitionHandle);
688 
689  /* Close the file and the partition */
691  NtClose(PartitionHandle);
692 
693  return Status;
694 }
695 
696 
697 static
698 NTSTATUS
700  IN PCWSTR SrcPath, // MBR source file (on the installation medium)
701  IN HANDLE DstPath, // Where to save the bootsector built from the source + disk information
702  IN HANDLE DiskHandle) // Disk holding the (old) MBR information
703 {
708  BOOTCODE OrigBootSector = {0};
709  BOOTCODE NewBootSector = {0};
710 
712 
713  /* Allocate and read the current original MBR bootsector */
714  Status = ReadBootCodeByHandle(&OrigBootSector,
715  DiskHandle,
716  sizeof(PARTITION_SECTOR));
717  if (!NT_SUCCESS(Status))
718  return Status;
719 
720  /* Allocate and read the new bootsector from SrcPath */
721  RtlInitUnicodeString(&Name, SrcPath);
722  Status = ReadBootCodeFromFile(&NewBootSector,
723  &Name,
724  sizeof(PARTITION_SECTOR));
725  if (!NT_SUCCESS(Status))
726  {
727  FreeBootCode(&OrigBootSector);
728  return Status;
729  }
730 
731  /*
732  * Copy the disk signature, the reserved fields and
733  * the partition table from the old MBR to the new one.
734  */
735  RtlCopyMemory(&((PPARTITION_SECTOR)NewBootSector.BootCode)->Signature,
736  &((PPARTITION_SECTOR)OrigBootSector.BootCode)->Signature,
737  sizeof(PARTITION_SECTOR) -
739  /* Length of partition table */);
740 
741  /* Free the original bootsector */
742  FreeBootCode(&OrigBootSector);
743 
744  /* Write the new bootsector to DstPath */
745  FileOffset.QuadPart = 0ULL;
747  NULL,
748  NULL,
749  NULL,
750  &IoStatusBlock,
751  NewBootSector.BootCode,
752  NewBootSector.Length,
753  &FileOffset,
754  NULL);
755 
756  /* Free the new bootsector */
757  FreeBootCode(&NewBootSector);
758 
759  return Status;
760 }
761 
762 NTSTATUS
764  IN PUNICODE_STRING SystemRootPath,
765  IN PUNICODE_STRING SourceRootPath,
766  IN PCWSTR DestinationDevicePathBuffer)
767 {
769  WCHAR SourceMbrPathBuffer[MAX_PATH];
771 
772 #if 0
773  /*
774  * The DestinationDevicePathBuffer parameter has been built with
775  * the following instruction by the caller; I'm not yet sure whether
776  * I actually want this function to build the path instead, hence
777  * I keep this code here but disabled for now...
778  */
779  WCHAR DestinationDevicePathBuffer[MAX_PATH];
780  RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
781  L"\\Device\\Harddisk%d\\Partition0",
782  DiskNumber);
783 #endif
784 
785  CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2,
786  SourceRootPath->Buffer, L"\\loader\\dosmbr.bin");
787 
788  if (IsThereAValidBootSector(DestinationDevicePathBuffer))
789  {
790  /* Save current MBR */
792  SystemRootPath->Buffer, L"mbr.old");
793 
794  DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
795  Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
796  if (!NT_SUCCESS(Status))
797  {
798  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
799  // Don't care if we succeeded or not saving the old MBR, just go ahead.
800  }
801  }
802 
803  DPRINT1("Install MBR bootcode: %S ==> %S\n",
804  SourceMbrPathBuffer, DestinationDevicePathBuffer);
805 
806  /* Install the MBR */
807  return InstallBootCodeToDisk(SourceMbrPathBuffer,
808  DestinationDevicePathBuffer,
810 }
811 
812 
813 static
814 NTSTATUS
816  IN PUNICODE_STRING SystemRootPath,
817  IN PUNICODE_STRING SourceRootPath,
818  IN PUNICODE_STRING DestinationArcPath,
819  IN PCWSTR FileSystemName)
820 {
822  BOOLEAN DoesFreeLdrExist;
823  WCHAR SrcPath[MAX_PATH];
825 
826  /* FAT or FAT32 partition */
827  DPRINT("System path: '%wZ'\n", SystemRootPath);
828 
829  /* Copy FreeLoader to the system partition, always overwriting the older version */
830  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
831  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
832 
833  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
834  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
835  if (!NT_SUCCESS(Status))
836  {
837  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
838  return Status;
839  }
840 
841  /* Prepare for possibly updating 'freeldr.ini' */
842  DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
843  if (DoesFreeLdrExist)
844  {
845  /* Update existing 'freeldr.ini' */
846  DPRINT1("Update existing 'freeldr.ini'\n");
847  Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
848  if (!NT_SUCCESS(Status))
849  {
850  DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
851  return Status;
852  }
853  }
854 
855  /* Check for NT and other bootloaders */
856 
857  // FIXME: Check for Vista+ bootloader!
858  /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
859  /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
860  if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
861  DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
862  {
863  /* Search root directory for 'NTLDR' and 'BOOT.INI' */
864  DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
865 
866  /* Create or update 'freeldr.ini' */
867  if (DoesFreeLdrExist == FALSE)
868  {
869  /* Create new 'freeldr.ini' */
870  DPRINT1("Create new 'freeldr.ini'\n");
871  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
872  if (!NT_SUCCESS(Status))
873  {
874  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
875  return Status;
876  }
877 
878  /* Install new bootcode into a file */
879  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
880 
881  if (wcsicmp(FileSystemName, L"FAT32") == 0)
882  {
883  /* Install FAT32 bootcode */
884  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
885 
886  DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
888  SystemRootPath->Buffer,
890  if (!NT_SUCCESS(Status))
891  {
892  DPRINT1("InstallBootCodeToFile(FAT32) failed (Status %lx)\n", Status);
893  return Status;
894  }
895  }
896  else // if (wcsicmp(FileSystemName, L"FAT") == 0)
897  {
898  /* Install FAT16 bootcode */
899  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
900 
901  DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, DstPath);
903  SystemRootPath->Buffer,
905  if (!NT_SUCCESS(Status))
906  {
907  DPRINT1("InstallBootCodeToFile(FAT16) failed (Status %lx)\n", Status);
908  return Status;
909  }
910  }
911  }
912 
913  /* Update 'boot.ini' */
914  /* Windows' NTLDR loads an external bootsector file when the specified drive
915  letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
916  DPRINT1("Update 'boot.ini'\n");
917  Status = UpdateBootIni(SystemRootPath->Buffer,
918  L"C:\\bootsect.ros",
919  L"\"ReactOS\"");
920  if (!NT_SUCCESS(Status))
921  {
922  DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
923  return Status;
924  }
925  }
926  else
927  {
928  /* Non-NT bootloaders: install our own bootloader */
929 
930  PCWSTR Section;
932  PCWSTR BootDrive;
933  PCWSTR BootPartition;
935 
936  /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
937  if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
938  DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
939  {
940  DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
941 
942  Section = L"CPQDOS";
943  Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
944  BootDrive = L"hd0";
945  BootPartition = L"1";
946  BootSector = L"BOOTSECT.DOS";
947  }
948  else
949  /* Search for Microsoft DOS or Windows 9x boot loader */
950  if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
951  DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
952  // WINBOOT.SYS
953  {
954  DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
955 
956  Section = L"MSDOS";
957  Description = L"\"MS-DOS/Windows\"";
958  BootDrive = L"hd0";
959  BootPartition = L"1";
960  BootSector = L"BOOTSECT.DOS";
961  }
962  else
963  /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
964  if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
965  DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
966  DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
967  {
968  DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
969 
970  Section = L"IBMDOS";
971  Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
972  BootDrive = L"hd0";
973  BootPartition = L"1";
974  BootSector = L"BOOTSECT.DOS";
975  }
976  else
977  /* Search for DR-DOS 3.x boot loader */
978  if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
979  DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
980  {
981  DPRINT1("Found DR-DOS 3.x\n");
982 
983  Section = L"DRDOS";
984  Description = L"\"DR-DOS 3.x\"";
985  BootDrive = L"hd0";
986  BootPartition = L"1";
987  BootSector = L"BOOTSECT.DOS";
988  }
989  else
990  /* Search for Dell Real-Mode Kernel (DRMK) OS */
991  if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
992  DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
993  {
994  DPRINT1("Found Dell Real-Mode Kernel OS\n");
995 
996  Section = L"DRMK";
997  Description = L"\"Dell Real-Mode Kernel OS\"";
998  BootDrive = L"hd0";
999  BootPartition = L"1";
1000  BootSector = L"BOOTSECT.DOS";
1001  }
1002  else
1003  /* Search for MS OS/2 1.x */
1004  if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
1005  DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
1006  DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
1007  {
1008  DPRINT1("Found MS OS/2 1.x\n");
1009 
1010  Section = L"MSOS2";
1011  Description = L"\"MS OS/2 1.x\"";
1012  BootDrive = L"hd0";
1013  BootPartition = L"1";
1014  BootSector = L"BOOTSECT.OS2";
1015  }
1016  else
1017  /* Search for MS or IBM OS/2 */
1018  if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
1019  DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
1020  DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
1021  {
1022  DPRINT1("Found MS/IBM OS/2\n");
1023 
1024  Section = L"IBMOS2";
1025  Description = L"\"MS/IBM OS/2\"";
1026  BootDrive = L"hd0";
1027  BootPartition = L"1";
1028  BootSector = L"BOOTSECT.OS2";
1029  }
1030  else
1031  /* Search for FreeDOS boot loader */
1032  if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
1033  {
1034  DPRINT1("Found FreeDOS boot loader\n");
1035 
1036  Section = L"FDOS";
1037  Description = L"\"FreeDOS\"";
1038  BootDrive = L"hd0";
1039  BootPartition = L"1";
1040  BootSector = L"BOOTSECT.DOS";
1041  }
1042  else
1043  {
1044  /* No or unknown boot loader */
1045  DPRINT1("No or unknown boot loader found\n");
1046 
1047  Section = L"Unknown";
1048  Description = L"\"Unknown Operating System\"";
1049  BootDrive = L"hd0";
1050  BootPartition = L"1";
1051  BootSector = L"BOOTSECT.OLD";
1052  }
1053 
1054  /* Create or update 'freeldr.ini' */
1055  if (DoesFreeLdrExist == FALSE)
1056  {
1057  /* Create new 'freeldr.ini' */
1058  DPRINT1("Create new 'freeldr.ini'\n");
1059 
1060  if (IsThereAValidBootSector(SystemRootPath->Buffer))
1061  {
1063  SystemRootPath->Buffer, DestinationArcPath->Buffer,
1064  Section, Description,
1065  BootDrive, BootPartition, BootSector);
1066  if (!NT_SUCCESS(Status))
1067  {
1068  DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1069  return Status;
1070  }
1071 
1072  /* Save current bootsector */
1073  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1074 
1075  DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1076  Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
1077  if (!NT_SUCCESS(Status))
1078  {
1079  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1080  return Status;
1081  }
1082  }
1083  else
1084  {
1085  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1086  if (!NT_SUCCESS(Status))
1087  {
1088  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1089  return Status;
1090  }
1091  }
1092 
1093  /* Install new bootsector on the disk */
1094  if (wcsicmp(FileSystemName, L"FAT32") == 0)
1095  {
1096  /* Install FAT32 bootcode */
1097  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1098 
1099  DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1100  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat32BootCode);
1101  DPRINT1("Status: 0x%08X\n", Status);
1102  if (!NT_SUCCESS(Status))
1103  {
1104  DPRINT1("InstallBootCodeToDisk(FAT32) failed (Status %lx)\n", Status);
1105  return Status;
1106  }
1107  }
1108  else // if (wcsicmp(FileSystemName, L"FAT") == 0)
1109  {
1110  /* Install FAT16 bootcode */
1111  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1112 
1113  DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1114  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallFat16BootCode);
1115  if (!NT_SUCCESS(Status))
1116  {
1117  DPRINT1("InstallBootCodeToDisk(FAT16) failed (Status %lx)\n", Status);
1118  return Status;
1119  }
1120  }
1121  }
1122  }
1123 
1124  return STATUS_SUCCESS;
1125 }
1126 
1127 static
1128 NTSTATUS
1130  IN PUNICODE_STRING SystemRootPath,
1131  IN PUNICODE_STRING SourceRootPath,
1132  IN PUNICODE_STRING DestinationArcPath)
1133 {
1134  NTSTATUS Status;
1135  BOOLEAN DoesFreeLdrExist;
1136  WCHAR SrcPath[MAX_PATH];
1138 
1139  /* BTRFS partition */
1140  DPRINT("System path: '%wZ'\n", SystemRootPath);
1141 
1142  /* Copy FreeLoader to the system partition, always overwriting the older version */
1143  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1144  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
1145 
1146  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1147  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1148  if (!NT_SUCCESS(Status))
1149  {
1150  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1151  return Status;
1152  }
1153 
1154  /* Prepare for possibly updating 'freeldr.ini' */
1155  DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1156  if (DoesFreeLdrExist)
1157  {
1158  /* Update existing 'freeldr.ini' */
1159  DPRINT1("Update existing 'freeldr.ini'\n");
1160  Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1161  if (!NT_SUCCESS(Status))
1162  {
1163  DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1164  return Status;
1165  }
1166  }
1167 
1168  /* Check for *nix bootloaders */
1169 
1170  /* Create or update 'freeldr.ini' */
1171  if (DoesFreeLdrExist == FALSE)
1172  {
1173  /* Create new 'freeldr.ini' */
1174  DPRINT1("Create new 'freeldr.ini'\n");
1175 
1176  /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
1177  DPRINT1("*nix or unknown boot loader found\n");
1178 
1179  if (IsThereAValidBootSector(SystemRootPath->Buffer))
1180  {
1181  PCWSTR BootSector = L"BOOTSECT.OLD";
1182 
1184  SystemRootPath->Buffer, DestinationArcPath->Buffer,
1185  L"Linux", L"\"Linux\"",
1186  L"hd0", L"1", BootSector);
1187  if (!NT_SUCCESS(Status))
1188  {
1189  DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
1190  return Status;
1191  }
1192 
1193  /* Save current bootsector */
1194  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
1195 
1196  DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
1197  Status = SaveBootSector(SystemRootPath->Buffer, DstPath, BTRFS_BOOTSECTOR_SIZE);
1198  if (!NT_SUCCESS(Status))
1199  {
1200  DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
1201  return Status;
1202  }
1203  }
1204  else
1205  {
1206  Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1207  if (!NT_SUCCESS(Status))
1208  {
1209  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1210  return Status;
1211  }
1212  }
1213 
1214  /* Install new bootsector on the disk */
1215  /* Install BTRFS bootcode */
1216  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
1217 
1218  DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1219  Status = InstallBootCodeToDisk(SrcPath, SystemRootPath->Buffer, InstallBtrfsBootCode);
1220  if (!NT_SUCCESS(Status))
1221  {
1222  DPRINT1("InstallBootCodeToDisk(BTRFS) failed (Status %lx)\n", Status);
1223  return Status;
1224  }
1225  }
1226 
1227  return STATUS_SUCCESS;
1228 }
1229 
1230 
1231 NTSTATUS
1233  IN PUNICODE_STRING SystemRootPath,
1234  IN PUNICODE_STRING SourceRootPath,
1235  IN PUNICODE_STRING DestinationArcPath,
1236  IN PCWSTR FileSystemName)
1237 {
1238  if (wcsicmp(FileSystemName, L"FAT") == 0 ||
1239  wcsicmp(FileSystemName, L"FAT32") == 0)
1240  {
1241  return InstallFatBootcodeToPartition(SystemRootPath,
1242  SourceRootPath,
1243  DestinationArcPath,
1244  FileSystemName);
1245  }
1246  /*
1247  else if (wcsicmp(FileSystemName, L"NTFS") == 0)
1248  {
1249  DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
1250  return STATUS_NOT_SUPPORTED;
1251  }
1252  */
1253  else if (wcsicmp(FileSystemName, L"BTRFS") == 0)
1254  {
1255  return InstallBtrfsBootcodeToPartition(SystemRootPath,
1256  SourceRootPath,
1257  DestinationArcPath);
1258  }
1259  /*
1260  else if (wcsicmp(FileSystemName, L"EXT2") == 0 ||
1261  wcsicmp(FileSystemName, L"EXT3") == 0 ||
1262  wcsicmp(FileSystemName, L"EXT4") == 0)
1263  {
1264  return STATUS_NOT_SUPPORTED;
1265  }
1266  */
1267  else
1268  {
1269  /* Unknown file system */
1270  DPRINT1("Unknown file system '%S'\n", FileSystemName);
1271  }
1272 
1273  return STATUS_NOT_SUPPORTED;
1274 }
1275 
1276 
1277 NTSTATUS
1279  IN PUNICODE_STRING SourceRootPath,
1280  IN PUNICODE_STRING DestinationArcPath)
1281 {
1282  static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\";
1283 
1284  NTSTATUS Status;
1285  WCHAR SrcPath[MAX_PATH];
1287 
1288  /* Verify that the floppy disk is accessible */
1290  return STATUS_DEVICE_NOT_READY;
1291 
1292  /* Format the floppy disk */
1293  // FormatPartition(...)
1295  L"FAT",
1296  FMIFS_FLOPPY,
1297  NULL,
1298  TRUE,
1299  0,
1300  NULL);
1301  if (!NT_SUCCESS(Status))
1302  {
1304  DPRINT1("FAT FS non existent on this system?!\n");
1305  else
1306  DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
1307 
1308  return Status;
1309  }
1310 
1311  /* Copy FreeLoader to the boot partition */
1312  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1313  CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice, L"freeldr.sys");
1314 
1315  DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1316  Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1317  if (!NT_SUCCESS(Status))
1318  {
1319  DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1320  return Status;
1321  }
1322 
1323  /* Create new 'freeldr.ini' */
1324  DPRINT("Create new 'freeldr.ini'\n");
1325  Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer);
1326  if (!NT_SUCCESS(Status))
1327  {
1328  DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1329  return Status;
1330  }
1331 
1332  /* Install FAT12 boosector */
1333  CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1335 
1336  DPRINT("Install FAT12 bootcode: %S ==> %S\n", SrcPath, DstPath);
1338  if (!NT_SUCCESS(Status))
1339  {
1340  DPRINT1("InstallBootCodeToDisk(FAT12) failed (Status %lx)\n", Status);
1341  return Status;
1342  }
1343 
1344  return STATUS_SUCCESS;
1345 }
1346 
1347 /* 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:552
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:815
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:699
_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:556
NTSTATUS CloseBootStore(IN PVOID Handle)
Definition: bldrsup.c:827
static NTSTATUS SaveBootSector(IN PCWSTR RootPath, IN PCWSTR DstPath, IN ULONG Length)
Definition: bootsup.c:487
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:165
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:186
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:447
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:386
#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:1278
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:763
#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:347
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:620
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:248
_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:435
#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:1232
#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:1129
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:328
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define InstallFat16BootCode
Definition: fsutil.h:85
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68