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