Sync with trunk r64509.
[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
1448 /* Allocate buffer for original bootsector */
1449 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1450 if (OrigBootSector == NULL)
1451 return STATUS_INSUFFICIENT_RESOURCES;
1452
1453 /* Read current boot sector into buffer */
1454 RtlInitUnicodeString(&Name, RootPath);
1455
1456 InitializeObjectAttributes(&ObjectAttributes,
1457 &Name,
1458 OBJ_CASE_INSENSITIVE,
1459 NULL,
1460 NULL);
1461
1462 Status = NtOpenFile(&FileHandle,
1463 GENERIC_READ | SYNCHRONIZE,
1464 &ObjectAttributes,
1465 &IoStatusBlock,
1466 0,
1467 FILE_SYNCHRONOUS_IO_NONALERT);
1468 if (!NT_SUCCESS(Status))
1469 {
1470 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1471 return Status;
1472 }
1473
1474 Status = NtReadFile(FileHandle,
1475 NULL,
1476 NULL,
1477 NULL,
1478 &IoStatusBlock,
1479 OrigBootSector,
1480 SECTORSIZE,
1481 NULL,
1482 NULL);
1483 NtClose(FileHandle);
1484 if (!NT_SUCCESS(Status))
1485 {
1486 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1487 return Status;
1488 }
1489
1490 /* Allocate buffer for new bootsector */
1491 NewBootSector = RtlAllocateHeap(ProcessHeap,
1492 0,
1493 SECTORSIZE);
1494 if (NewBootSector == NULL)
1495 {
1496 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1497 return STATUS_INSUFFICIENT_RESOURCES;
1498 }
1499
1500 /* Read new bootsector from SrcPath */
1501 RtlInitUnicodeString(&Name, SrcPath);
1502
1503 InitializeObjectAttributes(&ObjectAttributes,
1504 &Name,
1505 OBJ_CASE_INSENSITIVE,
1506 NULL,
1507 NULL);
1508
1509 Status = NtOpenFile(&FileHandle,
1510 GENERIC_READ | SYNCHRONIZE,
1511 &ObjectAttributes,
1512 &IoStatusBlock,
1513 0,
1514 FILE_SYNCHRONOUS_IO_NONALERT);
1515 if (!NT_SUCCESS(Status))
1516 {
1517 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1518 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1519 return Status;
1520 }
1521
1522 Status = NtReadFile(FileHandle,
1523 NULL,
1524 NULL,
1525 NULL,
1526 &IoStatusBlock,
1527 NewBootSector,
1528 SECTORSIZE,
1529 NULL,
1530 NULL);
1531 NtClose(FileHandle);
1532 if (!NT_SUCCESS(Status))
1533 {
1534 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1535 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1536 return Status;
1537 }
1538
1539 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1540 memcpy(&NewBootSector->OemName,
1541 &OrigBootSector->OemName,
1542 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1543 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1544
1545 NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
1546
1547 /* Free the original boot sector */
1548 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1549
1550 /* Write new bootsector to RootPath */
1551 RtlInitUnicodeString(&Name, RootPath);
1552
1553 InitializeObjectAttributes(&ObjectAttributes,
1554 &Name,
1555 0,
1556 NULL,
1557 NULL);
1558
1559 Status = NtOpenFile(&FileHandle,
1560 GENERIC_WRITE | SYNCHRONIZE,
1561 &ObjectAttributes,
1562 &IoStatusBlock,
1563 0,
1564 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1565 if (!NT_SUCCESS(Status))
1566 {
1567 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1568 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1569 return Status;
1570 }
1571
1572 #if 0
1573 FilePosition.QuadPart = 0;
1574 #endif
1575 Status = NtWriteFile(FileHandle,
1576 NULL,
1577 NULL,
1578 NULL,
1579 &IoStatusBlock,
1580 NewBootSector,
1581 SECTORSIZE,
1582 NULL,
1583 NULL);
1584 NtClose(FileHandle);
1585
1586 /* Free the new boot sector */
1587 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1588
1589 return Status;
1590 }
1591
1592
1593 NTSTATUS
1594 InstallFat32BootCodeToDisk(
1595 PWSTR SrcPath,
1596 PWSTR RootPath)
1597 {
1598 OBJECT_ATTRIBUTES ObjectAttributes;
1599 IO_STATUS_BLOCK IoStatusBlock;
1600 UNICODE_STRING Name;
1601 HANDLE FileHandle;
1602 NTSTATUS Status;
1603 PFAT32_BOOTSECTOR OrigBootSector;
1604 PFAT32_BOOTSECTOR NewBootSector;
1605 LARGE_INTEGER FileOffset;
1606 USHORT BackupBootSector;
1607
1608 /* Allocate buffer for original bootsector */
1609 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1610 if (OrigBootSector == NULL)
1611 return STATUS_INSUFFICIENT_RESOURCES;
1612
1613 /* Read current boot sector into buffer */
1614 RtlInitUnicodeString(&Name, RootPath);
1615
1616 InitializeObjectAttributes(&ObjectAttributes,
1617 &Name,
1618 OBJ_CASE_INSENSITIVE,
1619 NULL,
1620 NULL);
1621
1622 Status = NtOpenFile(&FileHandle,
1623 GENERIC_READ | SYNCHRONIZE,
1624 &ObjectAttributes,
1625 &IoStatusBlock,
1626 0,
1627 FILE_SYNCHRONOUS_IO_NONALERT);
1628 if (!NT_SUCCESS(Status))
1629 {
1630 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1631 return Status;
1632 }
1633
1634 Status = NtReadFile(FileHandle,
1635 NULL,
1636 NULL,
1637 NULL,
1638 &IoStatusBlock,
1639 OrigBootSector,
1640 SECTORSIZE,
1641 NULL,
1642 NULL);
1643 NtClose(FileHandle);
1644 if (!NT_SUCCESS(Status))
1645 {
1646 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1647 return Status;
1648 }
1649
1650
1651 /* Allocate buffer for new bootsector (2 sectors) */
1652 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1653 if (NewBootSector == NULL)
1654 {
1655 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1656 return STATUS_INSUFFICIENT_RESOURCES;
1657 }
1658
1659 /* Read new bootsector from SrcPath */
1660 RtlInitUnicodeString(&Name, SrcPath);
1661
1662 InitializeObjectAttributes(&ObjectAttributes,
1663 &Name,
1664 OBJ_CASE_INSENSITIVE,
1665 NULL,
1666 NULL);
1667
1668 Status = NtOpenFile(&FileHandle,
1669 GENERIC_READ | SYNCHRONIZE,
1670 &ObjectAttributes,
1671 &IoStatusBlock,
1672 0,
1673 FILE_SYNCHRONOUS_IO_NONALERT);
1674 if (!NT_SUCCESS(Status))
1675 {
1676 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1677 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1678 return Status;
1679 }
1680
1681 Status = NtReadFile(FileHandle,
1682 NULL,
1683 NULL,
1684 NULL,
1685 &IoStatusBlock,
1686 NewBootSector,
1687 2 * SECTORSIZE,
1688 NULL,
1689 NULL);
1690 NtClose(FileHandle);
1691 if (!NT_SUCCESS(Status))
1692 {
1693 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1694 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1695 return Status;
1696 }
1697
1698 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1699 memcpy(&NewBootSector->OemName,
1700 &OrigBootSector->OemName,
1701 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1702 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1703
1704 NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
1705
1706 /* Get the location of the backup boot sector */
1707 BackupBootSector = OrigBootSector->BackupBootSector;
1708
1709 /* Free the original boot sector */
1710 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1711
1712 /* Write the first sector of the new bootcode to DstPath */
1713 RtlInitUnicodeString(&Name, RootPath);
1714
1715 InitializeObjectAttributes(&ObjectAttributes,
1716 &Name,
1717 0,
1718 NULL,
1719 NULL);
1720
1721 Status = NtOpenFile(&FileHandle,
1722 GENERIC_WRITE | SYNCHRONIZE,
1723 &ObjectAttributes,
1724 &IoStatusBlock,
1725 0,
1726 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1727 if (!NT_SUCCESS(Status))
1728 {
1729 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1730 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1731 return Status;
1732 }
1733
1734 /* Write sector 0 */
1735 FileOffset.QuadPart = 0ULL;
1736 Status = NtWriteFile(FileHandle,
1737 NULL,
1738 NULL,
1739 NULL,
1740 &IoStatusBlock,
1741 NewBootSector,
1742 SECTORSIZE,
1743 &FileOffset,
1744 NULL);
1745 if (!NT_SUCCESS(Status))
1746 {
1747 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1748 NtClose(FileHandle);
1749 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1750 return Status;
1751 }
1752
1753 /* Write backup boot sector */
1754 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1755 {
1756 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1757 Status = NtWriteFile(FileHandle,
1758 NULL,
1759 NULL,
1760 NULL,
1761 &IoStatusBlock,
1762 NewBootSector,
1763 SECTORSIZE,
1764 &FileOffset,
1765 NULL);
1766 if (!NT_SUCCESS(Status))
1767 {
1768 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1769 NtClose(FileHandle);
1770 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1771 return Status;
1772 }
1773 }
1774
1775 /* Write sector 14 */
1776 FileOffset.QuadPart = 14 * SECTORSIZE;
1777 Status = NtWriteFile(FileHandle,
1778 NULL,
1779 NULL,
1780 NULL,
1781 &IoStatusBlock,
1782 ((PUCHAR)NewBootSector + SECTORSIZE),
1783 SECTORSIZE,
1784 &FileOffset,
1785 NULL);
1786 if (!NT_SUCCESS(Status))
1787 {
1788 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1789 }
1790 NtClose(FileHandle);
1791
1792 /* Free the new boot sector */
1793 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1794
1795 return Status;
1796 }
1797
1798
1799 static
1800 NTSTATUS
1801 UnprotectBootIni(
1802 PWSTR FileName,
1803 PULONG Attributes)
1804 {
1805 UNICODE_STRING Name;
1806 OBJECT_ATTRIBUTES ObjectAttributes;
1807 IO_STATUS_BLOCK IoStatusBlock;
1808 FILE_BASIC_INFORMATION FileInfo;
1809 HANDLE FileHandle;
1810 NTSTATUS Status;
1811
1812 RtlInitUnicodeString(&Name, FileName);
1813
1814 InitializeObjectAttributes(&ObjectAttributes,
1815 &Name,
1816 OBJ_CASE_INSENSITIVE,
1817 NULL,
1818 NULL);
1819
1820 Status = NtOpenFile(&FileHandle,
1821 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1822 &ObjectAttributes,
1823 &IoStatusBlock,
1824 0,
1825 FILE_SYNCHRONOUS_IO_NONALERT);
1826 if (Status == STATUS_NO_SUCH_FILE)
1827 {
1828 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1829 *Attributes = 0;
1830 return STATUS_SUCCESS;
1831 }
1832 if (!NT_SUCCESS(Status))
1833 {
1834 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1835 return Status;
1836 }
1837
1838 Status = NtQueryInformationFile(FileHandle,
1839 &IoStatusBlock,
1840 &FileInfo,
1841 sizeof(FILE_BASIC_INFORMATION),
1842 FileBasicInformation);
1843 if (!NT_SUCCESS(Status))
1844 {
1845 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1846 NtClose(FileHandle);
1847 return Status;
1848 }
1849
1850 *Attributes = FileInfo.FileAttributes;
1851
1852 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1853 FileInfo.FileAttributes = FileInfo.FileAttributes &
1854 ~(FILE_ATTRIBUTE_SYSTEM |
1855 FILE_ATTRIBUTE_HIDDEN |
1856 FILE_ATTRIBUTE_READONLY);
1857
1858 Status = NtSetInformationFile(FileHandle,
1859 &IoStatusBlock,
1860 &FileInfo,
1861 sizeof(FILE_BASIC_INFORMATION),
1862 FileBasicInformation);
1863 if (!NT_SUCCESS(Status))
1864 {
1865 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1866 }
1867
1868 NtClose(FileHandle);
1869 return Status;
1870 }
1871
1872
1873 static
1874 NTSTATUS
1875 ProtectBootIni(
1876 PWSTR FileName,
1877 ULONG Attributes)
1878 {
1879 UNICODE_STRING Name;
1880 OBJECT_ATTRIBUTES ObjectAttributes;
1881 IO_STATUS_BLOCK IoStatusBlock;
1882 FILE_BASIC_INFORMATION FileInfo;
1883 HANDLE FileHandle;
1884 NTSTATUS Status;
1885
1886 RtlInitUnicodeString(&Name, FileName);
1887
1888 InitializeObjectAttributes(&ObjectAttributes,
1889 &Name,
1890 OBJ_CASE_INSENSITIVE,
1891 NULL,
1892 NULL);
1893
1894 Status = NtOpenFile(&FileHandle,
1895 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1896 &ObjectAttributes,
1897 &IoStatusBlock,
1898 0,
1899 FILE_SYNCHRONOUS_IO_NONALERT);
1900 if (!NT_SUCCESS(Status))
1901 {
1902 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1903 return Status;
1904 }
1905
1906 Status = NtQueryInformationFile(FileHandle,
1907 &IoStatusBlock,
1908 &FileInfo,
1909 sizeof(FILE_BASIC_INFORMATION),
1910 FileBasicInformation);
1911 if (!NT_SUCCESS(Status))
1912 {
1913 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1914 NtClose(FileHandle);
1915 return Status;
1916 }
1917
1918 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1919
1920 Status = NtSetInformationFile(FileHandle,
1921 &IoStatusBlock,
1922 &FileInfo,
1923 sizeof(FILE_BASIC_INFORMATION),
1924 FileBasicInformation);
1925 if (!NT_SUCCESS(Status))
1926 {
1927 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1928 }
1929
1930 NtClose(FileHandle);
1931 return Status;
1932 }
1933
1934
1935 NTSTATUS
1936 UpdateBootIni(
1937 PWSTR BootIniPath,
1938 PWSTR EntryName,
1939 PWSTR EntryValue)
1940 {
1941 UNICODE_STRING Name;
1942 PINICACHE Cache = NULL;
1943 PINICACHESECTION Section = NULL;
1944 NTSTATUS Status;
1945 ULONG FileAttribute;
1946 PWCHAR OldValue = NULL;
1947
1948 RtlInitUnicodeString(&Name, BootIniPath);
1949
1950 Status = IniCacheLoad(&Cache, &Name, FALSE);
1951 if (!NT_SUCCESS(Status))
1952 {
1953 return Status;
1954 }
1955
1956 Section = IniCacheGetSection(Cache,
1957 L"operating systems");
1958 if (Section == NULL)
1959 {
1960 IniCacheDestroy(Cache);
1961 return STATUS_UNSUCCESSFUL;
1962 }
1963
1964 /* Check - maybe record already exists */
1965 Status = IniCacheGetKey(Section, EntryName, &OldValue);
1966
1967 /* If either key was not found, or contains something else - add new one */
1968 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
1969 {
1970 IniCacheInsertKey(Section,
1971 NULL,
1972 INSERT_LAST,
1973 EntryName,
1974 EntryValue);
1975 }
1976
1977 Status = UnprotectBootIni(BootIniPath,
1978 &FileAttribute);
1979 if (!NT_SUCCESS(Status))
1980 {
1981 IniCacheDestroy(Cache);
1982 return Status;
1983 }
1984
1985 Status = IniCacheSave(Cache, BootIniPath);
1986 if (!NT_SUCCESS(Status))
1987 {
1988 IniCacheDestroy(Cache);
1989 return Status;
1990 }
1991
1992 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1993 Status = ProtectBootIni(BootIniPath, FileAttribute);
1994
1995 IniCacheDestroy(Cache);
1996
1997 return Status;
1998 }
1999
2000
2001 BOOLEAN
2002 CheckInstallFatBootcodeToPartition(
2003 PUNICODE_STRING SystemRootPath)
2004 {
2005 #ifdef __REACTOS__
2006 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") ||
2007 DoesFileExist(SystemRootPath->Buffer, L"boot.ini"))
2008 {
2009 return TRUE;
2010 }
2011 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") ||
2012 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys"))
2013 {
2014 return TRUE;
2015 }
2016 #endif
2017
2018 return FALSE;
2019 }
2020
2021
2022 NTSTATUS
2023 InstallFatBootcodeToPartition(
2024 PUNICODE_STRING SystemRootPath,
2025 PUNICODE_STRING SourceRootPath,
2026 PUNICODE_STRING DestinationArcPath,
2027 UCHAR PartitionType)
2028 {
2029 #ifdef __REACTOS__
2030 WCHAR SrcPath[MAX_PATH];
2031 WCHAR DstPath[MAX_PATH];
2032 NTSTATUS Status;
2033
2034 /* FAT or FAT32 partition */
2035 DPRINT("System path: '%wZ'\n", SystemRootPath);
2036
2037 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
2038 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
2039 {
2040 /* Search root directory for 'ntldr' and 'boot.ini'. */
2041 DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n");
2042
2043 /* Copy FreeLoader to the boot partition */
2044 wcscpy(SrcPath, SourceRootPath->Buffer);
2045 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2046 wcscpy(DstPath, SystemRootPath->Buffer);
2047 wcscat(DstPath, L"\\freeldr.sys");
2048
2049 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2050 Status = SetupCopyFile(SrcPath, DstPath);
2051 if (!NT_SUCCESS(Status))
2052 {
2053 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2054 return Status;
2055 }
2056
2057 /* Create or update freeldr.ini */
2058 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2059 {
2060 /* Create new 'freeldr.ini' */
2061 DPRINT1("Create new 'freeldr.ini'\n");
2062 wcscpy(DstPath, SystemRootPath->Buffer);
2063 wcscat(DstPath, L"\\freeldr.ini");
2064
2065 Status = CreateFreeLoaderIniForReactos(DstPath,
2066 DestinationArcPath->Buffer);
2067 if (!NT_SUCCESS(Status))
2068 {
2069 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2070 return Status;
2071 }
2072
2073 /* Install new bootcode */
2074 if (PartitionType == PARTITION_FAT32 ||
2075 PartitionType == PARTITION_FAT32_XINT13)
2076 {
2077 /* Install FAT32 bootcode */
2078 wcscpy(SrcPath, SourceRootPath->Buffer);
2079 wcscat(SrcPath, L"\\loader\\fat32.bin");
2080 wcscpy(DstPath, SystemRootPath->Buffer);
2081 wcscat(DstPath, L"\\bootsect.ros");
2082
2083 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2084 Status = InstallFat32BootCodeToFile(SrcPath,
2085 DstPath,
2086 SystemRootPath->Buffer);
2087 if (!NT_SUCCESS(Status))
2088 {
2089 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2090 return Status;
2091 }
2092 }
2093 else
2094 {
2095 /* Install FAT16 bootcode */
2096 wcscpy(SrcPath, SourceRootPath->Buffer);
2097 wcscat(SrcPath, L"\\loader\\fat.bin");
2098 wcscpy(DstPath, SystemRootPath->Buffer);
2099 wcscat(DstPath, L"\\bootsect.ros");
2100
2101 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2102 Status = InstallFat16BootCodeToFile(SrcPath,
2103 DstPath,
2104 SystemRootPath->Buffer);
2105 if (!NT_SUCCESS(Status))
2106 {
2107 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2108 return Status;
2109 }
2110 }
2111 }
2112 else
2113 {
2114 /* Update existing 'freeldr.ini' */
2115 DPRINT1("Update existing 'freeldr.ini'\n");
2116 wcscpy(DstPath, SystemRootPath->Buffer);
2117 wcscat(DstPath, L"\\freeldr.ini");
2118
2119 Status = UpdateFreeLoaderIni(DstPath,
2120 DestinationArcPath->Buffer);
2121 if (!NT_SUCCESS(Status))
2122 {
2123 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2124 return Status;
2125 }
2126 }
2127
2128 /* Update 'boot.ini' */
2129 wcscpy(DstPath, SystemRootPath->Buffer);
2130 wcscat(DstPath, L"\\boot.ini");
2131
2132 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2133 Status = UpdateBootIni(DstPath,
2134 L"C:\\bootsect.ros",
2135 L"\"ReactOS\"");
2136 if (!NT_SUCCESS(Status))
2137 {
2138 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2139 return Status;
2140 }
2141 }
2142 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
2143 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
2144 {
2145 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2146 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2147
2148 /* Copy FreeLoader to the boot partition */
2149 wcscpy(SrcPath, SourceRootPath->Buffer);
2150 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2151 wcscpy(DstPath, SystemRootPath->Buffer);
2152 wcscat(DstPath, L"\\freeldr.sys");
2153
2154 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2155 Status = SetupCopyFile(SrcPath, DstPath);
2156 if (!NT_SUCCESS(Status))
2157 {
2158 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2159 return Status;
2160 }
2161
2162 /* Create or update 'freeldr.ini' */
2163 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2164 {
2165 /* Create new 'freeldr.ini' */
2166 DPRINT1("Create new 'freeldr.ini'\n");
2167 wcscpy(DstPath, SystemRootPath->Buffer);
2168 wcscat(DstPath, L"\\freeldr.ini");
2169
2170 Status = CreateFreeLoaderIniForDos(DstPath,
2171 DestinationArcPath->Buffer);
2172 if (!NT_SUCCESS(Status))
2173 {
2174 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2175 return Status;
2176 }
2177
2178 /* Save current bootsector as 'BOOTSECT.DOS' */
2179 wcscpy(SrcPath, SystemRootPath->Buffer);
2180 wcscpy(DstPath, SystemRootPath->Buffer);
2181 wcscat(DstPath, L"\\bootsect.dos");
2182
2183 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2184 Status = SaveCurrentBootSector(SrcPath,
2185 DstPath);
2186 if (!NT_SUCCESS(Status))
2187 {
2188 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2189 return Status;
2190 }
2191
2192 /* Install new bootsector */
2193 if (PartitionType == PARTITION_FAT32 ||
2194 PartitionType == PARTITION_FAT32_XINT13)
2195 {
2196 wcscpy(SrcPath, SourceRootPath->Buffer);
2197 wcscat(SrcPath, L"\\loader\\fat32.bin");
2198
2199 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2200 Status = InstallFat32BootCodeToDisk(SrcPath,
2201 SystemRootPath->Buffer);
2202 if (!NT_SUCCESS(Status))
2203 {
2204 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2205 return Status;
2206 }
2207 }
2208 else
2209 {
2210 wcscpy(SrcPath, SourceRootPath->Buffer);
2211 wcscat(SrcPath, L"\\loader\\fat.bin");
2212
2213 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2214 Status = InstallFat16BootCodeToDisk(SrcPath,
2215 SystemRootPath->Buffer);
2216 if (!NT_SUCCESS(Status))
2217 {
2218 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2219 return Status;
2220 }
2221 }
2222 }
2223 else
2224 {
2225 /* Update existing 'freeldr.ini' */
2226 wcscpy(DstPath, SystemRootPath->Buffer);
2227 wcscat(DstPath, L"\\freeldr.ini");
2228
2229 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2230 if (!NT_SUCCESS(Status))
2231 {
2232 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2233 return Status;
2234 }
2235 }
2236 }
2237 else
2238 {
2239 /* No or unknown boot loader */
2240 DPRINT1("No or unknown boot loader found\n");
2241
2242 /* Copy FreeLoader to the boot partition */
2243 wcscpy(SrcPath, SourceRootPath->Buffer);
2244 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2245 wcscpy(DstPath, SystemRootPath->Buffer);
2246 wcscat(DstPath, L"\\freeldr.sys");
2247
2248 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2249 Status = SetupCopyFile(SrcPath, DstPath);
2250 if (!NT_SUCCESS(Status))
2251 {
2252 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2253 return Status;
2254 }
2255
2256 /* Create or update 'freeldr.ini' */
2257 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2258 {
2259 /* Create new freeldr.ini */
2260 wcscpy(DstPath, SystemRootPath->Buffer);
2261 wcscat(DstPath, L"\\freeldr.ini");
2262
2263 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2264 Status = CreateFreeLoaderIniForReactos(DstPath,
2265 DestinationArcPath->Buffer);
2266 if (!NT_SUCCESS(Status))
2267 {
2268 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2269 return Status;
2270 }
2271
2272 /* Save current bootsector as 'BOOTSECT.OLD' */
2273 wcscpy(SrcPath, SystemRootPath->Buffer);
2274 wcscpy(DstPath, SystemRootPath->Buffer);
2275 wcscat(DstPath, L"\\bootsect.old");
2276
2277 DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2278 Status = SaveCurrentBootSector(SrcPath,
2279 DstPath);
2280 if (!NT_SUCCESS(Status))
2281 {
2282 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2283 return Status;
2284 }
2285
2286 /* Install new bootsector */
2287 if ((PartitionType == PARTITION_FAT32) ||
2288 (PartitionType == PARTITION_FAT32_XINT13))
2289 {
2290 wcscpy(SrcPath, SourceRootPath->Buffer);
2291 wcscat(SrcPath, L"\\loader\\fat32.bin");
2292
2293 DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2294 Status = InstallFat32BootCodeToDisk(SrcPath,
2295 SystemRootPath->Buffer);
2296 if (!NT_SUCCESS(Status))
2297 {
2298 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2299 return Status;
2300 }
2301 }
2302 else
2303 {
2304 wcscpy(SrcPath, SourceRootPath->Buffer);
2305 wcscat(SrcPath, L"\\loader\\fat.bin");
2306
2307 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2308 Status = InstallFat16BootCodeToDisk(SrcPath,
2309 SystemRootPath->Buffer);
2310 if (!NT_SUCCESS(Status))
2311 {
2312 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2313 return Status;
2314 }
2315 }
2316 }
2317 else
2318 {
2319 /* Update existing 'freeldr.ini' */
2320 wcscpy(DstPath, SystemRootPath->Buffer);
2321 wcscat(DstPath, L"\\freeldr.ini");
2322
2323 Status = UpdateFreeLoaderIni(DstPath,
2324 DestinationArcPath->Buffer);
2325 if (!NT_SUCCESS(Status))
2326 {
2327 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2328 return Status;
2329 }
2330 }
2331 }
2332
2333 return STATUS_SUCCESS;
2334 #else
2335 return STATUS_NOT_IMPLEMENTED;
2336 #endif
2337 }
2338
2339
2340 NTSTATUS
2341 InstallVBRToPartition(
2342 PUNICODE_STRING SystemRootPath,
2343 PUNICODE_STRING SourceRootPath,
2344 PUNICODE_STRING DestinationArcPath,
2345 UCHAR PartitionType)
2346 {
2347 if ((PartitionType == PARTITION_FAT_12) ||
2348 (PartitionType == PARTITION_FAT_16) ||
2349 (PartitionType == PARTITION_HUGE) ||
2350 (PartitionType == PARTITION_XINT13) ||
2351 (PartitionType == PARTITION_FAT32) ||
2352 (PartitionType == PARTITION_FAT32_XINT13))
2353 {
2354 return InstallFatBootcodeToPartition(SystemRootPath,
2355 SourceRootPath,
2356 DestinationArcPath,
2357 PartitionType);
2358 }
2359
2360 return STATUS_UNSUCCESSFUL;
2361 }
2362
2363
2364 NTSTATUS
2365 InstallFatBootcodeToFloppy(
2366 PUNICODE_STRING SourceRootPath,
2367 PUNICODE_STRING DestinationArcPath)
2368 {
2369 #ifdef __REACTOS__
2370 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0");
2371 WCHAR SrcPath[MAX_PATH];
2372 WCHAR DstPath[MAX_PATH];
2373 NTSTATUS Status;
2374
2375 /* Format the floppy first */
2376 Status = VfatFormat(&FloppyDevice,
2377 FMIFS_FLOPPY,
2378 NULL,
2379 TRUE,
2380 0,
2381 NULL);
2382 if (!NT_SUCCESS(Status))
2383 {
2384 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2385 return Status;
2386 }
2387
2388 /* Copy FreeLoader to the boot partition */
2389 wcscpy(SrcPath, SourceRootPath->Buffer);
2390 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2391
2392 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2393
2394 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2395 Status = SetupCopyFile(SrcPath, DstPath);
2396 if (!NT_SUCCESS(Status))
2397 {
2398 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2399 return Status;
2400 }
2401
2402 /* Create new 'freeldr.ini' */
2403 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2404
2405 DPRINT("Create new 'freeldr.ini'\n");
2406 Status = CreateFreeLoaderIniForReactos(DstPath, DestinationArcPath->Buffer);
2407 if (!NT_SUCCESS(Status))
2408 {
2409 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2410 return Status;
2411 }
2412
2413 /* Install FAT12/16 boosector */
2414 wcscpy(SrcPath, SourceRootPath->Buffer);
2415 wcscat(SrcPath, L"\\loader\\fat.bin");
2416
2417 wcscpy(DstPath, L"\\Device\\Floppy0");
2418
2419 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2420 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2421 if (!NT_SUCCESS(Status))
2422 {
2423 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2424 return Status;
2425 }
2426
2427 return STATUS_SUCCESS;
2428 #else
2429 return STATUS_NOT_IMPLEMENTED;
2430 #endif
2431 }
2432
2433 /* EOF */