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