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