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