* Sync to trunk HEAD (r53318).
[reactos.git] / base / setup / usetup / bootsup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: 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 (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
1263 NTSTATUS
1264 InstallFat16BootCodeToDisk(
1265 PWSTR SrcPath,
1266 PWSTR RootPath)
1267 {
1268 OBJECT_ATTRIBUTES ObjectAttributes;
1269 IO_STATUS_BLOCK IoStatusBlock;
1270 UNICODE_STRING Name;
1271 HANDLE FileHandle;
1272 NTSTATUS Status;
1273 PFAT_BOOTSECTOR OrigBootSector;
1274 PFAT_BOOTSECTOR NewBootSector;
1275 PARTITION_INFORMATION *PartInfo;
1276
1277 /* Allocate buffer for original bootsector */
1278 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1279 if (OrigBootSector == NULL)
1280 return STATUS_INSUFFICIENT_RESOURCES;
1281
1282 /* Read current boot sector into buffer */
1283 RtlInitUnicodeString(&Name, RootPath);
1284
1285 InitializeObjectAttributes(&ObjectAttributes,
1286 &Name,
1287 OBJ_CASE_INSENSITIVE,
1288 NULL,
1289 NULL);
1290
1291 Status = NtOpenFile(&FileHandle,
1292 GENERIC_READ,
1293 &ObjectAttributes,
1294 &IoStatusBlock,
1295 0,
1296 FILE_SYNCHRONOUS_IO_NONALERT);
1297 if (!NT_SUCCESS(Status))
1298 {
1299 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1300 return Status;
1301 }
1302
1303 Status = NtReadFile(FileHandle,
1304 NULL,
1305 NULL,
1306 NULL,
1307 &IoStatusBlock,
1308 OrigBootSector,
1309 SECTORSIZE,
1310 NULL,
1311 NULL);
1312 NtClose(FileHandle);
1313 if (!NT_SUCCESS(Status))
1314 {
1315 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1316 return Status;
1317 }
1318
1319
1320 /* Allocate buffer for new bootsector */
1321 NewBootSector = RtlAllocateHeap(ProcessHeap,
1322 0,
1323 SECTORSIZE);
1324 if (NewBootSector == NULL)
1325 {
1326 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1327 return STATUS_INSUFFICIENT_RESOURCES;
1328 }
1329
1330 /* Read new bootsector from SrcPath */
1331 RtlInitUnicodeString(&Name, SrcPath);
1332
1333 InitializeObjectAttributes(&ObjectAttributes,
1334 &Name,
1335 OBJ_CASE_INSENSITIVE,
1336 NULL,
1337 NULL);
1338
1339 Status = NtOpenFile(&FileHandle,
1340 GENERIC_READ,
1341 &ObjectAttributes,
1342 &IoStatusBlock,
1343 0,
1344 FILE_SYNCHRONOUS_IO_NONALERT);
1345 if (!NT_SUCCESS(Status))
1346 {
1347 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1348 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1349 return Status;
1350 }
1351
1352 Status = NtReadFile(FileHandle,
1353 NULL,
1354 NULL,
1355 NULL,
1356 &IoStatusBlock,
1357 NewBootSector,
1358 SECTORSIZE,
1359 NULL,
1360 NULL);
1361 NtClose(FileHandle);
1362 if (!NT_SUCCESS(Status))
1363 {
1364 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1365 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1366 return Status;
1367 }
1368
1369 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1370 memcpy(&NewBootSector->OemName,
1371 &OrigBootSector->OemName,
1372 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1373 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1374
1375 PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
1376 NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
1377
1378 /* Free the original boot sector */
1379 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1380
1381 /* Write new bootsector to RootPath */
1382 RtlInitUnicodeString(&Name, RootPath);
1383
1384 InitializeObjectAttributes(&ObjectAttributes,
1385 &Name,
1386 0,
1387 NULL,
1388 NULL);
1389
1390 Status = NtOpenFile(&FileHandle,
1391 GENERIC_WRITE,
1392 &ObjectAttributes,
1393 &IoStatusBlock,
1394 0,
1395 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1396 if (!NT_SUCCESS(Status))
1397 {
1398 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1399 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1400 return Status;
1401 }
1402
1403 #if 0
1404 FilePosition.QuadPart = 0;
1405 #endif
1406 Status = NtWriteFile(FileHandle,
1407 NULL,
1408 NULL,
1409 NULL,
1410 &IoStatusBlock,
1411 NewBootSector,
1412 SECTORSIZE,
1413 NULL,
1414 NULL);
1415 NtClose(FileHandle);
1416
1417 /* Free the new boot sector */
1418 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1419
1420 return Status;
1421 }
1422
1423
1424 NTSTATUS
1425 InstallFat32BootCodeToDisk(
1426 PWSTR SrcPath,
1427 PWSTR RootPath)
1428 {
1429 OBJECT_ATTRIBUTES ObjectAttributes;
1430 IO_STATUS_BLOCK IoStatusBlock;
1431 UNICODE_STRING Name;
1432 HANDLE FileHandle;
1433 NTSTATUS Status;
1434 PFAT32_BOOTSECTOR OrigBootSector;
1435 PFAT32_BOOTSECTOR NewBootSector;
1436 LARGE_INTEGER FileOffset;
1437 USHORT BackupBootSector;
1438 PARTITION_INFORMATION *PartInfo;
1439
1440 /* Allocate buffer for original bootsector */
1441 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1442 if (OrigBootSector == NULL)
1443 return STATUS_INSUFFICIENT_RESOURCES;
1444
1445 /* Read current boot sector into buffer */
1446 RtlInitUnicodeString(&Name, RootPath);
1447
1448 InitializeObjectAttributes(&ObjectAttributes,
1449 &Name,
1450 OBJ_CASE_INSENSITIVE,
1451 NULL,
1452 NULL);
1453
1454 Status = NtOpenFile(&FileHandle,
1455 GENERIC_READ,
1456 &ObjectAttributes,
1457 &IoStatusBlock,
1458 0,
1459 FILE_SYNCHRONOUS_IO_NONALERT);
1460 if (!NT_SUCCESS(Status))
1461 {
1462 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1463 return Status;
1464 }
1465
1466 Status = NtReadFile(FileHandle,
1467 NULL,
1468 NULL,
1469 NULL,
1470 &IoStatusBlock,
1471 OrigBootSector,
1472 SECTORSIZE,
1473 NULL,
1474 NULL);
1475 NtClose(FileHandle);
1476 if (!NT_SUCCESS(Status))
1477 {
1478 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1479 return Status;
1480 }
1481
1482
1483 /* Allocate buffer for new bootsector (2 sectors) */
1484 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1485 if (NewBootSector == NULL)
1486 {
1487 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1488 return STATUS_INSUFFICIENT_RESOURCES;
1489 }
1490
1491 /* Read new bootsector from SrcPath */
1492 RtlInitUnicodeString(&Name, SrcPath);
1493
1494 InitializeObjectAttributes(&ObjectAttributes,
1495 &Name,
1496 OBJ_CASE_INSENSITIVE,
1497 NULL,
1498 NULL);
1499
1500 Status = NtOpenFile(&FileHandle,
1501 GENERIC_READ,
1502 &ObjectAttributes,
1503 &IoStatusBlock,
1504 0,
1505 FILE_SYNCHRONOUS_IO_NONALERT);
1506 if (!NT_SUCCESS(Status))
1507 {
1508 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1509 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1510 return Status;
1511 }
1512
1513 Status = NtReadFile(FileHandle,
1514 NULL,
1515 NULL,
1516 NULL,
1517 &IoStatusBlock,
1518 NewBootSector,
1519 2 * SECTORSIZE,
1520 NULL,
1521 NULL);
1522 NtClose(FileHandle);
1523 if (!NT_SUCCESS(Status))
1524 {
1525 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1526 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1527 return Status;
1528 }
1529
1530 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1531 memcpy(&NewBootSector->OemName,
1532 &OrigBootSector->OemName,
1533 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1534 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1535
1536 PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
1537 NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
1538
1539 /* Get the location of the backup boot sector */
1540 BackupBootSector = OrigBootSector->BackupBootSector;
1541
1542 /* Free the original boot sector */
1543 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1544
1545 /* Write the first sector of the new bootcode to DstPath */
1546 RtlInitUnicodeString(&Name, RootPath);
1547
1548 InitializeObjectAttributes(&ObjectAttributes,
1549 &Name,
1550 0,
1551 NULL,
1552 NULL);
1553
1554 Status = NtOpenFile(&FileHandle,
1555 GENERIC_WRITE,
1556 &ObjectAttributes,
1557 &IoStatusBlock,
1558 0,
1559 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1560 if (!NT_SUCCESS(Status))
1561 {
1562 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1563 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1564 return Status;
1565 }
1566
1567 /* Write sector 0 */
1568 FileOffset.QuadPart = 0ULL;
1569 Status = NtWriteFile(FileHandle,
1570 NULL,
1571 NULL,
1572 NULL,
1573 &IoStatusBlock,
1574 NewBootSector,
1575 SECTORSIZE,
1576 &FileOffset,
1577 NULL);
1578 if (!NT_SUCCESS(Status))
1579 {
1580 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1581 NtClose(FileHandle);
1582 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1583 return Status;
1584 }
1585
1586 /* Write backup boot sector */
1587 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1588 {
1589 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1590 Status = NtWriteFile(FileHandle,
1591 NULL,
1592 NULL,
1593 NULL,
1594 &IoStatusBlock,
1595 NewBootSector,
1596 SECTORSIZE,
1597 &FileOffset,
1598 NULL);
1599 if (!NT_SUCCESS(Status))
1600 {
1601 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1602 NtClose(FileHandle);
1603 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1604 return Status;
1605 }
1606 }
1607
1608 /* Write sector 14 */
1609 FileOffset.QuadPart = 14 * SECTORSIZE;
1610 Status = NtWriteFile(FileHandle,
1611 NULL,
1612 NULL,
1613 NULL,
1614 &IoStatusBlock,
1615 ((PUCHAR)NewBootSector + SECTORSIZE),
1616 SECTORSIZE,
1617 &FileOffset,
1618 NULL);
1619 if (!NT_SUCCESS(Status))
1620 {
1621 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1622 }
1623 NtClose(FileHandle);
1624
1625 /* Free the new boot sector */
1626 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1627
1628 return Status;
1629 }
1630
1631
1632 static
1633 NTSTATUS
1634 UnprotectBootIni(
1635 PWSTR FileName,
1636 PULONG Attributes)
1637 {
1638 UNICODE_STRING Name;
1639 OBJECT_ATTRIBUTES ObjectAttributes;
1640 IO_STATUS_BLOCK IoStatusBlock;
1641 FILE_BASIC_INFORMATION FileInfo;
1642 HANDLE FileHandle;
1643 NTSTATUS Status;
1644
1645 RtlInitUnicodeString(&Name, FileName);
1646
1647 InitializeObjectAttributes(&ObjectAttributes,
1648 &Name,
1649 OBJ_CASE_INSENSITIVE,
1650 NULL,
1651 NULL);
1652
1653 Status = NtOpenFile(&FileHandle,
1654 GENERIC_READ|GENERIC_WRITE,
1655 &ObjectAttributes,
1656 &IoStatusBlock,
1657 0,
1658 FILE_SYNCHRONOUS_IO_NONALERT);
1659 if (Status == STATUS_NO_SUCH_FILE)
1660 {
1661 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1662 *Attributes = 0;
1663 return STATUS_SUCCESS;
1664 }
1665 if (!NT_SUCCESS(Status))
1666 {
1667 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1668 return Status;
1669 }
1670
1671 Status = NtQueryInformationFile(FileHandle,
1672 &IoStatusBlock,
1673 &FileInfo,
1674 sizeof(FILE_BASIC_INFORMATION),
1675 FileBasicInformation);
1676 if (!NT_SUCCESS(Status))
1677 {
1678 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1679 NtClose(FileHandle);
1680 return Status;
1681 }
1682
1683 *Attributes = FileInfo.FileAttributes;
1684
1685 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1686 FileInfo.FileAttributes = FileInfo.FileAttributes &
1687 ~(FILE_ATTRIBUTE_SYSTEM |
1688 FILE_ATTRIBUTE_HIDDEN |
1689 FILE_ATTRIBUTE_READONLY);
1690
1691 Status = NtSetInformationFile(FileHandle,
1692 &IoStatusBlock,
1693 &FileInfo,
1694 sizeof(FILE_BASIC_INFORMATION),
1695 FileBasicInformation);
1696 if (!NT_SUCCESS(Status))
1697 {
1698 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1699 }
1700
1701 NtClose(FileHandle);
1702 return Status;
1703 }
1704
1705
1706 static
1707 NTSTATUS
1708 ProtectBootIni(
1709 PWSTR FileName,
1710 ULONG Attributes)
1711 {
1712 UNICODE_STRING Name;
1713 OBJECT_ATTRIBUTES ObjectAttributes;
1714 IO_STATUS_BLOCK IoStatusBlock;
1715 FILE_BASIC_INFORMATION FileInfo;
1716 HANDLE FileHandle;
1717 NTSTATUS Status;
1718
1719 RtlInitUnicodeString(&Name, FileName);
1720
1721 InitializeObjectAttributes(&ObjectAttributes,
1722 &Name,
1723 OBJ_CASE_INSENSITIVE,
1724 NULL,
1725 NULL);
1726
1727 Status = NtOpenFile(&FileHandle,
1728 GENERIC_READ|GENERIC_WRITE,
1729 &ObjectAttributes,
1730 &IoStatusBlock,
1731 0,
1732 FILE_SYNCHRONOUS_IO_NONALERT);
1733 if (!NT_SUCCESS(Status))
1734 {
1735 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1736 return Status;
1737 }
1738
1739 Status = NtQueryInformationFile(FileHandle,
1740 &IoStatusBlock,
1741 &FileInfo,
1742 sizeof(FILE_BASIC_INFORMATION),
1743 FileBasicInformation);
1744 if (!NT_SUCCESS(Status))
1745 {
1746 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1747 NtClose(FileHandle);
1748 return Status;
1749 }
1750
1751 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1752
1753 Status = NtSetInformationFile(FileHandle,
1754 &IoStatusBlock,
1755 &FileInfo,
1756 sizeof(FILE_BASIC_INFORMATION),
1757 FileBasicInformation);
1758 if (!NT_SUCCESS(Status))
1759 {
1760 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1761 }
1762
1763 NtClose(FileHandle);
1764 return Status;
1765 }
1766
1767
1768 NTSTATUS
1769 UpdateBootIni(
1770 PWSTR BootIniPath,
1771 PWSTR EntryName,
1772 PWSTR EntryValue)
1773 {
1774 UNICODE_STRING Name;
1775 PINICACHE Cache = NULL;
1776 PINICACHESECTION Section = NULL;
1777 NTSTATUS Status;
1778 ULONG FileAttribute;
1779 PWCHAR OldValue = NULL;
1780
1781 RtlInitUnicodeString(&Name, BootIniPath);
1782
1783 Status = IniCacheLoad(&Cache, &Name, FALSE);
1784 if (!NT_SUCCESS(Status))
1785 {
1786 return Status;
1787 }
1788
1789 Section = IniCacheGetSection(Cache,
1790 L"operating systems");
1791 if (Section == NULL)
1792 {
1793 IniCacheDestroy(Cache);
1794 return STATUS_UNSUCCESSFUL;
1795 }
1796
1797 /* Check - maybe record already exists */
1798 Status = IniCacheGetKey(Section, EntryName, &OldValue);
1799
1800 /* If either key was not found, or contains something else - add new one */
1801 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
1802 {
1803 IniCacheInsertKey(Section,
1804 NULL,
1805 INSERT_LAST,
1806 EntryName,
1807 EntryValue);
1808 }
1809
1810 Status = UnprotectBootIni(BootIniPath,
1811 &FileAttribute);
1812 if (!NT_SUCCESS(Status))
1813 {
1814 IniCacheDestroy(Cache);
1815 return Status;
1816 }
1817
1818 Status = IniCacheSave(Cache, BootIniPath);
1819 if (!NT_SUCCESS(Status))
1820 {
1821 IniCacheDestroy(Cache);
1822 return Status;
1823 }
1824
1825 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1826 Status = ProtectBootIni(BootIniPath, FileAttribute);
1827
1828 IniCacheDestroy(Cache);
1829
1830 return Status;
1831 }
1832
1833 BOOLEAN
1834 CheckInstallFatBootcodeToPartition(
1835 PUNICODE_STRING SystemRootPath)
1836 {
1837 #ifdef __REACTOS__
1838 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") ||
1839 DoesFileExist(SystemRootPath->Buffer, L"boot.ini"))
1840 {
1841 return TRUE;
1842 }
1843 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") ||
1844 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys"))
1845 {
1846 return TRUE;
1847 }
1848 #endif
1849
1850 return FALSE;
1851 }
1852
1853
1854 NTSTATUS
1855 InstallFatBootcodeToPartition(
1856 PUNICODE_STRING SystemRootPath,
1857 PUNICODE_STRING SourceRootPath,
1858 PUNICODE_STRING DestinationArcPath,
1859 UCHAR PartitionType)
1860 {
1861 #ifdef __REACTOS__
1862 WCHAR SrcPath[MAX_PATH];
1863 WCHAR DstPath[MAX_PATH];
1864 NTSTATUS Status;
1865
1866 /* FAT or FAT32 partition */
1867 DPRINT("System path: '%wZ'\n", SystemRootPath);
1868
1869 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
1870 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
1871 {
1872 /* Search root directory for 'ntldr' and 'boot.ini'. */
1873 DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n");
1874
1875 /* Copy FreeLoader to the boot partition */
1876 wcscpy(SrcPath, SourceRootPath->Buffer);
1877 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1878 wcscpy(DstPath, SystemRootPath->Buffer);
1879 wcscat(DstPath, L"\\freeldr.sys");
1880
1881 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1882 Status = SetupCopyFile(SrcPath, DstPath);
1883 if (!NT_SUCCESS(Status))
1884 {
1885 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1886 return Status;
1887 }
1888
1889 /* Create or update freeldr.ini */
1890 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
1891 {
1892 /* Create new 'freeldr.ini' */
1893 DPRINT1("Create new 'freeldr.ini'\n");
1894 wcscpy(DstPath, SystemRootPath->Buffer);
1895 wcscat(DstPath, L"\\freeldr.ini");
1896
1897 Status = CreateFreeLoaderIniForReactos(DstPath,
1898 DestinationArcPath->Buffer);
1899 if (!NT_SUCCESS(Status))
1900 {
1901 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1902 return Status;
1903 }
1904
1905 /* Install new bootcode */
1906 if (PartitionType == PARTITION_FAT32 ||
1907 PartitionType == PARTITION_FAT32_XINT13)
1908 {
1909 /* Install FAT32 bootcode */
1910 wcscpy(SrcPath, SourceRootPath->Buffer);
1911 wcscat(SrcPath, L"\\loader\\fat32.bin");
1912 wcscpy(DstPath, SystemRootPath->Buffer);
1913 wcscat(DstPath, L"\\bootsect.ros");
1914
1915 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1916 Status = InstallFat32BootCodeToFile(SrcPath,
1917 DstPath,
1918 SystemRootPath->Buffer);
1919 if (!NT_SUCCESS(Status))
1920 {
1921 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1922 return Status;
1923 }
1924 }
1925 else
1926 {
1927 /* Install FAT16 bootcode */
1928 wcscpy(SrcPath, SourceRootPath->Buffer);
1929 wcscat(SrcPath, L"\\loader\\fat.bin");
1930 wcscpy(DstPath, SystemRootPath->Buffer);
1931 wcscat(DstPath, L"\\bootsect.ros");
1932
1933 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1934 Status = InstallFat16BootCodeToFile(SrcPath,
1935 DstPath,
1936 SystemRootPath->Buffer);
1937 if (!NT_SUCCESS(Status))
1938 {
1939 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1940 return Status;
1941 }
1942 }
1943 }
1944 else
1945 {
1946 /* Update existing 'freeldr.ini' */
1947 DPRINT1("Update existing 'freeldr.ini'\n");
1948 wcscpy(DstPath, SystemRootPath->Buffer);
1949 wcscat(DstPath, L"\\freeldr.ini");
1950
1951 Status = UpdateFreeLoaderIni(DstPath,
1952 DestinationArcPath->Buffer);
1953 if (!NT_SUCCESS(Status))
1954 {
1955 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1956 return Status;
1957 }
1958 }
1959
1960 /* Update 'boot.ini' */
1961 wcscpy(DstPath, SystemRootPath->Buffer);
1962 wcscat(DstPath, L"\\boot.ini");
1963
1964 DPRINT1("Update 'boot.ini': %S\n", DstPath);
1965 Status = UpdateBootIni(DstPath,
1966 L"C:\\bootsect.ros",
1967 L"\"ReactOS\"");
1968 if (!NT_SUCCESS(Status))
1969 {
1970 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1971 return Status;
1972 }
1973 }
1974 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
1975 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
1976 {
1977 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1978 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1979
1980 /* Copy FreeLoader to the boot partition */
1981 wcscpy(SrcPath, SourceRootPath->Buffer);
1982 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1983 wcscpy(DstPath, SystemRootPath->Buffer);
1984 wcscat(DstPath, L"\\freeldr.sys");
1985
1986 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1987 Status = SetupCopyFile(SrcPath, DstPath);
1988 if (!NT_SUCCESS(Status))
1989 {
1990 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1991 return Status;
1992 }
1993
1994 /* Create or update 'freeldr.ini' */
1995 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
1996 {
1997 /* Create new 'freeldr.ini' */
1998 DPRINT1("Create new 'freeldr.ini'\n");
1999 wcscpy(DstPath, SystemRootPath->Buffer);
2000 wcscat(DstPath, L"\\freeldr.ini");
2001
2002 Status = CreateFreeLoaderIniForDos(DstPath,
2003 DestinationArcPath->Buffer);
2004 if (!NT_SUCCESS(Status))
2005 {
2006 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2007 return Status;
2008 }
2009
2010 /* Save current bootsector as 'BOOTSECT.DOS' */
2011 wcscpy(SrcPath, SystemRootPath->Buffer);
2012 wcscpy(DstPath, SystemRootPath->Buffer);
2013 wcscat(DstPath, L"\\bootsect.dos");
2014
2015 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2016 Status = SaveCurrentBootSector(SrcPath,
2017 DstPath);
2018 if (!NT_SUCCESS(Status))
2019 {
2020 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2021 return Status;
2022 }
2023
2024 /* Install new bootsector */
2025 if (PartitionType == PARTITION_FAT32 ||
2026 PartitionType == PARTITION_FAT32_XINT13)
2027 {
2028 wcscpy(SrcPath, SourceRootPath->Buffer);
2029 wcscat(SrcPath, L"\\loader\\fat32.bin");
2030
2031 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2032 Status = InstallFat32BootCodeToDisk(SrcPath,
2033 SystemRootPath->Buffer);
2034 if (!NT_SUCCESS(Status))
2035 {
2036 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2037 return Status;
2038 }
2039 }
2040 else
2041 {
2042 wcscpy(SrcPath, SourceRootPath->Buffer);
2043 wcscat(SrcPath, L"\\loader\\fat.bin");
2044
2045 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2046 Status = InstallFat16BootCodeToDisk(SrcPath,
2047 SystemRootPath->Buffer);
2048 if (!NT_SUCCESS(Status))
2049 {
2050 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2051 return Status;
2052 }
2053 }
2054 }
2055 else
2056 {
2057 /* Update existing 'freeldr.ini' */
2058 wcscpy(DstPath, SystemRootPath->Buffer);
2059 wcscat(DstPath, L"\\freeldr.ini");
2060
2061 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2062 if (!NT_SUCCESS(Status))
2063 {
2064 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2065 return Status;
2066 }
2067 }
2068 }
2069 else
2070 {
2071 /* No or unknown boot loader */
2072 DPRINT1("No or unknown boot loader found\n");
2073
2074 /* Copy FreeLoader to the boot partition */
2075 wcscpy(SrcPath, SourceRootPath->Buffer);
2076 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2077 wcscpy(DstPath, SystemRootPath->Buffer);
2078 wcscat(DstPath, L"\\freeldr.sys");
2079
2080 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2081 Status = SetupCopyFile(SrcPath, DstPath);
2082 if (!NT_SUCCESS(Status))
2083 {
2084 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2085 return Status;
2086 }
2087
2088 /* Create or update 'freeldr.ini' */
2089 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2090 {
2091 /* Create new freeldr.ini */
2092 wcscpy(DstPath, SystemRootPath->Buffer);
2093 wcscat(DstPath, L"\\freeldr.ini");
2094
2095 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2096 Status = CreateFreeLoaderIniForReactos(DstPath,
2097 DestinationArcPath->Buffer);
2098 if (!NT_SUCCESS(Status))
2099 {
2100 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2101 return Status;
2102 }
2103
2104 /* Save current bootsector as 'BOOTSECT.OLD' */
2105 wcscpy(SrcPath, SystemRootPath->Buffer);
2106 wcscpy(DstPath, SystemRootPath->Buffer);
2107 wcscat(DstPath, L"\\bootsect.old");
2108
2109 DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2110 Status = SaveCurrentBootSector(SrcPath,
2111 DstPath);
2112 if (!NT_SUCCESS(Status))
2113 {
2114 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2115 return Status;
2116 }
2117
2118 /* Install new bootsector */
2119 if ((PartitionType == PARTITION_FAT32) ||
2120 (PartitionType == PARTITION_FAT32_XINT13))
2121 {
2122 wcscpy(SrcPath, SourceRootPath->Buffer);
2123 wcscat(SrcPath, L"\\loader\\fat32.bin");
2124
2125 DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2126 Status = InstallFat32BootCodeToDisk(SrcPath,
2127 SystemRootPath->Buffer);
2128 if (!NT_SUCCESS(Status))
2129 {
2130 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2131 return Status;
2132 }
2133 }
2134 else
2135 {
2136 wcscpy(SrcPath, SourceRootPath->Buffer);
2137 wcscat(SrcPath, L"\\loader\\fat.bin");
2138
2139 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2140 Status = InstallFat16BootCodeToDisk(SrcPath,
2141 SystemRootPath->Buffer);
2142 if (!NT_SUCCESS(Status))
2143 {
2144 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2145 return Status;
2146 }
2147 }
2148 }
2149 else
2150 {
2151 /* Update existing 'freeldr.ini' */
2152 wcscpy(DstPath, SystemRootPath->Buffer);
2153 wcscat(DstPath, L"\\freeldr.ini");
2154
2155 Status = UpdateFreeLoaderIni(DstPath,
2156 DestinationArcPath->Buffer);
2157 if (!NT_SUCCESS(Status))
2158 {
2159 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2160 return Status;
2161 }
2162 }
2163 }
2164
2165 return STATUS_SUCCESS;
2166 #else
2167 return STATUS_NOT_IMPLEMENTED;
2168 #endif
2169 }
2170
2171 NTSTATUS
2172 InstallVBRToPartition(
2173 PUNICODE_STRING SystemRootPath,
2174 PUNICODE_STRING SourceRootPath,
2175 PUNICODE_STRING DestinationArcPath,
2176 UCHAR PartitionType)
2177 {
2178 if ((PartitionType == PARTITION_FAT_12) ||
2179 (PartitionType == PARTITION_FAT_16) ||
2180 (PartitionType == PARTITION_HUGE) ||
2181 (PartitionType == PARTITION_XINT13) ||
2182 (PartitionType == PARTITION_FAT32) ||
2183 (PartitionType == PARTITION_FAT32_XINT13))
2184 {
2185 return InstallFatBootcodeToPartition(SystemRootPath,
2186 SourceRootPath,
2187 DestinationArcPath,
2188 PartitionType);
2189 }
2190
2191 return STATUS_UNSUCCESSFUL;
2192 }
2193
2194
2195 NTSTATUS
2196 InstallFatBootcodeToFloppy(
2197 PUNICODE_STRING SourceRootPath,
2198 PUNICODE_STRING DestinationArcPath)
2199 {
2200 #ifdef __REACTOS__
2201 WCHAR SrcPath[MAX_PATH];
2202 WCHAR DstPath[MAX_PATH];
2203 NTSTATUS Status;
2204
2205 /* Copy FreeLoader to the boot partition */
2206 wcscpy(SrcPath, SourceRootPath->Buffer);
2207 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2208
2209 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2210
2211 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2212 Status = SetupCopyFile(SrcPath, DstPath);
2213 if (!NT_SUCCESS(Status))
2214 {
2215 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2216 return Status;
2217 }
2218
2219 /* Create new 'freeldr.ini' */
2220 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2221
2222 DPRINT("Create new 'freeldr.ini'\n");
2223 Status = CreateFreeLoaderIniForReactos(DstPath, DestinationArcPath->Buffer);
2224 if (!NT_SUCCESS(Status))
2225 {
2226 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2227 return Status;
2228 }
2229
2230 /* Install FAT12/16 boosector */
2231 wcscpy(SrcPath, SourceRootPath->Buffer);
2232 wcscat(SrcPath, L"\\loader\\fat.bin");
2233
2234 wcscpy(DstPath, L"\\Device\\Floppy0");
2235
2236 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2237 Status = InstallFat16BootCodeToDisk(SrcPath, DstPath);
2238 if (!NT_SUCCESS(Status))
2239 {
2240 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2241 return Status;
2242 }
2243
2244 return STATUS_SUCCESS;
2245 #else
2246 return STATUS_NOT_IMPLEMENTED;
2247 #endif
2248 }
2249
2250 /* EOF */