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