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