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