3059d0c884c0aa20a294003c342ca7c8bbacb53c
[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 // DPRINT1(" An installation '%S' of unsupported type '%S'\n",
360 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
361 DPRINT1(" 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 DPRINT1(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
392 BootEntry->FriendlyName, Options->OsLoadPath);
393 // DPRINT1(" Found a Win2k3 install '%S' with ARC path '%S'\n",
394 // BootEntry->FriendlyName, Options->OsLoadPath);
395
396 DPRINT1("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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 0,
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 UNICODE_STRING Name;
1617 OBJECT_ATTRIBUTES ObjectAttributes;
1618 IO_STATUS_BLOCK IoStatusBlock;
1619 HANDLE FileHandle;
1620 LARGE_INTEGER FileOffset;
1621 // PEXT2_BOOTSECTOR OrigBootSector;
1622 PBTRFS_BOOTSECTOR NewBootSector;
1623 // USHORT BackupBootSector;
1624 PARTITION_INFORMATION_EX PartInfo;
1625
1626 #if 0
1627 /* Allocate buffer for original bootsector */
1628 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1629 if (OrigBootSector == NULL)
1630 return STATUS_INSUFFICIENT_RESOURCES;
1631
1632 /* Open the root partition - Remove any trailing backslash if needed */
1633 RtlInitUnicodeString(&Name, RootPath);
1634 TrimTrailingPathSeparators_UStr(&Name);
1635
1636 InitializeObjectAttributes(&ObjectAttributes,
1637 &Name,
1638 OBJ_CASE_INSENSITIVE,
1639 NULL,
1640 NULL);
1641
1642 Status = NtOpenFile(&FileHandle,
1643 GENERIC_READ | SYNCHRONIZE,
1644 &ObjectAttributes,
1645 &IoStatusBlock,
1646 0,
1647 FILE_SYNCHRONOUS_IO_NONALERT);
1648 if (!NT_SUCCESS(Status))
1649 {
1650 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1651 return Status;
1652 }
1653
1654 /* Read current boot sector into buffer */
1655 FileOffset.QuadPart = 0ULL;
1656 Status = NtReadFile(FileHandle,
1657 NULL,
1658 NULL,
1659 NULL,
1660 &IoStatusBlock,
1661 OrigBootSector,
1662 SECTORSIZE,
1663 &FileOffset,
1664 NULL);
1665 NtClose(FileHandle);
1666 if (!NT_SUCCESS(Status))
1667 {
1668 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1669 return Status;
1670 }
1671 #endif
1672
1673 /* Allocate buffer for new bootsector */
1674 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR));
1675 if (NewBootSector == NULL)
1676 {
1677 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1678 return STATUS_INSUFFICIENT_RESOURCES;
1679 }
1680
1681 /* Read new bootsector from SrcPath */
1682 RtlInitUnicodeString(&Name, SrcPath);
1683
1684 InitializeObjectAttributes(&ObjectAttributes,
1685 &Name,
1686 OBJ_CASE_INSENSITIVE,
1687 NULL,
1688 NULL);
1689
1690 Status = NtOpenFile(&FileHandle,
1691 GENERIC_READ | SYNCHRONIZE,
1692 &ObjectAttributes,
1693 &IoStatusBlock,
1694 0,
1695 FILE_SYNCHRONOUS_IO_NONALERT);
1696 if (!NT_SUCCESS(Status))
1697 {
1698 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1699 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1700 return Status;
1701 }
1702
1703 Status = NtReadFile(FileHandle,
1704 NULL,
1705 NULL,
1706 NULL,
1707 &IoStatusBlock,
1708 NewBootSector,
1709 sizeof(BTRFS_BOOTSECTOR),
1710 NULL,
1711 NULL);
1712 NtClose(FileHandle);
1713 if (!NT_SUCCESS(Status))
1714 {
1715 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1716 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1717 return Status;
1718 }
1719
1720 #if 0
1721 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1722 memcpy(&NewBootSector->OemName,
1723 &OrigBootSector->OemName,
1724 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1725 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1726
1727 /* Get the location of the backup boot sector */
1728 BackupBootSector = OrigBootSector->BackupBootSector;
1729
1730 /* Free the original boot sector */
1731 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1732 #endif
1733
1734 /* Open the root partition - Remove any trailing backslash if needed */
1735 RtlInitUnicodeString(&Name, RootPath);
1736 TrimTrailingPathSeparators_UStr(&Name);
1737
1738 InitializeObjectAttributes(&ObjectAttributes,
1739 &Name,
1740 OBJ_CASE_INSENSITIVE,
1741 NULL,
1742 NULL);
1743
1744 Status = NtOpenFile(&FileHandle,
1745 GENERIC_WRITE | SYNCHRONIZE,
1746 &ObjectAttributes,
1747 &IoStatusBlock,
1748 0,
1749 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1750 if (!NT_SUCCESS(Status))
1751 {
1752 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1753 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1754 return Status;
1755 }
1756
1757 /* Obtaining partition info and writing it to bootsector */
1758 Status = NtDeviceIoControlFile(FileHandle,
1759 NULL,
1760 NULL,
1761 NULL,
1762 &IoStatusBlock,
1763 IOCTL_DISK_GET_PARTITION_INFO_EX,
1764 NULL,
1765 0,
1766 &PartInfo,
1767 sizeof(PartInfo));
1768 if (!NT_SUCCESS(Status))
1769 {
1770 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status);
1771 NtClose(FileHandle);
1772 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1773 return Status;
1774 }
1775
1776 /* Write new bootsector to RootPath */
1777
1778 NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE;
1779
1780 /* Write sector 0 */
1781 FileOffset.QuadPart = 0ULL;
1782 Status = NtWriteFile(FileHandle,
1783 NULL,
1784 NULL,
1785 NULL,
1786 &IoStatusBlock,
1787 NewBootSector,
1788 sizeof(BTRFS_BOOTSECTOR),
1789 &FileOffset,
1790 NULL);
1791 #if 0
1792 if (!NT_SUCCESS(Status))
1793 {
1794 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1795 NtClose(FileHandle);
1796 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1797 return Status;
1798 }
1799
1800 /* Write backup boot sector */
1801 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1802 {
1803 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1804 Status = NtWriteFile(FileHandle,
1805 NULL,
1806 NULL,
1807 NULL,
1808 &IoStatusBlock,
1809 NewBootSector,
1810 SECTORSIZE,
1811 &FileOffset,
1812 NULL);
1813 if (!NT_SUCCESS(Status))
1814 {
1815 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1816 NtClose(FileHandle);
1817 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1818 return Status;
1819 }
1820 }
1821
1822 /* Write sector 14 */
1823 FileOffset.QuadPart = 14 * SECTORSIZE;
1824 Status = NtWriteFile(FileHandle,
1825 NULL,
1826 NULL,
1827 NULL,
1828 &IoStatusBlock,
1829 ((PUCHAR)NewBootSector + SECTORSIZE),
1830 SECTORSIZE,
1831 &FileOffset,
1832 NULL);
1833 if (!NT_SUCCESS(Status))
1834 {
1835 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1836 }
1837 #endif
1838 NtClose(FileHandle);
1839
1840 /* Free the new boot sector */
1841 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1842
1843 return Status;
1844 }
1845
1846
1847 static
1848 NTSTATUS
1849 InstallFatBootcodeToPartition(
1850 IN PUNICODE_STRING SystemRootPath,
1851 IN PUNICODE_STRING SourceRootPath,
1852 IN PUNICODE_STRING DestinationArcPath,
1853 IN UCHAR PartitionType)
1854 {
1855 NTSTATUS Status;
1856 BOOLEAN DoesFreeLdrExist;
1857 WCHAR SrcPath[MAX_PATH];
1858 WCHAR DstPath[MAX_PATH];
1859
1860 /* FAT or FAT32 partition */
1861 DPRINT("System path: '%wZ'\n", SystemRootPath);
1862
1863 /* Copy FreeLoader to the system partition, always overwriting the older version */
1864 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
1865 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
1866
1867 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1868 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
1869 if (!NT_SUCCESS(Status))
1870 {
1871 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1872 return Status;
1873 }
1874
1875 /* Prepare for possibly updating 'freeldr.ini' */
1876 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
1877 if (DoesFreeLdrExist)
1878 {
1879 /* Update existing 'freeldr.ini' */
1880 DPRINT1("Update existing 'freeldr.ini'\n");
1881 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1882 if (!NT_SUCCESS(Status))
1883 {
1884 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1885 return Status;
1886 }
1887 }
1888
1889 /* Check for NT and other bootloaders */
1890
1891 // FIXME: Check for Vista+ bootloader!
1892 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/
1893 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/
1894 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
1895 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
1896 {
1897 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
1898 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
1899
1900 /* Create or update 'freeldr.ini' */
1901 if (DoesFreeLdrExist == FALSE)
1902 {
1903 /* Create new 'freeldr.ini' */
1904 DPRINT1("Create new 'freeldr.ini'\n");
1905 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
1906 if (!NT_SUCCESS(Status))
1907 {
1908 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
1909 return Status;
1910 }
1911
1912 /* Install new bootcode into a file */
1913 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
1914
1915 if (PartitionType == PARTITION_FAT32 ||
1916 PartitionType == PARTITION_FAT32_XINT13)
1917 {
1918 /* Install FAT32 bootcode */
1919 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
1920
1921 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1922 Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
1923 SystemRootPath->Buffer);
1924 if (!NT_SUCCESS(Status))
1925 {
1926 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1927 return Status;
1928 }
1929 }
1930 else
1931 {
1932 /* Install FAT16 bootcode */
1933 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
1934
1935 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1936 Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
1937 SystemRootPath->Buffer);
1938 if (!NT_SUCCESS(Status))
1939 {
1940 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1941 return Status;
1942 }
1943 }
1944 }
1945
1946 /* Update 'boot.ini' */
1947 /* Windows' NTLDR loads an external bootsector file when the specified drive
1948 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */
1949 DPRINT1("Update 'boot.ini'\n");
1950 Status = UpdateBootIni(SystemRootPath->Buffer,
1951 L"C:\\bootsect.ros",
1952 L"\"ReactOS\"");
1953 if (!NT_SUCCESS(Status))
1954 {
1955 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1956 return Status;
1957 }
1958 }
1959 else
1960 {
1961 /* Non-NT bootloaders: install our own bootloader */
1962
1963 PCWSTR Section;
1964 PCWSTR Description;
1965 PCWSTR BootDrive;
1966 PCWSTR BootPartition;
1967 PCWSTR BootSector;
1968
1969 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
1970 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
1971 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
1972 {
1973 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
1974
1975 Section = L"CPQDOS";
1976 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
1977 BootDrive = L"hd0";
1978 BootPartition = L"1";
1979 BootSector = L"BOOTSECT.DOS";
1980 }
1981 else
1982 /* Search for Microsoft DOS or Windows 9x boot loader */
1983 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
1984 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
1985 // WINBOOT.SYS
1986 {
1987 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1988
1989 Section = L"MSDOS";
1990 Description = L"\"MS-DOS/Windows\"";
1991 BootDrive = L"hd0";
1992 BootPartition = L"1";
1993 BootSector = L"BOOTSECT.DOS";
1994 }
1995 else
1996 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
1997 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
1998 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
1999 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
2000 {
2001 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
2002
2003 Section = L"IBMDOS";
2004 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
2005 BootDrive = L"hd0";
2006 BootPartition = L"1";
2007 BootSector = L"BOOTSECT.DOS";
2008 }
2009 else
2010 /* Search for DR-DOS 3.x boot loader */
2011 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
2012 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
2013 {
2014 DPRINT1("Found DR-DOS 3.x\n");
2015
2016 Section = L"DRDOS";
2017 Description = L"\"DR-DOS 3.x\"";
2018 BootDrive = L"hd0";
2019 BootPartition = L"1";
2020 BootSector = L"BOOTSECT.DOS";
2021 }
2022 else
2023 /* Search for Dell Real-Mode Kernel (DRMK) OS */
2024 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE ||
2025 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE)
2026 {
2027 DPRINT1("Found Dell Real-Mode Kernel OS\n");
2028
2029 Section = L"DRMK";
2030 Description = L"\"Dell Real-Mode Kernel OS\"";
2031 BootDrive = L"hd0";
2032 BootPartition = L"1";
2033 BootSector = L"BOOTSECT.DOS";
2034 }
2035 else
2036 /* Search for MS OS/2 1.x */
2037 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
2038 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
2039 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
2040 {
2041 DPRINT1("Found MS OS/2 1.x\n");
2042
2043 Section = L"MSOS2";
2044 Description = L"\"MS OS/2 1.x\"";
2045 BootDrive = L"hd0";
2046 BootPartition = L"1";
2047 BootSector = L"BOOTSECT.OS2";
2048 }
2049 else
2050 /* Search for MS or IBM OS/2 */
2051 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
2052 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
2053 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
2054 {
2055 DPRINT1("Found MS/IBM OS/2\n");
2056
2057 Section = L"IBMOS2";
2058 Description = L"\"MS/IBM OS/2\"";
2059 BootDrive = L"hd0";
2060 BootPartition = L"1";
2061 BootSector = L"BOOTSECT.OS2";
2062 }
2063 else
2064 /* Search for FreeDOS boot loader */
2065 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
2066 {
2067 DPRINT1("Found FreeDOS boot loader\n");
2068
2069 Section = L"FDOS";
2070 Description = L"\"FreeDOS\"";
2071 BootDrive = L"hd0";
2072 BootPartition = L"1";
2073 BootSector = L"BOOTSECT.DOS";
2074 }
2075 else
2076 {
2077 /* No or unknown boot loader */
2078 DPRINT1("No or unknown boot loader found\n");
2079
2080 Section = L"Unknown";
2081 Description = L"\"Unknown Operating System\"";
2082 BootDrive = L"hd0";
2083 BootPartition = L"1";
2084 BootSector = L"BOOTSECT.OLD";
2085 }
2086
2087 /* Create or update 'freeldr.ini' */
2088 if (DoesFreeLdrExist == FALSE)
2089 {
2090 /* Create new 'freeldr.ini' */
2091 DPRINT1("Create new 'freeldr.ini'\n");
2092
2093 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2094 {
2095 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2096 SystemRootPath->Buffer, DestinationArcPath->Buffer,
2097 Section, Description,
2098 BootDrive, BootPartition, BootSector);
2099 if (!NT_SUCCESS(Status))
2100 {
2101 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2102 return Status;
2103 }
2104
2105 /* Save current bootsector */
2106 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2107
2108 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2109 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
2110 if (!NT_SUCCESS(Status))
2111 {
2112 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2113 return Status;
2114 }
2115 }
2116 else
2117 {
2118 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2119 if (!NT_SUCCESS(Status))
2120 {
2121 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2122 return Status;
2123 }
2124 }
2125
2126 /* Install new bootsector on the disk */
2127 if (PartitionType == PARTITION_FAT32 ||
2128 PartitionType == PARTITION_FAT32_XINT13)
2129 {
2130 /* Install FAT32 bootcode */
2131 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
2132
2133 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2134 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2135 if (!NT_SUCCESS(Status))
2136 {
2137 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2138 return Status;
2139 }
2140 }
2141 else
2142 {
2143 /* Install FAT16 bootcode */
2144 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2145
2146 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2147 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2148 if (!NT_SUCCESS(Status))
2149 {
2150 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2151 return Status;
2152 }
2153 }
2154 }
2155 }
2156
2157 return STATUS_SUCCESS;
2158 }
2159
2160 static
2161 NTSTATUS
2162 InstallBtrfsBootcodeToPartition(
2163 IN PUNICODE_STRING SystemRootPath,
2164 IN PUNICODE_STRING SourceRootPath,
2165 IN PUNICODE_STRING DestinationArcPath,
2166 IN UCHAR PartitionType)
2167 {
2168 NTSTATUS Status;
2169 BOOLEAN DoesFreeLdrExist;
2170 WCHAR SrcPath[MAX_PATH];
2171 WCHAR DstPath[MAX_PATH];
2172
2173 /* BTRFS partition */
2174 DPRINT("System path: '%wZ'\n", SystemRootPath);
2175
2176 /* Copy FreeLoader to the system partition, always overwriting the older version */
2177 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2178 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
2179
2180 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2181 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
2182 if (!NT_SUCCESS(Status))
2183 {
2184 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2185 return Status;
2186 }
2187
2188 /* Prepare for possibly updating 'freeldr.ini' */
2189 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini");
2190 if (DoesFreeLdrExist)
2191 {
2192 /* Update existing 'freeldr.ini' */
2193 DPRINT1("Update existing 'freeldr.ini'\n");
2194 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2195 if (!NT_SUCCESS(Status))
2196 {
2197 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2198 return Status;
2199 }
2200 }
2201
2202 /* Check for *nix bootloaders */
2203
2204 /* Create or update 'freeldr.ini' */
2205 if (DoesFreeLdrExist == FALSE)
2206 {
2207 /* Create new 'freeldr.ini' */
2208 DPRINT1("Create new 'freeldr.ini'\n");
2209
2210 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2211 DPRINT1("*nix or unknown boot loader found\n");
2212
2213 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2214 {
2215 PCWSTR BootSector = L"BOOTSECT.OLD";
2216
2217 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2218 SystemRootPath->Buffer, DestinationArcPath->Buffer,
2219 L"Linux", L"\"Linux\"",
2220 L"hd0", L"1", BootSector);
2221 if (!NT_SUCCESS(Status))
2222 {
2223 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2224 return Status;
2225 }
2226
2227 /* Save current bootsector */
2228 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2229
2230 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2231 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(BTRFS_BOOTSECTOR));
2232 if (!NT_SUCCESS(Status))
2233 {
2234 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2235 return Status;
2236 }
2237 }
2238 else
2239 {
2240 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer);
2241 if (!NT_SUCCESS(Status))
2242 {
2243 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2244 return Status;
2245 }
2246 }
2247
2248 /* Install new bootsector on the disk */
2249 // if (PartitionType == PARTITION_EXT2)
2250 {
2251 /* Install BTRFS bootcode */
2252 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
2253
2254 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2255 Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2256 if (!NT_SUCCESS(Status))
2257 {
2258 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status);
2259 return Status;
2260 }
2261 }
2262 }
2263
2264 return STATUS_SUCCESS;
2265 }
2266
2267
2268 NTSTATUS
2269 InstallVBRToPartition(
2270 IN PUNICODE_STRING SystemRootPath,
2271 IN PUNICODE_STRING SourceRootPath,
2272 IN PUNICODE_STRING DestinationArcPath,
2273 IN UCHAR PartitionType)
2274 {
2275 switch (PartitionType)
2276 {
2277 case PARTITION_FAT_12:
2278 case PARTITION_FAT_16:
2279 case PARTITION_HUGE:
2280 case PARTITION_XINT13:
2281 case PARTITION_FAT32:
2282 case PARTITION_FAT32_XINT13:
2283 {
2284 return InstallFatBootcodeToPartition(SystemRootPath,
2285 SourceRootPath,
2286 DestinationArcPath,
2287 PartitionType);
2288 }
2289
2290 case PARTITION_LINUX:
2291 {
2292 return InstallBtrfsBootcodeToPartition(SystemRootPath,
2293 SourceRootPath,
2294 DestinationArcPath,
2295 PartitionType);
2296 }
2297
2298 case PARTITION_IFS:
2299 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2300 break;
2301
2302 default:
2303 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
2304 break;
2305 }
2306
2307 return STATUS_UNSUCCESSFUL;
2308 }
2309
2310
2311 NTSTATUS
2312 InstallFatBootcodeToFloppy(
2313 IN PUNICODE_STRING SourceRootPath,
2314 IN PUNICODE_STRING DestinationArcPath)
2315 {
2316 NTSTATUS Status;
2317 PFILE_SYSTEM FatFS;
2318 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
2319 WCHAR SrcPath[MAX_PATH];
2320 WCHAR DstPath[MAX_PATH];
2321
2322 /* Verify that the floppy disk is accessible */
2323 if (DoesDirExist(NULL, FloppyDevice.Buffer) == FALSE)
2324 return STATUS_DEVICE_NOT_READY;
2325
2326 /* Format the floppy disk */
2327 FatFS = GetFileSystemByName(L"FAT");
2328 if (!FatFS)
2329 {
2330 DPRINT1("FAT FS non existent on this system?!\n");
2331 return STATUS_NOT_SUPPORTED;
2332 }
2333 Status = FatFS->FormatFunc(&FloppyDevice,
2334 FMIFS_FLOPPY,
2335 NULL,
2336 TRUE,
2337 0,
2338 NULL);
2339 if (!NT_SUCCESS(Status))
2340 {
2341 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2342 return Status;
2343 }
2344
2345 /* Copy FreeLoader to the boot partition */
2346 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2347 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.sys");
2348
2349 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2350 Status = SetupCopyFile(SrcPath, DstPath, FALSE);
2351 if (!NT_SUCCESS(Status))
2352 {
2353 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2354 return Status;
2355 }
2356
2357 /* Create new 'freeldr.ini' */
2358 DPRINT("Create new 'freeldr.ini'\n");
2359 Status = CreateFreeLoaderIniForReactOS(FloppyDevice.Buffer, DestinationArcPath->Buffer);
2360 if (!NT_SUCCESS(Status))
2361 {
2362 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2363 return Status;
2364 }
2365
2366 /* Install FAT12 boosector */
2367 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2368 CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice.Buffer);
2369
2370 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2371 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2372 if (!NT_SUCCESS(Status))
2373 {
2374 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status);
2375 return Status;
2376 }
2377
2378 return STATUS_SUCCESS;
2379 }
2380
2381 /* EOF */