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