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