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