[rshell]
[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"Windows2003", L"ramdisk(0)\\ReactOS",
505 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDIMAGEPATH=reactos.img /RDIMAGEOFFSET=32256");
506
507 /* ReactOS_EMS */
508 CreateFreeLoaderEntry(IniCache, IniSection,
509 L"ReactOS_EMS", L"\"ReactOS (Emergency Management Services)\"",
510 L"Windows2003", ArcPath,
511 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200");
512 #endif
513
514 /* Save the ini file */
515 IniCacheSave(IniCache, IniPath);
516 IniCacheDestroy(IniCache);
517
518 return STATUS_SUCCESS;
519 }
520
521
522 NTSTATUS
523 UpdateFreeLoaderIni(
524 PWCHAR IniPath,
525 PWCHAR ArcPath)
526 {
527 UNICODE_STRING Name;
528 PINICACHE IniCache;
529 PINICACHESECTION IniSection;
530 PINICACHESECTION OsIniSection;
531 WCHAR SectionName[80];
532 WCHAR OsName[80];
533 WCHAR SystemPath[200];
534 WCHAR SectionName2[200];
535 PWCHAR KeyData;
536 ULONG i,j;
537 NTSTATUS Status;
538
539 RtlInitUnicodeString(&Name, IniPath);
540
541 Status = IniCacheLoad(&IniCache, &Name, FALSE);
542 if (!NT_SUCCESS(Status))
543 return Status;
544
545 /* Get "Operating Systems" section */
546 IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
547 if (IniSection == NULL)
548 {
549 IniCacheDestroy(IniCache);
550 return STATUS_UNSUCCESSFUL;
551 }
552
553 /* Find an existing usable or an unused section name */
554 i = 1;
555 wcscpy(SectionName, L"ReactOS");
556 wcscpy(OsName, L"\"ReactOS\"");
557 while(TRUE)
558 {
559 Status = IniCacheGetKey(IniSection, SectionName, &KeyData);
560 if (!NT_SUCCESS(Status))
561 break;
562
563 /* Get operation system section */
564 if (KeyData[0] == '"')
565 {
566 wcscpy(SectionName2, &KeyData[1]);
567 j = wcslen(SectionName2);
568 if (j > 0)
569 {
570 SectionName2[j-1] = 0;
571 }
572 }
573 else
574 {
575 wcscpy(SectionName2, KeyData);
576 }
577
578 OsIniSection = IniCacheGetSection(IniCache, SectionName2);
579 if (OsIniSection != NULL)
580 {
581 BOOLEAN UseExistingEntry = TRUE;
582
583 /* Check BootType */
584 Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
585 if (NT_SUCCESS(Status))
586 {
587 if ((KeyData == NULL) ||
588 ( (_wcsicmp(KeyData, L"ReactOS") != 0) &&
589 (_wcsicmp(KeyData, L"\"ReactOS\"") != 0) ))
590 {
591 /* This is not a ReactOS entry */
592 UseExistingEntry = FALSE;
593 }
594 }
595 else
596 {
597 UseExistingEntry = FALSE;
598 }
599
600 if (UseExistingEntry)
601 {
602 /* BootType is ReactOS. Now check SystemPath */
603 Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
604 if (NT_SUCCESS(Status))
605 {
606 swprintf(SystemPath, L"\"%S\"", ArcPath);
607 if ((KeyData == NULL) ||
608 ((_wcsicmp(KeyData, ArcPath) != 0) &&
609 (_wcsicmp(KeyData, SystemPath) != 0) ))
610 {
611 /* This entry is a ReactOS entry, but the SystemRoot does not
612 match the one we are looking for */
613 UseExistingEntry = FALSE;
614 }
615 }
616 else
617 {
618 UseExistingEntry = FALSE;
619 }
620 }
621
622 if (UseExistingEntry)
623 {
624 IniCacheDestroy(IniCache);
625 return STATUS_SUCCESS;
626 }
627 }
628
629 swprintf(SectionName, L"ReactOS_%lu", i);
630 swprintf(OsName, L"\"ReactOS %lu\"", i);
631 i++;
632 }
633
634 /* <SectionName>=<OsName> */
635 IniCacheInsertKey(IniSection,
636 NULL,
637 INSERT_LAST,
638 SectionName,
639 OsName);
640
641 /* Create <SectionName> section */
642 IniSection = IniCacheAppendSection(IniCache, SectionName);
643
644 /* BootType=ReactOS */
645 IniCacheInsertKey(IniSection,
646 NULL,
647 INSERT_LAST,
648 L"BootType",
649 L"ReactOS");
650
651 /* SystemPath=<ArcPath> */
652 IniCacheInsertKey(IniSection,
653 NULL,
654 INSERT_LAST,
655 L"SystemPath",
656 ArcPath);
657
658 IniCacheSave(IniCache, IniPath);
659 IniCacheDestroy(IniCache);
660
661 return STATUS_SUCCESS;
662 }
663
664
665 NTSTATUS
666 SaveCurrentBootSector(
667 PWSTR RootPath,
668 PWSTR DstPath)
669 {
670 OBJECT_ATTRIBUTES ObjectAttributes;
671 IO_STATUS_BLOCK IoStatusBlock;
672 UNICODE_STRING Name;
673 HANDLE FileHandle;
674 NTSTATUS Status;
675 PUCHAR BootSector;
676
677 /* Allocate buffer for bootsector */
678 BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
679 if (BootSector == NULL)
680 return STATUS_INSUFFICIENT_RESOURCES;
681
682 /* Read current boot sector into buffer */
683 RtlInitUnicodeString(&Name, RootPath);
684
685 InitializeObjectAttributes(&ObjectAttributes,
686 &Name,
687 OBJ_CASE_INSENSITIVE,
688 NULL,
689 NULL);
690
691 Status = NtOpenFile(&FileHandle,
692 GENERIC_READ | SYNCHRONIZE,
693 &ObjectAttributes,
694 &IoStatusBlock,
695 0,
696 FILE_SYNCHRONOUS_IO_NONALERT);
697 if (!NT_SUCCESS(Status))
698 {
699 RtlFreeHeap(ProcessHeap, 0, BootSector);
700 return Status;
701 }
702
703 Status = NtReadFile(FileHandle,
704 NULL,
705 NULL,
706 NULL,
707 &IoStatusBlock,
708 BootSector,
709 SECTORSIZE,
710 NULL,
711 NULL);
712 NtClose(FileHandle);
713 if (!NT_SUCCESS(Status))
714 {
715 RtlFreeHeap(ProcessHeap, 0, BootSector);
716 return Status;
717 }
718
719 /* Write bootsector to DstPath */
720 RtlInitUnicodeString(&Name, DstPath);
721
722 InitializeObjectAttributes(&ObjectAttributes,
723 &Name,
724 0,
725 NULL,
726 NULL);
727
728 Status = NtCreateFile(&FileHandle,
729 GENERIC_WRITE | SYNCHRONIZE,
730 &ObjectAttributes,
731 &IoStatusBlock,
732 NULL,
733 FILE_ATTRIBUTE_NORMAL,
734 0,
735 FILE_SUPERSEDE,
736 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
737 NULL,
738 0);
739 if (!NT_SUCCESS(Status))
740 {
741 RtlFreeHeap(ProcessHeap, 0, BootSector);
742 return Status;
743 }
744
745 Status = NtWriteFile(FileHandle,
746 NULL,
747 NULL,
748 NULL,
749 &IoStatusBlock,
750 BootSector,
751 SECTORSIZE,
752 NULL,
753 NULL);
754 NtClose(FileHandle);
755
756 /* Free the new boot sector */
757 RtlFreeHeap(ProcessHeap, 0, BootSector);
758
759 return Status;
760 }
761
762
763 NTSTATUS
764 InstallFat16BootCodeToFile(
765 PWSTR SrcPath,
766 PWSTR DstPath,
767 PWSTR RootPath)
768 {
769 OBJECT_ATTRIBUTES ObjectAttributes;
770 IO_STATUS_BLOCK IoStatusBlock;
771 UNICODE_STRING Name;
772 HANDLE FileHandle;
773 NTSTATUS Status;
774 PFAT_BOOTSECTOR OrigBootSector;
775 PFAT_BOOTSECTOR NewBootSector;
776
777 /* Allocate buffer for original bootsector */
778 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
779 if (OrigBootSector == NULL)
780 return STATUS_INSUFFICIENT_RESOURCES ;
781
782 /* Read current boot sector into buffer */
783 RtlInitUnicodeString(&Name, RootPath);
784
785 InitializeObjectAttributes(&ObjectAttributes,
786 &Name,
787 OBJ_CASE_INSENSITIVE,
788 NULL,
789 NULL);
790
791 Status = NtOpenFile(&FileHandle,
792 GENERIC_READ | SYNCHRONIZE,
793 &ObjectAttributes,
794 &IoStatusBlock,
795 0,
796 FILE_SYNCHRONOUS_IO_NONALERT);
797 if (!NT_SUCCESS(Status))
798 {
799 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
800 return Status;
801 }
802
803 Status = NtReadFile(FileHandle,
804 NULL,
805 NULL,
806 NULL,
807 &IoStatusBlock,
808 OrigBootSector,
809 SECTORSIZE,
810 NULL,
811 NULL);
812 NtClose(FileHandle);
813 if (!NT_SUCCESS(Status))
814 {
815 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
816 return Status;
817 }
818
819 /* Allocate buffer for new bootsector */
820 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
821 if (NewBootSector == NULL)
822 {
823 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
824 return STATUS_INSUFFICIENT_RESOURCES;
825 }
826
827 /* Read new bootsector from SrcPath */
828 RtlInitUnicodeString(&Name, SrcPath);
829
830 InitializeObjectAttributes(&ObjectAttributes,
831 &Name,
832 OBJ_CASE_INSENSITIVE,
833 NULL,
834 NULL);
835
836 Status = NtOpenFile(&FileHandle,
837 GENERIC_READ | SYNCHRONIZE,
838 &ObjectAttributes,
839 &IoStatusBlock,
840 0,
841 FILE_SYNCHRONOUS_IO_NONALERT);
842 if (!NT_SUCCESS(Status))
843 {
844 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
845 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
846 return Status;
847 }
848
849 Status = NtReadFile(FileHandle,
850 NULL,
851 NULL,
852 NULL,
853 &IoStatusBlock,
854 NewBootSector,
855 SECTORSIZE,
856 NULL,
857 NULL);
858 NtClose(FileHandle);
859 if (!NT_SUCCESS(Status))
860 {
861 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
862 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
863 return Status;
864 }
865
866 /* Adjust bootsector (copy a part of the FAT BPB) */
867 memcpy(&NewBootSector->OemName,
868 &OrigBootSector->OemName,
869 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
870 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
871
872 /* Free the original boot sector */
873 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
874
875 /* Write new bootsector to DstPath */
876 RtlInitUnicodeString(&Name, DstPath);
877
878 InitializeObjectAttributes(&ObjectAttributes,
879 &Name,
880 0,
881 NULL,
882 NULL);
883
884 Status = NtCreateFile(&FileHandle,
885 GENERIC_WRITE | SYNCHRONIZE,
886 &ObjectAttributes,
887 &IoStatusBlock,
888 NULL,
889 FILE_ATTRIBUTE_NORMAL,
890 0,
891 FILE_OVERWRITE_IF,
892 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
893 NULL,
894 0);
895 if (!NT_SUCCESS(Status))
896 {
897 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
898 return Status;
899 }
900
901 #if 0
902 FilePosition.QuadPart = 0;
903 #endif
904 Status = NtWriteFile(FileHandle,
905 NULL,
906 NULL,
907 NULL,
908 &IoStatusBlock,
909 NewBootSector,
910 SECTORSIZE,
911 NULL,
912 NULL);
913 NtClose(FileHandle);
914
915 /* Free the new boot sector */
916 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
917
918 return Status;
919 }
920
921
922 NTSTATUS
923 InstallFat32BootCodeToFile(
924 PWSTR SrcPath,
925 PWSTR DstPath,
926 PWSTR RootPath)
927 {
928 OBJECT_ATTRIBUTES ObjectAttributes;
929 IO_STATUS_BLOCK IoStatusBlock;
930 UNICODE_STRING Name;
931 HANDLE FileHandle;
932 NTSTATUS Status;
933 PFAT32_BOOTSECTOR OrigBootSector;
934 PFAT32_BOOTSECTOR NewBootSector;
935 LARGE_INTEGER FileOffset;
936
937 /* Allocate buffer for original bootsector */
938 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
939 if (OrigBootSector == NULL)
940 return STATUS_INSUFFICIENT_RESOURCES;
941
942 /* Read current boot sector into buffer */
943 RtlInitUnicodeString(&Name, RootPath);
944
945 InitializeObjectAttributes(&ObjectAttributes,
946 &Name,
947 OBJ_CASE_INSENSITIVE,
948 NULL,
949 NULL);
950
951 Status = NtOpenFile(&FileHandle,
952 GENERIC_READ | SYNCHRONIZE,
953 &ObjectAttributes,
954 &IoStatusBlock,
955 0,
956 FILE_SYNCHRONOUS_IO_NONALERT);
957 if (!NT_SUCCESS(Status))
958 {
959 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
960 return Status;
961 }
962
963 Status = NtReadFile(FileHandle,
964 NULL,
965 NULL,
966 NULL,
967 &IoStatusBlock,
968 OrigBootSector,
969 SECTORSIZE,
970 NULL,
971 NULL);
972 NtClose(FileHandle);
973 if (!NT_SUCCESS(Status))
974 {
975 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
976 return Status;
977 }
978
979 /* Allocate buffer for new bootsector (2 sectors) */
980 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
981 if (NewBootSector == NULL)
982 {
983 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
984 return STATUS_INSUFFICIENT_RESOURCES;
985 }
986
987 /* Read new bootsector from SrcPath */
988 RtlInitUnicodeString(&Name, SrcPath);
989
990 InitializeObjectAttributes(&ObjectAttributes,
991 &Name,
992 OBJ_CASE_INSENSITIVE,
993 NULL,
994 NULL);
995
996 Status = NtOpenFile(&FileHandle,
997 GENERIC_READ | SYNCHRONIZE,
998 &ObjectAttributes,
999 &IoStatusBlock,
1000 0,
1001 FILE_SYNCHRONOUS_IO_NONALERT);
1002 if (!NT_SUCCESS(Status))
1003 {
1004 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1005 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1006 return Status;
1007 }
1008
1009 Status = NtReadFile(FileHandle,
1010 NULL,
1011 NULL,
1012 NULL,
1013 &IoStatusBlock,
1014 NewBootSector,
1015 2 * SECTORSIZE,
1016 NULL,
1017 NULL);
1018 NtClose(FileHandle);
1019 if (!NT_SUCCESS(Status))
1020 {
1021 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1022 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1023 return Status;
1024 }
1025
1026 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1027 memcpy(&NewBootSector->OemName,
1028 &OrigBootSector->OemName,
1029 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1030 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1031
1032 /* Disable the backup boot sector */
1033 NewBootSector->BackupBootSector = 0;
1034
1035 /* Free the original boot sector */
1036 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1037
1038 /* Write the first sector of the new bootcode to DstPath */
1039 RtlInitUnicodeString(&Name, DstPath);
1040
1041 InitializeObjectAttributes(&ObjectAttributes,
1042 &Name,
1043 0,
1044 NULL,
1045 NULL);
1046
1047 Status = NtCreateFile(&FileHandle,
1048 GENERIC_WRITE | SYNCHRONIZE,
1049 &ObjectAttributes,
1050 &IoStatusBlock,
1051 NULL,
1052 FILE_ATTRIBUTE_NORMAL,
1053 0,
1054 FILE_SUPERSEDE,
1055 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1056 NULL,
1057 0);
1058 if (!NT_SUCCESS(Status))
1059 {
1060 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1061 return Status;
1062 }
1063
1064 Status = NtWriteFile(FileHandle,
1065 NULL,
1066 NULL,
1067 NULL,
1068 &IoStatusBlock,
1069 NewBootSector,
1070 SECTORSIZE,
1071 NULL,
1072 NULL);
1073 NtClose(FileHandle);
1074 if (!NT_SUCCESS(Status))
1075 {
1076 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1077 return Status;
1078 }
1079
1080 /* Write the second sector of the new bootcode to boot disk sector 14 */
1081 RtlInitUnicodeString(&Name, RootPath);
1082
1083 InitializeObjectAttributes(&ObjectAttributes,
1084 &Name,
1085 0,
1086 NULL,
1087 NULL);
1088
1089 Status = NtOpenFile(&FileHandle,
1090 GENERIC_WRITE | SYNCHRONIZE,
1091 &ObjectAttributes,
1092 &IoStatusBlock,
1093 0,
1094 FILE_SYNCHRONOUS_IO_NONALERT);
1095 if (!NT_SUCCESS(Status))
1096 {
1097 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1098 return Status;
1099 }
1100
1101 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1102 Status = NtWriteFile(FileHandle,
1103 NULL,
1104 NULL,
1105 NULL,
1106 &IoStatusBlock,
1107 ((PUCHAR)NewBootSector + SECTORSIZE),
1108 SECTORSIZE,
1109 &FileOffset,
1110 NULL);
1111 if (!NT_SUCCESS(Status))
1112 {
1113 }
1114 NtClose(FileHandle);
1115
1116 /* Free the new boot sector */
1117 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1118
1119 return Status;
1120 }
1121
1122
1123 NTSTATUS
1124 InstallMbrBootCodeToDisk(
1125 PWSTR SrcPath,
1126 PWSTR RootPath)
1127 {
1128 OBJECT_ATTRIBUTES ObjectAttributes;
1129 IO_STATUS_BLOCK IoStatusBlock;
1130 UNICODE_STRING Name;
1131 HANDLE FileHandle;
1132 NTSTATUS Status;
1133 PPARTITION_SECTOR OrigBootSector;
1134 PPARTITION_SECTOR NewBootSector;
1135
1136 /* Allocate buffer for original bootsector */
1137 OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1138 0,
1139 sizeof(PARTITION_SECTOR));
1140 if (OrigBootSector == NULL)
1141 return STATUS_INSUFFICIENT_RESOURCES;
1142
1143 /* Read current boot sector into buffer */
1144 RtlInitUnicodeString(&Name,
1145 RootPath);
1146
1147 InitializeObjectAttributes(&ObjectAttributes,
1148 &Name,
1149 OBJ_CASE_INSENSITIVE,
1150 NULL,
1151 NULL);
1152
1153 Status = NtOpenFile(&FileHandle,
1154 GENERIC_READ | SYNCHRONIZE,
1155 &ObjectAttributes,
1156 &IoStatusBlock,
1157 0,
1158 FILE_SYNCHRONOUS_IO_NONALERT);
1159 if (!NT_SUCCESS(Status))
1160 {
1161 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1162 return Status;
1163 }
1164
1165 Status = NtReadFile(FileHandle,
1166 NULL,
1167 NULL,
1168 NULL,
1169 &IoStatusBlock,
1170 OrigBootSector,
1171 SECTORSIZE,
1172 NULL,
1173 NULL);
1174 NtClose(FileHandle);
1175 if (!NT_SUCCESS(Status))
1176 {
1177 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1178 return Status;
1179 }
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 NTSTATUS
1279 InstallFat12BootCodeToFloppy(PWSTR SrcPath,
1280 PWSTR RootPath)
1281 {
1282 OBJECT_ATTRIBUTES ObjectAttributes;
1283 IO_STATUS_BLOCK IoStatusBlock;
1284 UNICODE_STRING Name;
1285 HANDLE FileHandle;
1286 NTSTATUS Status;
1287 PFAT_BOOTSECTOR OrigBootSector;
1288 PFAT_BOOTSECTOR NewBootSector;
1289
1290 /* Allocate buffer for original bootsector */
1291 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1292 if (OrigBootSector == NULL)
1293 return STATUS_INSUFFICIENT_RESOURCES;
1294
1295 /* Read current boot sector into buffer */
1296 RtlInitUnicodeString(&Name, RootPath);
1297
1298 InitializeObjectAttributes(&ObjectAttributes,
1299 &Name,
1300 OBJ_CASE_INSENSITIVE,
1301 NULL,
1302 NULL);
1303
1304 Status = NtOpenFile(&FileHandle,
1305 GENERIC_READ | SYNCHRONIZE,
1306 &ObjectAttributes,
1307 &IoStatusBlock,
1308 0,
1309 FILE_SYNCHRONOUS_IO_NONALERT);
1310 if (!NT_SUCCESS(Status))
1311 {
1312 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1313 return Status;
1314 }
1315
1316 Status = NtReadFile(FileHandle,
1317 NULL,
1318 NULL,
1319 NULL,
1320 &IoStatusBlock,
1321 OrigBootSector,
1322 SECTORSIZE,
1323 NULL,
1324 NULL);
1325 NtClose(FileHandle);
1326 if (!NT_SUCCESS(Status))
1327 {
1328 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1329 return Status;
1330 }
1331
1332
1333 /* Allocate buffer for new bootsector */
1334 NewBootSector = RtlAllocateHeap(ProcessHeap,
1335 0,
1336 SECTORSIZE);
1337 if (NewBootSector == NULL)
1338 {
1339 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1340 return STATUS_INSUFFICIENT_RESOURCES;
1341 }
1342
1343 /* Read new bootsector from SrcPath */
1344 RtlInitUnicodeString(&Name, SrcPath);
1345
1346 InitializeObjectAttributes(&ObjectAttributes,
1347 &Name,
1348 OBJ_CASE_INSENSITIVE,
1349 NULL,
1350 NULL);
1351
1352 Status = NtOpenFile(&FileHandle,
1353 GENERIC_READ | SYNCHRONIZE,
1354 &ObjectAttributes,
1355 &IoStatusBlock,
1356 0,
1357 FILE_SYNCHRONOUS_IO_NONALERT);
1358 if (!NT_SUCCESS(Status))
1359 {
1360 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1361 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1362 return Status;
1363 }
1364
1365 Status = NtReadFile(FileHandle,
1366 NULL,
1367 NULL,
1368 NULL,
1369 &IoStatusBlock,
1370 NewBootSector,
1371 SECTORSIZE,
1372 NULL,
1373 NULL);
1374 NtClose(FileHandle);
1375 if (!NT_SUCCESS(Status))
1376 {
1377 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1378 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1379 return Status;
1380 }
1381
1382 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1383 memcpy(&NewBootSector->OemName,
1384 &OrigBootSector->OemName,
1385 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1386 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1387
1388 /* Free the original boot sector */
1389 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1390
1391 /* Write new bootsector to RootPath */
1392 RtlInitUnicodeString(&Name, RootPath);
1393
1394 InitializeObjectAttributes(&ObjectAttributes,
1395 &Name,
1396 0,
1397 NULL,
1398 NULL);
1399
1400 Status = NtOpenFile(&FileHandle,
1401 GENERIC_WRITE | SYNCHRONIZE,
1402 &ObjectAttributes,
1403 &IoStatusBlock,
1404 0,
1405 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1406 if (!NT_SUCCESS(Status))
1407 {
1408 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1409 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1410 return Status;
1411 }
1412
1413 #if 0
1414 FilePosition.QuadPart = 0;
1415 #endif
1416 Status = NtWriteFile(FileHandle,
1417 NULL,
1418 NULL,
1419 NULL,
1420 &IoStatusBlock,
1421 NewBootSector,
1422 SECTORSIZE,
1423 NULL,
1424 NULL);
1425 NtClose(FileHandle);
1426
1427 /* Free the new boot sector */
1428 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1429
1430 return Status;
1431 }
1432
1433
1434 NTSTATUS
1435 InstallFat16BootCodeToDisk(
1436 PWSTR SrcPath,
1437 PWSTR RootPath)
1438 {
1439 OBJECT_ATTRIBUTES ObjectAttributes;
1440 IO_STATUS_BLOCK IoStatusBlock;
1441 UNICODE_STRING Name;
1442 HANDLE FileHandle;
1443 NTSTATUS Status;
1444 PFAT_BOOTSECTOR OrigBootSector;
1445 PFAT_BOOTSECTOR NewBootSector;
1446 PARTITION_INFORMATION *PartInfo;
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
1491 /* Allocate buffer for new bootsector */
1492 NewBootSector = RtlAllocateHeap(ProcessHeap,
1493 0,
1494 SECTORSIZE);
1495 if (NewBootSector == NULL)
1496 {
1497 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1498 return STATUS_INSUFFICIENT_RESOURCES;
1499 }
1500
1501 /* Read new bootsector from SrcPath */
1502 RtlInitUnicodeString(&Name, SrcPath);
1503
1504 InitializeObjectAttributes(&ObjectAttributes,
1505 &Name,
1506 OBJ_CASE_INSENSITIVE,
1507 NULL,
1508 NULL);
1509
1510 Status = NtOpenFile(&FileHandle,
1511 GENERIC_READ | SYNCHRONIZE,
1512 &ObjectAttributes,
1513 &IoStatusBlock,
1514 0,
1515 FILE_SYNCHRONOUS_IO_NONALERT);
1516 if (!NT_SUCCESS(Status))
1517 {
1518 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1519 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1520 return Status;
1521 }
1522
1523 Status = NtReadFile(FileHandle,
1524 NULL,
1525 NULL,
1526 NULL,
1527 &IoStatusBlock,
1528 NewBootSector,
1529 SECTORSIZE,
1530 NULL,
1531 NULL);
1532 NtClose(FileHandle);
1533 if (!NT_SUCCESS(Status))
1534 {
1535 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1536 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1537 return Status;
1538 }
1539
1540 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1541 memcpy(&NewBootSector->OemName,
1542 &OrigBootSector->OemName,
1543 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1544 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1545
1546 PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
1547 NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
1548
1549 /* Free the original boot sector */
1550 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1551
1552 /* Write new bootsector to RootPath */
1553 RtlInitUnicodeString(&Name, RootPath);
1554
1555 InitializeObjectAttributes(&ObjectAttributes,
1556 &Name,
1557 0,
1558 NULL,
1559 NULL);
1560
1561 Status = NtOpenFile(&FileHandle,
1562 GENERIC_WRITE | SYNCHRONIZE,
1563 &ObjectAttributes,
1564 &IoStatusBlock,
1565 0,
1566 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1567 if (!NT_SUCCESS(Status))
1568 {
1569 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1570 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1571 return Status;
1572 }
1573
1574 #if 0
1575 FilePosition.QuadPart = 0;
1576 #endif
1577 Status = NtWriteFile(FileHandle,
1578 NULL,
1579 NULL,
1580 NULL,
1581 &IoStatusBlock,
1582 NewBootSector,
1583 SECTORSIZE,
1584 NULL,
1585 NULL);
1586 NtClose(FileHandle);
1587
1588 /* Free the new boot sector */
1589 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1590
1591 return Status;
1592 }
1593
1594
1595 NTSTATUS
1596 InstallFat32BootCodeToDisk(
1597 PWSTR SrcPath,
1598 PWSTR RootPath)
1599 {
1600 OBJECT_ATTRIBUTES ObjectAttributes;
1601 IO_STATUS_BLOCK IoStatusBlock;
1602 UNICODE_STRING Name;
1603 HANDLE FileHandle;
1604 NTSTATUS Status;
1605 PFAT32_BOOTSECTOR OrigBootSector;
1606 PFAT32_BOOTSECTOR NewBootSector;
1607 LARGE_INTEGER FileOffset;
1608 USHORT BackupBootSector;
1609 PARTITION_INFORMATION *PartInfo;
1610
1611 /* Allocate buffer for original bootsector */
1612 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1613 if (OrigBootSector == NULL)
1614 return STATUS_INSUFFICIENT_RESOURCES;
1615
1616 /* Read current boot sector into buffer */
1617 RtlInitUnicodeString(&Name, RootPath);
1618
1619 InitializeObjectAttributes(&ObjectAttributes,
1620 &Name,
1621 OBJ_CASE_INSENSITIVE,
1622 NULL,
1623 NULL);
1624
1625 Status = NtOpenFile(&FileHandle,
1626 GENERIC_READ | SYNCHRONIZE,
1627 &ObjectAttributes,
1628 &IoStatusBlock,
1629 0,
1630 FILE_SYNCHRONOUS_IO_NONALERT);
1631 if (!NT_SUCCESS(Status))
1632 {
1633 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1634 return Status;
1635 }
1636
1637 Status = NtReadFile(FileHandle,
1638 NULL,
1639 NULL,
1640 NULL,
1641 &IoStatusBlock,
1642 OrigBootSector,
1643 SECTORSIZE,
1644 NULL,
1645 NULL);
1646 NtClose(FileHandle);
1647 if (!NT_SUCCESS(Status))
1648 {
1649 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1650 return Status;
1651 }
1652
1653
1654 /* Allocate buffer for new bootsector (2 sectors) */
1655 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1656 if (NewBootSector == NULL)
1657 {
1658 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1659 return STATUS_INSUFFICIENT_RESOURCES;
1660 }
1661
1662 /* Read new bootsector from SrcPath */
1663 RtlInitUnicodeString(&Name, SrcPath);
1664
1665 InitializeObjectAttributes(&ObjectAttributes,
1666 &Name,
1667 OBJ_CASE_INSENSITIVE,
1668 NULL,
1669 NULL);
1670
1671 Status = NtOpenFile(&FileHandle,
1672 GENERIC_READ | SYNCHRONIZE,
1673 &ObjectAttributes,
1674 &IoStatusBlock,
1675 0,
1676 FILE_SYNCHRONOUS_IO_NONALERT);
1677 if (!NT_SUCCESS(Status))
1678 {
1679 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1680 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1681 return Status;
1682 }
1683
1684 Status = NtReadFile(FileHandle,
1685 NULL,
1686 NULL,
1687 NULL,
1688 &IoStatusBlock,
1689 NewBootSector,
1690 2 * SECTORSIZE,
1691 NULL,
1692 NULL);
1693 NtClose(FileHandle);
1694 if (!NT_SUCCESS(Status))
1695 {
1696 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1697 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1698 return Status;
1699 }
1700
1701 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1702 memcpy(&NewBootSector->OemName,
1703 &OrigBootSector->OemName,
1704 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1705 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1706
1707 PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
1708 NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
1709
1710 /* Get the location of the backup boot sector */
1711 BackupBootSector = OrigBootSector->BackupBootSector;
1712
1713 /* Free the original boot sector */
1714 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1715
1716 /* Write the first sector of the new bootcode to DstPath */
1717 RtlInitUnicodeString(&Name, RootPath);
1718
1719 InitializeObjectAttributes(&ObjectAttributes,
1720 &Name,
1721 0,
1722 NULL,
1723 NULL);
1724
1725 Status = NtOpenFile(&FileHandle,
1726 GENERIC_WRITE | SYNCHRONIZE,
1727 &ObjectAttributes,
1728 &IoStatusBlock,
1729 0,
1730 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1731 if (!NT_SUCCESS(Status))
1732 {
1733 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1734 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1735 return Status;
1736 }
1737
1738 /* Write sector 0 */
1739 FileOffset.QuadPart = 0ULL;
1740 Status = NtWriteFile(FileHandle,
1741 NULL,
1742 NULL,
1743 NULL,
1744 &IoStatusBlock,
1745 NewBootSector,
1746 SECTORSIZE,
1747 &FileOffset,
1748 NULL);
1749 if (!NT_SUCCESS(Status))
1750 {
1751 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1752 NtClose(FileHandle);
1753 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1754 return Status;
1755 }
1756
1757 /* Write backup boot sector */
1758 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1759 {
1760 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1761 Status = NtWriteFile(FileHandle,
1762 NULL,
1763 NULL,
1764 NULL,
1765 &IoStatusBlock,
1766 NewBootSector,
1767 SECTORSIZE,
1768 &FileOffset,
1769 NULL);
1770 if (!NT_SUCCESS(Status))
1771 {
1772 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1773 NtClose(FileHandle);
1774 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1775 return Status;
1776 }
1777 }
1778
1779 /* Write sector 14 */
1780 FileOffset.QuadPart = 14 * SECTORSIZE;
1781 Status = NtWriteFile(FileHandle,
1782 NULL,
1783 NULL,
1784 NULL,
1785 &IoStatusBlock,
1786 ((PUCHAR)NewBootSector + SECTORSIZE),
1787 SECTORSIZE,
1788 &FileOffset,
1789 NULL);
1790 if (!NT_SUCCESS(Status))
1791 {
1792 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1793 }
1794 NtClose(FileHandle);
1795
1796 /* Free the new boot sector */
1797 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1798
1799 return Status;
1800 }
1801
1802
1803 static
1804 NTSTATUS
1805 UnprotectBootIni(
1806 PWSTR FileName,
1807 PULONG Attributes)
1808 {
1809 UNICODE_STRING Name;
1810 OBJECT_ATTRIBUTES ObjectAttributes;
1811 IO_STATUS_BLOCK IoStatusBlock;
1812 FILE_BASIC_INFORMATION FileInfo;
1813 HANDLE FileHandle;
1814 NTSTATUS Status;
1815
1816 RtlInitUnicodeString(&Name, FileName);
1817
1818 InitializeObjectAttributes(&ObjectAttributes,
1819 &Name,
1820 OBJ_CASE_INSENSITIVE,
1821 NULL,
1822 NULL);
1823
1824 Status = NtOpenFile(&FileHandle,
1825 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1826 &ObjectAttributes,
1827 &IoStatusBlock,
1828 0,
1829 FILE_SYNCHRONOUS_IO_NONALERT);
1830 if (Status == STATUS_NO_SUCH_FILE)
1831 {
1832 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1833 *Attributes = 0;
1834 return STATUS_SUCCESS;
1835 }
1836 if (!NT_SUCCESS(Status))
1837 {
1838 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1839 return Status;
1840 }
1841
1842 Status = NtQueryInformationFile(FileHandle,
1843 &IoStatusBlock,
1844 &FileInfo,
1845 sizeof(FILE_BASIC_INFORMATION),
1846 FileBasicInformation);
1847 if (!NT_SUCCESS(Status))
1848 {
1849 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1850 NtClose(FileHandle);
1851 return Status;
1852 }
1853
1854 *Attributes = FileInfo.FileAttributes;
1855
1856 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1857 FileInfo.FileAttributes = FileInfo.FileAttributes &
1858 ~(FILE_ATTRIBUTE_SYSTEM |
1859 FILE_ATTRIBUTE_HIDDEN |
1860 FILE_ATTRIBUTE_READONLY);
1861
1862 Status = NtSetInformationFile(FileHandle,
1863 &IoStatusBlock,
1864 &FileInfo,
1865 sizeof(FILE_BASIC_INFORMATION),
1866 FileBasicInformation);
1867 if (!NT_SUCCESS(Status))
1868 {
1869 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1870 }
1871
1872 NtClose(FileHandle);
1873 return Status;
1874 }
1875
1876
1877 static
1878 NTSTATUS
1879 ProtectBootIni(
1880 PWSTR FileName,
1881 ULONG Attributes)
1882 {
1883 UNICODE_STRING Name;
1884 OBJECT_ATTRIBUTES ObjectAttributes;
1885 IO_STATUS_BLOCK IoStatusBlock;
1886 FILE_BASIC_INFORMATION FileInfo;
1887 HANDLE FileHandle;
1888 NTSTATUS Status;
1889
1890 RtlInitUnicodeString(&Name, FileName);
1891
1892 InitializeObjectAttributes(&ObjectAttributes,
1893 &Name,
1894 OBJ_CASE_INSENSITIVE,
1895 NULL,
1896 NULL);
1897
1898 Status = NtOpenFile(&FileHandle,
1899 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1900 &ObjectAttributes,
1901 &IoStatusBlock,
1902 0,
1903 FILE_SYNCHRONOUS_IO_NONALERT);
1904 if (!NT_SUCCESS(Status))
1905 {
1906 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1907 return Status;
1908 }
1909
1910 Status = NtQueryInformationFile(FileHandle,
1911 &IoStatusBlock,
1912 &FileInfo,
1913 sizeof(FILE_BASIC_INFORMATION),
1914 FileBasicInformation);
1915 if (!NT_SUCCESS(Status))
1916 {
1917 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1918 NtClose(FileHandle);
1919 return Status;
1920 }
1921
1922 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1923
1924 Status = NtSetInformationFile(FileHandle,
1925 &IoStatusBlock,
1926 &FileInfo,
1927 sizeof(FILE_BASIC_INFORMATION),
1928 FileBasicInformation);
1929 if (!NT_SUCCESS(Status))
1930 {
1931 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1932 }
1933
1934 NtClose(FileHandle);
1935 return Status;
1936 }
1937
1938
1939 NTSTATUS
1940 UpdateBootIni(
1941 PWSTR BootIniPath,
1942 PWSTR EntryName,
1943 PWSTR EntryValue)
1944 {
1945 UNICODE_STRING Name;
1946 PINICACHE Cache = NULL;
1947 PINICACHESECTION Section = NULL;
1948 NTSTATUS Status;
1949 ULONG FileAttribute;
1950 PWCHAR OldValue = NULL;
1951
1952 RtlInitUnicodeString(&Name, BootIniPath);
1953
1954 Status = IniCacheLoad(&Cache, &Name, FALSE);
1955 if (!NT_SUCCESS(Status))
1956 {
1957 return Status;
1958 }
1959
1960 Section = IniCacheGetSection(Cache,
1961 L"operating systems");
1962 if (Section == NULL)
1963 {
1964 IniCacheDestroy(Cache);
1965 return STATUS_UNSUCCESSFUL;
1966 }
1967
1968 /* Check - maybe record already exists */
1969 Status = IniCacheGetKey(Section, EntryName, &OldValue);
1970
1971 /* If either key was not found, or contains something else - add new one */
1972 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
1973 {
1974 IniCacheInsertKey(Section,
1975 NULL,
1976 INSERT_LAST,
1977 EntryName,
1978 EntryValue);
1979 }
1980
1981 Status = UnprotectBootIni(BootIniPath,
1982 &FileAttribute);
1983 if (!NT_SUCCESS(Status))
1984 {
1985 IniCacheDestroy(Cache);
1986 return Status;
1987 }
1988
1989 Status = IniCacheSave(Cache, BootIniPath);
1990 if (!NT_SUCCESS(Status))
1991 {
1992 IniCacheDestroy(Cache);
1993 return Status;
1994 }
1995
1996 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1997 Status = ProtectBootIni(BootIniPath, FileAttribute);
1998
1999 IniCacheDestroy(Cache);
2000
2001 return Status;
2002 }
2003
2004 BOOLEAN
2005 CheckInstallFatBootcodeToPartition(
2006 PUNICODE_STRING SystemRootPath)
2007 {
2008 #ifdef __REACTOS__
2009 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") ||
2010 DoesFileExist(SystemRootPath->Buffer, L"boot.ini"))
2011 {
2012 return TRUE;
2013 }
2014 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") ||
2015 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys"))
2016 {
2017 return TRUE;
2018 }
2019 #endif
2020
2021 return FALSE;
2022 }
2023
2024
2025 NTSTATUS
2026 InstallFatBootcodeToPartition(
2027 PUNICODE_STRING SystemRootPath,
2028 PUNICODE_STRING SourceRootPath,
2029 PUNICODE_STRING DestinationArcPath,
2030 UCHAR PartitionType)
2031 {
2032 #ifdef __REACTOS__
2033 WCHAR SrcPath[MAX_PATH];
2034 WCHAR DstPath[MAX_PATH];
2035 NTSTATUS Status;
2036
2037 /* FAT or FAT32 partition */
2038 DPRINT("System path: '%wZ'\n", SystemRootPath);
2039
2040 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
2041 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
2042 {
2043 /* Search root directory for 'ntldr' and 'boot.ini'. */
2044 DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n");
2045
2046 /* Copy FreeLoader to the boot partition */
2047 wcscpy(SrcPath, SourceRootPath->Buffer);
2048 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2049 wcscpy(DstPath, SystemRootPath->Buffer);
2050 wcscat(DstPath, L"\\freeldr.sys");
2051
2052 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2053 Status = SetupCopyFile(SrcPath, DstPath);
2054 if (!NT_SUCCESS(Status))
2055 {
2056 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2057 return Status;
2058 }
2059
2060 /* Create or update freeldr.ini */
2061 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2062 {
2063 /* Create new 'freeldr.ini' */
2064 DPRINT1("Create new 'freeldr.ini'\n");
2065 wcscpy(DstPath, SystemRootPath->Buffer);
2066 wcscat(DstPath, L"\\freeldr.ini");
2067
2068 Status = CreateFreeLoaderIniForReactos(DstPath,
2069 DestinationArcPath->Buffer);
2070 if (!NT_SUCCESS(Status))
2071 {
2072 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2073 return Status;
2074 }
2075
2076 /* Install new bootcode */
2077 if (PartitionType == PARTITION_FAT32 ||
2078 PartitionType == PARTITION_FAT32_XINT13)
2079 {
2080 /* Install FAT32 bootcode */
2081 wcscpy(SrcPath, SourceRootPath->Buffer);
2082 wcscat(SrcPath, L"\\loader\\fat32.bin");
2083 wcscpy(DstPath, SystemRootPath->Buffer);
2084 wcscat(DstPath, L"\\bootsect.ros");
2085
2086 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2087 Status = InstallFat32BootCodeToFile(SrcPath,
2088 DstPath,
2089 SystemRootPath->Buffer);
2090 if (!NT_SUCCESS(Status))
2091 {
2092 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2093 return Status;
2094 }
2095 }
2096 else
2097 {
2098 /* Install FAT16 bootcode */
2099 wcscpy(SrcPath, SourceRootPath->Buffer);
2100 wcscat(SrcPath, L"\\loader\\fat.bin");
2101 wcscpy(DstPath, SystemRootPath->Buffer);
2102 wcscat(DstPath, L"\\bootsect.ros");
2103
2104 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2105 Status = InstallFat16BootCodeToFile(SrcPath,
2106 DstPath,
2107 SystemRootPath->Buffer);
2108 if (!NT_SUCCESS(Status))
2109 {
2110 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2111 return Status;
2112 }
2113 }
2114 }
2115 else
2116 {
2117 /* Update existing 'freeldr.ini' */
2118 DPRINT1("Update existing 'freeldr.ini'\n");
2119 wcscpy(DstPath, SystemRootPath->Buffer);
2120 wcscat(DstPath, L"\\freeldr.ini");
2121
2122 Status = UpdateFreeLoaderIni(DstPath,
2123 DestinationArcPath->Buffer);
2124 if (!NT_SUCCESS(Status))
2125 {
2126 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2127 return Status;
2128 }
2129 }
2130
2131 /* Update 'boot.ini' */
2132 wcscpy(DstPath, SystemRootPath->Buffer);
2133 wcscat(DstPath, L"\\boot.ini");
2134
2135 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2136 Status = UpdateBootIni(DstPath,
2137 L"C:\\bootsect.ros",
2138 L"\"ReactOS\"");
2139 if (!NT_SUCCESS(Status))
2140 {
2141 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2142 return Status;
2143 }
2144 }
2145 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
2146 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
2147 {
2148 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
2149 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2150
2151 /* Copy FreeLoader to the boot partition */
2152 wcscpy(SrcPath, SourceRootPath->Buffer);
2153 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2154 wcscpy(DstPath, SystemRootPath->Buffer);
2155 wcscat(DstPath, L"\\freeldr.sys");
2156
2157 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2158 Status = SetupCopyFile(SrcPath, DstPath);
2159 if (!NT_SUCCESS(Status))
2160 {
2161 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2162 return Status;
2163 }
2164
2165 /* Create or update 'freeldr.ini' */
2166 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2167 {
2168 /* Create new 'freeldr.ini' */
2169 DPRINT1("Create new 'freeldr.ini'\n");
2170 wcscpy(DstPath, SystemRootPath->Buffer);
2171 wcscat(DstPath, L"\\freeldr.ini");
2172
2173 Status = CreateFreeLoaderIniForDos(DstPath,
2174 DestinationArcPath->Buffer);
2175 if (!NT_SUCCESS(Status))
2176 {
2177 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
2178 return Status;
2179 }
2180
2181 /* Save current bootsector as 'BOOTSECT.DOS' */
2182 wcscpy(SrcPath, SystemRootPath->Buffer);
2183 wcscpy(DstPath, SystemRootPath->Buffer);
2184 wcscat(DstPath, L"\\bootsect.dos");
2185
2186 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2187 Status = SaveCurrentBootSector(SrcPath,
2188 DstPath);
2189 if (!NT_SUCCESS(Status))
2190 {
2191 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2192 return Status;
2193 }
2194
2195 /* Install new bootsector */
2196 if (PartitionType == PARTITION_FAT32 ||
2197 PartitionType == PARTITION_FAT32_XINT13)
2198 {
2199 wcscpy(SrcPath, SourceRootPath->Buffer);
2200 wcscat(SrcPath, L"\\loader\\fat32.bin");
2201
2202 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2203 Status = InstallFat32BootCodeToDisk(SrcPath,
2204 SystemRootPath->Buffer);
2205 if (!NT_SUCCESS(Status))
2206 {
2207 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2208 return Status;
2209 }
2210 }
2211 else
2212 {
2213 wcscpy(SrcPath, SourceRootPath->Buffer);
2214 wcscat(SrcPath, L"\\loader\\fat.bin");
2215
2216 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2217 Status = InstallFat16BootCodeToDisk(SrcPath,
2218 SystemRootPath->Buffer);
2219 if (!NT_SUCCESS(Status))
2220 {
2221 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2222 return Status;
2223 }
2224 }
2225 }
2226 else
2227 {
2228 /* Update existing 'freeldr.ini' */
2229 wcscpy(DstPath, SystemRootPath->Buffer);
2230 wcscat(DstPath, L"\\freeldr.ini");
2231
2232 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2233 if (!NT_SUCCESS(Status))
2234 {
2235 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2236 return Status;
2237 }
2238 }
2239 }
2240 else
2241 {
2242 /* No or unknown boot loader */
2243 DPRINT1("No or unknown boot loader found\n");
2244
2245 /* Copy FreeLoader to the boot partition */
2246 wcscpy(SrcPath, SourceRootPath->Buffer);
2247 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2248 wcscpy(DstPath, SystemRootPath->Buffer);
2249 wcscat(DstPath, L"\\freeldr.sys");
2250
2251 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2252 Status = SetupCopyFile(SrcPath, DstPath);
2253 if (!NT_SUCCESS(Status))
2254 {
2255 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2256 return Status;
2257 }
2258
2259 /* Create or update 'freeldr.ini' */
2260 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
2261 {
2262 /* Create new freeldr.ini */
2263 wcscpy(DstPath, SystemRootPath->Buffer);
2264 wcscat(DstPath, L"\\freeldr.ini");
2265
2266 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2267 Status = CreateFreeLoaderIniForReactos(DstPath,
2268 DestinationArcPath->Buffer);
2269 if (!NT_SUCCESS(Status))
2270 {
2271 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2272 return Status;
2273 }
2274
2275 /* Save current bootsector as 'BOOTSECT.OLD' */
2276 wcscpy(SrcPath, SystemRootPath->Buffer);
2277 wcscpy(DstPath, SystemRootPath->Buffer);
2278 wcscat(DstPath, L"\\bootsect.old");
2279
2280 DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2281 Status = SaveCurrentBootSector(SrcPath,
2282 DstPath);
2283 if (!NT_SUCCESS(Status))
2284 {
2285 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2286 return Status;
2287 }
2288
2289 /* Install new bootsector */
2290 if ((PartitionType == PARTITION_FAT32) ||
2291 (PartitionType == PARTITION_FAT32_XINT13))
2292 {
2293 wcscpy(SrcPath, SourceRootPath->Buffer);
2294 wcscat(SrcPath, L"\\loader\\fat32.bin");
2295
2296 DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2297 Status = InstallFat32BootCodeToDisk(SrcPath,
2298 SystemRootPath->Buffer);
2299 if (!NT_SUCCESS(Status))
2300 {
2301 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2302 return Status;
2303 }
2304 }
2305 else
2306 {
2307 wcscpy(SrcPath, SourceRootPath->Buffer);
2308 wcscat(SrcPath, L"\\loader\\fat.bin");
2309
2310 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2311 Status = InstallFat16BootCodeToDisk(SrcPath,
2312 SystemRootPath->Buffer);
2313 if (!NT_SUCCESS(Status))
2314 {
2315 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2316 return Status;
2317 }
2318 }
2319 }
2320 else
2321 {
2322 /* Update existing 'freeldr.ini' */
2323 wcscpy(DstPath, SystemRootPath->Buffer);
2324 wcscat(DstPath, L"\\freeldr.ini");
2325
2326 Status = UpdateFreeLoaderIni(DstPath,
2327 DestinationArcPath->Buffer);
2328 if (!NT_SUCCESS(Status))
2329 {
2330 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2331 return Status;
2332 }
2333 }
2334 }
2335
2336 return STATUS_SUCCESS;
2337 #else
2338 return STATUS_NOT_IMPLEMENTED;
2339 #endif
2340 }
2341
2342 NTSTATUS
2343 InstallVBRToPartition(
2344 PUNICODE_STRING SystemRootPath,
2345 PUNICODE_STRING SourceRootPath,
2346 PUNICODE_STRING DestinationArcPath,
2347 UCHAR PartitionType)
2348 {
2349 if ((PartitionType == PARTITION_FAT_12) ||
2350 (PartitionType == PARTITION_FAT_16) ||
2351 (PartitionType == PARTITION_HUGE) ||
2352 (PartitionType == PARTITION_XINT13) ||
2353 (PartitionType == PARTITION_FAT32) ||
2354 (PartitionType == PARTITION_FAT32_XINT13))
2355 {
2356 return InstallFatBootcodeToPartition(SystemRootPath,
2357 SourceRootPath,
2358 DestinationArcPath,
2359 PartitionType);
2360 }
2361
2362 return STATUS_UNSUCCESSFUL;
2363 }
2364
2365
2366 NTSTATUS
2367 InstallFatBootcodeToFloppy(
2368 PUNICODE_STRING SourceRootPath,
2369 PUNICODE_STRING DestinationArcPath)
2370 {
2371 #ifdef __REACTOS__
2372 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0");
2373 WCHAR SrcPath[MAX_PATH];
2374 WCHAR DstPath[MAX_PATH];
2375 NTSTATUS Status;
2376
2377 /* Format the floppy first */
2378 Status = VfatFormat(&FloppyDevice,
2379 FMIFS_FLOPPY,
2380 NULL,
2381 TRUE,
2382 0,
2383 NULL);
2384 if (!NT_SUCCESS(Status))
2385 {
2386 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2387 return Status;
2388 }
2389
2390 /* Copy FreeLoader to the boot partition */
2391 wcscpy(SrcPath, SourceRootPath->Buffer);
2392 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2393
2394 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2395
2396 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2397 Status = SetupCopyFile(SrcPath, DstPath);
2398 if (!NT_SUCCESS(Status))
2399 {
2400 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2401 return Status;
2402 }
2403
2404 /* Create new 'freeldr.ini' */
2405 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2406
2407 DPRINT("Create new 'freeldr.ini'\n");
2408 Status = CreateFreeLoaderIniForReactos(DstPath, DestinationArcPath->Buffer);
2409 if (!NT_SUCCESS(Status))
2410 {
2411 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2412 return Status;
2413 }
2414
2415 /* Install FAT12/16 boosector */
2416 wcscpy(SrcPath, SourceRootPath->Buffer);
2417 wcscat(SrcPath, L"\\loader\\fat.bin");
2418
2419 wcscpy(DstPath, L"\\Device\\Floppy0");
2420
2421 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2422 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2423 if (!NT_SUCCESS(Status))
2424 {
2425 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2426 return Status;
2427 }
2428
2429 return STATUS_SUCCESS;
2430 #else
2431 return STATUS_NOT_IMPLEMENTED;
2432 #endif
2433 }
2434
2435 /* EOF */