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