Copy w32api from trunk
[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 GENERIC_READ,
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 GENERIC_WRITE,
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 GENERIC_READ,
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 GENERIC_READ,
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 GENERIC_WRITE,
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 GENERIC_READ,
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 GENERIC_READ,
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 GENERIC_WRITE,
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 GENERIC_WRITE,
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 GENERIC_READ,
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 GENERIC_READ,
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 = NtOpenFile(&FileHandle,
1138 GENERIC_WRITE,
1139 &ObjectAttributes,
1140 &IoStatusBlock,
1141 0,
1142 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1143 if (!NT_SUCCESS(Status))
1144 {
1145 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1146 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1147 return(Status);
1148 }
1149
1150 Status = NtWriteFile(FileHandle,
1151 NULL,
1152 NULL,
1153 NULL,
1154 &IoStatusBlock,
1155 NewBootSector,
1156 SECTORSIZE,
1157 NULL,
1158 NULL);
1159 NtClose(FileHandle);
1160
1161 /* Free the new boot sector */
1162 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1163
1164 return(Status);
1165 }
1166
1167
1168 NTSTATUS
1169 InstallFat16BootCodeToDisk(PWSTR SrcPath,
1170 PWSTR RootPath)
1171 {
1172 OBJECT_ATTRIBUTES ObjectAttributes;
1173 IO_STATUS_BLOCK IoStatusBlock;
1174 UNICODE_STRING Name;
1175 HANDLE FileHandle;
1176 NTSTATUS Status;
1177 PUCHAR OrigBootSector;
1178 PUCHAR NewBootSector;
1179
1180 /* Allocate buffer for original bootsector */
1181 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1182 0,
1183 SECTORSIZE);
1184 if (OrigBootSector == NULL)
1185 return(STATUS_INSUFFICIENT_RESOURCES);
1186
1187 /* Read current boot sector into buffer */
1188 RtlInitUnicodeString(&Name,
1189 RootPath);
1190
1191 InitializeObjectAttributes(&ObjectAttributes,
1192 &Name,
1193 OBJ_CASE_INSENSITIVE,
1194 NULL,
1195 NULL);
1196
1197 Status = NtOpenFile(&FileHandle,
1198 GENERIC_READ,
1199 &ObjectAttributes,
1200 &IoStatusBlock,
1201 0,
1202 FILE_SYNCHRONOUS_IO_NONALERT);
1203 if (!NT_SUCCESS(Status))
1204 {
1205 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1206 return(Status);
1207 }
1208
1209 Status = NtReadFile(FileHandle,
1210 NULL,
1211 NULL,
1212 NULL,
1213 &IoStatusBlock,
1214 OrigBootSector,
1215 SECTORSIZE,
1216 NULL,
1217 NULL);
1218 NtClose(FileHandle);
1219 if (!NT_SUCCESS(Status))
1220 {
1221 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1222 return(Status);
1223 }
1224
1225
1226 /* Allocate buffer for new bootsector */
1227 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1228 0,
1229 SECTORSIZE);
1230 if (NewBootSector == NULL)
1231 {
1232 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1233 return(STATUS_INSUFFICIENT_RESOURCES);
1234 }
1235
1236 /* Read new bootsector from SrcPath */
1237 RtlInitUnicodeString(&Name,
1238 SrcPath);
1239
1240 InitializeObjectAttributes(&ObjectAttributes,
1241 &Name,
1242 OBJ_CASE_INSENSITIVE,
1243 NULL,
1244 NULL);
1245
1246 Status = NtOpenFile(&FileHandle,
1247 GENERIC_READ,
1248 &ObjectAttributes,
1249 &IoStatusBlock,
1250 0,
1251 FILE_SYNCHRONOUS_IO_NONALERT);
1252 if (!NT_SUCCESS(Status))
1253 {
1254 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1255 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1256 return(Status);
1257 }
1258
1259 Status = NtReadFile(FileHandle,
1260 NULL,
1261 NULL,
1262 NULL,
1263 &IoStatusBlock,
1264 NewBootSector,
1265 SECTORSIZE,
1266 NULL,
1267 NULL);
1268 NtClose(FileHandle);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1272 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1273 return(Status);
1274 }
1275
1276 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1277 memcpy((NewBootSector + 3),
1278 (OrigBootSector + 3),
1279 59); /* FAT16 BPB length*/
1280
1281 /* Free the original boot sector */
1282 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1283
1284 /* Write new bootsector to RootPath */
1285 RtlInitUnicodeString(&Name,
1286 RootPath);
1287
1288 InitializeObjectAttributes(&ObjectAttributes,
1289 &Name,
1290 0,
1291 NULL,
1292 NULL);
1293
1294 Status = NtOpenFile(&FileHandle,
1295 GENERIC_WRITE,
1296 &ObjectAttributes,
1297 &IoStatusBlock,
1298 0,
1299 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1300 if (!NT_SUCCESS(Status))
1301 {
1302 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1303 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1304 return(Status);
1305 }
1306
1307 #if 0
1308 FilePosition.QuadPart = 0;
1309 #endif
1310 Status = NtWriteFile(FileHandle,
1311 NULL,
1312 NULL,
1313 NULL,
1314 &IoStatusBlock,
1315 NewBootSector,
1316 SECTORSIZE,
1317 NULL,
1318 NULL);
1319 NtClose(FileHandle);
1320
1321 /* Free the new boot sector */
1322 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1323
1324 return(Status);
1325 }
1326
1327
1328 NTSTATUS
1329 InstallFat32BootCodeToDisk(PWSTR SrcPath,
1330 PWSTR RootPath)
1331 {
1332 OBJECT_ATTRIBUTES ObjectAttributes;
1333 IO_STATUS_BLOCK IoStatusBlock;
1334 UNICODE_STRING Name;
1335 HANDLE FileHandle;
1336 NTSTATUS Status;
1337 PUCHAR OrigBootSector;
1338 PUCHAR NewBootSector;
1339 LARGE_INTEGER FileOffset;
1340 USHORT BackupBootSector;
1341
1342 /* Allocate buffer for original bootsector */
1343 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1344 0,
1345 SECTORSIZE);
1346 if (OrigBootSector == NULL)
1347 return(STATUS_INSUFFICIENT_RESOURCES);
1348
1349 /* Read current boot sector into buffer */
1350 RtlInitUnicodeString(&Name,
1351 RootPath);
1352
1353 InitializeObjectAttributes(&ObjectAttributes,
1354 &Name,
1355 OBJ_CASE_INSENSITIVE,
1356 NULL,
1357 NULL);
1358
1359 Status = NtOpenFile(&FileHandle,
1360 GENERIC_READ,
1361 &ObjectAttributes,
1362 &IoStatusBlock,
1363 0,
1364 FILE_SYNCHRONOUS_IO_NONALERT);
1365 if (!NT_SUCCESS(Status))
1366 {
1367 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1368 return(Status);
1369 }
1370
1371 Status = NtReadFile(FileHandle,
1372 NULL,
1373 NULL,
1374 NULL,
1375 &IoStatusBlock,
1376 OrigBootSector,
1377 SECTORSIZE,
1378 NULL,
1379 NULL);
1380 NtClose(FileHandle);
1381 if (!NT_SUCCESS(Status))
1382 {
1383 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1384 return(Status);
1385 }
1386
1387
1388 /* Allocate buffer for new bootsector (2 sectors) */
1389 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1390 0,
1391 2 * SECTORSIZE);
1392 if (NewBootSector == NULL)
1393 {
1394 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1395 return(STATUS_INSUFFICIENT_RESOURCES);
1396 }
1397
1398 /* Read new bootsector from SrcPath */
1399 RtlInitUnicodeString(&Name,
1400 SrcPath);
1401
1402 InitializeObjectAttributes(&ObjectAttributes,
1403 &Name,
1404 OBJ_CASE_INSENSITIVE,
1405 NULL,
1406 NULL);
1407
1408 Status = NtOpenFile(&FileHandle,
1409 GENERIC_READ,
1410 &ObjectAttributes,
1411 &IoStatusBlock,
1412 0,
1413 FILE_SYNCHRONOUS_IO_NONALERT);
1414 if (!NT_SUCCESS(Status))
1415 {
1416 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1417 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1418 return(Status);
1419 }
1420
1421 Status = NtReadFile(FileHandle,
1422 NULL,
1423 NULL,
1424 NULL,
1425 &IoStatusBlock,
1426 NewBootSector,
1427 2 * SECTORSIZE,
1428 NULL,
1429 NULL);
1430 NtClose(FileHandle);
1431 if (!NT_SUCCESS(Status))
1432 {
1433 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1434 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1435 return(Status);
1436 }
1437
1438 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1439 memcpy((NewBootSector + 3),
1440 (OrigBootSector + 3),
1441 87); /* FAT32 BPB length */
1442
1443 /* Get the location of the backup boot sector */
1444 BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x32];
1445
1446 /* Free the original boot sector */
1447 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1448
1449 /* Write the first sector of the new bootcode to DstPath */
1450 RtlInitUnicodeString(&Name,
1451 RootPath);
1452
1453 InitializeObjectAttributes(&ObjectAttributes,
1454 &Name,
1455 0,
1456 NULL,
1457 NULL);
1458
1459 Status = NtOpenFile(&FileHandle,
1460 GENERIC_WRITE,
1461 &ObjectAttributes,
1462 &IoStatusBlock,
1463 0,
1464 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1465 if (!NT_SUCCESS(Status))
1466 {
1467 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1468 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1469 return(Status);
1470 }
1471
1472 /* Write sector 0 */
1473 FileOffset.QuadPart = 0ULL;
1474 Status = NtWriteFile(FileHandle,
1475 NULL,
1476 NULL,
1477 NULL,
1478 &IoStatusBlock,
1479 NewBootSector,
1480 SECTORSIZE,
1481 &FileOffset,
1482 NULL);
1483 if (!NT_SUCCESS(Status))
1484 {
1485 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1486 NtClose(FileHandle);
1487 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1488 return(Status);
1489 }
1490
1491 /* Write backup boot sector */
1492 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1493 {
1494 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1495 Status = NtWriteFile(FileHandle,
1496 NULL,
1497 NULL,
1498 NULL,
1499 &IoStatusBlock,
1500 NewBootSector,
1501 SECTORSIZE,
1502 &FileOffset,
1503 NULL);
1504 if (!NT_SUCCESS(Status))
1505 {
1506 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1507 NtClose(FileHandle);
1508 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1509 return(Status);
1510 }
1511 }
1512
1513 /* Write sector 14 */
1514 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1515 Status = NtWriteFile(FileHandle,
1516 NULL,
1517 NULL,
1518 NULL,
1519 &IoStatusBlock,
1520 (NewBootSector + SECTORSIZE),
1521 SECTORSIZE,
1522 &FileOffset,
1523 NULL);
1524 if (!NT_SUCCESS(Status))
1525 {
1526 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1527 }
1528 NtClose(FileHandle);
1529
1530 /* Free the new boot sector */
1531 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1532
1533 return(Status);
1534 }
1535
1536
1537 static NTSTATUS
1538 UnprotectBootIni(PWSTR FileName,
1539 PULONG Attributes)
1540 {
1541 UNICODE_STRING Name;
1542 OBJECT_ATTRIBUTES ObjectAttributes;
1543 IO_STATUS_BLOCK IoStatusBlock;
1544 FILE_BASIC_INFORMATION FileInfo;
1545 HANDLE FileHandle;
1546 NTSTATUS Status;
1547
1548 RtlInitUnicodeString(&Name,
1549 FileName);
1550
1551 InitializeObjectAttributes(&ObjectAttributes,
1552 &Name,
1553 OBJ_CASE_INSENSITIVE,
1554 NULL,
1555 NULL);
1556
1557 Status = NtOpenFile(&FileHandle,
1558 GENERIC_READ|GENERIC_WRITE,
1559 &ObjectAttributes,
1560 &IoStatusBlock,
1561 0,
1562 FILE_SYNCHRONOUS_IO_NONALERT);
1563 if (Status == STATUS_NO_SUCH_FILE)
1564 {
1565 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1566 *Attributes = 0;
1567 return(STATUS_SUCCESS);
1568 }
1569 if (!NT_SUCCESS(Status))
1570 {
1571 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1572 return(Status);
1573 }
1574
1575 Status = NtQueryInformationFile(FileHandle,
1576 &IoStatusBlock,
1577 &FileInfo,
1578 sizeof(FILE_BASIC_INFORMATION),
1579 FileBasicInformation);
1580 if (!NT_SUCCESS(Status))
1581 {
1582 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1583 NtClose(FileHandle);
1584 return(Status);
1585 }
1586
1587 *Attributes = FileInfo.FileAttributes;
1588
1589 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1590 FileInfo.FileAttributes = FileInfo.FileAttributes &
1591 ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1592
1593 Status = NtSetInformationFile(FileHandle,
1594 &IoStatusBlock,
1595 &FileInfo,
1596 sizeof(FILE_BASIC_INFORMATION),
1597 FileBasicInformation);
1598 if (!NT_SUCCESS(Status))
1599 {
1600 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1601 }
1602
1603 NtClose(FileHandle);
1604 return(Status);
1605 }
1606
1607
1608 static NTSTATUS
1609 ProtectBootIni(PWSTR FileName,
1610 ULONG Attributes)
1611 {
1612 UNICODE_STRING Name;
1613 OBJECT_ATTRIBUTES ObjectAttributes;
1614 IO_STATUS_BLOCK IoStatusBlock;
1615 FILE_BASIC_INFORMATION FileInfo;
1616 HANDLE FileHandle;
1617 NTSTATUS Status;
1618
1619 RtlInitUnicodeString(&Name,
1620 FileName);
1621
1622 InitializeObjectAttributes(&ObjectAttributes,
1623 &Name,
1624 OBJ_CASE_INSENSITIVE,
1625 NULL,
1626 NULL);
1627
1628 Status = NtOpenFile(&FileHandle,
1629 GENERIC_READ|GENERIC_WRITE,
1630 &ObjectAttributes,
1631 &IoStatusBlock,
1632 0,
1633 FILE_SYNCHRONOUS_IO_NONALERT);
1634 if (!NT_SUCCESS(Status))
1635 {
1636 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1637 return(Status);
1638 }
1639
1640 Status = NtQueryInformationFile(FileHandle,
1641 &IoStatusBlock,
1642 &FileInfo,
1643 sizeof(FILE_BASIC_INFORMATION),
1644 FileBasicInformation);
1645 if (!NT_SUCCESS(Status))
1646 {
1647 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1648 NtClose(FileHandle);
1649 return(Status);
1650 }
1651
1652 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1653
1654 Status = NtSetInformationFile(FileHandle,
1655 &IoStatusBlock,
1656 &FileInfo,
1657 sizeof(FILE_BASIC_INFORMATION),
1658 FileBasicInformation);
1659 if (!NT_SUCCESS(Status))
1660 {
1661 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1662 }
1663
1664 NtClose(FileHandle);
1665 return(Status);
1666 }
1667
1668
1669 NTSTATUS
1670 UpdateBootIni(PWSTR BootIniPath,
1671 PWSTR EntryName,
1672 PWSTR EntryValue)
1673 {
1674 UNICODE_STRING Name;
1675 PINICACHE Cache = NULL;
1676 PINICACHESECTION Section = NULL;
1677 NTSTATUS Status;
1678 ULONG FileAttribute;
1679
1680 RtlInitUnicodeString(&Name,
1681 BootIniPath);
1682
1683 Status = IniCacheLoad(&Cache,
1684 &Name,
1685 FALSE);
1686 if (!NT_SUCCESS(Status))
1687 {
1688 return(Status);
1689 }
1690
1691 Section = IniCacheGetSection(Cache,
1692 L"operating systems");
1693 if (Section == NULL)
1694 {
1695 IniCacheDestroy(Cache);
1696 return(STATUS_UNSUCCESSFUL);
1697 }
1698
1699 IniCacheInsertKey(Section,
1700 NULL,
1701 INSERT_LAST,
1702 EntryName,
1703 EntryValue);
1704
1705 Status = UnprotectBootIni(BootIniPath,
1706 &FileAttribute);
1707 if (!NT_SUCCESS(Status))
1708 {
1709 IniCacheDestroy(Cache);
1710 return(Status);
1711 }
1712
1713 Status = IniCacheSave(Cache,
1714 BootIniPath);
1715 if (!NT_SUCCESS(Status))
1716 {
1717 IniCacheDestroy(Cache);
1718 return(Status);
1719 }
1720
1721 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1722 Status = ProtectBootIni(BootIniPath,
1723 FileAttribute);
1724
1725 IniCacheDestroy(Cache);
1726
1727 return(Status);
1728 }
1729
1730
1731 BOOLEAN
1732 CheckInstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath)
1733 {
1734 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") ||
1735 DoesFileExist(SystemRootPath->Buffer, L"boot.ini"))
1736 {
1737 return TRUE;
1738 }
1739 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") ||
1740 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys"))
1741 {
1742 return TRUE;
1743 }
1744
1745 return FALSE;
1746 }
1747
1748
1749 NTSTATUS
1750 InstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath,
1751 PUNICODE_STRING SourceRootPath,
1752 PUNICODE_STRING DestinationArcPath,
1753 UCHAR PartitionType)
1754 {
1755 WCHAR SrcPath[MAX_PATH];
1756 WCHAR DstPath[MAX_PATH];
1757 NTSTATUS Status;
1758
1759 /* FAT or FAT32 partition */
1760 DPRINT1("System path: '%wZ'\n", SystemRootPath);
1761
1762 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
1763 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
1764 {
1765 /* Search root directory for 'ntldr' and 'boot.ini'. */
1766 DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n");
1767
1768 /* Copy FreeLoader to the boot partition */
1769 wcscpy(SrcPath, SourceRootPath->Buffer);
1770 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1771 wcscpy(DstPath, SystemRootPath->Buffer);
1772 wcscat(DstPath, L"\\freeldr.sys");
1773
1774 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1775 Status = SetupCopyFile(SrcPath, DstPath);
1776 if (!NT_SUCCESS(Status))
1777 {
1778 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1779 return Status;
1780 }
1781
1782 /* Create or update freeldr.ini */
1783 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
1784 {
1785 /* Create new 'freeldr.ini' */
1786 DPRINT1("Create new 'freeldr.ini'\n");
1787 wcscpy(DstPath, SystemRootPath->Buffer);
1788 wcscat(DstPath, L"\\freeldr.ini");
1789
1790 Status = CreateFreeLoaderIniForReactos(DstPath,
1791 DestinationArcPath->Buffer);
1792 if (!NT_SUCCESS(Status))
1793 {
1794 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1795 return Status;
1796 }
1797
1798 /* Install new bootcode */
1799 if (PartitionType == PARTITION_FAT32 ||
1800 PartitionType == PARTITION_FAT32_XINT13)
1801 {
1802 /* Install FAT32 bootcode */
1803 wcscpy(SrcPath, SourceRootPath->Buffer);
1804 wcscat(SrcPath, L"\\loader\\fat32.bin");
1805 wcscpy(DstPath, SystemRootPath->Buffer);
1806 wcscat(DstPath, L"\\bootsect.ros");
1807
1808 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
1809 Status = InstallFat32BootCodeToFile(SrcPath,
1810 DstPath,
1811 SystemRootPath->Buffer);
1812 if (!NT_SUCCESS(Status))
1813 {
1814 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
1815 return Status;
1816 }
1817 }
1818 else
1819 {
1820 /* Install FAT16 bootcode */
1821 wcscpy(SrcPath, SourceRootPath->Buffer);
1822 wcscat(SrcPath, L"\\loader\\fat.bin");
1823 wcscpy(DstPath, SystemRootPath->Buffer);
1824 wcscat(DstPath, L"\\bootsect.ros");
1825
1826 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
1827 Status = InstallFat16BootCodeToFile(SrcPath,
1828 DstPath,
1829 SystemRootPath->Buffer);
1830 if (!NT_SUCCESS(Status))
1831 {
1832 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
1833 return Status;
1834 }
1835 }
1836
1837 /* Update 'boot.ini' */
1838 wcscpy(DstPath, SystemRootPath->Buffer);
1839 wcscat(DstPath, L"\\boot.ini");
1840
1841 DPRINT1("Update 'boot.ini': %S\n", DstPath);
1842 Status = UpdateBootIni(DstPath,
1843 L"C:\\bootsect.ros",
1844 L"\"ReactOS\"");
1845 if (!NT_SUCCESS(Status))
1846 {
1847 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
1848 return Status;
1849 }
1850 }
1851 else
1852 {
1853 /* Update existing 'freeldr.ini' */
1854 DPRINT1("Update existing 'freeldr.ini'\n");
1855 wcscpy(DstPath, SystemRootPath->Buffer);
1856 wcscat(DstPath, L"\\freeldr.ini");
1857
1858 Status = UpdateFreeLoaderIni(DstPath,
1859 DestinationArcPath->Buffer);
1860 if (!NT_SUCCESS(Status))
1861 {
1862 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1863 return Status;
1864 }
1865 }
1866 }
1867 else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
1868 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
1869 {
1870 /* Search for root directory for 'io.sys' and 'msdos.sys'. */
1871 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
1872
1873 /* Copy FreeLoader to the boot partition */
1874 wcscpy(SrcPath, SourceRootPath->Buffer);
1875 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1876 wcscpy(DstPath, SystemRootPath->Buffer);
1877 wcscat(DstPath, L"\\freeldr.sys");
1878
1879 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
1880 Status = SetupCopyFile(SrcPath, DstPath);
1881 if (!NT_SUCCESS(Status))
1882 {
1883 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1884 return Status;
1885 }
1886
1887 /* Create or update 'freeldr.ini' */
1888 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
1889 {
1890 /* Create new 'freeldr.ini' */
1891 DPRINT1("Create new 'freeldr.ini'\n");
1892 wcscpy(DstPath, SystemRootPath->Buffer);
1893 wcscat(DstPath, L"\\freeldr.ini");
1894
1895 Status = CreateFreeLoaderIniForDos(DstPath,
1896 DestinationArcPath->Buffer);
1897 if (!NT_SUCCESS(Status))
1898 {
1899 DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status);
1900 return Status;
1901 }
1902
1903 /* Save current bootsector as 'BOOTSECT.DOS' */
1904 wcscpy(SrcPath, SystemRootPath->Buffer);
1905 wcscpy(DstPath, SystemRootPath->Buffer);
1906 wcscat(DstPath, L"\\bootsect.dos");
1907
1908 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
1909 Status = SaveCurrentBootSector(SrcPath,
1910 DstPath);
1911 if (!NT_SUCCESS(Status))
1912 {
1913 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
1914 return Status;
1915 }
1916
1917 /* Install new bootsector */
1918 if (PartitionType == PARTITION_FAT32 ||
1919 PartitionType == PARTITION_FAT32_XINT13)
1920 {
1921 wcscpy(SrcPath, SourceRootPath->Buffer);
1922 wcscat(SrcPath, L"\\loader\\fat32.bin");
1923
1924 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1925 Status = InstallFat32BootCodeToDisk(SrcPath,
1926 SystemRootPath->Buffer);
1927 if (!NT_SUCCESS(Status))
1928 {
1929 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
1930 return Status;
1931 }
1932 }
1933 else
1934 {
1935 wcscpy(SrcPath, SourceRootPath->Buffer);
1936 wcscat(SrcPath, L"\\loader\\fat.bin");
1937
1938 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
1939 Status = InstallFat16BootCodeToDisk(SrcPath,
1940 SystemRootPath->Buffer);
1941 if (!NT_SUCCESS(Status))
1942 {
1943 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
1944 return Status;
1945 }
1946 }
1947 }
1948 else
1949 {
1950 /* Update existing 'freeldr.ini' */
1951 wcscpy(DstPath, SystemRootPath->Buffer);
1952 wcscat(DstPath, L"\\freeldr.ini");
1953
1954 Status = UpdateFreeLoaderIni(DstPath,
1955 DestinationArcPath->Buffer);
1956 if (!NT_SUCCESS(Status))
1957 {
1958 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
1959 return Status;
1960 }
1961 }
1962 }
1963 else
1964 {
1965 /* No or unknown boot loader */
1966 DPRINT1("No or unknown boot loader found\n");
1967
1968 /* Copy FreeLoader to the boot partition */
1969 wcscpy(SrcPath, SourceRootPath->Buffer);
1970 wcscat(SrcPath, L"\\loader\\freeldr.sys");
1971 wcscpy(DstPath, SystemRootPath->Buffer);
1972 wcscat(DstPath, L"\\freeldr.sys");
1973
1974 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1975 Status = SetupCopyFile(SrcPath, DstPath);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
1979 return Status;
1980 }
1981
1982 /* Create or update 'freeldr.ini' */
1983 if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE)
1984 {
1985 /* Create new freeldr.ini */
1986 wcscpy(DstPath, SystemRootPath->Buffer);
1987 wcscat(DstPath, L"\\freeldr.ini");
1988
1989 DPRINT1("Copy: %S ==> %S\n", SrcPath, DstPath);
1990 Status = CreateFreeLoaderIniForReactos(DstPath,
1991 DestinationArcPath->Buffer);
1992 if (!NT_SUCCESS(Status))
1993 {
1994 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
1995 return Status;
1996 }
1997
1998 /* Save current bootsector as 'BOOTSECT.OLD' */
1999 wcscpy(SrcPath, SystemRootPath->Buffer);
2000 wcscpy(DstPath, SystemRootPath->Buffer);
2001 wcscat(DstPath, L"\\bootsect.old");
2002
2003 DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath);
2004 Status = SaveCurrentBootSector(SrcPath,
2005 DstPath);
2006 if (!NT_SUCCESS(Status))
2007 {
2008 DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status);
2009 return Status;
2010 }
2011
2012 /* Install new bootsector */
2013 if (PartitionType == PARTITION_FAT32 ||
2014 PartitionType == PARTITION_FAT32_XINT13)
2015 {
2016 wcscpy(SrcPath, SourceRootPath->Buffer);
2017 wcscat(SrcPath, L"\\loader\\fat32.bin");
2018
2019 DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2020 Status = InstallFat32BootCodeToDisk(SrcPath,
2021 SystemRootPath->Buffer);
2022 if (!NT_SUCCESS(Status))
2023 {
2024 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2025 return Status;
2026 }
2027 }
2028 else
2029 {
2030 wcscpy(SrcPath, SourceRootPath->Buffer);
2031 wcscat(SrcPath, L"\\loader\\fat.bin");
2032
2033 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2034 Status = InstallFat16BootCodeToDisk(SrcPath,
2035 SystemRootPath->Buffer);
2036 if (!NT_SUCCESS(Status))
2037 {
2038 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2039 return Status;
2040 }
2041 }
2042 }
2043 else
2044 {
2045 /* Update existing 'freeldr.ini' */
2046 wcscpy(DstPath, SystemRootPath->Buffer);
2047 wcscat(DstPath, L"\\freeldr.ini");
2048
2049 Status = UpdateFreeLoaderIni(DstPath,
2050 DestinationArcPath->Buffer);
2051 if (!NT_SUCCESS(Status))
2052 {
2053 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2054 return Status;
2055 }
2056 }
2057 }
2058
2059 return STATUS_SUCCESS;
2060 }
2061
2062
2063 NTSTATUS
2064 InstallFatBootcodeToFloppy(PUNICODE_STRING SourceRootPath,
2065 PUNICODE_STRING DestinationArcPath)
2066 {
2067 WCHAR SrcPath[MAX_PATH];
2068 WCHAR DstPath[MAX_PATH];
2069 NTSTATUS Status;
2070
2071 /* Copy FreeLoader to the boot partition */
2072 wcscpy(SrcPath, SourceRootPath->Buffer);
2073 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2074
2075 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2076
2077 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2078 Status = SetupCopyFile(SrcPath, DstPath);
2079 if (!NT_SUCCESS(Status))
2080 {
2081 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2082 return Status;
2083 }
2084
2085 /* Create new 'freeldr.ini' */
2086 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2087
2088 DPRINT("Create new 'freeldr.ini'\n");
2089 Status = CreateFreeLoaderIniForReactos(DstPath,
2090 DestinationArcPath->Buffer);
2091 if (!NT_SUCCESS(Status))
2092 {
2093 DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status);
2094 return Status;
2095 }
2096
2097 /* Install FAT12/16 boosector */
2098 wcscpy(SrcPath, SourceRootPath->Buffer);
2099 wcscat(SrcPath, L"\\loader\\fat.bin");
2100
2101 wcscpy(DstPath, L"\\Device\\Floppy0");
2102
2103 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2104 Status = InstallFat16BootCodeToDisk(SrcPath,
2105 DstPath);
2106 if (!NT_SUCCESS(Status))
2107 {
2108 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2109 return Status;
2110 }
2111
2112 return STATUS_SUCCESS;
2113 }
2114
2115 /* EOF */