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