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