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