[USETUP][SETUPLIB] Added support for formatting partition in BTRFS and installing...
[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 * PROGRAMMER:
7 */
8
9 #include "usetup.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define SECTORSIZE 512
15
16 #include <pshpack1.h>
17 typedef struct _FAT_BOOTSECTOR
18 {
19 UCHAR JumpBoot[3]; // Jump instruction to boot code
20 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
21 USHORT BytesPerSector; // Bytes per sector
22 UCHAR SectorsPerCluster; // Number of sectors in a cluster
23 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
24 UCHAR NumberOfFats; // Number of FAT tables
25 USHORT RootDirEntries; // Number of root directory entries (fat12/16)
26 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
27 UCHAR MediaDescriptor; // Media descriptor byte
28 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
29 USHORT SectorsPerTrack; // Number of sectors in a track
30 USHORT NumberOfHeads; // Number of heads on the disk
31 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
32 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
33 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
34 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
35 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
36 ULONG VolumeSerialNumber; // Volume serial number
37 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
38 CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
39
40 UCHAR BootCodeAndData[448]; // The remainder of the boot sector
41
42 USHORT BootSectorMagic; // 0xAA55
43
44 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
45
46 typedef struct _FAT32_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 ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
63 USHORT ExtendedFlags; // Extended flags (fat32)
64 USHORT FileSystemVersion; // File system version (fat32)
65 ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32)
66 USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
67 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.
68 UCHAR Reserved[12]; // Reserved for future expansion
69 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
70 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
71 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
72 ULONG VolumeSerialNumber; // Volume serial number
73 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
74 CHAR FileSystemType[8]; // Always set to the string "FAT32 "
75
76 UCHAR BootCodeAndData[420]; // The remainder of the boot sector
77
78 USHORT BootSectorMagic; // 0xAA55
79
80 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
81
82 typedef struct _BTRFS_BOOTSECTOR
83 {
84 UCHAR JumpBoot[3];
85 UCHAR ChunkMapSize;
86 UCHAR BootDrive;
87 ULONGLONG PartitionStartLBA;
88 UCHAR Fill[1521]; // 1536 - 15
89 USHORT BootSectorMagic;
90 } BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR;
91 C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == 3 * 512);
92
93 // TODO: Add more bootsector structures!
94
95 #include <poppack.h>
96
97 extern PPARTLIST PartitionList;
98
99 /* FUNCTIONS ****************************************************************/
100
101
102 static
103 VOID
104 CreateCommonFreeLoaderSections(
105 PINICACHE IniCache)
106 {
107 PINICACHESECTION IniSection;
108
109 /* Create "FREELOADER" section */
110 IniSection = IniCacheAppendSection(IniCache, L"FREELOADER");
111
112 #if DBG
113 if (IsUnattendedSetup)
114 {
115 /* DefaultOS=ReactOS */
116 IniCacheInsertKey(IniSection,
117 NULL,
118 INSERT_LAST,
119 L"DefaultOS",
120 #ifndef _WINKD_
121 L"ReactOS_KdSerial");
122 #else
123 L"ReactOS_Debug");
124 #endif
125 }
126 else
127 #endif
128 {
129 /* DefaultOS=ReactOS */
130 IniCacheInsertKey(IniSection,
131 NULL,
132 INSERT_LAST,
133 L"DefaultOS",
134 L"ReactOS");
135 }
136
137 #if DBG
138 if (IsUnattendedSetup)
139 #endif
140 {
141 /* Timeout=0 for unattended or non debug*/
142 IniCacheInsertKey(IniSection,
143 NULL,
144 INSERT_LAST,
145 L"TimeOut",
146 L"0");
147 }
148 #if DBG
149 else
150 {
151 /* Timeout=0 or 10 */
152 IniCacheInsertKey(IniSection,
153 NULL,
154 INSERT_LAST,
155 L"TimeOut",
156 L"10");
157 }
158 #endif
159
160 /* Create "Display" section */
161 IniSection = IniCacheAppendSection(IniCache, L"Display");
162
163 /* TitleText=ReactOS Boot Manager */
164 IniCacheInsertKey(IniSection,
165 NULL,
166 INSERT_LAST,
167 L"TitleText",
168 L"ReactOS Boot Manager");
169
170 /* StatusBarColor=Cyan */
171 IniCacheInsertKey(IniSection,
172 NULL,
173 INSERT_LAST,
174 L"StatusBarColor",
175 L"Cyan");
176
177 /* StatusBarTextColor=Black */
178 IniCacheInsertKey(IniSection,
179 NULL,
180 INSERT_LAST,
181 L"StatusBarTextColor",
182 L"Black");
183
184 /* BackdropTextColor=White */
185 IniCacheInsertKey(IniSection,
186 NULL,
187 INSERT_LAST,
188 L"BackdropTextColor",
189 L"White");
190
191 /* BackdropColor=Blue */
192 IniCacheInsertKey(IniSection,
193 NULL,
194 INSERT_LAST,
195 L"BackdropColor",
196 L"Blue");
197
198 /* BackdropFillStyle=Medium */
199 IniCacheInsertKey(IniSection,
200 NULL,
201 INSERT_LAST,
202 L"BackdropFillStyle",
203 L"Medium");
204
205 /* TitleBoxTextColor=White */
206 IniCacheInsertKey(IniSection,
207 NULL,
208 INSERT_LAST,
209 L"TitleBoxTextColor",
210 L"White");
211
212 /* TitleBoxColor=Red */
213 IniCacheInsertKey(IniSection,
214 NULL,
215 INSERT_LAST,
216 L"TitleBoxColor",
217 L"Red");
218
219 /* MessageBoxTextColor=White */
220 IniCacheInsertKey(IniSection,
221 NULL,
222 INSERT_LAST,
223 L"MessageBoxTextColor",
224 L"White");
225
226 /* MessageBoxColor=Blue */
227 IniCacheInsertKey(IniSection,
228 NULL,
229 INSERT_LAST,
230 L"MessageBoxColor",
231 L"Blue");
232
233 /* MenuTextColor=White */
234 IniCacheInsertKey(IniSection,
235 NULL,
236 INSERT_LAST,
237 L"MenuTextColor",
238 L"Gray");
239
240 /* MenuColor=Blue */
241 IniCacheInsertKey(IniSection,
242 NULL,
243 INSERT_LAST,
244 L"MenuColor",
245 L"Black");
246
247 /* TextColor=Yellow */
248 IniCacheInsertKey(IniSection,
249 NULL,
250 INSERT_LAST,
251 L"TextColor",
252 L"Gray");
253
254 /* SelectedTextColor=Black */
255 IniCacheInsertKey(IniSection,
256 NULL,
257 INSERT_LAST,
258 L"SelectedTextColor",
259 L"Black");
260
261 /* SelectedColor=Gray */
262 IniCacheInsertKey(IniSection,
263 NULL,
264 INSERT_LAST,
265 L"SelectedColor",
266 L"Gray");
267
268 /* SelectedColor=Gray */
269 IniCacheInsertKey(IniSection,
270 NULL,
271 INSERT_LAST,
272 L"ShowTime",
273 L"No");
274
275 /* SelectedColor=Gray */
276 IniCacheInsertKey(IniSection,
277 NULL,
278 INSERT_LAST,
279 L"MenuBox",
280 L"No");
281
282 /* SelectedColor=Gray */
283 IniCacheInsertKey(IniSection,
284 NULL,
285 INSERT_LAST,
286 L"CenterMenu",
287 L"No");
288
289 /* SelectedColor=Gray */
290 IniCacheInsertKey(IniSection,
291 NULL,
292 INSERT_LAST,
293 L"MinimalUI",
294 L"Yes");
295
296 /* SelectedColor=Gray */
297 IniCacheInsertKey(IniSection,
298 NULL,
299 INSERT_LAST,
300 L"TimeText",
301 L"Seconds until highlighted choice will be started automatically: ");
302 }
303
304 static
305 NTSTATUS
306 CreateNTOSEntry(
307 PINICACHE IniCache,
308 PINICACHESECTION OSSection,
309 PWCHAR Section,
310 PWCHAR Description,
311 PWCHAR BootType,
312 PWCHAR ArcPath,
313 PWCHAR Options)
314 {
315 PINICACHESECTION IniSection;
316
317 /* Insert entry into "Operating Systems" section */
318 IniCacheInsertKey(OSSection,
319 NULL,
320 INSERT_LAST,
321 Section,
322 Description);
323
324 /* Create new section */
325 IniSection = IniCacheAppendSection(IniCache, Section);
326
327 /* BootType= */
328 IniCacheInsertKey(IniSection,
329 NULL,
330 INSERT_LAST,
331 L"BootType",
332 BootType);
333
334 /* SystemPath= */
335 IniCacheInsertKey(IniSection,
336 NULL,
337 INSERT_LAST,
338 L"SystemPath",
339 ArcPath);
340
341 /* Options= */
342 IniCacheInsertKey(IniSection,
343 NULL,
344 INSERT_LAST,
345 L"Options",
346 Options);
347
348 return STATUS_SUCCESS;
349 }
350
351 static
352 VOID
353 CreateFreeLoaderReactOSEntries(
354 PINICACHE IniCache,
355 PWCHAR ArcPath)
356 {
357 PINICACHESECTION IniSection;
358
359 /* Create "Operating Systems" section */
360 IniSection = IniCacheAppendSection(IniCache, L"Operating Systems");
361
362 /* ReactOS */
363 CreateNTOSEntry(IniCache, IniSection,
364 L"ReactOS", L"\"ReactOS\"",
365 L"Windows2003", ArcPath,
366 L"");
367
368 /* ReactOS_Debug */
369 CreateNTOSEntry(IniCache, IniSection,
370 L"ReactOS_Debug", L"\"ReactOS (Debug)\"",
371 L"Windows2003", ArcPath,
372 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS");
373 #ifdef _WINKD_
374 /* ReactOS_VBoxDebug */
375 CreateNTOSEntry(IniCache, IniSection,
376 L"ReactOS_VBoxDebug", L"\"ReactOS (VBoxDebug)\"",
377 L"Windows2003", ArcPath,
378 L"/DEBUG /DEBUGPORT=VBOX /SOS");
379 #endif
380 #if DBG
381 #ifndef _WINKD_
382 /* ReactOS_KdSerial */
383 CreateNTOSEntry(IniCache, IniSection,
384 L"ReactOS_KdSerial", L"\"ReactOS (RosDbg)\"",
385 L"Windows2003", ArcPath,
386 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL");
387 #endif
388
389 /* ReactOS_Screen */
390 CreateNTOSEntry(IniCache, IniSection,
391 L"ReactOS_Screen", L"\"ReactOS (Screen)\"",
392 L"Windows2003", ArcPath,
393 L"/DEBUG /DEBUGPORT=SCREEN /SOS");
394
395 /* ReactOS_LogFile */
396 CreateNTOSEntry(IniCache, IniSection,
397 L"ReactOS_LogFile", L"\"ReactOS (Log file)\"",
398 L"Windows2003", ArcPath,
399 L"/DEBUG /DEBUGPORT=FILE /SOS");
400
401 /* ReactOS_Ram */
402 CreateNTOSEntry(IniCache, IniSection,
403 L"ReactOS_Ram", L"\"ReactOS (RAM Disk)\"",
404 L"Windows2003", L"ramdisk(0)\\ReactOS",
405 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256");
406
407 /* ReactOS_EMS */
408 CreateNTOSEntry(IniCache, IniSection,
409 L"ReactOS_EMS", L"\"ReactOS (Emergency Management Services)\"",
410 L"Windows2003", ArcPath,
411 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200");
412 #endif
413 }
414
415 static
416 NTSTATUS
417 CreateFreeLoaderIniForReactOS(
418 PWCHAR IniPath,
419 PWCHAR ArcPath)
420 {
421 PINICACHE IniCache;
422
423 /* Initialize the INI file */
424 IniCache = IniCacheCreate();
425
426 /* Create the common FreeLdr sections */
427 CreateCommonFreeLoaderSections(IniCache);
428
429 /* Add the ReactOS entries */
430 CreateFreeLoaderReactOSEntries(IniCache, ArcPath);
431
432 /* Save the INI file */
433 IniCacheSave(IniCache, IniPath);
434 IniCacheDestroy(IniCache);
435
436 return STATUS_SUCCESS;
437 }
438
439 static
440 NTSTATUS
441 CreateFreeLoaderIniForReactOSAndBootSector(
442 IN PCWSTR IniPath,
443 IN PCWSTR ArcPath,
444 IN PCWSTR Section,
445 IN PCWSTR Description,
446 IN PCWSTR BootDrive,
447 IN PCWSTR BootPartition,
448 IN PCWSTR BootSector)
449 {
450 PINICACHE IniCache;
451 PINICACHESECTION IniSection;
452
453 /* Initialize the INI file */
454 IniCache = IniCacheCreate();
455
456 /* Create the common FreeLdr sections */
457 CreateCommonFreeLoaderSections(IniCache);
458
459 /* Add the ReactOS entries */
460 CreateFreeLoaderReactOSEntries(IniCache, (PWCHAR)ArcPath);
461
462 /* Get "Operating Systems" section */
463 IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
464
465 /* Insert entry into "Operating Systems" section */
466 IniCacheInsertKey(IniSection,
467 NULL,
468 INSERT_LAST,
469 (PWCHAR)Section,
470 (PWCHAR)Description);
471
472 /* Create new section */
473 IniSection = IniCacheAppendSection(IniCache, (PWCHAR)Section);
474
475 /* BootType=BootSector */
476 IniCacheInsertKey(IniSection,
477 NULL,
478 INSERT_LAST,
479 L"BootType",
480 L"BootSector");
481
482 /* BootDrive= */
483 IniCacheInsertKey(IniSection,
484 NULL,
485 INSERT_LAST,
486 L"BootDrive",
487 (PWCHAR)BootDrive);
488
489 /* BootPartition= */
490 IniCacheInsertKey(IniSection,
491 NULL,
492 INSERT_LAST,
493 L"BootPartition",
494 (PWCHAR)BootPartition);
495
496 /* BootSector= */
497 IniCacheInsertKey(IniSection,
498 NULL,
499 INSERT_LAST,
500 L"BootSectorFile",
501 (PWCHAR)BootSector);
502
503 /* Save the INI file */
504 IniCacheSave(IniCache, (PWCHAR)IniPath);
505 IniCacheDestroy(IniCache);
506
507 return STATUS_SUCCESS;
508 }
509
510 static
511 NTSTATUS
512 UpdateFreeLoaderIni(
513 PWCHAR IniPath,
514 PWCHAR ArcPath)
515 {
516 NTSTATUS Status;
517 PINICACHE IniCache;
518 PINICACHESECTION IniSection;
519 PINICACHESECTION OsIniSection;
520 WCHAR SectionName[80];
521 WCHAR OsName[80];
522 WCHAR SystemPath[200];
523 WCHAR SectionName2[200];
524 PWCHAR KeyData;
525 ULONG i,j;
526
527 Status = IniCacheLoad(&IniCache, IniPath, FALSE);
528 if (!NT_SUCCESS(Status))
529 return Status;
530
531 /* Get "Operating Systems" section */
532 IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
533 if (IniSection == NULL)
534 {
535 IniCacheDestroy(IniCache);
536 return STATUS_UNSUCCESSFUL;
537 }
538
539 /* Find an existing usable or an unused section name */
540 i = 1;
541 wcscpy(SectionName, L"ReactOS");
542 wcscpy(OsName, L"\"ReactOS\"");
543 while(TRUE)
544 {
545 Status = IniCacheGetKey(IniSection, SectionName, &KeyData);
546 if (!NT_SUCCESS(Status))
547 break;
548
549 /* Get operation system section */
550 if (KeyData[0] == '"')
551 {
552 wcscpy(SectionName2, &KeyData[1]);
553 j = wcslen(SectionName2);
554 if (j > 0)
555 {
556 SectionName2[j-1] = 0;
557 }
558 }
559 else
560 {
561 wcscpy(SectionName2, KeyData);
562 }
563
564 /* Search for an existing ReactOS entry */
565 OsIniSection = IniCacheGetSection(IniCache, SectionName2);
566 if (OsIniSection != NULL)
567 {
568 BOOLEAN UseExistingEntry = TRUE;
569
570 /* Check for boot type "Windows2003" */
571 Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
572 if (NT_SUCCESS(Status))
573 {
574 if ((KeyData == NULL) ||
575 ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
576 (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
577 {
578 /* This is not a ReactOS entry */
579 UseExistingEntry = FALSE;
580 }
581 }
582 else
583 {
584 UseExistingEntry = FALSE;
585 }
586
587 if (UseExistingEntry)
588 {
589 /* BootType is Windows2003. Now check SystemPath. */
590 Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
591 if (NT_SUCCESS(Status))
592 {
593 swprintf(SystemPath, L"\"%s\"", ArcPath);
594 if ((KeyData == NULL) ||
595 ( (_wcsicmp(KeyData, ArcPath) != 0) &&
596 (_wcsicmp(KeyData, SystemPath) != 0) ))
597 {
598 /* This entry is a ReactOS entry, but the SystemRoot
599 does not match the one we are looking for. */
600 UseExistingEntry = FALSE;
601 }
602 }
603 else
604 {
605 UseExistingEntry = FALSE;
606 }
607 }
608
609 if (UseExistingEntry)
610 {
611 IniCacheDestroy(IniCache);
612 return STATUS_SUCCESS;
613 }
614 }
615
616 swprintf(SectionName, L"ReactOS_%lu", i);
617 swprintf(OsName, L"\"ReactOS %lu\"", i);
618 i++;
619 }
620
621 /* Create a new "ReactOS" entry */
622 CreateNTOSEntry(IniCache, IniSection,
623 SectionName, OsName,
624 L"Windows2003", ArcPath,
625 L"");
626
627 IniCacheSave(IniCache, IniPath);
628 IniCacheDestroy(IniCache);
629
630 return STATUS_SUCCESS;
631 }
632
633 BOOLEAN
634 IsThereAValidBootSector(PWSTR RootPath)
635 {
636 /*
637 * We first demand that the bootsector has a valid signature at its end.
638 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
639 * potential "valid" instruction (the BIOS starts execution of the bootsector
640 * at its beginning). Currently this criterium is that this ULONG must be
641 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
642 * it is invalid and certainly needs to be overwritten.
643 */
644 BOOLEAN IsValid = FALSE;
645 NTSTATUS Status;
646 UNICODE_STRING Name;
647 OBJECT_ATTRIBUTES ObjectAttributes;
648 IO_STATUS_BLOCK IoStatusBlock;
649 HANDLE FileHandle;
650 LARGE_INTEGER FileOffset;
651 PUCHAR BootSector;
652 ULONG Instruction;
653
654 /* Allocate buffer for bootsector */
655 BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
656 if (BootSector == NULL)
657 return FALSE; // STATUS_INSUFFICIENT_RESOURCES;
658
659 /* Read current boot sector into buffer */
660 RtlInitUnicodeString(&Name, RootPath);
661
662 InitializeObjectAttributes(&ObjectAttributes,
663 &Name,
664 OBJ_CASE_INSENSITIVE,
665 NULL,
666 NULL);
667
668 Status = NtOpenFile(&FileHandle,
669 GENERIC_READ | SYNCHRONIZE,
670 &ObjectAttributes,
671 &IoStatusBlock,
672 0,
673 FILE_SYNCHRONOUS_IO_NONALERT);
674 if (!NT_SUCCESS(Status))
675 goto Quit;
676
677 RtlZeroMemory(BootSector, SECTORSIZE);
678
679 FileOffset.QuadPart = 0ULL;
680 Status = NtReadFile(FileHandle,
681 NULL,
682 NULL,
683 NULL,
684 &IoStatusBlock,
685 BootSector,
686 SECTORSIZE,
687 &FileOffset,
688 NULL);
689 NtClose(FileHandle);
690 if (!NT_SUCCESS(Status))
691 goto Quit;
692
693 /* Check the instruction; we use a ULONG to read three bytes */
694 Instruction = (*(PULONG)BootSector) & 0x00FFFFFF;
695 IsValid = (Instruction != 0x00000000);
696
697 /* Check the bootsector signature */
698 IsValid &= (*(PUSHORT)(BootSector + 0x1fe) == 0xaa55);
699
700 Quit:
701 /* Free the boot sector */
702 RtlFreeHeap(ProcessHeap, 0, BootSector);
703 return IsValid; // Status;
704 }
705
706 NTSTATUS
707 SaveBootSector(
708 PWSTR RootPath,
709 PWSTR DstPath,
710 ULONG Length)
711 {
712 NTSTATUS Status;
713 UNICODE_STRING Name;
714 OBJECT_ATTRIBUTES ObjectAttributes;
715 IO_STATUS_BLOCK IoStatusBlock;
716 HANDLE FileHandle;
717 LARGE_INTEGER FileOffset;
718 PUCHAR BootSector;
719
720 /* Allocate buffer for bootsector */
721 BootSector = RtlAllocateHeap(ProcessHeap, 0, Length);
722 if (BootSector == NULL)
723 return STATUS_INSUFFICIENT_RESOURCES;
724
725 /* Read current boot sector into buffer */
726 RtlInitUnicodeString(&Name, RootPath);
727
728 InitializeObjectAttributes(&ObjectAttributes,
729 &Name,
730 OBJ_CASE_INSENSITIVE,
731 NULL,
732 NULL);
733
734 Status = NtOpenFile(&FileHandle,
735 GENERIC_READ | SYNCHRONIZE,
736 &ObjectAttributes,
737 &IoStatusBlock,
738 0,
739 FILE_SYNCHRONOUS_IO_NONALERT);
740 if (!NT_SUCCESS(Status))
741 {
742 RtlFreeHeap(ProcessHeap, 0, BootSector);
743 return Status;
744 }
745
746 FileOffset.QuadPart = 0ULL;
747 Status = NtReadFile(FileHandle,
748 NULL,
749 NULL,
750 NULL,
751 &IoStatusBlock,
752 BootSector,
753 Length,
754 &FileOffset,
755 NULL);
756 NtClose(FileHandle);
757 if (!NT_SUCCESS(Status))
758 {
759 RtlFreeHeap(ProcessHeap, 0, BootSector);
760 return Status;
761 }
762
763 /* Write bootsector to DstPath */
764 RtlInitUnicodeString(&Name, DstPath);
765
766 InitializeObjectAttributes(&ObjectAttributes,
767 &Name,
768 0,
769 NULL,
770 NULL);
771
772 Status = NtCreateFile(&FileHandle,
773 GENERIC_WRITE | SYNCHRONIZE,
774 &ObjectAttributes,
775 &IoStatusBlock,
776 NULL,
777 FILE_ATTRIBUTE_NORMAL,
778 0,
779 FILE_SUPERSEDE,
780 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
781 NULL,
782 0);
783 if (!NT_SUCCESS(Status))
784 {
785 RtlFreeHeap(ProcessHeap, 0, BootSector);
786 return Status;
787 }
788
789 Status = NtWriteFile(FileHandle,
790 NULL,
791 NULL,
792 NULL,
793 &IoStatusBlock,
794 BootSector,
795 Length,
796 NULL,
797 NULL);
798 NtClose(FileHandle);
799
800 /* Free the boot sector */
801 RtlFreeHeap(ProcessHeap, 0, BootSector);
802
803 return Status;
804 }
805
806 static
807 NTSTATUS
808 InstallFat16BootCodeToFile(
809 PWSTR SrcPath,
810 PWSTR DstPath,
811 PWSTR RootPath)
812 {
813 NTSTATUS Status;
814 UNICODE_STRING Name;
815 OBJECT_ATTRIBUTES ObjectAttributes;
816 IO_STATUS_BLOCK IoStatusBlock;
817 HANDLE FileHandle;
818 LARGE_INTEGER FileOffset;
819 PFAT_BOOTSECTOR OrigBootSector;
820 PFAT_BOOTSECTOR NewBootSector;
821
822 /* Allocate buffer for original bootsector */
823 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
824 if (OrigBootSector == NULL)
825 return STATUS_INSUFFICIENT_RESOURCES;
826
827 /* Read current boot sector into buffer */
828 RtlInitUnicodeString(&Name, RootPath);
829
830 InitializeObjectAttributes(&ObjectAttributes,
831 &Name,
832 OBJ_CASE_INSENSITIVE,
833 NULL,
834 NULL);
835
836 Status = NtOpenFile(&FileHandle,
837 GENERIC_READ | SYNCHRONIZE,
838 &ObjectAttributes,
839 &IoStatusBlock,
840 0,
841 FILE_SYNCHRONOUS_IO_NONALERT);
842 if (!NT_SUCCESS(Status))
843 {
844 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
845 return Status;
846 }
847
848 FileOffset.QuadPart = 0ULL;
849 Status = NtReadFile(FileHandle,
850 NULL,
851 NULL,
852 NULL,
853 &IoStatusBlock,
854 OrigBootSector,
855 SECTORSIZE,
856 &FileOffset,
857 NULL);
858 NtClose(FileHandle);
859 if (!NT_SUCCESS(Status))
860 {
861 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
862 return Status;
863 }
864
865 /* Allocate buffer for new bootsector */
866 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
867 if (NewBootSector == NULL)
868 {
869 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
870 return STATUS_INSUFFICIENT_RESOURCES;
871 }
872
873 /* Read new bootsector from SrcPath */
874 RtlInitUnicodeString(&Name, SrcPath);
875
876 InitializeObjectAttributes(&ObjectAttributes,
877 &Name,
878 OBJ_CASE_INSENSITIVE,
879 NULL,
880 NULL);
881
882 Status = NtOpenFile(&FileHandle,
883 GENERIC_READ | SYNCHRONIZE,
884 &ObjectAttributes,
885 &IoStatusBlock,
886 0,
887 FILE_SYNCHRONOUS_IO_NONALERT);
888 if (!NT_SUCCESS(Status))
889 {
890 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
891 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
892 return Status;
893 }
894
895 FileOffset.QuadPart = 0ULL;
896 Status = NtReadFile(FileHandle,
897 NULL,
898 NULL,
899 NULL,
900 &IoStatusBlock,
901 NewBootSector,
902 SECTORSIZE,
903 &FileOffset,
904 NULL);
905 NtClose(FileHandle);
906 if (!NT_SUCCESS(Status))
907 {
908 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
909 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
910 return Status;
911 }
912
913 /* Adjust bootsector (copy a part of the FAT BPB) */
914 memcpy(&NewBootSector->OemName,
915 &OrigBootSector->OemName,
916 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
917 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
918
919 /* Free the original boot sector */
920 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
921
922 /* Write new bootsector to DstPath */
923 RtlInitUnicodeString(&Name, DstPath);
924
925 InitializeObjectAttributes(&ObjectAttributes,
926 &Name,
927 0,
928 NULL,
929 NULL);
930
931 Status = NtCreateFile(&FileHandle,
932 GENERIC_WRITE | SYNCHRONIZE,
933 &ObjectAttributes,
934 &IoStatusBlock,
935 NULL,
936 FILE_ATTRIBUTE_NORMAL,
937 0,
938 FILE_OVERWRITE_IF,
939 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
940 NULL,
941 0);
942 if (!NT_SUCCESS(Status))
943 {
944 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
945 return Status;
946 }
947
948 Status = NtWriteFile(FileHandle,
949 NULL,
950 NULL,
951 NULL,
952 &IoStatusBlock,
953 NewBootSector,
954 SECTORSIZE,
955 NULL,
956 NULL);
957 NtClose(FileHandle);
958
959 /* Free the new boot sector */
960 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
961
962 return Status;
963 }
964
965 static
966 NTSTATUS
967 InstallFat32BootCodeToFile(
968 PWSTR SrcPath,
969 PWSTR DstPath,
970 PWSTR RootPath)
971 {
972 NTSTATUS Status;
973 UNICODE_STRING Name;
974 OBJECT_ATTRIBUTES ObjectAttributes;
975 IO_STATUS_BLOCK IoStatusBlock;
976 HANDLE FileHandle;
977 LARGE_INTEGER FileOffset;
978 PFAT32_BOOTSECTOR OrigBootSector;
979 PFAT32_BOOTSECTOR NewBootSector;
980
981 /* Allocate buffer for original bootsector */
982 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
983 if (OrigBootSector == NULL)
984 return STATUS_INSUFFICIENT_RESOURCES;
985
986 /* Read current boot sector into buffer */
987 RtlInitUnicodeString(&Name, RootPath);
988
989 InitializeObjectAttributes(&ObjectAttributes,
990 &Name,
991 OBJ_CASE_INSENSITIVE,
992 NULL,
993 NULL);
994
995 Status = NtOpenFile(&FileHandle,
996 GENERIC_READ | SYNCHRONIZE,
997 &ObjectAttributes,
998 &IoStatusBlock,
999 0,
1000 FILE_SYNCHRONOUS_IO_NONALERT);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1004 return Status;
1005 }
1006
1007 Status = NtReadFile(FileHandle,
1008 NULL,
1009 NULL,
1010 NULL,
1011 &IoStatusBlock,
1012 OrigBootSector,
1013 SECTORSIZE,
1014 NULL,
1015 NULL);
1016 NtClose(FileHandle);
1017 if (!NT_SUCCESS(Status))
1018 {
1019 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1020 return Status;
1021 }
1022
1023 /* Allocate buffer for new bootsector (2 sectors) */
1024 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1025 if (NewBootSector == NULL)
1026 {
1027 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1028 return STATUS_INSUFFICIENT_RESOURCES;
1029 }
1030
1031 /* Read new bootsector from SrcPath */
1032 RtlInitUnicodeString(&Name, SrcPath);
1033
1034 InitializeObjectAttributes(&ObjectAttributes,
1035 &Name,
1036 OBJ_CASE_INSENSITIVE,
1037 NULL,
1038 NULL);
1039
1040 Status = NtOpenFile(&FileHandle,
1041 GENERIC_READ | SYNCHRONIZE,
1042 &ObjectAttributes,
1043 &IoStatusBlock,
1044 0,
1045 FILE_SYNCHRONOUS_IO_NONALERT);
1046 if (!NT_SUCCESS(Status))
1047 {
1048 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1049 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1050 return Status;
1051 }
1052
1053 Status = NtReadFile(FileHandle,
1054 NULL,
1055 NULL,
1056 NULL,
1057 &IoStatusBlock,
1058 NewBootSector,
1059 2 * SECTORSIZE,
1060 NULL,
1061 NULL);
1062 NtClose(FileHandle);
1063 if (!NT_SUCCESS(Status))
1064 {
1065 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1066 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1067 return Status;
1068 }
1069
1070 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1071 memcpy(&NewBootSector->OemName,
1072 &OrigBootSector->OemName,
1073 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1074 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1075
1076 /* Disable the backup boot sector */
1077 NewBootSector->BackupBootSector = 0;
1078
1079 /* Free the original boot sector */
1080 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1081
1082 /* Write the first sector of the new bootcode to DstPath */
1083 RtlInitUnicodeString(&Name, DstPath);
1084
1085 InitializeObjectAttributes(&ObjectAttributes,
1086 &Name,
1087 0,
1088 NULL,
1089 NULL);
1090
1091 Status = NtCreateFile(&FileHandle,
1092 GENERIC_WRITE | SYNCHRONIZE,
1093 &ObjectAttributes,
1094 &IoStatusBlock,
1095 NULL,
1096 FILE_ATTRIBUTE_NORMAL,
1097 0,
1098 FILE_SUPERSEDE,
1099 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1100 NULL,
1101 0);
1102 if (!NT_SUCCESS(Status))
1103 {
1104 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1105 return Status;
1106 }
1107
1108 Status = NtWriteFile(FileHandle,
1109 NULL,
1110 NULL,
1111 NULL,
1112 &IoStatusBlock,
1113 NewBootSector,
1114 SECTORSIZE,
1115 NULL,
1116 NULL);
1117 NtClose(FileHandle);
1118 if (!NT_SUCCESS(Status))
1119 {
1120 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1121 return Status;
1122 }
1123
1124 /* Write the second sector of the new bootcode to boot disk sector 14 */
1125 RtlInitUnicodeString(&Name, RootPath);
1126
1127 InitializeObjectAttributes(&ObjectAttributes,
1128 &Name,
1129 0,
1130 NULL,
1131 NULL);
1132
1133 Status = NtOpenFile(&FileHandle,
1134 GENERIC_WRITE | SYNCHRONIZE,
1135 &ObjectAttributes,
1136 &IoStatusBlock,
1137 0,
1138 FILE_SYNCHRONOUS_IO_NONALERT);
1139 if (!NT_SUCCESS(Status))
1140 {
1141 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1142 return Status;
1143 }
1144
1145 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1146 Status = NtWriteFile(FileHandle,
1147 NULL,
1148 NULL,
1149 NULL,
1150 &IoStatusBlock,
1151 ((PUCHAR)NewBootSector + SECTORSIZE),
1152 SECTORSIZE,
1153 &FileOffset,
1154 NULL);
1155 if (!NT_SUCCESS(Status))
1156 {
1157 }
1158 NtClose(FileHandle);
1159
1160 /* Free the new boot sector */
1161 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1162
1163 return Status;
1164 }
1165
1166
1167 NTSTATUS
1168 InstallMbrBootCodeToDisk(
1169 PWSTR SrcPath,
1170 PWSTR RootPath)
1171 {
1172 NTSTATUS Status;
1173 UNICODE_STRING Name;
1174 OBJECT_ATTRIBUTES ObjectAttributes;
1175 IO_STATUS_BLOCK IoStatusBlock;
1176 HANDLE FileHandle;
1177 LARGE_INTEGER FileOffset;
1178 PPARTITION_SECTOR OrigBootSector;
1179 PPARTITION_SECTOR NewBootSector;
1180
1181 /* Allocate buffer for original bootsector */
1182 OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1183 0,
1184 sizeof(PARTITION_SECTOR));
1185 if (OrigBootSector == NULL)
1186 return STATUS_INSUFFICIENT_RESOURCES;
1187
1188 /* Read current boot sector into buffer */
1189 RtlInitUnicodeString(&Name,
1190 RootPath);
1191
1192 InitializeObjectAttributes(&ObjectAttributes,
1193 &Name,
1194 OBJ_CASE_INSENSITIVE,
1195 NULL,
1196 NULL);
1197
1198 Status = NtOpenFile(&FileHandle,
1199 GENERIC_READ | SYNCHRONIZE,
1200 &ObjectAttributes,
1201 &IoStatusBlock,
1202 0,
1203 FILE_SYNCHRONOUS_IO_NONALERT);
1204 if (!NT_SUCCESS(Status))
1205 {
1206 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1207 return Status;
1208 }
1209
1210 FileOffset.QuadPart = 0ULL;
1211 Status = NtReadFile(FileHandle,
1212 NULL,
1213 NULL,
1214 NULL,
1215 &IoStatusBlock,
1216 OrigBootSector,
1217 sizeof(PARTITION_SECTOR),
1218 &FileOffset,
1219 NULL);
1220 NtClose(FileHandle);
1221 if (!NT_SUCCESS(Status))
1222 {
1223 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1224 return Status;
1225 }
1226
1227 /* Allocate buffer for new bootsector */
1228 NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1229 0,
1230 sizeof(PARTITION_SECTOR));
1231 if (NewBootSector == NULL)
1232 {
1233 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1234 return STATUS_INSUFFICIENT_RESOURCES;
1235 }
1236
1237 /* Read new bootsector from SrcPath */
1238 RtlInitUnicodeString(&Name, SrcPath);
1239
1240 InitializeObjectAttributes(&ObjectAttributes,
1241 &Name,
1242 OBJ_CASE_INSENSITIVE,
1243 NULL,
1244 NULL);
1245
1246 Status = NtOpenFile(&FileHandle,
1247 GENERIC_READ | SYNCHRONIZE,
1248 &ObjectAttributes,
1249 &IoStatusBlock,
1250 0,
1251 FILE_SYNCHRONOUS_IO_NONALERT);
1252 if (!NT_SUCCESS(Status))
1253 {
1254 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1255 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1256 return Status;
1257 }
1258
1259 Status = NtReadFile(FileHandle,
1260 NULL,
1261 NULL,
1262 NULL,
1263 &IoStatusBlock,
1264 NewBootSector,
1265 sizeof(PARTITION_SECTOR),
1266 NULL,
1267 NULL);
1268 NtClose(FileHandle);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1272 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1273 return Status;
1274 }
1275
1276 /*
1277 * Copy the disk signature, the reserved fields and
1278 * the partition table from the old MBR to the new one.
1279 */
1280 RtlCopyMemory(&NewBootSector->Signature,
1281 &OrigBootSector->Signature,
1282 sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */);
1283
1284 /* Free the original boot sector */
1285 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1286
1287 /* Write new bootsector to RootPath */
1288 RtlInitUnicodeString(&Name, RootPath);
1289
1290 InitializeObjectAttributes(&ObjectAttributes,
1291 &Name,
1292 0,
1293 NULL,
1294 NULL);
1295
1296 Status = NtOpenFile(&FileHandle,
1297 GENERIC_WRITE | SYNCHRONIZE,
1298 &ObjectAttributes,
1299 &IoStatusBlock,
1300 0,
1301 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1302 if (!NT_SUCCESS(Status))
1303 {
1304 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1305 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1306 return Status;
1307 }
1308
1309 FileOffset.QuadPart = 0ULL;
1310 Status = NtWriteFile(FileHandle,
1311 NULL,
1312 NULL,
1313 NULL,
1314 &IoStatusBlock,
1315 NewBootSector,
1316 sizeof(PARTITION_SECTOR),
1317 &FileOffset,
1318 NULL);
1319 NtClose(FileHandle);
1320
1321 /* Free the new boot sector */
1322 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1323
1324 return Status;
1325 }
1326
1327 static
1328 NTSTATUS
1329 InstallFat12BootCodeToFloppy(
1330 PWSTR SrcPath,
1331 PWSTR RootPath)
1332 {
1333 NTSTATUS Status;
1334 UNICODE_STRING Name;
1335 OBJECT_ATTRIBUTES ObjectAttributes;
1336 IO_STATUS_BLOCK IoStatusBlock;
1337 HANDLE FileHandle;
1338 LARGE_INTEGER FileOffset;
1339 PFAT_BOOTSECTOR OrigBootSector;
1340 PFAT_BOOTSECTOR NewBootSector;
1341
1342 /* Allocate buffer for original bootsector */
1343 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1344 if (OrigBootSector == NULL)
1345 return STATUS_INSUFFICIENT_RESOURCES;
1346
1347 /* Read current boot sector into buffer */
1348 RtlInitUnicodeString(&Name, RootPath);
1349
1350 InitializeObjectAttributes(&ObjectAttributes,
1351 &Name,
1352 OBJ_CASE_INSENSITIVE,
1353 NULL,
1354 NULL);
1355
1356 Status = NtOpenFile(&FileHandle,
1357 GENERIC_READ | SYNCHRONIZE,
1358 &ObjectAttributes,
1359 &IoStatusBlock,
1360 0,
1361 FILE_SYNCHRONOUS_IO_NONALERT);
1362 if (!NT_SUCCESS(Status))
1363 {
1364 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1365 return Status;
1366 }
1367
1368 FileOffset.QuadPart = 0ULL;
1369 Status = NtReadFile(FileHandle,
1370 NULL,
1371 NULL,
1372 NULL,
1373 &IoStatusBlock,
1374 OrigBootSector,
1375 SECTORSIZE,
1376 &FileOffset,
1377 NULL);
1378 NtClose(FileHandle);
1379 if (!NT_SUCCESS(Status))
1380 {
1381 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1382 return Status;
1383 }
1384
1385 /* Allocate buffer for new bootsector */
1386 NewBootSector = RtlAllocateHeap(ProcessHeap,
1387 0,
1388 SECTORSIZE);
1389 if (NewBootSector == NULL)
1390 {
1391 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1392 return STATUS_INSUFFICIENT_RESOURCES;
1393 }
1394
1395 /* Read new bootsector from SrcPath */
1396 RtlInitUnicodeString(&Name, SrcPath);
1397
1398 InitializeObjectAttributes(&ObjectAttributes,
1399 &Name,
1400 OBJ_CASE_INSENSITIVE,
1401 NULL,
1402 NULL);
1403
1404 Status = NtOpenFile(&FileHandle,
1405 GENERIC_READ | SYNCHRONIZE,
1406 &ObjectAttributes,
1407 &IoStatusBlock,
1408 0,
1409 FILE_SYNCHRONOUS_IO_NONALERT);
1410 if (!NT_SUCCESS(Status))
1411 {
1412 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1413 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1414 return Status;
1415 }
1416
1417 Status = NtReadFile(FileHandle,
1418 NULL,
1419 NULL,
1420 NULL,
1421 &IoStatusBlock,
1422 NewBootSector,
1423 SECTORSIZE,
1424 NULL,
1425 NULL);
1426 NtClose(FileHandle);
1427 if (!NT_SUCCESS(Status))
1428 {
1429 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1430 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1431 return Status;
1432 }
1433
1434 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1435 memcpy(&NewBootSector->OemName,
1436 &OrigBootSector->OemName,
1437 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1438 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1439
1440 /* Free the original boot sector */
1441 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1442
1443 /* Write new bootsector to RootPath */
1444 RtlInitUnicodeString(&Name, RootPath);
1445
1446 InitializeObjectAttributes(&ObjectAttributes,
1447 &Name,
1448 0,
1449 NULL,
1450 NULL);
1451
1452 Status = NtOpenFile(&FileHandle,
1453 GENERIC_WRITE | SYNCHRONIZE,
1454 &ObjectAttributes,
1455 &IoStatusBlock,
1456 0,
1457 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1458 if (!NT_SUCCESS(Status))
1459 {
1460 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1461 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1462 return Status;
1463 }
1464
1465 FileOffset.QuadPart = 0ULL;
1466 Status = NtWriteFile(FileHandle,
1467 NULL,
1468 NULL,
1469 NULL,
1470 &IoStatusBlock,
1471 NewBootSector,
1472 SECTORSIZE,
1473 &FileOffset,
1474 NULL);
1475 NtClose(FileHandle);
1476
1477 /* Free the new boot sector */
1478 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1479
1480 return Status;
1481 }
1482
1483 static
1484 NTSTATUS
1485 InstallFat16BootCodeToDisk(
1486 PWSTR SrcPath,
1487 PWSTR RootPath)
1488 {
1489 NTSTATUS Status;
1490 UNICODE_STRING Name;
1491 OBJECT_ATTRIBUTES ObjectAttributes;
1492 IO_STATUS_BLOCK IoStatusBlock;
1493 HANDLE FileHandle;
1494 LARGE_INTEGER FileOffset;
1495 PFAT_BOOTSECTOR OrigBootSector;
1496 PFAT_BOOTSECTOR NewBootSector;
1497
1498 /* Allocate buffer for original bootsector */
1499 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1500 if (OrigBootSector == NULL)
1501 return STATUS_INSUFFICIENT_RESOURCES;
1502
1503 /* Read current boot sector into buffer */
1504 RtlInitUnicodeString(&Name, RootPath);
1505
1506 InitializeObjectAttributes(&ObjectAttributes,
1507 &Name,
1508 OBJ_CASE_INSENSITIVE,
1509 NULL,
1510 NULL);
1511
1512 Status = NtOpenFile(&FileHandle,
1513 GENERIC_READ | SYNCHRONIZE,
1514 &ObjectAttributes,
1515 &IoStatusBlock,
1516 0,
1517 FILE_SYNCHRONOUS_IO_NONALERT);
1518 if (!NT_SUCCESS(Status))
1519 {
1520 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1521 return Status;
1522 }
1523
1524 FileOffset.QuadPart = 0ULL;
1525 Status = NtReadFile(FileHandle,
1526 NULL,
1527 NULL,
1528 NULL,
1529 &IoStatusBlock,
1530 OrigBootSector,
1531 SECTORSIZE,
1532 &FileOffset,
1533 NULL);
1534 NtClose(FileHandle);
1535 if (!NT_SUCCESS(Status))
1536 {
1537 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1538 return Status;
1539 }
1540
1541 /* Allocate buffer for new bootsector */
1542 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1543 if (NewBootSector == NULL)
1544 {
1545 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1546 return STATUS_INSUFFICIENT_RESOURCES;
1547 }
1548
1549 /* Read new bootsector from SrcPath */
1550 RtlInitUnicodeString(&Name, SrcPath);
1551
1552 InitializeObjectAttributes(&ObjectAttributes,
1553 &Name,
1554 OBJ_CASE_INSENSITIVE,
1555 NULL,
1556 NULL);
1557
1558 Status = NtOpenFile(&FileHandle,
1559 GENERIC_READ | SYNCHRONIZE,
1560 &ObjectAttributes,
1561 &IoStatusBlock,
1562 0,
1563 FILE_SYNCHRONOUS_IO_NONALERT);
1564 if (!NT_SUCCESS(Status))
1565 {
1566 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1567 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1568 return Status;
1569 }
1570
1571 Status = NtReadFile(FileHandle,
1572 NULL,
1573 NULL,
1574 NULL,
1575 &IoStatusBlock,
1576 NewBootSector,
1577 SECTORSIZE,
1578 NULL,
1579 NULL);
1580 NtClose(FileHandle);
1581 if (!NT_SUCCESS(Status))
1582 {
1583 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1584 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1585 return Status;
1586 }
1587
1588 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1589 memcpy(&NewBootSector->OemName,
1590 &OrigBootSector->OemName,
1591 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1592 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1593
1594 /* Free the original boot sector */
1595 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1596
1597 /* Write new bootsector to RootPath */
1598 RtlInitUnicodeString(&Name, RootPath);
1599
1600 InitializeObjectAttributes(&ObjectAttributes,
1601 &Name,
1602 0,
1603 NULL,
1604 NULL);
1605
1606 Status = NtOpenFile(&FileHandle,
1607 GENERIC_WRITE | SYNCHRONIZE,
1608 &ObjectAttributes,
1609 &IoStatusBlock,
1610 0,
1611 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1612 if (!NT_SUCCESS(Status))
1613 {
1614 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1615 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1616 return Status;
1617 }
1618
1619 FileOffset.QuadPart = 0ULL;
1620 Status = NtWriteFile(FileHandle,
1621 NULL,
1622 NULL,
1623 NULL,
1624 &IoStatusBlock,
1625 NewBootSector,
1626 SECTORSIZE,
1627 &FileOffset,
1628 NULL);
1629 NtClose(FileHandle);
1630
1631 /* Free the new boot sector */
1632 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1633
1634 return Status;
1635 }
1636
1637 static
1638 NTSTATUS
1639 InstallFat32BootCodeToDisk(
1640 PWSTR SrcPath,
1641 PWSTR RootPath)
1642 {
1643 NTSTATUS Status;
1644 UNICODE_STRING Name;
1645 OBJECT_ATTRIBUTES ObjectAttributes;
1646 IO_STATUS_BLOCK IoStatusBlock;
1647 HANDLE FileHandle;
1648 LARGE_INTEGER FileOffset;
1649 PFAT32_BOOTSECTOR OrigBootSector;
1650 PFAT32_BOOTSECTOR NewBootSector;
1651 USHORT BackupBootSector;
1652
1653 /* Allocate buffer for original bootsector */
1654 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1655 if (OrigBootSector == NULL)
1656 return STATUS_INSUFFICIENT_RESOURCES;
1657
1658 /* Read current boot sector into buffer */
1659 RtlInitUnicodeString(&Name, RootPath);
1660
1661 InitializeObjectAttributes(&ObjectAttributes,
1662 &Name,
1663 OBJ_CASE_INSENSITIVE,
1664 NULL,
1665 NULL);
1666
1667 Status = NtOpenFile(&FileHandle,
1668 GENERIC_READ | SYNCHRONIZE,
1669 &ObjectAttributes,
1670 &IoStatusBlock,
1671 0,
1672 FILE_SYNCHRONOUS_IO_NONALERT);
1673 if (!NT_SUCCESS(Status))
1674 {
1675 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1676 return Status;
1677 }
1678
1679 FileOffset.QuadPart = 0ULL;
1680 Status = NtReadFile(FileHandle,
1681 NULL,
1682 NULL,
1683 NULL,
1684 &IoStatusBlock,
1685 OrigBootSector,
1686 SECTORSIZE,
1687 &FileOffset,
1688 NULL);
1689 NtClose(FileHandle);
1690 if (!NT_SUCCESS(Status))
1691 {
1692 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1693 return Status;
1694 }
1695
1696
1697 /* Allocate buffer for new bootsector (2 sectors) */
1698 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1699 if (NewBootSector == NULL)
1700 {
1701 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1702 return STATUS_INSUFFICIENT_RESOURCES;
1703 }
1704
1705 /* Read new bootsector from SrcPath */
1706 RtlInitUnicodeString(&Name, SrcPath);
1707
1708 InitializeObjectAttributes(&ObjectAttributes,
1709 &Name,
1710 OBJ_CASE_INSENSITIVE,
1711 NULL,
1712 NULL);
1713
1714 Status = NtOpenFile(&FileHandle,
1715 GENERIC_READ | SYNCHRONIZE,
1716 &ObjectAttributes,
1717 &IoStatusBlock,
1718 0,
1719 FILE_SYNCHRONOUS_IO_NONALERT);
1720 if (!NT_SUCCESS(Status))
1721 {
1722 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1723 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1724 return Status;
1725 }
1726
1727 Status = NtReadFile(FileHandle,
1728 NULL,
1729 NULL,
1730 NULL,
1731 &IoStatusBlock,
1732 NewBootSector,
1733 2 * SECTORSIZE,
1734 NULL,
1735 NULL);
1736 NtClose(FileHandle);
1737 if (!NT_SUCCESS(Status))
1738 {
1739 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1740 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1741 return Status;
1742 }
1743
1744 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1745 memcpy(&NewBootSector->OemName,
1746 &OrigBootSector->OemName,
1747 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1748 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1749
1750 /* Get the location of the backup boot sector */
1751 BackupBootSector = OrigBootSector->BackupBootSector;
1752
1753 /* Free the original boot sector */
1754 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1755
1756 /* Write the first sector of the new bootcode to DstPath */
1757 RtlInitUnicodeString(&Name, RootPath);
1758
1759 InitializeObjectAttributes(&ObjectAttributes,
1760 &Name,
1761 0,
1762 NULL,
1763 NULL);
1764
1765 Status = NtOpenFile(&FileHandle,
1766 GENERIC_WRITE | SYNCHRONIZE,
1767 &ObjectAttributes,
1768 &IoStatusBlock,
1769 0,
1770 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1771 if (!NT_SUCCESS(Status))
1772 {
1773 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1774 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1775 return Status;
1776 }
1777
1778 /* Write sector 0 */
1779 FileOffset.QuadPart = 0ULL;
1780 Status = NtWriteFile(FileHandle,
1781 NULL,
1782 NULL,
1783 NULL,
1784 &IoStatusBlock,
1785 NewBootSector,
1786 SECTORSIZE,
1787 &FileOffset,
1788 NULL);
1789 if (!NT_SUCCESS(Status))
1790 {
1791 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1792 NtClose(FileHandle);
1793 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1794 return Status;
1795 }
1796
1797 /* Write backup boot sector */
1798 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1799 {
1800 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1801 Status = NtWriteFile(FileHandle,
1802 NULL,
1803 NULL,
1804 NULL,
1805 &IoStatusBlock,
1806 NewBootSector,
1807 SECTORSIZE,
1808 &FileOffset,
1809 NULL);
1810 if (!NT_SUCCESS(Status))
1811 {
1812 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1813 NtClose(FileHandle);
1814 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1815 return Status;
1816 }
1817 }
1818
1819 /* Write sector 14 */
1820 FileOffset.QuadPart = 14 * SECTORSIZE;
1821 Status = NtWriteFile(FileHandle,
1822 NULL,
1823 NULL,
1824 NULL,
1825 &IoStatusBlock,
1826 ((PUCHAR)NewBootSector + SECTORSIZE),
1827 SECTORSIZE,
1828 &FileOffset,
1829 NULL);
1830 if (!NT_SUCCESS(Status))
1831 {
1832 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1833 }
1834 NtClose(FileHandle);
1835
1836 /* Free the new boot sector */
1837 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1838
1839 return Status;
1840 }
1841
1842 static
1843 NTSTATUS
1844 InstallBtrfsBootCodeToDisk(
1845 PWSTR SrcPath,
1846 PWSTR RootPath)
1847 {
1848 NTSTATUS Status;
1849 UNICODE_STRING Name;
1850 OBJECT_ATTRIBUTES ObjectAttributes;
1851 IO_STATUS_BLOCK IoStatusBlock;
1852 HANDLE FileHandle;
1853 LARGE_INTEGER FileOffset;
1854 // PEXT2_BOOTSECTOR OrigBootSector;
1855 PBTRFS_BOOTSECTOR NewBootSector;
1856 // USHORT BackupBootSector;
1857 PARTITION_INFORMATION_EX PartInfo;
1858
1859 #if 0
1860 /* Allocate buffer for original bootsector */
1861 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1862 if (OrigBootSector == NULL)
1863 return STATUS_INSUFFICIENT_RESOURCES;
1864
1865 /* Read current boot sector into buffer */
1866 RtlInitUnicodeString(&Name, RootPath);
1867
1868 InitializeObjectAttributes(&ObjectAttributes,
1869 &Name,
1870 OBJ_CASE_INSENSITIVE,
1871 NULL,
1872 NULL);
1873
1874 Status = NtOpenFile(&FileHandle,
1875 GENERIC_READ | SYNCHRONIZE,
1876 &ObjectAttributes,
1877 &IoStatusBlock,
1878 0,
1879 FILE_SYNCHRONOUS_IO_NONALERT);
1880 if (!NT_SUCCESS(Status))
1881 {
1882 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1883 return Status;
1884 }
1885
1886 FileOffset.QuadPart = 0ULL;
1887 Status = NtReadFile(FileHandle,
1888 NULL,
1889 NULL,
1890 NULL,
1891 &IoStatusBlock,
1892 OrigBootSector,
1893 SECTORSIZE,
1894 &FileOffset,
1895 NULL);
1896 NtClose(FileHandle);
1897 if (!NT_SUCCESS(Status))
1898 {
1899 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1900 return Status;
1901 }
1902 #endif
1903
1904 /* Allocate buffer for new bootsector */
1905 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR));
1906 if (NewBootSector == NULL)
1907 {
1908 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1909 return STATUS_INSUFFICIENT_RESOURCES;
1910 }
1911
1912 /* Read new bootsector from SrcPath */
1913 RtlInitUnicodeString(&Name, SrcPath);
1914
1915 InitializeObjectAttributes(&ObjectAttributes,
1916 &Name,
1917 OBJ_CASE_INSENSITIVE,
1918 NULL,
1919 NULL);
1920
1921 Status = NtOpenFile(&FileHandle,
1922 GENERIC_READ | SYNCHRONIZE,
1923 &ObjectAttributes,
1924 &IoStatusBlock,
1925 0,
1926 FILE_SYNCHRONOUS_IO_NONALERT);
1927 if (!NT_SUCCESS(Status))
1928 {
1929 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1930 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1931 return Status;
1932 }
1933
1934 Status = NtReadFile(FileHandle,
1935 NULL,
1936 NULL,
1937 NULL,
1938 &IoStatusBlock,
1939 NewBootSector,
1940 sizeof(BTRFS_BOOTSECTOR),
1941 NULL,
1942 NULL);
1943 NtClose(FileHandle);
1944 if (!NT_SUCCESS(Status))
1945 {
1946 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1947 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1948 return Status;
1949 }
1950
1951 #if 0
1952 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1953 memcpy(&NewBootSector->OemName,
1954 &OrigBootSector->OemName,
1955 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1956 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1957
1958 NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
1959
1960 /* Get the location of the backup boot sector */
1961 BackupBootSector = OrigBootSector->BackupBootSector;
1962
1963 /* Free the original boot sector */
1964 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1965 #endif
1966
1967 /* Write new bootsector to RootPath */
1968 RtlInitUnicodeString(&Name, RootPath);
1969
1970 InitializeObjectAttributes(&ObjectAttributes,
1971 &Name,
1972 0,
1973 NULL,
1974 NULL);
1975
1976 Status = NtOpenFile(&FileHandle,
1977 GENERIC_WRITE | SYNCHRONIZE,
1978 &ObjectAttributes,
1979 &IoStatusBlock,
1980 0,
1981 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1982 if (!NT_SUCCESS(Status))
1983 {
1984 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1985 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1986 return Status;
1987 }
1988
1989 /* Obtaining partition info and writing it to bootsector */
1990 Status = NtDeviceIoControlFile(FileHandle,
1991 NULL,
1992 NULL,
1993 NULL,
1994 &IoStatusBlock,
1995 IOCTL_DISK_GET_PARTITION_INFO_EX,
1996 NULL,
1997 0,
1998 &PartInfo,
1999 sizeof(PartInfo));
2000
2001 if (!NT_SUCCESS(Status))
2002 {
2003 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status);
2004 NtClose(FileHandle);
2005 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2006 return Status;
2007 }
2008
2009 NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE;
2010
2011 /* Write sector 0 */
2012 FileOffset.QuadPart = 0ULL;
2013 Status = NtWriteFile(FileHandle,
2014 NULL,
2015 NULL,
2016 NULL,
2017 &IoStatusBlock,
2018 NewBootSector,
2019 sizeof(BTRFS_BOOTSECTOR),
2020 &FileOffset,
2021 NULL);
2022 #if 0
2023 if (!NT_SUCCESS(Status))
2024 {
2025 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2026 NtClose(FileHandle);
2027 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2028 return Status;
2029 }
2030
2031 /* Write backup boot sector */
2032 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
2033 {
2034 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
2035 Status = NtWriteFile(FileHandle,
2036 NULL,
2037 NULL,
2038 NULL,
2039 &IoStatusBlock,
2040 NewBootSector,
2041 SECTORSIZE,
2042 &FileOffset,
2043 NULL);
2044 if (!NT_SUCCESS(Status))
2045 {
2046 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2047 NtClose(FileHandle);
2048 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2049 return Status;
2050 }
2051 }
2052
2053 /* Write sector 14 */
2054 FileOffset.QuadPart = 14 * SECTORSIZE;
2055 Status = NtWriteFile(FileHandle,
2056 NULL,
2057 NULL,
2058 NULL,
2059 &IoStatusBlock,
2060 ((PUCHAR)NewBootSector + SECTORSIZE),
2061 SECTORSIZE,
2062 &FileOffset,
2063 NULL);
2064 if (!NT_SUCCESS(Status))
2065 {
2066 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2067 }
2068 #endif
2069 NtClose(FileHandle);
2070
2071 /* Free the new boot sector */
2072 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2073
2074 return Status;
2075 }
2076
2077 static
2078 NTSTATUS
2079 UnprotectBootIni(
2080 PWSTR FileName,
2081 PULONG Attributes)
2082 {
2083 NTSTATUS Status;
2084 UNICODE_STRING Name;
2085 OBJECT_ATTRIBUTES ObjectAttributes;
2086 IO_STATUS_BLOCK IoStatusBlock;
2087 FILE_BASIC_INFORMATION FileInfo;
2088 HANDLE FileHandle;
2089
2090 RtlInitUnicodeString(&Name, FileName);
2091
2092 InitializeObjectAttributes(&ObjectAttributes,
2093 &Name,
2094 OBJ_CASE_INSENSITIVE,
2095 NULL,
2096 NULL);
2097
2098 Status = NtOpenFile(&FileHandle,
2099 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2100 &ObjectAttributes,
2101 &IoStatusBlock,
2102 0,
2103 FILE_SYNCHRONOUS_IO_NONALERT);
2104 if (Status == STATUS_NO_SUCH_FILE)
2105 {
2106 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2107 *Attributes = 0;
2108 return STATUS_SUCCESS;
2109 }
2110 if (!NT_SUCCESS(Status))
2111 {
2112 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2113 return Status;
2114 }
2115
2116 Status = NtQueryInformationFile(FileHandle,
2117 &IoStatusBlock,
2118 &FileInfo,
2119 sizeof(FILE_BASIC_INFORMATION),
2120 FileBasicInformation);
2121 if (!NT_SUCCESS(Status))
2122 {
2123 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2124 NtClose(FileHandle);
2125 return Status;
2126 }
2127
2128 *Attributes = FileInfo.FileAttributes;
2129
2130 /* Delete attributes SYSTEM, HIDDEN and READONLY */
2131 FileInfo.FileAttributes = FileInfo.FileAttributes &
2132 ~(FILE_ATTRIBUTE_SYSTEM |
2133 FILE_ATTRIBUTE_HIDDEN |
2134 FILE_ATTRIBUTE_READONLY);
2135
2136 Status = NtSetInformationFile(FileHandle,
2137 &IoStatusBlock,
2138 &FileInfo,
2139 sizeof(FILE_BASIC_INFORMATION),
2140 FileBasicInformation);
2141 if (!NT_SUCCESS(Status))
2142 {
2143 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2144 }
2145
2146 NtClose(FileHandle);
2147 return Status;
2148 }
2149
2150 static
2151 NTSTATUS
2152 ProtectBootIni(
2153 PWSTR FileName,
2154 ULONG Attributes)
2155 {
2156 NTSTATUS Status;
2157 UNICODE_STRING Name;
2158 OBJECT_ATTRIBUTES ObjectAttributes;
2159 IO_STATUS_BLOCK IoStatusBlock;
2160 FILE_BASIC_INFORMATION FileInfo;
2161 HANDLE FileHandle;
2162
2163 RtlInitUnicodeString(&Name, FileName);
2164
2165 InitializeObjectAttributes(&ObjectAttributes,
2166 &Name,
2167 OBJ_CASE_INSENSITIVE,
2168 NULL,
2169 NULL);
2170
2171 Status = NtOpenFile(&FileHandle,
2172 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2173 &ObjectAttributes,
2174 &IoStatusBlock,
2175 0,
2176 FILE_SYNCHRONOUS_IO_NONALERT);
2177 if (!NT_SUCCESS(Status))
2178 {
2179 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2180 return Status;
2181 }
2182
2183 Status = NtQueryInformationFile(FileHandle,
2184 &IoStatusBlock,
2185 &FileInfo,
2186 sizeof(FILE_BASIC_INFORMATION),
2187 FileBasicInformation);
2188 if (!NT_SUCCESS(Status))
2189 {
2190 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2191 NtClose(FileHandle);
2192 return Status;
2193 }
2194
2195 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
2196
2197 Status = NtSetInformationFile(FileHandle,
2198 &IoStatusBlock,
2199 &FileInfo,
2200 sizeof(FILE_BASIC_INFORMATION),
2201 FileBasicInformation);
2202 if (!NT_SUCCESS(Status))
2203 {
2204 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2205 }
2206
2207 NtClose(FileHandle);
2208 return Status;
2209 }
2210
2211 static
2212 NTSTATUS
2213 UpdateBootIni(
2214 PWSTR BootIniPath,
2215 PWSTR EntryName,
2216 PWSTR EntryValue)
2217 {
2218 NTSTATUS Status;
2219 PINICACHE Cache = NULL;
2220 PINICACHESECTION Section = NULL;
2221 ULONG FileAttribute;
2222 PWCHAR OldValue = NULL;
2223
2224 Status = IniCacheLoad(&Cache, BootIniPath, FALSE);
2225 if (!NT_SUCCESS(Status))
2226 {
2227 return Status;
2228 }
2229
2230 Section = IniCacheGetSection(Cache,
2231 L"operating systems");
2232 if (Section == NULL)
2233 {
2234 IniCacheDestroy(Cache);
2235 return STATUS_UNSUCCESSFUL;
2236 }
2237
2238 /* Check - maybe record already exists */
2239 Status = IniCacheGetKey(Section, EntryName, &OldValue);
2240
2241 /* If either key was not found, or contains something else - add new one */
2242 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
2243 {
2244 IniCacheInsertKey(Section,
2245 NULL,
2246 INSERT_LAST,
2247 EntryName,
2248 EntryValue);
2249 }
2250
2251 Status = UnprotectBootIni(BootIniPath,
2252 &FileAttribute);
2253 if (!NT_SUCCESS(Status))
2254 {
2255 IniCacheDestroy(Cache);
2256 return Status;
2257 }
2258
2259 Status = IniCacheSave(Cache, BootIniPath);
2260 if (!NT_SUCCESS(Status))
2261 {
2262 IniCacheDestroy(Cache);
2263 return Status;
2264 }
2265
2266 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
2267 Status = ProtectBootIni(BootIniPath, FileAttribute);
2268
2269 IniCacheDestroy(Cache);
2270
2271 return Status;
2272 }
2273
2274 static
2275 NTSTATUS
2276 InstallFatBootcodeToPartition(
2277 PUNICODE_STRING SystemRootPath,
2278 PUNICODE_STRING SourceRootPath,
2279 PUNICODE_STRING DestinationArcPath,
2280 UCHAR PartitionType)
2281 {
2282 NTSTATUS Status;
2283 BOOLEAN DoesFreeLdrExist;
2284 WCHAR SrcPath[MAX_PATH];
2285 WCHAR DstPath[MAX_PATH];
2286
2287 /* FAT or FAT32 partition */
2288 DPRINT("System path: '%wZ'\n", SystemRootPath);
2289
2290 /* Copy FreeLoader to the system partition, always overwriting the older version */
2291 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2292 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
2293
2294 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2295 Status = SetupCopyFile(SrcPath, DstPath);
2296 if (!NT_SUCCESS(Status))
2297 {
2298 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2299 return Status;
2300 }
2301
2302 /* Prepare for possibly updating 'freeldr.ini' */
2303 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.ini");
2304
2305 DoesFreeLdrExist = DoesFileExist(NULL, DstPath);
2306 if (DoesFreeLdrExist)
2307 {
2308 /* Update existing 'freeldr.ini' */
2309 DPRINT1("Update existing 'freeldr.ini'\n");
2310
2311 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2312 if (!NT_SUCCESS(Status))
2313 {
2314 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2315 return Status;
2316 }
2317 }
2318
2319 /* Check for NT and other bootloaders */
2320
2321 // FIXME: Check for Vista+ bootloader!
2322 /*** Status = FindNTOSBootLoader(PartitionHandle, NtLdr, &Version); ***/
2323 /*** Status = FindNTOSBootLoader(PartitionHandle, BootMgr, &Version); ***/
2324 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE ||
2325 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE)
2326 {
2327 /* Search root directory for 'NTLDR' and 'BOOT.INI' */
2328 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2329
2330 /* Create or update 'freeldr.ini' */
2331 if (DoesFreeLdrExist == FALSE)
2332 {
2333 /* Create new 'freeldr.ini' */
2334 DPRINT1("Create new 'freeldr.ini'\n");
2335 // CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.ini");
2336
2337 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2338 if (!NT_SUCCESS(Status))
2339 {
2340 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2341 return Status;
2342 }
2343
2344 /* Install new bootcode into a file */
2345 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros");
2346
2347 if (PartitionType == PARTITION_FAT32 ||
2348 PartitionType == PARTITION_FAT32_XINT13)
2349 {
2350 /* Install FAT32 bootcode */
2351 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
2352
2353 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2354 Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
2355 SystemRootPath->Buffer);
2356 if (!NT_SUCCESS(Status))
2357 {
2358 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2359 return Status;
2360 }
2361 }
2362 else
2363 {
2364 /* Install FAT16 bootcode */
2365 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2366
2367 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2368 Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
2369 SystemRootPath->Buffer);
2370 if (!NT_SUCCESS(Status))
2371 {
2372 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2373 return Status;
2374 }
2375 }
2376 }
2377
2378 /* Update 'boot.ini' */
2379 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"boot.ini");
2380
2381 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2382 Status = UpdateBootIni(DstPath,
2383 L"C:\\bootsect.ros",
2384 L"\"ReactOS\"");
2385 if (!NT_SUCCESS(Status))
2386 {
2387 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2388 return Status;
2389 }
2390 }
2391 else
2392 {
2393 /* Non-NT bootloaders: install our own bootloader */
2394
2395 PCWSTR Section;
2396 PCWSTR Description;
2397 PCWSTR BootDrive;
2398 PCWSTR BootPartition;
2399 PCWSTR BootSector;
2400
2401 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
2402 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE ||
2403 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE)
2404 {
2405 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
2406
2407 Section = L"DOS";
2408 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
2409 BootDrive = L"hd0";
2410 BootPartition = L"1";
2411 BootSector = L"BOOTSECT.DOS";
2412 }
2413 else
2414 /* Search for Microsoft DOS or Windows 9x boot loader */
2415 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE ||
2416 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE)
2417 // WINBOOT.SYS
2418 {
2419 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2420
2421 Section = L"DOS";
2422 Description = L"\"MS-DOS/Windows\"";
2423 BootDrive = L"hd0";
2424 BootPartition = L"1";
2425 BootSector = L"BOOTSECT.DOS";
2426 }
2427 else
2428 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
2429 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM...
2430 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE ||
2431 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE)
2432 {
2433 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
2434
2435 Section = L"DOS";
2436 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
2437 BootDrive = L"hd0";
2438 BootPartition = L"1";
2439 BootSector = L"BOOTSECT.DOS";
2440 }
2441 else
2442 /* Search for DR-DOS 3.x boot loader */
2443 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE ||
2444 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE)
2445 {
2446 DPRINT1("Found DR-DOS 3.x\n");
2447
2448 Section = L"DOS";
2449 Description = L"\"DR-DOS 3.x\"";
2450 BootDrive = L"hd0";
2451 BootPartition = L"1";
2452 BootSector = L"BOOTSECT.DOS";
2453 }
2454 else
2455 /* Search for MS OS/2 1.x */
2456 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE ||
2457 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE ||
2458 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE)
2459 {
2460 DPRINT1("Found MS OS/2 1.x\n");
2461
2462 Section = L"DOS";
2463 Description = L"\"MS OS/2 1.x\"";
2464 BootDrive = L"hd0";
2465 BootPartition = L"1";
2466 BootSector = L"BOOTSECT.OS2";
2467 }
2468 else
2469 /* Search for MS or IBM OS/2 */
2470 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE ||
2471 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE ||
2472 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE)
2473 {
2474 DPRINT1("Found MS/IBM OS/2\n");
2475
2476 Section = L"DOS";
2477 Description = L"\"MS/IBM OS/2\"";
2478 BootDrive = L"hd0";
2479 BootPartition = L"1";
2480 BootSector = L"BOOTSECT.OS2";
2481 }
2482 else
2483 /* Search for FreeDOS boot loader */
2484 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
2485 {
2486 DPRINT1("Found FreeDOS boot loader\n");
2487
2488 Section = L"DOS";
2489 Description = L"\"FreeDOS\"";
2490 BootDrive = L"hd0";
2491 BootPartition = L"1";
2492 BootSector = L"BOOTSECT.DOS";
2493 }
2494 else
2495 {
2496 /* No or unknown boot loader */
2497 DPRINT1("No or unknown boot loader found\n");
2498
2499 Section = L"Unknown";
2500 Description = L"\"Unknown Operating System\"";
2501 BootDrive = L"hd0";
2502 BootPartition = L"1";
2503 BootSector = L"BOOTSECT.OLD";
2504 }
2505
2506 /* Create or update 'freeldr.ini' */
2507 if (DoesFreeLdrExist == FALSE)
2508 {
2509 /* Create new 'freeldr.ini' */
2510 DPRINT1("Create new 'freeldr.ini'\n");
2511 // CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.ini");
2512
2513 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2514 {
2515 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2516 DstPath, DestinationArcPath->Buffer,
2517 Section, Description,
2518 BootDrive, BootPartition, BootSector);
2519 if (!NT_SUCCESS(Status))
2520 {
2521 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2522 return Status;
2523 }
2524
2525 /* Save current bootsector */
2526 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2527
2528 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2529 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
2530 if (!NT_SUCCESS(Status))
2531 {
2532 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2533 return Status;
2534 }
2535 }
2536 else
2537 {
2538 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2539 if (!NT_SUCCESS(Status))
2540 {
2541 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2542 return Status;
2543 }
2544 }
2545
2546 /* Install new bootsector on the disk */
2547 if (PartitionType == PARTITION_FAT32 ||
2548 PartitionType == PARTITION_FAT32_XINT13)
2549 {
2550 /* Install FAT32 bootcode */
2551 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin");
2552
2553 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2554 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2555 if (!NT_SUCCESS(Status))
2556 {
2557 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2558 return Status;
2559 }
2560 }
2561 else
2562 {
2563 /* Install FAT16 bootcode */
2564 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2565
2566 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2567 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2568 if (!NT_SUCCESS(Status))
2569 {
2570 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2571 return Status;
2572 }
2573 }
2574 }
2575 }
2576
2577 return STATUS_SUCCESS;
2578 }
2579
2580 static
2581 NTSTATUS
2582 InstallBtrfsBootcodeToPartition(
2583 PUNICODE_STRING SystemRootPath,
2584 PUNICODE_STRING SourceRootPath,
2585 PUNICODE_STRING DestinationArcPath,
2586 UCHAR PartitionType)
2587 {
2588 NTSTATUS Status;
2589 BOOLEAN DoesFreeLdrExist;
2590 WCHAR SrcPath[MAX_PATH];
2591 WCHAR DstPath[MAX_PATH];
2592
2593 /* BTRFS partition */
2594 DPRINT("System path: '%wZ'\n", SystemRootPath);
2595
2596 /* Copy FreeLoader to the system partition, always overwriting the older version */
2597 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2598 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys");
2599
2600 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2601 Status = SetupCopyFile(SrcPath, DstPath);
2602 if (!NT_SUCCESS(Status))
2603 {
2604 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2605 return Status;
2606 }
2607
2608 /* Prepare for possibly copying 'freeldr.ini' */
2609 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.ini");
2610
2611 DoesFreeLdrExist = DoesFileExist(NULL, DstPath);
2612 if (DoesFreeLdrExist)
2613 {
2614 /* Update existing 'freeldr.ini' */
2615 DPRINT1("Update existing 'freeldr.ini'\n");
2616
2617 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2618 if (!NT_SUCCESS(Status))
2619 {
2620 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2621 return Status;
2622 }
2623 }
2624
2625 /* Check for *nix bootloaders */
2626
2627 /* Create or update 'freeldr.ini' */
2628 if (DoesFreeLdrExist == FALSE)
2629 {
2630 /* Create new 'freeldr.ini' */
2631 DPRINT1("Create new 'freeldr.ini'\n");
2632 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"\\freeldr.ini");
2633
2634 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2635 DPRINT1("*nix or unknown boot loader found\n");
2636
2637 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2638 {
2639 PCWSTR BootSector = L"BOOTSECT.OLD";
2640
2641 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2642 DstPath, DestinationArcPath->Buffer,
2643 L"Linux", L"\"Linux\"",
2644 L"hd0", L"1", BootSector);
2645 if (!NT_SUCCESS(Status))
2646 {
2647 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2648 return Status;
2649 }
2650
2651 /* Save current bootsector */
2652 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector);
2653
2654 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2655 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(BTRFS_BOOTSECTOR));
2656 if (!NT_SUCCESS(Status))
2657 {
2658 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2659 return Status;
2660 }
2661 }
2662 else
2663 {
2664 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2665 if (!NT_SUCCESS(Status))
2666 {
2667 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2668 return Status;
2669 }
2670 }
2671
2672 /* Install new bootsector on the disk */
2673 // if (PartitionType == PARTITION_EXT2)
2674 {
2675 /* Install BTRFS bootcode */
2676 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin");
2677
2678 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2679 Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2680 if (!NT_SUCCESS(Status))
2681 {
2682 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status);
2683 return Status;
2684 }
2685 }
2686 }
2687
2688 return STATUS_SUCCESS;
2689 }
2690
2691
2692 NTSTATUS
2693 InstallVBRToPartition(
2694 PUNICODE_STRING SystemRootPath,
2695 PUNICODE_STRING SourceRootPath,
2696 PUNICODE_STRING DestinationArcPath,
2697 UCHAR PartitionType)
2698 {
2699 switch (PartitionType)
2700 {
2701 case PARTITION_FAT_12:
2702 case PARTITION_FAT_16:
2703 case PARTITION_HUGE:
2704 case PARTITION_XINT13:
2705 case PARTITION_FAT32:
2706 case PARTITION_FAT32_XINT13:
2707 {
2708 return InstallFatBootcodeToPartition(SystemRootPath,
2709 SourceRootPath,
2710 DestinationArcPath,
2711 PartitionType);
2712 }
2713
2714 case PARTITION_LINUX:
2715 {
2716 return InstallBtrfsBootcodeToPartition(SystemRootPath,
2717 SourceRootPath,
2718 DestinationArcPath,
2719 PartitionType);
2720 }
2721
2722 case PARTITION_IFS:
2723 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n");
2724 break;
2725
2726 default:
2727 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
2728 break;
2729 }
2730
2731 return STATUS_UNSUCCESSFUL;
2732 }
2733
2734
2735 NTSTATUS
2736 InstallFatBootcodeToFloppy(
2737 PUNICODE_STRING SourceRootPath,
2738 PUNICODE_STRING DestinationArcPath)
2739 {
2740 NTSTATUS Status;
2741 PFILE_SYSTEM FatFS;
2742 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
2743 WCHAR SrcPath[MAX_PATH];
2744 WCHAR DstPath[MAX_PATH];
2745
2746 /* Format the floppy first */
2747 FatFS = GetFileSystemByName(L"FAT");
2748 if (!FatFS)
2749 {
2750 DPRINT1("FAT FS non existent on this system?!\n");
2751 return STATUS_NOT_SUPPORTED;
2752 }
2753 Status = FatFS->FormatFunc(&FloppyDevice,
2754 FMIFS_FLOPPY,
2755 NULL,
2756 TRUE,
2757 0,
2758 NULL);
2759 if (!NT_SUCCESS(Status))
2760 {
2761 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2762 return Status;
2763 }
2764
2765 /* Copy FreeLoader to the boot partition */
2766 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
2767 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.sys");
2768
2769 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2770 Status = SetupCopyFile(SrcPath, DstPath);
2771 if (!NT_SUCCESS(Status))
2772 {
2773 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2774 return Status;
2775 }
2776
2777 /* Create new 'freeldr.ini' */
2778 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.ini");
2779
2780 DPRINT("Create new 'freeldr.ini'\n");
2781 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2782 if (!NT_SUCCESS(Status))
2783 {
2784 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2785 return Status;
2786 }
2787
2788 /* Install FAT12 boosector */
2789 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
2790 RtlStringCchCopyW(DstPath, ARRAYSIZE(DstPath), FloppyDevice.Buffer);
2791
2792 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2793 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2794 if (!NT_SUCCESS(Status))
2795 {
2796 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status);
2797 return Status;
2798 }
2799
2800 return STATUS_SUCCESS;
2801 }
2802
2803 /* EOF */