3d494c949ad6e51458a9e0e6f136cdf5357347a5
[reactos.git] / base / setup / lib / bootsup.c
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 "fsutil.h"
17 #include "partlist.h"
18
19 #include "setuplib.h" // HAXX for IsUnattendedSetup!!
20
21 #include "bootsup.h"
22
23 #define NDEBUG
24 #include <debug.h>
25
26
27 /* TYPEDEFS *****************************************************************/
28
29 /*
30 * BIG FIXME!!
31 * ===========
32 *
33 * All that stuff *MUST* go into the fsutil.c module.
34 * Indeed, all that relates to filesystem formatting details and as such
35 * *MUST* be abstracted out from this module (bootsup.c).
36 * However, bootsup.c can still deal with MBR code (actually it'll have
37 * at some point to share or give it to partlist.c, because when we'll
38 * support GPT disks, things will change a bit).
39 * And, bootsup.c can still manage initializing / adding boot entries
40 * into NTLDR and FREELDR, and installing the latter, and saving the old
41 * MBR / boot sectors in files.
42 */
43 #define SECTORSIZE 512
44
45 #include <pshpack1.h>
46 typedef struct _FAT_BOOTSECTOR
47 {
48 UCHAR JumpBoot[3]; // Jump instruction to boot code
49 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
50 USHORT BytesPerSector; // Bytes per sector
51 UCHAR SectorsPerCluster; // Number of sectors in a cluster
52 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
53 UCHAR NumberOfFats; // Number of FAT tables
54 USHORT RootDirEntries; // Number of root directory entries (fat12/16)
55 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
56 UCHAR MediaDescriptor; // Media descriptor byte
57 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
58 USHORT SectorsPerTrack; // Number of sectors in a track
59 USHORT NumberOfHeads; // Number of heads on the disk
60 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
61 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
62 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
63 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
64 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
65 ULONG VolumeSerialNumber; // Volume serial number
66 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
67 CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
68
69 UCHAR BootCodeAndData[448]; // The remainder of the boot sector
70
71 USHORT BootSectorMagic; // 0xAA55
72
73 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
74
75 typedef struct _FAT32_BOOTSECTOR
76 {
77 UCHAR JumpBoot[3]; // Jump instruction to boot code
78 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
79 USHORT BytesPerSector; // Bytes per sector
80 UCHAR SectorsPerCluster; // Number of sectors in a cluster
81 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
82 UCHAR NumberOfFats; // Number of FAT tables
83 USHORT RootDirEntries; // Number of root directory entries (fat12/16)
84 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
85 UCHAR MediaDescriptor; // Media descriptor byte
86 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
87 USHORT SectorsPerTrack; // Number of sectors in a track
88 USHORT NumberOfHeads; // Number of heads on the disk
89 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
90 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
91 ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
92 USHORT ExtendedFlags; // Extended flags (fat32)
93 USHORT FileSystemVersion; // File system version (fat32)
94 ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32)
95 USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
96 USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
97 UCHAR Reserved[12]; // Reserved for future expansion
98 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
99 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
100 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
101 ULONG VolumeSerialNumber; // Volume serial number
102 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
103 CHAR FileSystemType[8]; // Always set to the string "FAT32 "
104
105 UCHAR BootCodeAndData[420]; // The remainder of the boot sector
106
107 USHORT BootSectorMagic; // 0xAA55
108
109 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
110
111 typedef struct _BTRFS_BOOTSECTOR
112 {
113 UCHAR JumpBoot[3];
114 UCHAR ChunkMapSize;
115 UCHAR BootDrive;
116 ULONGLONG PartitionStartLBA;
117 UCHAR Fill[1521]; // 1536 - 15
118 USHORT BootSectorMagic;
119 } BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
120 C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == 3 * 512);
121
122 // TODO: Add more bootsector structures!
123
124 #include <poppack.h>
125
126 /* End of BIG FIXME!! */
127
128
129 /* FUNCTIONS ****************************************************************/
130
131 static VOID
132 TrimTrailingPathSeparators_UStr(
133 IN OUT PUNICODE_STRING UnicodeString)
134 {
135 while (UnicodeString->Length >= sizeof(WCHAR) &&
136 UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
137 {
138 UnicodeString->Length -= sizeof(WCHAR);
139 }
140 }
141
142
143 static VOID
144 CreateFreeLoaderReactOSEntries(
145 IN PVOID BootStoreHandle,
146 IN PCWSTR ArcPath)
147 {
148 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
149 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
150 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
151 BOOT_STORE_OPTIONS BootOptions;
152
153 BootEntry->Version = FreeLdr;
154 BootEntry->BootFilePath = NULL;
155
156 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
157 RtlCopyMemory(Options->Signature,
158 NTOS_OPTIONS_SIGNATURE,
159 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
160
161 Options->OsLoadPath = ArcPath;
162
163 /* ReactOS */
164 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS");
165 BootEntry->FriendlyName = L"\"ReactOS\"";
166 Options->OsLoadOptions = NULL; // L"";
167 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS"));
168
169 /* ReactOS_Debug */
170 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
171 BootEntry->FriendlyName = L"\"ReactOS (Debug)\"";
172 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS";
173 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug"));
174
175 #ifdef _WINKD_
176 /* ReactOS_VBoxDebug */
177 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug");
178 BootEntry->FriendlyName = L"\"ReactOS (VBoxDebug)\"";
179 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS";
180 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug"));
181 #endif
182 #if DBG
183 #ifndef _WINKD_
184 /* ReactOS_KdSerial */
185 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
186 BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\"";
187 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL";
188 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial"));
189 #endif
190
191 /* ReactOS_Screen */
192 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen");
193 BootEntry->FriendlyName = L"\"ReactOS (Screen)\"";
194 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS";
195 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen"));
196
197 /* ReactOS_LogFile */
198 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile");
199 BootEntry->FriendlyName = L"\"ReactOS (Log file)\"";
200 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS";
201 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile"));
202
203 /* ReactOS_Ram */
204 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram");
205 BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\"";
206 Options->OsLoadPath = L"ramdisk(0)\\ReactOS";
207 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256";
208 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram"));
209
210 /* ReactOS_EMS */
211 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS");
212 BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\"";
213 Options->OsLoadPath = ArcPath;
214 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200";
215 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS"));
216 #endif
217
218
219 #if DBG
220 if (IsUnattendedSetup)
221 {
222 /* DefaultOS=ReactOS */
223 #ifndef _WINKD_
224 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial");
225 #else
226 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug");
227 #endif
228 }
229 else
230 #endif
231 {
232 /* DefaultOS=ReactOS */
233 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS");
234 }
235
236 #if DBG
237 if (IsUnattendedSetup)
238 #endif
239 {
240 /* Timeout=0 for unattended or non debug */
241 BootOptions.Timeout = 0;
242 }
243 #if DBG
244 else
245 {
246 /* Timeout=10 */
247 BootOptions.Timeout = 10;
248 }
249 #endif
250
251 BootOptions.Version = FreeLdr;
252 SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1);
253 }
254
255 static NTSTATUS
256 CreateFreeLoaderIniForReactOS(
257 IN PCWSTR IniPath,
258 IN PCWSTR ArcPath)
259 {
260 NTSTATUS Status;
261 PVOID BootStoreHandle;
262
263 /* Initialize the INI file and create the common FreeLdr sections */
264 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
265 if (!NT_SUCCESS(Status))
266 return Status;
267
268 /* Add the ReactOS entries */
269 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
270
271 /* Close the INI file */
272 CloseBootStore(BootStoreHandle);
273 return STATUS_SUCCESS;
274 }
275
276 static NTSTATUS
277 CreateFreeLoaderIniForReactOSAndBootSector(
278 IN PCWSTR IniPath,
279 IN PCWSTR ArcPath,
280 IN PCWSTR Section,
281 IN PCWSTR Description,
282 IN PCWSTR BootDrive,
283 IN PCWSTR BootPartition,
284 IN PCWSTR BootSector)
285 {
286 NTSTATUS Status;
287 PVOID BootStoreHandle;
288 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)];
289 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
290 PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
291
292 /* Initialize the INI file and create the common FreeLdr sections */
293 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE);
294 if (!NT_SUCCESS(Status))
295 return Status;
296
297 /* Add the ReactOS entries */
298 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath);
299
300 BootEntry->Version = FreeLdr;
301 BootEntry->BootFilePath = NULL;
302
303 BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
304 RtlCopyMemory(Options->Signature,
305 BOOT_SECTOR_OPTIONS_SIGNATURE,
306 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature));
307
308 Options->Drive = BootDrive;
309 Options->Partition = BootPartition;
310 Options->BootSectorFileName = BootSector;
311
312 // BootEntry->BootEntryKey = MAKESTRKEY(Section);
313 BootEntry->FriendlyName = Description;
314 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section));
315
316 /* Close the INI file */
317 CloseBootStore(BootStoreHandle);
318 return STATUS_SUCCESS;
319 }
320
321 //
322 // I think this function can be generalizable as:
323 // "find the corresponding 'ReactOS' boot entry in this loader config file
324 // (here abstraction comes there), and if none, add a new one".
325 //
326
327 typedef struct _ENUM_REACTOS_ENTRIES_DATA
328 {
329 ULONG i;
330 BOOLEAN UseExistingEntry;
331 PCWSTR ArcPath;
332 WCHAR SectionName[80];
333 WCHAR OsName[80];
334 } ENUM_REACTOS_ENTRIES_DATA, *PENUM_REACTOS_ENTRIES_DATA;
335
336 // PENUM_BOOT_ENTRIES_ROUTINE
337 static NTSTATUS
338 NTAPI
339 EnumerateReactOSEntries(
340 IN BOOT_STORE_TYPE Type,
341 IN PBOOT_STORE_ENTRY BootEntry,
342 IN PVOID Parameter OPTIONAL)
343 {
344 NTSTATUS Status;
345 PENUM_REACTOS_ENTRIES_DATA Data = (PENUM_REACTOS_ENTRIES_DATA)Parameter;
346 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
347 WCHAR SystemPath[MAX_PATH];
348
349 /* We have a boot entry */
350
351 /* Check for supported boot type "Windows2003" */
352 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
353 RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
354 NTOS_OPTIONS_SIGNATURE,
355 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) !=
356 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature))
357 {
358 /* This is not a ReactOS entry */
359 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
360 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
361 DPRINT(" An installation '%S' of unsupported type %lu\n",
362 BootEntry->FriendlyName, BootEntry->OsOptionsLength);
363 /* Continue the enumeration */
364 goto SkipThisEntry;
365 }
366
367 /* BootType is Windows2003, now check OsLoadPath */
368 if (!Options->OsLoadPath || !*Options->OsLoadPath)
369 {
370 /* Certainly not a ReactOS installation */
371 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
372 /* Continue the enumeration */
373 goto SkipThisEntry;
374 }
375
376 if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0)
377 {
378 /* Not found, retry with a quoted path */
379 Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath);
380 if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0)
381 {
382 /*
383 * This entry is a ReactOS entry, but the SystemRoot
384 * does not match the one we are looking for.
385 */
386 /* Continue the enumeration */
387 goto SkipThisEntry;
388 }
389 }
390
391 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
392 BootEntry->FriendlyName, Options->OsLoadPath);
393 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
394 // BootEntry->FriendlyName, Options->OsLoadPath);
395
396 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath);
397
398 Data->UseExistingEntry = TRUE;
399 RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName);
400
401 /* We have found our entry, stop the enumeration now! */
402 return STATUS_NO_MORE_ENTRIES;
403
404 SkipThisEntry:
405 Data->UseExistingEntry = FALSE;
406 if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0)
407 {
408 RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName),
409 L"ReactOS_%lu", Data->i);
410 RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName),
411 L"\"ReactOS %lu\"", Data->i);
412 Data->i++;
413 }
414 return STATUS_SUCCESS;
415 }
416
417 static
418 NTSTATUS
419 UpdateFreeLoaderIni(
420 IN PCWSTR IniPath,
421 IN PCWSTR ArcPath)
422 {
423 NTSTATUS Status;
424 PVOID BootStoreHandle;
425 ENUM_REACTOS_ENTRIES_DATA Data;
426 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
427 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
428 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
429
430 /* Open the INI file */
431 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE);
432 if (!NT_SUCCESS(Status))
433 return Status;
434
435 /* Find an existing usable or an unused section name */
436 Data.UseExistingEntry = TRUE;
437 Data.i = 1;
438 Data.ArcPath = ArcPath;
439 RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
440 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
441
442 //
443 // FIXME: We temporarily use EnumerateBootStoreEntries, until
444 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
445 //
446 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
447
448 /* Create a new "ReactOS" entry if there is none already existing that suits us */
449 if (!Data.UseExistingEntry)
450 {
451 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i);
452 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i);
453
454 BootEntry->Version = FreeLdr;
455 BootEntry->BootFilePath = NULL;
456
457 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
458 RtlCopyMemory(Options->Signature,
459 NTOS_OPTIONS_SIGNATURE,
460 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
461
462 Options->OsLoadPath = ArcPath;
463
464 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
465 BootEntry->FriendlyName = Data.OsName;
466 Options->OsLoadOptions = NULL; // L"";
467 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName));
468 }
469
470 /* Close the INI file */
471 CloseBootStore(BootStoreHandle);
472 return STATUS_SUCCESS;
473 }
474
475 static
476 NTSTATUS
477 UpdateBootIni(
478 IN PCWSTR IniPath,
479 IN PCWSTR EntryName, // ~= ArcPath
480 IN PCWSTR EntryValue)
481 {
482 NTSTATUS Status;
483 PVOID BootStoreHandle;
484 ENUM_REACTOS_ENTRIES_DATA Data;
485
486 // NOTE: Technically it would be "BootSector"...
487 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)];
488 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
489 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
490
491 /* Open the INI file */
492 Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE);
493 if (!NT_SUCCESS(Status))
494 return Status;
495
496 /* Find an existing usable or an unused section name */
497 Data.UseExistingEntry = TRUE;
498 // Data.i = 1;
499 Data.ArcPath = EntryName;
500 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS");
501 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\"");
502
503 //
504 // FIXME: We temporarily use EnumerateBootStoreEntries, until
505 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented.
506 //
507 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data);
508
509 /* If either the key was not found, or contains something else, add a new one */
510 if (!Data.UseExistingEntry /* ||
511 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */)
512 {
513 BootEntry->Version = NtLdr;
514 BootEntry->BootFilePath = NULL;
515
516 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS);
517 RtlCopyMemory(Options->Signature,
518 NTOS_OPTIONS_SIGNATURE,
519 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature));
520
521 Options->OsLoadPath = EntryName;
522
523 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName);
524 // BootEntry->FriendlyName = Data.OsName;
525 BootEntry->FriendlyName = EntryValue;
526 Options->OsLoadOptions = NULL; // L"";
527 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/));
528 }
529
530 /* Close the INI file */
531 CloseBootStore(BootStoreHandle);
532 return STATUS_SUCCESS; // Status;
533 }
534
535
536 static
537 BOOLEAN
538 IsThereAValidBootSector(
539 IN PCWSTR RootPath)
540 {
541 /*
542 * We first demand that the bootsector has a valid signature at its end.
543 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
544 * potential "valid" instruction (the BIOS starts execution of the bootsector
545 * at its beginning). Currently this criterium is that this ULONG must be
546 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
547 * it is invalid and certainly needs to be overwritten.
548 */
549
550 BOOLEAN IsValid = FALSE;
551 NTSTATUS Status;
552 UNICODE_STRING RootPartition;
553 OBJECT_ATTRIBUTES ObjectAttributes;
554 IO_STATUS_BLOCK IoStatusBlock;
555 HANDLE FileHandle;
556 LARGE_INTEGER FileOffset;
557 PUCHAR BootSector;
558
559 /* Allocate buffer for bootsector */
560 BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
561 if (BootSector == NULL)
562 return FALSE; // STATUS_INSUFFICIENT_RESOURCES;
563 RtlZeroMemory(BootSector, SECTORSIZE);
564
565 /* Open the root partition - Remove any trailing backslash if needed */
566 RtlInitUnicodeString(&RootPartition, RootPath);
567 TrimTrailingPathSeparators_UStr(&RootPartition);
568
569 InitializeObjectAttributes(&ObjectAttributes,
570 &RootPartition,
571 OBJ_CASE_INSENSITIVE,
572 NULL,
573 NULL);
574
575 Status = NtOpenFile(&FileHandle,
576 GENERIC_READ | SYNCHRONIZE,
577 &ObjectAttributes,
578 &IoStatusBlock,
579 FILE_SHARE_READ | FILE_SHARE_WRITE,
580 FILE_SYNCHRONOUS_IO_NONALERT);
581 if (!NT_SUCCESS(Status))
582 goto Quit;
583
584 /* Read current boot sector into buffer */
585 FileOffset.QuadPart = 0ULL;
586 Status = NtReadFile(FileHandle,
587 NULL,
588 NULL,
589 NULL,
590 &IoStatusBlock,
591 BootSector,
592 SECTORSIZE,
593 &FileOffset,
594 NULL);
595 NtClose(FileHandle);
596 if (!NT_SUCCESS(Status))
597 goto Quit;
598
599 /* Check for the existence of the bootsector signature */
600 IsValid = (*(PUSHORT)(BootSector + 0x1FE) == 0xAA55);
601 if (IsValid)
602 {
603 /* Check for the first instruction encoded on three bytes */
604 IsValid = (((*(PULONG)BootSector) & 0x00FFFFFF) != 0x00000000);
605 }
606
607 Quit:
608 /* Free the boot sector */
609 RtlFreeHeap(ProcessHeap, 0, BootSector);
610 return IsValid;
611 }
612
613 static
614 NTSTATUS
615 SaveBootSector(
616 IN PCWSTR RootPath,
617 IN PCWSTR DstPath,
618 IN ULONG Length)
619 {
620 NTSTATUS Status;
621 UNICODE_STRING Name;
622 OBJECT_ATTRIBUTES ObjectAttributes;
623 IO_STATUS_BLOCK IoStatusBlock;
624 HANDLE FileHandle;
625 LARGE_INTEGER FileOffset;
626 PUCHAR BootSector;
627
628 /* Allocate buffer for bootsector */
629 BootSector = RtlAllocateHeap(ProcessHeap, 0, Length);
630 if (BootSector == NULL)
631 return STATUS_INSUFFICIENT_RESOURCES;
632
633 /* Open the root partition - Remove any trailing backslash if needed */
634 RtlInitUnicodeString(&Name, RootPath);
635 TrimTrailingPathSeparators_UStr(&Name);
636
637 InitializeObjectAttributes(&ObjectAttributes,
638 &Name,
639 OBJ_CASE_INSENSITIVE,
640 NULL,
641 NULL);
642
643 Status = NtOpenFile(&FileHandle,
644 GENERIC_READ | SYNCHRONIZE,
645 &ObjectAttributes,
646 &IoStatusBlock,
647 FILE_SHARE_READ | FILE_SHARE_WRITE,
648 FILE_SYNCHRONOUS_IO_NONALERT);
649 if (!NT_SUCCESS(Status))
650 {
651 RtlFreeHeap(ProcessHeap, 0, BootSector);
652 return Status;
653 }
654
655 /* Read current boot sector into buffer */
656 FileOffset.QuadPart = 0ULL;
657 Status = NtReadFile(FileHandle,
658 NULL,
659 NULL,
660 NULL,
661 &IoStatusBlock,
662 BootSector,
663 Length,
664 &FileOffset,
665 NULL);
666 NtClose(FileHandle);
667 if (!NT_SUCCESS(Status))
668 {
669 RtlFreeHeap(ProcessHeap, 0, BootSector);
670 return Status;
671 }
672
673 /* Write bootsector to DstPath */
674 RtlInitUnicodeString(&Name, DstPath);
675 InitializeObjectAttributes(&ObjectAttributes,
676 &Name,
677 OBJ_CASE_INSENSITIVE,
678 NULL,
679 NULL);
680
681 Status = NtCreateFile(&FileHandle,
682 GENERIC_WRITE | SYNCHRONIZE,
683 &ObjectAttributes,
684 &IoStatusBlock,
685 NULL,
686 FILE_ATTRIBUTE_NORMAL,
687 0,
688 FILE_SUPERSEDE,
689 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
690 NULL,
691 0);
692 if (!NT_SUCCESS(Status))
693 {
694 RtlFreeHeap(ProcessHeap, 0, BootSector);
695 return Status;
696 }
697
698 Status = NtWriteFile(FileHandle,
699 NULL,
700 NULL,
701 NULL,
702 &IoStatusBlock,
703 BootSector,
704 Length,
705 NULL,
706 NULL);
707 NtClose(FileHandle);
708
709 /* Free the boot sector */
710 RtlFreeHeap(ProcessHeap, 0, BootSector);
711
712 return Status;
713 }
714
715
716 static
717 NTSTATUS
718 InstallMbrBootCodeToDiskHelper(
719 IN PCWSTR SrcPath,
720 IN PCWSTR RootPath)
721 {
722 NTSTATUS Status;
723 UNICODE_STRING Name;
724 OBJECT_ATTRIBUTES ObjectAttributes;
725 IO_STATUS_BLOCK IoStatusBlock;
726 HANDLE FileHandle;
727 LARGE_INTEGER FileOffset;
728 PPARTITION_SECTOR OrigBootSector;
729 PPARTITION_SECTOR NewBootSector;
730
731 /* Allocate buffer for original bootsector */
732 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
733 if (OrigBootSector == NULL)
734 return STATUS_INSUFFICIENT_RESOURCES;
735
736 /* Open the root partition - Remove any trailing backslash if needed */
737 RtlInitUnicodeString(&Name, RootPath);
738 TrimTrailingPathSeparators_UStr(&Name);
739
740 InitializeObjectAttributes(&ObjectAttributes,
741 &Name,
742 OBJ_CASE_INSENSITIVE,
743 NULL,
744 NULL);
745
746 Status = NtOpenFile(&FileHandle,
747 GENERIC_READ | SYNCHRONIZE,
748 &ObjectAttributes,
749 &IoStatusBlock,
750 FILE_SHARE_READ | FILE_SHARE_WRITE,
751 FILE_SYNCHRONOUS_IO_NONALERT);
752 if (!NT_SUCCESS(Status))
753 {
754 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
755 return Status;
756 }
757
758 /* Read current boot sector into buffer */
759 FileOffset.QuadPart = 0ULL;
760 Status = NtReadFile(FileHandle,
761 NULL,
762 NULL,
763 NULL,
764 &IoStatusBlock,
765 OrigBootSector,
766 sizeof(PARTITION_SECTOR),
767 &FileOffset,
768 NULL);
769 NtClose(FileHandle);
770 if (!NT_SUCCESS(Status))
771 {
772 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
773 return Status;
774 }
775
776 /* Allocate buffer for new bootsector */
777 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR));
778 if (NewBootSector == NULL)
779 {
780 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
781 return STATUS_INSUFFICIENT_RESOURCES;
782 }
783
784 /* Read new bootsector from SrcPath */
785 RtlInitUnicodeString(&Name, SrcPath);
786 InitializeObjectAttributes(&ObjectAttributes,
787 &Name,
788 OBJ_CASE_INSENSITIVE,
789 NULL,
790 NULL);
791
792 Status = NtOpenFile(&FileHandle,
793 GENERIC_READ | SYNCHRONIZE,
794 &ObjectAttributes,
795 &IoStatusBlock,
796 FILE_SHARE_READ,
797 FILE_SYNCHRONOUS_IO_NONALERT);
798 if (!NT_SUCCESS(Status))
799 {
800 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
801 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
802 return Status;
803 }
804
805 Status = NtReadFile(FileHandle,
806 NULL,
807 NULL,
808 NULL,
809 &IoStatusBlock,
810 NewBootSector,
811 sizeof(PARTITION_SECTOR),
812 NULL,
813 NULL);
814 NtClose(FileHandle);
815 if (!NT_SUCCESS(Status))
816 {
817 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
818 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
819 return Status;
820 }
821
822 /*
823 * Copy the disk signature, the reserved fields and
824 * the partition table from the old MBR to the new one.
825 */
826 RtlCopyMemory(&NewBootSector->Signature,
827 &OrigBootSector->Signature,
828 sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature)
829 /* Length of partition table */);
830
831 /* Free the original boot sector */
832 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
833
834 /* Open the root partition - Remove any trailing backslash if needed */
835 RtlInitUnicodeString(&Name, RootPath);
836 TrimTrailingPathSeparators_UStr(&Name);
837
838 InitializeObjectAttributes(&ObjectAttributes,
839 &Name,
840 OBJ_CASE_INSENSITIVE,
841 NULL,
842 NULL);
843
844 Status = NtOpenFile(&FileHandle,
845 GENERIC_WRITE | SYNCHRONIZE,
846 &ObjectAttributes,
847 &IoStatusBlock,
848 FILE_SHARE_READ | FILE_SHARE_WRITE,
849 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
850 if (!NT_SUCCESS(Status))
851 {
852 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
853 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
854 return Status;
855 }
856
857 /* Write new bootsector to RootPath */
858 FileOffset.QuadPart = 0ULL;
859 Status = NtWriteFile(FileHandle,
860 NULL,
861 NULL,
862 NULL,
863 &IoStatusBlock,
864 NewBootSector,
865 sizeof(PARTITION_SECTOR),
866 &FileOffset,
867 NULL);
868 NtClose(FileHandle);
869
870 /* Free the new boot sector */
871 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
872
873 return Status;
874 }
875
876 NTSTATUS
877 InstallMbrBootCodeToDisk(
878 IN PUNICODE_STRING SystemRootPath,
879 IN PUNICODE_STRING SourceRootPath,
880 IN PCWSTR DestinationDevicePathBuffer)
881 {
882 NTSTATUS Status;
883 WCHAR SourceMbrPathBuffer[MAX_PATH];
884 WCHAR DstPath[MAX_PATH];
885
886 #if 0
887 /*
888 * The DestinationDevicePathBuffer parameter has been built with
889 * the following instruction by the caller; I'm not yet sure whether
890 * I actually want this function to build the path instead, hence
891 * I keep this code here but disabled for now...
892 */
893 WCHAR DestinationDevicePathBuffer[MAX_PATH];
894 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
895 L"\\Device\\Harddisk%d\\Partition0",
896 DiskNumber);
897 #endif
898
899 CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2,
900 SourceRootPath->Buffer, L"\\loader\\dosmbr.bin");
901
902 if (IsThereAValidBootSector(DestinationDevicePathBuffer))
903 {
904 /* Save current MBR */
905 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2,
906 SystemRootPath->Buffer, L"mbr.old");
907
908 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
909 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
910 if (!NT_SUCCESS(Status))
911 {
912 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
913 // Don't care if we succeeded or not saving the old MBR, just go ahead.
914 }
915 }
916
917 DPRINT1("Install MBR bootcode: %S ==> %S\n",
918 SourceMbrPathBuffer, DestinationDevicePathBuffer);
919
920 return InstallMbrBootCodeToDiskHelper(SourceMbrPathBuffer,
921 DestinationDevicePathBuffer);
922 }
923
924
925 static
926 NTSTATUS
927 InstallFat12BootCodeToFloppy(
928 IN PCWSTR SrcPath,
929 IN PCWSTR RootPath)
930 {
931 NTSTATUS Status;
932 UNICODE_STRING Name;
933 OBJECT_ATTRIBUTES ObjectAttributes;
934 IO_STATUS_BLOCK IoStatusBlock;
935 HANDLE FileHandle;
936 LARGE_INTEGER FileOffset;
937 PFAT_BOOTSECTOR OrigBootSector;
938 PFAT_BOOTSECTOR NewBootSector;
939
940 /* Allocate buffer for original bootsector */
941 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
942 if (OrigBootSector == NULL)
943 return STATUS_INSUFFICIENT_RESOURCES;
944
945 /* Open the root partition - Remove any trailing backslash if needed */
946 RtlInitUnicodeString(&Name, RootPath);
947 TrimTrailingPathSeparators_UStr(&Name);
948
949 InitializeObjectAttributes(&ObjectAttributes,
950 &Name,
951 OBJ_CASE_INSENSITIVE,
952 NULL,
953 NULL);
954
955 Status = NtOpenFile(&FileHandle,
956 GENERIC_READ | SYNCHRONIZE,
957 &ObjectAttributes,
958 &IoStatusBlock,
959 FILE_SHARE_READ | FILE_SHARE_WRITE,
960 FILE_SYNCHRONOUS_IO_NONALERT);
961 if (!NT_SUCCESS(Status))
962 {
963 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
964 return Status;
965 }
966
967 /* Read current boot sector into buffer */
968 FileOffset.QuadPart = 0ULL;
969 Status = NtReadFile(FileHandle,
970 NULL,
971 NULL,
972 NULL,
973 &IoStatusBlock,
974 OrigBootSector,
975 SECTORSIZE,
976 &FileOffset,
977 NULL);
978 NtClose(FileHandle);
979 if (!NT_SUCCESS(Status))
980 {
981 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
982 return Status;
983 }
984
985 /* Allocate buffer for new bootsector */
986 NewBootSector = RtlAllocateHeap(ProcessHeap,
987 0,
988 SECTORSIZE);
989 if (NewBootSector == NULL)
990 {
991 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
992 return STATUS_INSUFFICIENT_RESOURCES;
993 }
994
995 /* Read new bootsector from SrcPath */
996 RtlInitUnicodeString(&Name, SrcPath);
997
998 InitializeObjectAttributes(&ObjectAttributes,
999 &Name,
1000 OBJ_CASE_INSENSITIVE,
1001 NULL,
1002 NULL);
1003
1004 Status = NtOpenFile(&FileHandle,
1005 GENERIC_READ | SYNCHRONIZE,
1006 &ObjectAttributes,
1007 &IoStatusBlock,
1008 FILE_SHARE_READ,
1009 FILE_SYNCHRONOUS_IO_NONALERT);
1010 if (!NT_SUCCESS(Status))
1011 {
1012 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1013 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1014 return Status;
1015 }
1016
1017 Status = NtReadFile(FileHandle,
1018 NULL,
1019 NULL,
1020 NULL,
1021 &IoStatusBlock,
1022 NewBootSector,
1023 SECTORSIZE,
1024 NULL,
1025 NULL);
1026 NtClose(FileHandle);
1027 if (!NT_SUCCESS(Status))
1028 {
1029 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1030 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1031 return Status;
1032 }
1033
1034 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1035 memcpy(&NewBootSector->OemName,
1036 &OrigBootSector->OemName,
1037 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1038 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1039
1040 /* Free the original boot sector */
1041 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1042
1043 /* Open the root partition - Remove any trailing backslash if needed */
1044 RtlInitUnicodeString(&Name, RootPath);
1045 TrimTrailingPathSeparators_UStr(&Name);
1046
1047 InitializeObjectAttributes(&ObjectAttributes,
1048 &Name,
1049 OBJ_CASE_INSENSITIVE,
1050 NULL,
1051 NULL);
1052
1053 Status = NtOpenFile(&FileHandle,
1054 GENERIC_WRITE | SYNCHRONIZE,
1055 &ObjectAttributes,
1056 &IoStatusBlock,
1057 FILE_SHARE_READ | FILE_SHARE_WRITE,
1058 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1059 if (!NT_SUCCESS(Status))
1060 {
1061 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1062 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1063 return Status;
1064 }
1065
1066 /* Write new bootsector to RootPath */
1067 FileOffset.QuadPart = 0ULL;
1068 Status = NtWriteFile(FileHandle,
1069 NULL,
1070 NULL,
1071 NULL,
1072 &IoStatusBlock,
1073 NewBootSector,
1074 SECTORSIZE,
1075 &FileOffset,
1076 NULL);
1077 NtClose(FileHandle);
1078
1079 /* Free the new boot sector */
1080 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1081
1082 return Status;
1083 }
1084
1085 static
1086 NTSTATUS
1087 InstallFat16BootCode(
1088 IN PCWSTR SrcPath, // FAT16 bootsector source file (on the installation medium)
1089 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information
1090 IN HANDLE RootPartition) // Partition holding the (old) FAT16 information
1091 {
1092 NTSTATUS Status;
1093 UNICODE_STRING Name;
1094 OBJECT_ATTRIBUTES ObjectAttributes;
1095 IO_STATUS_BLOCK IoStatusBlock;
1096 HANDLE FileHandle;
1097 LARGE_INTEGER FileOffset;
1098 PFAT_BOOTSECTOR OrigBootSector;
1099 PFAT_BOOTSECTOR NewBootSector;
1100
1101 /* Allocate a buffer for the original bootsector */
1102 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1103 if (OrigBootSector == NULL)
1104 return STATUS_INSUFFICIENT_RESOURCES;
1105
1106 /* Read the current partition boot sector into the buffer */
1107 FileOffset.QuadPart = 0ULL;
1108 Status = NtReadFile(RootPartition,
1109 NULL,
1110 NULL,
1111 NULL,
1112 &IoStatusBlock,
1113 OrigBootSector,
1114 SECTORSIZE,
1115 &FileOffset,
1116 NULL);
1117 if (!NT_SUCCESS(Status))
1118 {
1119 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1120 return Status;
1121 }
1122
1123 /* Allocate a buffer for the new bootsector */
1124 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1125 if (NewBootSector == NULL)
1126 {
1127 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1128 return STATUS_INSUFFICIENT_RESOURCES;
1129 }
1130
1131 /* Read the new bootsector from SrcPath */
1132 RtlInitUnicodeString(&Name, SrcPath);
1133 InitializeObjectAttributes(&ObjectAttributes,
1134 &Name,
1135 OBJ_CASE_INSENSITIVE,
1136 NULL,
1137 NULL);
1138
1139 Status = NtOpenFile(&FileHandle,
1140 GENERIC_READ | SYNCHRONIZE,
1141 &ObjectAttributes,
1142 &IoStatusBlock,
1143 FILE_SHARE_READ,
1144 FILE_SYNCHRONOUS_IO_NONALERT);
1145 if (!NT_SUCCESS(Status))
1146 {
1147 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1148 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1149 return Status;
1150 }
1151
1152 FileOffset.QuadPart = 0ULL;
1153 Status = NtReadFile(FileHandle,
1154 NULL,
1155 NULL,
1156 NULL,
1157 &IoStatusBlock,
1158 NewBootSector,
1159 SECTORSIZE,
1160 &FileOffset,
1161 NULL);
1162 NtClose(FileHandle);
1163 if (!NT_SUCCESS(Status))
1164 {
1165 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1166 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1167 return Status;
1168 }
1169
1170 /* Adjust the bootsector (copy a part of the FAT16 BPB) */
1171 memcpy(&NewBootSector->OemName,
1172 &OrigBootSector->OemName,
1173 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1174 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1175
1176 /* Free the original boot sector */
1177 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1178
1179 /* Write the new bootsector to DstPath */
1180 FileOffset.QuadPart = 0ULL;
1181 Status = NtWriteFile(DstPath,
1182 NULL,
1183 NULL,
1184 NULL,
1185 &IoStatusBlock,
1186 NewBootSector,
1187 SECTORSIZE,
1188 &FileOffset,
1189 NULL);
1190
1191 /* Free the new boot sector */
1192 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1193
1194 return Status;
1195 }
1196
1197 static
1198 NTSTATUS
1199 InstallFat16BootCodeToFile(
1200 IN PCWSTR SrcPath,
1201 IN PCWSTR DstPath,
1202 IN PCWSTR RootPath)
1203 {
1204 NTSTATUS Status;
1205 UNICODE_STRING Name;
1206 OBJECT_ATTRIBUTES ObjectAttributes;
1207 IO_STATUS_BLOCK IoStatusBlock;
1208 HANDLE PartitionHandle, FileHandle;
1209
1210 /*
1211 * Open the root partition from which the boot sector
1212 * parameters will be obtained.
1213 * Remove any trailing backslash if needed.
1214 */
1215 RtlInitUnicodeString(&Name, RootPath);
1216 TrimTrailingPathSeparators_UStr(&Name);
1217
1218 InitializeObjectAttributes(&ObjectAttributes,
1219 &Name,
1220 OBJ_CASE_INSENSITIVE,
1221 NULL,
1222 NULL);
1223
1224 Status = NtOpenFile(&PartitionHandle,
1225 GENERIC_READ | SYNCHRONIZE,
1226 &ObjectAttributes,
1227 &IoStatusBlock,
1228 FILE_SHARE_READ | FILE_SHARE_WRITE,
1229 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
1230 if (!NT_SUCCESS(Status))
1231 return Status;
1232
1233 /* Open or create the file where the new bootsector will be saved */
1234 RtlInitUnicodeString(&Name, DstPath);
1235 InitializeObjectAttributes(&ObjectAttributes,
1236 &Name,
1237 OBJ_CASE_INSENSITIVE,
1238 NULL,
1239 NULL);
1240
1241 Status = NtCreateFile(&FileHandle,
1242 GENERIC_WRITE | SYNCHRONIZE,
1243 &ObjectAttributes,
1244 &IoStatusBlock,
1245 NULL,
1246 FILE_ATTRIBUTE_NORMAL,
1247 0,
1248 FILE_OVERWRITE_IF,
1249 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1250 NULL,
1251 0);
1252 if (!NT_SUCCESS(Status))
1253 {
1254 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
1255 NtClose(PartitionHandle);
1256 return Status;
1257 }
1258
1259 /* Install the FAT16 boot sector */
1260 Status = InstallFat16BootCode(SrcPath, FileHandle, PartitionHandle);
1261
1262 /* Close the file and the partition */
1263 NtClose(FileHandle);
1264 NtClose(PartitionHandle);
1265
1266 return Status;
1267 }
1268
1269 static
1270 NTSTATUS
1271 InstallFat16BootCodeToDisk(
1272 IN PCWSTR SrcPath,
1273 IN PCWSTR RootPath)
1274 {
1275 NTSTATUS Status;
1276 UNICODE_STRING Name;
1277 OBJECT_ATTRIBUTES ObjectAttributes;
1278 IO_STATUS_BLOCK IoStatusBlock;
1279 HANDLE PartitionHandle;
1280
1281 /*
1282 * Open the root partition from which the boot sector parameters will be
1283 * obtained; this is also where we will write the updated boot sector.
1284 * Remove any trailing backslash if needed.
1285 */
1286 RtlInitUnicodeString(&Name, RootPath);
1287 TrimTrailingPathSeparators_UStr(&Name);
1288
1289 InitializeObjectAttributes(&ObjectAttributes,
1290 &Name,
1291 OBJ_CASE_INSENSITIVE,
1292 NULL,
1293 NULL);
1294
1295 Status = NtOpenFile(&PartitionHandle,
1296 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1297 &ObjectAttributes,
1298 &IoStatusBlock,
1299 FILE_SHARE_READ | FILE_SHARE_WRITE,
1300 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1301 if (!NT_SUCCESS(Status))
1302 return Status;
1303
1304 /* Install the FAT16 boot sector */
1305 Status = InstallFat16BootCode(SrcPath, PartitionHandle, PartitionHandle);
1306
1307 /* Close the partition */
1308 NtClose(PartitionHandle);
1309
1310 return Status;
1311 }
1312
1313
1314 static
1315 NTSTATUS
1316 InstallFat32BootCode(
1317 IN PCWSTR SrcPath, // FAT32 bootsector source file (on the installation medium)
1318 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information
1319 IN HANDLE RootPartition) // Partition holding the (old) FAT32 information
1320 {
1321 NTSTATUS Status;
1322 UNICODE_STRING Name;
1323 OBJECT_ATTRIBUTES ObjectAttributes;
1324 IO_STATUS_BLOCK IoStatusBlock;
1325 HANDLE FileHandle;
1326 LARGE_INTEGER FileOffset;
1327 PFAT32_BOOTSECTOR OrigBootSector;
1328 PFAT32_BOOTSECTOR NewBootSector;
1329 USHORT BackupBootSector;
1330
1331 /* Allocate a buffer for the original bootsector */
1332 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1333 if (OrigBootSector == NULL)
1334 return STATUS_INSUFFICIENT_RESOURCES;
1335
1336 /* Read the current boot sector into the buffer */
1337 FileOffset.QuadPart = 0ULL;
1338 Status = NtReadFile(RootPartition,
1339 NULL,
1340 NULL,
1341 NULL,
1342 &IoStatusBlock,
1343 OrigBootSector,
1344 SECTORSIZE,
1345 &FileOffset,
1346 NULL);
1347 if (!NT_SUCCESS(Status))
1348 {
1349 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1350 return Status;
1351 }
1352
1353 /* Allocate a buffer for the new bootsector (2 sectors) */
1354 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1355 if (NewBootSector == NULL)
1356 {
1357 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1358 return STATUS_INSUFFICIENT_RESOURCES;
1359 }
1360
1361 /* Read the new bootsector from SrcPath */
1362 RtlInitUnicodeString(&Name, SrcPath);
1363 InitializeObjectAttributes(&ObjectAttributes,
1364 &Name,
1365 OBJ_CASE_INSENSITIVE,
1366 NULL,
1367 NULL);
1368
1369 Status = NtOpenFile(&FileHandle,
1370 GENERIC_READ | SYNCHRONIZE,
1371 &ObjectAttributes,
1372 &IoStatusBlock,
1373 FILE_SHARE_READ,
1374 FILE_SYNCHRONOUS_IO_NONALERT);
1375 if (!NT_SUCCESS(Status))
1376 {
1377 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1378 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1379 return Status;
1380 }
1381
1382 FileOffset.QuadPart = 0ULL;
1383 Status = NtReadFile(FileHandle,
1384 NULL,
1385 NULL,
1386 NULL,
1387 &IoStatusBlock,
1388 NewBootSector,
1389 2 * SECTORSIZE,
1390 &FileOffset,
1391 NULL);
1392 NtClose(FileHandle);
1393 if (!NT_SUCCESS(Status))
1394 {
1395 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1396 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1397 return Status;
1398 }
1399
1400 /* Adjust the bootsector (copy a part of the FAT32 BPB) */
1401 memcpy(&NewBootSector->OemName,
1402 &OrigBootSector->OemName,
1403 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1404 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1405
1406 /*
1407 * We know we copy the boot code to a file only when DstPath != RootPartition,
1408 * otherwise the boot code is copied to the specified root partition.
1409 */
1410 if (DstPath != RootPartition)
1411 {
1412 /* Copy to a file: Disable the backup boot sector */
1413 NewBootSector->BackupBootSector = 0;
1414 }
1415 else
1416 {
1417 /* Copy to a disk: Get the location of the backup boot sector */
1418 BackupBootSector = OrigBootSector->BackupBootSector;
1419 }
1420
1421 /* Free the original boot sector */
1422 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1423
1424 /* Write the first sector of the new bootcode to DstPath sector 0 */
1425 FileOffset.QuadPart = 0ULL;
1426 Status = NtWriteFile(DstPath,
1427 NULL,
1428 NULL,
1429 NULL,
1430 &IoStatusBlock,
1431 NewBootSector,
1432 SECTORSIZE,
1433 &FileOffset,
1434 NULL);
1435 if (!NT_SUCCESS(Status))
1436 {
1437 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1438 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1439 return Status;
1440 }
1441
1442 if (DstPath == RootPartition)
1443 {
1444 /* Copy to a disk: Write the backup boot sector */
1445 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1446 {
1447 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1448 Status = NtWriteFile(DstPath,
1449 NULL,
1450 NULL,
1451 NULL,
1452 &IoStatusBlock,
1453 NewBootSector,
1454 SECTORSIZE,
1455 &FileOffset,
1456 NULL);
1457 if (!NT_SUCCESS(Status))
1458 {
1459 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1460 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1461 return Status;
1462 }
1463 }
1464 }
1465
1466 /* Write the second sector of the new bootcode to boot disk sector 14 */
1467 // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1468 FileOffset.QuadPart = 14 * SECTORSIZE;
1469 Status = NtWriteFile(DstPath, // or really RootPartition ???
1470 NULL,
1471 NULL,
1472 NULL,
1473 &IoStatusBlock,
1474 ((PUCHAR)NewBootSector + SECTORSIZE),
1475 SECTORSIZE,
1476 &FileOffset,
1477 NULL);
1478 if (!NT_SUCCESS(Status))
1479 {
1480 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1481 }
1482
1483 /* Free the new boot sector */
1484 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1485
1486 return Status;
1487 }
1488
1489 static
1490 NTSTATUS
1491 InstallFat32BootCodeToFile(
1492 IN PCWSTR SrcPath,
1493 IN PCWSTR DstPath,
1494 IN PCWSTR RootPath)
1495 {
1496 NTSTATUS Status;
1497 UNICODE_STRING Name;
1498 OBJECT_ATTRIBUTES ObjectAttributes;
1499 IO_STATUS_BLOCK IoStatusBlock;
1500 HANDLE PartitionHandle, FileHandle;
1501
1502 /*
1503 * Open the root partition from which the boot sector parameters
1504 * will be obtained.
1505 * FIXME? It might be possible that we need to also open it for writing
1506 * access in case we really need to still write the second portion of
1507 * the boot sector ????
1508 *
1509 * Remove any trailing backslash if needed.
1510 */
1511 RtlInitUnicodeString(&Name, RootPath);
1512 TrimTrailingPathSeparators_UStr(&Name);
1513
1514 InitializeObjectAttributes(&ObjectAttributes,
1515 &Name,
1516 OBJ_CASE_INSENSITIVE,
1517 NULL,
1518 NULL);
1519
1520 Status = NtOpenFile(&PartitionHandle,
1521 GENERIC_READ | SYNCHRONIZE,
1522 &ObjectAttributes,
1523 &IoStatusBlock,
1524 FILE_SHARE_READ | FILE_SHARE_WRITE,
1525 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
1526 if (!NT_SUCCESS(Status))
1527 return Status;
1528
1529 /* Open or create the file where (the first sector of ????) the new bootsector will be saved */
1530 RtlInitUnicodeString(&Name, DstPath);
1531 InitializeObjectAttributes(&ObjectAttributes,
1532 &Name,
1533 OBJ_CASE_INSENSITIVE,
1534 NULL,
1535 NULL);
1536
1537 Status = NtCreateFile(&FileHandle,
1538 GENERIC_WRITE | SYNCHRONIZE,
1539 &ObjectAttributes,
1540 &IoStatusBlock,
1541 NULL,
1542 FILE_ATTRIBUTE_NORMAL,
1543 0,
1544 FILE_SUPERSEDE, // FILE_OVERWRITE_IF, <- is used for FAT16
1545 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1546 NULL,
1547 0);
1548 if (!NT_SUCCESS(Status))
1549 {
1550 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
1551 NtClose(PartitionHandle);
1552 return Status;
1553 }
1554
1555 /* Install the FAT32 boot sector */
1556 Status = InstallFat32BootCode(SrcPath, FileHandle, PartitionHandle);
1557
1558 /* Close the file and the partition */
1559 NtClose(FileHandle);
1560 NtClose(PartitionHandle);
1561
1562 return Status;
1563 }
1564
1565 static
1566 NTSTATUS
1567 InstallFat32BootCodeToDisk(
1568 IN PCWSTR SrcPath,
1569 IN PCWSTR RootPath)
1570 {
1571 NTSTATUS Status;
1572 UNICODE_STRING Name;
1573 OBJECT_ATTRIBUTES ObjectAttributes;
1574 IO_STATUS_BLOCK IoStatusBlock;
1575 HANDLE PartitionHandle;
1576
1577 /*
1578 * Open the root partition from which the boot sector parameters will be
1579 * obtained; this is also where we will write the updated boot sector.
1580 * Remove any trailing backslash if needed.
1581 */
1582 RtlInitUnicodeString(&Name, RootPath);
1583 TrimTrailingPathSeparators_UStr(&Name);
1584
1585 InitializeObjectAttributes(&ObjectAttributes,
1586 &Name,
1587 OBJ_CASE_INSENSITIVE,
1588 NULL,
1589 NULL);
1590
1591 Status = NtOpenFile(&PartitionHandle,
1592 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1593 &ObjectAttributes,
1594 &IoStatusBlock,
1595 FILE_SHARE_READ | FILE_SHARE_WRITE,
1596 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */);
1597 if (!NT_SUCCESS(Status))
1598 return Status;
1599
1600 /* Install the FAT32 boot sector */
1601 Status = InstallFat32BootCode(SrcPath, PartitionHandle, PartitionHandle);
1602
1603 /* Close the partition */
1604 NtClose(PartitionHandle);
1605
1606 return Status;
1607 }
1608
1609 static
1610 NTSTATUS
1611 InstallBtrfsBootCodeToDisk(
1612 IN PCWSTR SrcPath,
1613 IN PCWSTR RootPath)
1614 {
1615 NTSTATUS Status;
1616 NTSTATUS LockStatus;
1617 UNICODE_STRING Name;
1618 OBJECT_ATTRIBUTES ObjectAttributes;
1619 IO_STATUS_BLOCK IoStatusBlock;
1620 HANDLE FileHandle;
1621 LARGE_INTEGER FileOffset;
1622 // PEXT2_BOOTSECTOR OrigBootSector;
1623 PBTRFS_BOOTSECTOR NewBootSector;
1624 // USHORT BackupBootSector;
1625 PARTITION_INFORMATION_EX PartInfo;
1626
1627 #if 0
1628 /* Allocate buffer for original bootsector */
1629 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1630 if (OrigBootSector == NULL)
1631 return STATUS_INSUFFICIENT_RESOURCES;
1632
1633 /* Open the root partition - Remove any trailing backslash if needed */
1634 RtlInitUnicodeString(&Name, RootPath);
1635 TrimTrailingPathSeparators_UStr(&Name);
1636
1637 InitializeObjectAttributes(&ObjectAttributes,
1638 &Name,
1639 OBJ_CASE_INSENSITIVE,
1640 NULL,
1641 NULL);
1642
1643 Status = NtOpenFile(&FileHandle,
1644 GENERIC_READ | SYNCHRONIZE,
1645 &ObjectAttributes,
1646 &IoStatusBlock,
1647 FILE_SHARE_READ | FILE_SHARE_WRITE,
1648 FILE_SYNCHRONOUS_IO_NONALERT);
1649 if (!NT_SUCCESS(Status))
1650 {
1651 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1652 return Status;
1653 }
1654
1655 /* Read current boot sector into buffer */
1656 FileOffset.QuadPart = 0ULL;
1657 Status = NtReadFile(FileHandle,
1658 NULL,
1659 NULL,
1660 NULL,
1661 &IoStatusBlock,
1662 OrigBootSector,
1663 SECTORSIZE,
1664 &FileOffset,
1665 NULL);
1666 NtClose(FileHandle);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1670 return Status;
1671 }
1672 #endif
1673
1674 /* Allocate buffer for new bootsector */
1675 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR));
1676 if (NewBootSector == NULL)
1677 {
1678 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1679 return STATUS_INSUFFICIENT_RESOURCES;
1680 }
1681
1682 /* Read new bootsector from SrcPath */
1683 RtlInitUnicodeString(&Name, SrcPath);
1684
1685 InitializeObjectAttributes(&ObjectAttributes,
1686 &Name,
1687 OBJ_CASE_INSENSITIVE,
1688 NULL,
1689 NULL);
1690
1691 Status = NtOpenFile(&FileHandle,
1692 GENERIC_READ | SYNCHRONIZE,
1693 &ObjectAttributes,
1694 &IoStatusBlock,
1695 FILE_SHARE_READ,
1696 FILE_SYNCHRONOUS_IO_NONALERT);
1697 if (!NT_SUCCESS(Status))
1698 {
1699 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1700 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1701 return Status;
1702 }
1703
1704 Status = NtReadFile(FileHandle,
1705 NULL,
1706 NULL,
1707 NULL,
1708 &IoStatusBlock,
1709 NewBootSector,
1710 sizeof(BTRFS_BOOTSECTOR),
1711 NULL,
1712 NULL);
1713 NtClose(FileHandle);
1714 if (!NT_SUCCESS(Status))
1715 {
1716 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1717 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1718 return Status;
1719 }
1720
1721 #if 0
1722 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1723 memcpy(&NewBootSector->OemName,
1724 &OrigBootSector->OemName,
1725 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1726 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1727
1728 /* Get the location of the backup boot sector */
1729 BackupBootSector = OrigBootSector->BackupBootSector;
1730
1731 /* Free the original boot sector */
1732 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1733 #endif
1734
1735 /* Open the root partition - Remove any trailing backslash if needed */
1736 RtlInitUnicodeString(&Name, RootPath);
1737 TrimTrailingPathSeparators_UStr(&Name);
1738
1739 InitializeObjectAttributes(&ObjectAttributes,
1740 &Name,
1741 OBJ_CASE_INSENSITIVE,
1742 NULL,
1743 NULL);
1744
1745 Status = NtOpenFile(&FileHandle,
1746 GENERIC_WRITE | SYNCHRONIZE,
1747 &ObjectAttributes,
1748 &IoStatusBlock,
1749 FILE_SHARE_READ | FILE_SHARE_WRITE,
1750 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1751 if (!NT_SUCCESS(Status))
1752 {
1753 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1754 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1755 return Status;
1756 }
1757
1758 /*
1759 * The BTRFS driver requires the volume to be locked in order to modify
1760 * the first sectors of the partition, even though they are outside the
1761 * file-system space / in the reserved area (they are situated before
1762 * the super-block at 0x1000) and is in principle allowed by the NT
1763 * storage stack.
1764 * So we lock here in order to write the bootsector at sector 0.
1765 * If locking fails, we ignore and continue nonetheless.
1766 */
1767 LockStatus = NtFsControlFile(FileHandle,
1768 NULL,
1769 NULL,
1770 NULL,
1771 &IoStatusBlock,
1772 FSCTL_LOCK_VOLUME,
1773 NULL,
1774 0,
1775 NULL,
1776 0);
1777 if (!NT_SUCCESS(LockStatus))
1778 {
1779 DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector! Operations may fail! (Status 0x%lx)\n", LockStatus);
1780 }
1781
1782 /* Obtaining partition info and writing it to bootsector */
1783 Status = NtDeviceIoControlFile(FileHandle,
1784 NULL,
1785 NULL,
1786 NULL,
1787 &IoStatusBlock,
1788 IOCTL_DISK_GET_PARTITION_INFO_EX,
1789 NULL,
1790 0,
1791 &PartInfo,
1792 sizeof(PartInfo));
1793 if (!NT_SUCCESS(Status))
1794 {
1795 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status);
1796 goto Quit;
1797 }
1798
1799 /* Write new bootsector to RootPath */
1800
1801 NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE;
1802
1803 /* Write sector 0 */
1804 FileOffset.QuadPart = 0ULL;
1805 Status = NtWriteFile(FileHandle,
1806 NULL,
1807 NULL,
1808 NULL,
1809 &IoStatusBlock,
1810 NewBootSector,
1811 sizeof(BTRFS_BOOTSECTOR),
1812 &FileOffset,
1813 NULL);
1814 if (!NT_SUCCESS(Status))
1815 {
1816 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1817 goto Quit;
1818 }
1819
1820 #if 0
1821 /* Write backup boot sector */
1822 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1823 {
1824 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1825 Status = NtWriteFile(FileHandle,
1826 NULL,
1827 NULL,
1828 NULL,
1829 &IoStatusBlock,
1830 NewBootSector,
1831 SECTORSIZE,
1832 &FileOffset,
1833 NULL);
1834 if (!NT_SUCCESS(Status))
1835 {
1836 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1837 goto Quit;
1838 }
1839 }
1840
1841 /* Write sector 14 */
1842 FileOffset.QuadPart = 14 * SECTORSIZE;
1843 Status = NtWriteFile(FileHandle,
1844 NULL,
1845 NULL,
1846 NULL,
1847 &IoStatusBlock,
1848 ((PUCHAR)NewBootSector + SECTORSIZE),
1849 SECTORSIZE,
1850 &FileOffset,
1851 NULL);
1852 if (!NT_SUCCESS(Status))
1853 {
1854 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1855 }
1856 #endif
1857
1858 Quit:
1859 /* Unlock the volume */
1860 LockStatus = NtFsControlFile(FileHandle,
1861 NULL,
1862 NULL,
1863 NULL,
1864 &IoStatusBlock,
1865 FSCTL_UNLOCK_VOLUME,
1866 NULL,
1867 0,
1868 NULL,
1869 0);
1870 if (!NT_SUCCESS(LockStatus))
1871 {
1872 DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus);
1873 }
1874
1875 /* Close the volume */
1876 NtClose(FileHandle);
1877
1878 /* Free the new boot sector */
1879 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1880
1881 return Status;
1882 }
1883
1884
1885 static
1886 NTSTATUS
1887 InstallFatBootcodeToPartition(
1888 IN PUNICODE_STRING SystemRootPath,
1889 IN PUNICODE_STRING SourceRootPath,
1890 IN PUNICODE_STRING DestinationArcPath,
1891 IN UCHAR PartitionType)
1892 {
1893 NTSTATUS Status;
1894 BOOLEAN DoesFreeLdrExist;
1895 WCHAR SrcPath[MAX_PATH];
1896 WCHAR DstPath[MAX_PATH];
1897
1898 /* FAT or FAT32 partition */
1899 DPRINT("System path: '%wZ'\n", SystemRootPath);
1900
1901 /* Copy FreeLoader to the system partition, always overwriting the older version */
1902 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1903 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
1904
1905 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1906 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1907 if (!NT_SUCCESS(Status))
1908 {
1909 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1910 return Status;
1911 }
1912
1913 /* Prepare for possibly updating 'freeldr.ini' */
1914 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1915 if (DoesFreeLdrExist)
1916 {
1917 /* Update existing 'freeldr.ini' */
1918 DPRINT1("Update existing 'freeldr.ini'\n");
1919 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1920 if (!NT_SUCCESS(Status))
1921 {
1922 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1923 return Status;
1924 }
1925 }
1926
1927 /* Check for NT and other bootloaders */
1928
1929 // FIXME: Check for Vista+ bootloader!
1930 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
1931 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
1932 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
1933 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
1934 {
1935 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
1936 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1937
1938 /* Create or update 'freeldr.ini' */
1939 if (DoesFreeLdrExist == FALSE)
1940 {
1941 /* Create new 'freeldr.ini' */
1942 DPRINT1("Create new 'freeldr.ini'\n");
1943 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1944 if (!NT_SUCCESS(Status))
1945 {
1946 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1947 return Status;
1948 }
1949
1950 /* Install new bootcode into a file */
1951 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
1952
1953 if (PartitionType == PARTITION_FAT32 ||
1954 PartitionType == PARTITION_FAT32_XINT13)
1955 {
1956 /* Install FAT32 bootcode */
1957 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1958
1959 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1960 Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
1961 SystemRootPath->Buffer);
1962 if (!NT_SUCCESS(Status))
1963 {
1964 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1965 return Status;
1966 }
1967 }
1968 else
1969 {
1970 /* Install FAT16 bootcode */
1971 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1972
1973 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1974 Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
1975 SystemRootPath->Buffer);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1979 return Status;
1980 }
1981 }
1982 }
1983
1984 /* Update 'boot.ini' */
1985 /* Windows' NTLDR loads an external bootsector file when the specified drive
1986 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1987 DPRINT1("Update 'boot.ini'\n");
1988 Status = UpdateBootIni(SystemRootPath->Buffer,
1989 L"C:\\bootsect.ros",
1990 L"\"ReactOS\"");
1991 if (!NT_SUCCESS(Status))
1992 {
1993 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1994 return Status;
1995 }
1996 }
1997 else
1998 {
1999 /* Non-NT bootloaders: install our own bootloader */
2000
2001 PCWSTR Section;
2002 PCWSTR Description;
2003 PCWSTR BootDrive;
2004 PCWSTR BootPartition;
2005 PCWSTR BootSector;
2006
2007 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
2008 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
2009 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
2010 {
2011 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
2012
2013 Section = L"CPQDOS";
2014 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
2015 BootDrive = L"hd0";
2016 BootPartition = L"1";
2017 BootSector = L"BOOTSECT.DOS";
2018 }
2019 else
2020 /* Search for Microsoft DOS or Windows 9x boot loader */
2021 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
2022 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
2023 // WINBOOT.SYS
2024 {
2025 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2026
2027 Section = L"MSDOS";
2028 Description = L"\"MS-DOS/Windows\"";
2029 BootDrive = L"hd0";
2030 BootPartition = L"1";
2031 BootSector = L"BOOTSECT.DOS";
2032 }
2033 else
2034 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
2035 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
2036 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
2037 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
2038 {
2039 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
2040
2041 Section = L"IBMDOS";
2042 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
2043 BootDrive = L"hd0";
2044 BootPartition = L"1";
2045 BootSector = L"BOOTSECT.DOS";
2046 }
2047 else
2048 /* Search for DR-DOS 3.x boot loader */
2049 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
2050 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
2051 {
2052 DPRINT1("Found DR-DOS 3.x\n");
2053
2054 Section = L"DRDOS";
2055 Description = L"\"DR-DOS 3.x\"";
2056 BootDrive = L"hd0";
2057 BootPartition = L"1";
2058 BootSector = L"BOOTSECT.DOS";
2059 }
2060 else
2061 /* Search for Dell Real-Mode Kernel (DRMK) OS */
2062 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
2063 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
2064 {
2065 DPRINT1("Found Dell Real-Mode Kernel OS\n");
2066
2067 Section = L"DRMK";
2068 Description = L"\"Dell Real-Mode Kernel OS\"";
2069 BootDrive = L"hd0";
2070 BootPartition = L"1";
2071 BootSector = L"BOOTSECT.DOS";
2072 }
2073 else
2074 /* Search for MS OS/2 1.x */
2075 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
2076 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
2077 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
2078 {
2079 DPRINT1("Found MS OS/2 1.x\n");
2080
2081 Section = L"MSOS2";
2082 Description = L"\"MS OS/2 1.x\"";
2083 BootDrive = L"hd0";
2084 BootPartition = L"1";
2085 BootSector = L"BOOTSECT.OS2";
2086 }
2087 else
2088 /* Search for MS or IBM OS/2 */
2089 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
2090 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
2091 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
2092 {
2093 DPRINT1("Found MS/IBM OS/2\n");
2094
2095 Section = L"IBMOS2";
2096 Description = L"\"MS/IBM OS/2\"";
2097 BootDrive = L"hd0";
2098 BootPartition = L"1";
2099 BootSector = L"BOOTSECT.OS2";
2100 }
2101 else
2102 /* Search for FreeDOS boot loader */
2103 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
2104 {
2105 DPRINT1("Found FreeDOS boot loader\n");
2106
2107 Section = L"FDOS";
2108 Description = L"\"FreeDOS\"";
2109 BootDrive = L"hd0";
2110 BootPartition = L"1";
2111 BootSector = L"BOOTSECT.DOS";
2112 }
2113 else
2114 {
2115 /* No or unknown boot loader */
2116 DPRINT1("No or unknown boot loader found\n");
2117
2118 Section = L"Unknown";
2119 Description = L"\"Unknown Operating System\"";
2120 BootDrive = L"hd0";
2121 BootPartition = L"1";
2122 BootSector = L"BOOTSECT.OLD";
2123 }
2124
2125 /* Create or update 'freeldr.ini' */
2126 if (DoesFreeLdrExist == FALSE)
2127 {
2128 /* Create new 'freeldr.ini' */
2129 DPRINT1("Create new 'freeldr.ini'\n");
2130
2131 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2132 {
2133 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2134 SystemRootPath->Buffer, DestinationArcPath->Buffer,
2135 Section, Description,
2136 BootDrive, BootPartition, BootSector);
2137 if (!NT_SUCCESS(Status))
2138 {
2139 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2140 return Status;
2141 }
2142
2143 /* Save current bootsector */
2144 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2145
2146 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2147 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
2148 if (!NT_SUCCESS(Status))
2149 {
2150 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2151 return Status;
2152 }
2153 }
2154 else
2155 {
2156 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2157 if (!NT_SUCCESS(Status))
2158 {
2159 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2160 return Status;
2161 }
2162 }
2163
2164 /* Install new bootsector on the disk */
2165 if (PartitionType == PARTITION_FAT32 ||
2166 PartitionType == PARTITION_FAT32_XINT13)
2167 {
2168 /* Install FAT32 bootcode */
2169 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
2170
2171 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2172 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2173 if (!NT_SUCCESS(Status))
2174 {
2175 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2176 return Status;
2177 }
2178 }
2179 else
2180 {
2181 /* Install FAT16 bootcode */
2182 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2183
2184 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2185 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2186 if (!NT_SUCCESS(Status))
2187 {
2188 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2189 return Status;
2190 }
2191 }
2192 }
2193 }
2194
2195 return STATUS_SUCCESS;
2196 }
2197
2198 static
2199 NTSTATUS
2200 InstallBtrfsBootcodeToPartition(
2201 IN PUNICODE_STRING SystemRootPath,
2202 IN PUNICODE_STRING SourceRootPath,
2203 IN PUNICODE_STRING DestinationArcPath,
2204 IN UCHAR PartitionType)
2205 {
2206 NTSTATUS Status;
2207 BOOLEAN DoesFreeLdrExist;
2208 WCHAR SrcPath[MAX_PATH];
2209 WCHAR DstPath[MAX_PATH];
2210
2211 /* BTRFS partition */
2212 DPRINT("System path: '%wZ'\n", SystemRootPath);
2213
2214 /* Copy FreeLoader to the system partition, always overwriting the older version */
2215 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2216 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
2217
2218 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2219 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
2220 if (!NT_SUCCESS(Status))
2221 {
2222 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2223 return Status;
2224 }
2225
2226 /* Prepare for possibly updating 'freeldr.ini' */
2227 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
2228 if (DoesFreeLdrExist)
2229 {
2230 /* Update existing 'freeldr.ini' */
2231 DPRINT1("Update existing 'freeldr.ini'\n");
2232 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2233 if (!NT_SUCCESS(Status))
2234 {
2235 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2236 return Status;
2237 }
2238 }
2239
2240 /* Check for *nix bootloaders */
2241
2242 /* Create or update 'freeldr.ini' */
2243 if (DoesFreeLdrExist == FALSE)
2244 {
2245 /* Create new 'freeldr.ini' */
2246 DPRINT1("Create new 'freeldr.ini'\n");
2247
2248 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2249 DPRINT1("*nix or unknown boot loader found\n");
2250
2251 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2252 {
2253 PCWSTR BootSector = L"BOOTSECT.OLD";
2254
2255 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2256 SystemRootPath->Buffer, DestinationArcPath->Buffer,
2257 L"Linux", L"\"Linux\"",
2258 L"hd0", L"1", BootSector);
2259 if (!NT_SUCCESS(Status))
2260 {
2261 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2262 return Status;
2263 }
2264
2265 /* Save current bootsector */
2266 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2267
2268 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2269 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(BTRFS_BOOTSECTOR));
2270 if (!NT_SUCCESS(Status))
2271 {
2272 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2273 return Status;
2274 }
2275 }
2276 else
2277 {
2278 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2279 if (!NT_SUCCESS(Status))
2280 {
2281 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2282 return Status;
2283 }
2284 }
2285
2286 /* Install new bootsector on the disk */
2287 // if (PartitionType == PARTITION_EXT2)
2288 {
2289 /* Install BTRFS bootcode */
2290 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
2291
2292 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2293 Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2294 if (!NT_SUCCESS(Status))
2295 {
2296 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status);
2297 return Status;
2298 }
2299 }
2300 }
2301
2302 return STATUS_SUCCESS;
2303 }
2304
2305
2306 NTSTATUS
2307 InstallVBRToPartition(
2308 IN PUNICODE_STRING SystemRootPath,
2309 IN PUNICODE_STRING SourceRootPath,
2310 IN PUNICODE_STRING DestinationArcPath,
2311 IN UCHAR PartitionType)
2312 {
2313 switch (PartitionType)
2314 {
2315 case PARTITION_FAT_12:
2316 case PARTITION_FAT_16:
2317 case PARTITION_HUGE:
2318 case PARTITION_XINT13:
2319 case PARTITION_FAT32:
2320 case PARTITION_FAT32_XINT13:
2321 {
2322 return InstallFatBootcodeToPartition(SystemRootPath,
2323 SourceRootPath,
2324 DestinationArcPath,
2325 PartitionType);
2326 }
2327
2328 case PARTITION_LINUX:
2329 {
2330 return InstallBtrfsBootcodeToPartition(SystemRootPath,
2331 SourceRootPath,
2332 DestinationArcPath,
2333 PartitionType);
2334 }
2335
2336 case PARTITION_IFS:
2337 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2338 break;
2339
2340 default:
2341 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
2342 break;
2343 }
2344
2345 return STATUS_UNSUCCESSFUL;
2346 }
2347
2348
2349 NTSTATUS
2350 InstallFatBootcodeToFloppy(
2351 IN PUNICODE_STRING SourceRootPath,
2352 IN PUNICODE_STRING DestinationArcPath)
2353 {
2354 NTSTATUS Status;
2355 PFILE_SYSTEM FatFS;
2356 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
2357 WCHAR SrcPath[MAX_PATH];
2358 WCHAR DstPath[MAX_PATH];
2359
2360 /* Verify that the floppy disk is accessible */
2361 if (DoesDirExist(NULL, FloppyDevice.Buffer) == FALSE)
2362 return STATUS_DEVICE_NOT_READY;
2363
2364 /* Format the floppy disk */
2365 FatFS = GetFileSystemByName(L"FAT");
2366 if (!FatFS)
2367 {
2368 DPRINT1("FAT FS non existent on this system?!\n");
2369 return STATUS_NOT_SUPPORTED;
2370 }
2371 Status = FatFS->FormatFunc(&FloppyDevice,
2372 FMIFS_FLOPPY,
2373 NULL,
2374 TRUE,
2375 0,
2376 NULL);
2377 if (!NT_SUCCESS(Status))
2378 {
2379 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2380 return Status;
2381 }
2382
2383 /* Copy FreeLoader to the boot partition */
2384 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2385 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.sys");
2386
2387 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2388 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
2389 if (!NT_SUCCESS(Status))
2390 {
2391 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2392 return Status;
2393 }
2394
2395 /* Create new 'freeldr.ini' */
2396 DPRINT("Create new 'freeldr.ini'\n");
2397 Status = CreateFreeLoaderIniForReactOS(FloppyDevice.Buffer, DestinationArcPath->Buffer);
2398 if (!NT_SUCCESS(Status))
2399 {
2400 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2401 return Status;
2402 }
2403
2404 /* Install FAT12 boosector */
2405 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2406 CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice.Buffer);
2407
2408 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2409 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2410 if (!NT_SUCCESS(Status))
2411 {
2412 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status);
2413 return Status;
2414 }
2415
2416 return STATUS_SUCCESS;
2417 }
2418
2419 /* EOF */