- Added error messages
[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 <ddk/ntddk.h>
28 #include <ntdll/rtl.h>
29
30 #include "usetup.h"
31 #include "inicache.h"
32 #include "bootsup.h"
33
34
35 #define SECTORSIZE 512
36
37 /* FUNCTIONS ****************************************************************/
38
39
40 static VOID
41 CreateCommonFreeLoaderSections(PINICACHE IniCache)
42 {
43 PINICACHESECTION IniSection;
44
45 /* Create "FREELOADER" section */
46 IniSection = IniCacheAppendSection(IniCache,
47 L"FREELOADER");
48
49 /* DefaultOS=ReactOS */
50 IniCacheInsertKey(IniSection,
51 NULL,
52 INSERT_LAST,
53 L"DefaultOS",
54 L"ReactOS");
55
56 #if 0
57 /* Timeout=10 */
58 IniCacheInsertKey(IniSection,
59 NULL,
60 INSERT_LAST,
61 L"TimeOut",
62 L"10");
63 #endif
64
65 /* Create "Display" section */
66 IniSection = IniCacheAppendSection(IniCache,
67 L"Display");
68
69 /* TitleText=ReactOS Boot Manager */
70 IniCacheInsertKey(IniSection,
71 NULL,
72 INSERT_LAST,
73 L"TitleText",
74 L"ReactOS Boot Manager");
75
76 /* StatusBarColor=Cyan */
77 IniCacheInsertKey(IniSection,
78 NULL,
79 INSERT_LAST,
80 L"StatusBarColor",
81 L"Cyan");
82
83 /* StatusBarTextColor=Black */
84 IniCacheInsertKey(IniSection,
85 NULL,
86 INSERT_LAST,
87 L"StatusBarTextColor",
88 L"Black");
89
90 /* BackdropTextColor=White */
91 IniCacheInsertKey(IniSection,
92 NULL,
93 INSERT_LAST,
94 L"BackdropTextColor",
95 L"White");
96
97 /* BackdropColor=Blue */
98 IniCacheInsertKey(IniSection,
99 NULL,
100 INSERT_LAST,
101 L"BackdropColor",
102 L"Blue");
103
104 /* BackdropFillStyle=Medium */
105 IniCacheInsertKey(IniSection,
106 NULL,
107 INSERT_LAST,
108 L"BackdropFillStyle",
109 L"Medium");
110
111 /* TitleBoxTextColor=White */
112 IniCacheInsertKey(IniSection,
113 NULL,
114 INSERT_LAST,
115 L"TitleBoxTextColor",
116 L"White");
117
118 /* TitleBoxColor=Red */
119 IniCacheInsertKey(IniSection,
120 NULL,
121 INSERT_LAST,
122 L"TitleBoxColor",
123 L"Red");
124
125 /* MessageBoxTextColor=White */
126 IniCacheInsertKey(IniSection,
127 NULL,
128 INSERT_LAST,
129 L"MessageBoxTextColor",
130 L"White");
131
132 /* MessageBoxColor=Blue */
133 IniCacheInsertKey(IniSection,
134 NULL,
135 INSERT_LAST,
136 L"MessageBoxColor",
137 L"Blue");
138
139 /* MenuTextColor=White */
140 IniCacheInsertKey(IniSection,
141 NULL,
142 INSERT_LAST,
143 L"MenuTextColor",
144 L"White");
145
146 /* MenuColor=Blue */
147 IniCacheInsertKey(IniSection,
148 NULL,
149 INSERT_LAST,
150 L"MenuColor",
151 L"Blue");
152
153 /* TextColor=Yellow */
154 IniCacheInsertKey(IniSection,
155 NULL,
156 INSERT_LAST,
157 L"TextColor",
158 L"Yellow");
159
160 /* SelectedTextColor=Black */
161 IniCacheInsertKey(IniSection,
162 NULL,
163 INSERT_LAST,
164 L"SelectedTextColor",
165 L"Black");
166
167 /* SelectedColor=Gray */
168 IniCacheInsertKey(IniSection,
169 NULL,
170 INSERT_LAST,
171 L"SelectedColor",
172 L"Gray");
173 }
174
175
176 NTSTATUS
177 CreateFreeLoaderIniForDos(PWCHAR IniPath,
178 PWCHAR ArcPath)
179 {
180 PINICACHE IniCache;
181 PINICACHESECTION IniSection;
182
183 IniCache = IniCacheCreate();
184
185 CreateCommonFreeLoaderSections(IniCache);
186
187 /* Create "Operating Systems" section */
188 IniSection = IniCacheAppendSection(IniCache,
189 L"Operating Systems");
190
191 /* REACTOS=ReactOS */
192 IniCacheInsertKey(IniSection,
193 NULL,
194 INSERT_LAST,
195 L"ReactOS",
196 L"\"ReactOS\"");
197
198 /* ReactOS_Debug="ReactOS (Debug)" */
199 IniCacheInsertKey(IniSection,
200 NULL,
201 INSERT_LAST,
202 L"ReactOS_Debug",
203 L"\"ReactOS (Debug)\"");
204
205 /* DOS=Dos/Windows */
206 IniCacheInsertKey(IniSection,
207 NULL,
208 INSERT_LAST,
209 L"DOS",
210 L"\"DOS/Windows\"");
211
212 /* Create "ReactOS" section */
213 IniSection = IniCacheAppendSection(IniCache,
214 L"ReactOS");
215
216 /* BootType=ReactOS */
217 IniCacheInsertKey(IniSection,
218 NULL,
219 INSERT_LAST,
220 L"BootType",
221 L"ReactOS");
222
223 /* SystemPath=<ArcPath> */
224 IniCacheInsertKey(IniSection,
225 NULL,
226 INSERT_LAST,
227 L"SystemPath",
228 ArcPath);
229
230 /* Create "ReactOS_Debug" section */
231 IniSection = IniCacheAppendSection(IniCache,
232 L"ReactOS_Debug");
233
234 /* BootType=ReactOS */
235 IniCacheInsertKey(IniSection,
236 NULL,
237 INSERT_LAST,
238 L"BootType",
239 L"ReactOS");
240
241 /* SystemPath=<ArcPath> */
242 IniCacheInsertKey(IniSection,
243 NULL,
244 INSERT_LAST,
245 L"SystemPath",
246 ArcPath);
247
248 /* Options=/DEBUGPORT=SCREEN */
249 IniCacheInsertKey(IniSection,
250 NULL,
251 INSERT_LAST,
252 L"Options",
253 L"/DEBUGPORT=SCREEN");
254
255 /* Create "DOS" section */
256 IniSection = IniCacheAppendSection(IniCache,
257 L"DOS");
258
259 /* BootType=BootSector */
260 IniCacheInsertKey(IniSection,
261 NULL,
262 INSERT_LAST,
263 L"BootType",
264 L"BootSector");
265
266 /* BootDrive=hd0 */
267 IniCacheInsertKey(IniSection,
268 NULL,
269 INSERT_LAST,
270 L"BootDrive",
271 L"hd0");
272
273 /* BootPartition=1 */
274 IniCacheInsertKey(IniSection,
275 NULL,
276 INSERT_LAST,
277 L"BootPartition",
278 L"1");
279
280 /* BootSector=BOOTSECT.DOS */
281 IniCacheInsertKey(IniSection,
282 NULL,
283 INSERT_LAST,
284 L"BootSectorFile",
285 L"BOOTSECT.DOS");
286
287 IniCacheSave(IniCache, IniPath);
288 IniCacheDestroy(IniCache);
289
290 return(STATUS_SUCCESS);
291 }
292
293
294 NTSTATUS
295 CreateFreeLoaderIniForReactos(PWCHAR IniPath,
296 PWCHAR ArcPath)
297 {
298 PINICACHE IniCache;
299 PINICACHESECTION IniSection;
300
301 IniCache = IniCacheCreate();
302
303 CreateCommonFreeLoaderSections(IniCache);
304
305 /* Create "Operating Systems" section */
306 IniSection = IniCacheAppendSection(IniCache,
307 L"Operating Systems");
308
309 /* ReactOS="ReactOS" */
310 IniCacheInsertKey(IniSection,
311 NULL,
312 INSERT_LAST,
313 L"ReactOS",
314 L"\"ReactOS\"");
315
316 /* ReactOS_Debug="ReactOS (Debug)" */
317 IniCacheInsertKey(IniSection,
318 NULL,
319 INSERT_LAST,
320 L"ReactOS_Debug",
321 L"\"ReactOS (Debug)\"");
322
323 /* Create "ReactOS" section */
324 IniSection = IniCacheAppendSection(IniCache,
325 L"ReactOS");
326
327 /* BootType=ReactOS */
328 IniCacheInsertKey(IniSection,
329 NULL,
330 INSERT_LAST,
331 L"BootType",
332 L"ReactOS");
333
334 /* SystemPath=<ArcPath> */
335 IniCacheInsertKey(IniSection,
336 NULL,
337 INSERT_LAST,
338 L"SystemPath",
339 ArcPath);
340
341 /* Create "ReactOS_Debug" section */
342 IniSection = IniCacheAppendSection(IniCache,
343 L"ReactOS_Debug");
344
345 /* BootType=ReactOS */
346 IniCacheInsertKey(IniSection,
347 NULL,
348 INSERT_LAST,
349 L"BootType",
350 L"ReactOS");
351
352 /* SystemPath=<ArcPath> */
353 IniCacheInsertKey(IniSection,
354 NULL,
355 INSERT_LAST,
356 L"SystemPath",
357 ArcPath);
358
359 /* Options=/DEBUGPORT=SCREEN */
360 IniCacheInsertKey(IniSection,
361 NULL,
362 INSERT_LAST,
363 L"Options",
364 L"/DEBUGPORT=SCREEN");
365
366 /* Save the ini file */
367 IniCacheSave(IniCache, IniPath);
368 IniCacheDestroy(IniCache);
369
370 return(STATUS_SUCCESS);
371 }
372
373
374 NTSTATUS
375 UpdateFreeLoaderIni(PWCHAR IniPath,
376 PWCHAR ArcPath)
377 {
378 UNICODE_STRING Name;
379 PINICACHE IniCache;
380 PINICACHESECTION IniSection;
381 WCHAR SectionName[80];
382 WCHAR OsName[80];
383 PWCHAR KeyData;
384 ULONG i;
385 NTSTATUS Status;
386
387 RtlInitUnicodeString(&Name,
388 IniPath);
389
390 Status = IniCacheLoad(&IniCache,
391 &Name);
392 if (!NT_SUCCESS(Status))
393 return(Status);
394
395 /* Get "Operating Systems" section */
396 IniSection = IniCacheGetSection(IniCache,
397 L"Operating Systems");
398 if (IniSection == NULL)
399 return(STATUS_UNSUCCESSFUL);
400
401 /* Find an unused section name */
402 i = 1;
403 wcscpy(SectionName, L"ReactOS");
404 wcscpy(OsName, L"\"ReactOS\"");
405 while(TRUE)
406 {
407 Status = IniCacheGetKey(IniSection,
408 SectionName,
409 &KeyData);
410 if (!NT_SUCCESS(Status))
411 break;
412
413 swprintf(SectionName, L"ReactOS_%lu", i);
414 swprintf(OsName, L"\"ReactOS %lu\"", i);
415 i++;
416 }
417
418 /* <SectionName>=<OsName> */
419 IniCacheInsertKey(IniSection,
420 NULL,
421 INSERT_LAST,
422 SectionName,
423 OsName);
424
425 /* Create <SectionName> section */
426 IniSection = IniCacheAppendSection(IniCache,
427 SectionName);
428
429 /* BootType=ReactOS */
430 IniCacheInsertKey(IniSection,
431 NULL,
432 INSERT_LAST,
433 L"BootType",
434 L"ReactOS");
435
436 /* SystemPath=<ArcPath> */
437 IniCacheInsertKey(IniSection,
438 NULL,
439 INSERT_LAST,
440 L"SystemPath",
441 ArcPath);
442
443 IniCacheSave(IniCache, IniPath);
444 IniCacheDestroy(IniCache);
445
446 return(STATUS_SUCCESS);
447 }
448
449
450 NTSTATUS
451 SaveCurrentBootSector(PWSTR RootPath,
452 PWSTR DstPath)
453 {
454 OBJECT_ATTRIBUTES ObjectAttributes;
455 IO_STATUS_BLOCK IoStatusBlock;
456 UNICODE_STRING Name;
457 HANDLE FileHandle;
458 NTSTATUS Status;
459 PUCHAR BootSector;
460
461 /* Allocate buffer for bootsector */
462 BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
463 0,
464 SECTORSIZE);
465 if (BootSector == NULL)
466 return(STATUS_INSUFFICIENT_RESOURCES);
467
468 /* Read current boot sector into buffer */
469 RtlInitUnicodeString(&Name,
470 RootPath);
471
472 InitializeObjectAttributes(&ObjectAttributes,
473 &Name,
474 OBJ_CASE_INSENSITIVE,
475 NULL,
476 NULL);
477
478 Status = NtOpenFile(&FileHandle,
479 FILE_READ_ACCESS,
480 &ObjectAttributes,
481 &IoStatusBlock,
482 0,
483 FILE_SYNCHRONOUS_IO_ALERT);
484 if (!NT_SUCCESS(Status))
485 {
486 RtlFreeHeap(ProcessHeap, 0, BootSector);
487 return(Status);
488 }
489
490 Status = NtReadFile(FileHandle,
491 NULL,
492 NULL,
493 NULL,
494 &IoStatusBlock,
495 BootSector,
496 SECTORSIZE,
497 NULL,
498 NULL);
499 NtClose(FileHandle);
500 if (!NT_SUCCESS(Status))
501 {
502 RtlFreeHeap(ProcessHeap, 0, BootSector);
503 return(Status);
504 }
505
506 /* Write bootsector to DstPath */
507 RtlInitUnicodeString(&Name,
508 DstPath);
509
510 InitializeObjectAttributes(&ObjectAttributes,
511 &Name,
512 0,
513 NULL,
514 NULL);
515
516 Status = NtCreateFile(&FileHandle,
517 FILE_WRITE_ACCESS,
518 &ObjectAttributes,
519 &IoStatusBlock,
520 NULL,
521 FILE_ATTRIBUTE_NORMAL,
522 0,
523 FILE_SUPERSEDE,
524 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
525 NULL,
526 0);
527 if (!NT_SUCCESS(Status))
528 {
529 RtlFreeHeap(ProcessHeap, 0, BootSector);
530 return(Status);
531 }
532
533 Status = NtWriteFile(FileHandle,
534 NULL,
535 NULL,
536 NULL,
537 &IoStatusBlock,
538 BootSector,
539 SECTORSIZE,
540 NULL,
541 NULL);
542 NtClose(FileHandle);
543
544 /* Free the new boot sector */
545 RtlFreeHeap(ProcessHeap, 0, BootSector);
546
547 return(Status);
548 }
549
550
551 NTSTATUS
552 InstallFat16BootCodeToFile(PWSTR SrcPath,
553 PWSTR DstPath,
554 PWSTR RootPath)
555 {
556 OBJECT_ATTRIBUTES ObjectAttributes;
557 IO_STATUS_BLOCK IoStatusBlock;
558 UNICODE_STRING Name;
559 HANDLE FileHandle;
560 NTSTATUS Status;
561 PUCHAR OrigBootSector;
562 PUCHAR NewBootSector;
563
564 /* Allocate buffer for original bootsector */
565 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
566 0,
567 SECTORSIZE);
568 if (OrigBootSector == NULL)
569 return(STATUS_INSUFFICIENT_RESOURCES);
570
571 /* Read current boot sector into buffer */
572 RtlInitUnicodeString(&Name,
573 RootPath);
574
575 InitializeObjectAttributes(&ObjectAttributes,
576 &Name,
577 OBJ_CASE_INSENSITIVE,
578 NULL,
579 NULL);
580
581 Status = NtOpenFile(&FileHandle,
582 FILE_READ_ACCESS,
583 &ObjectAttributes,
584 &IoStatusBlock,
585 0,
586 FILE_SYNCHRONOUS_IO_ALERT);
587 if (!NT_SUCCESS(Status))
588 {
589 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
590 return(Status);
591 }
592
593 Status = NtReadFile(FileHandle,
594 NULL,
595 NULL,
596 NULL,
597 &IoStatusBlock,
598 OrigBootSector,
599 SECTORSIZE,
600 NULL,
601 NULL);
602 NtClose(FileHandle);
603 if (!NT_SUCCESS(Status))
604 {
605 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
606 return(Status);
607 }
608
609
610 /* Allocate buffer for new bootsector */
611 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
612 0,
613 SECTORSIZE);
614 if (NewBootSector == NULL)
615 {
616 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
617 return(STATUS_INSUFFICIENT_RESOURCES);
618 }
619
620 /* Read new bootsector from SrcPath */
621 RtlInitUnicodeString(&Name,
622 SrcPath);
623
624 InitializeObjectAttributes(&ObjectAttributes,
625 &Name,
626 OBJ_CASE_INSENSITIVE,
627 NULL,
628 NULL);
629
630 Status = NtOpenFile(&FileHandle,
631 FILE_READ_ACCESS,
632 &ObjectAttributes,
633 &IoStatusBlock,
634 0,
635 FILE_SYNCHRONOUS_IO_ALERT);
636 if (!NT_SUCCESS(Status))
637 {
638 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
639 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
640 return(Status);
641 }
642
643 Status = NtReadFile(FileHandle,
644 NULL,
645 NULL,
646 NULL,
647 &IoStatusBlock,
648 NewBootSector,
649 SECTORSIZE,
650 NULL,
651 NULL);
652 NtClose(FileHandle);
653 if (!NT_SUCCESS(Status))
654 {
655 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
656 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
657 return(Status);
658 }
659
660 /* Adjust bootsector (copy a part of the FAT BPB) */
661 memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
662
663 /* Free the original boot sector */
664 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
665
666 /* Write new bootsector to DstPath */
667 RtlInitUnicodeString(&Name,
668 DstPath);
669
670 InitializeObjectAttributes(&ObjectAttributes,
671 &Name,
672 0,
673 NULL,
674 NULL);
675
676 Status = NtCreateFile(&FileHandle,
677 FILE_WRITE_ACCESS,
678 &ObjectAttributes,
679 &IoStatusBlock,
680 NULL,
681 FILE_ATTRIBUTE_NORMAL,
682 0,
683 FILE_OVERWRITE_IF,
684 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
685 NULL,
686 0);
687 if (!NT_SUCCESS(Status))
688 {
689 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
690 return(Status);
691 }
692
693 #if 0
694 FilePosition.QuadPart = 0;
695 #endif
696 Status = NtWriteFile(FileHandle,
697 NULL,
698 NULL,
699 NULL,
700 &IoStatusBlock,
701 NewBootSector,
702 SECTORSIZE,
703 NULL,
704 NULL);
705 NtClose(FileHandle);
706
707 /* Free the new boot sector */
708 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
709
710 return(Status);
711 }
712
713
714 NTSTATUS
715 InstallFat32BootCodeToFile(PWSTR SrcPath,
716 PWSTR DstPath,
717 PWSTR RootPath)
718 {
719 OBJECT_ATTRIBUTES ObjectAttributes;
720 IO_STATUS_BLOCK IoStatusBlock;
721 UNICODE_STRING Name;
722 HANDLE FileHandle;
723 NTSTATUS Status;
724 PUCHAR OrigBootSector;
725 PUCHAR NewBootSector;
726 LARGE_INTEGER FileOffset;
727
728 /* Allocate buffer for original bootsector */
729 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
730 0,
731 SECTORSIZE);
732 if (OrigBootSector == NULL)
733 return(STATUS_INSUFFICIENT_RESOURCES);
734
735 /* Read current boot sector into buffer */
736 RtlInitUnicodeString(&Name,
737 RootPath);
738
739 InitializeObjectAttributes(&ObjectAttributes,
740 &Name,
741 OBJ_CASE_INSENSITIVE,
742 NULL,
743 NULL);
744
745 Status = NtOpenFile(&FileHandle,
746 FILE_READ_ACCESS,
747 &ObjectAttributes,
748 &IoStatusBlock,
749 0,
750 FILE_SYNCHRONOUS_IO_ALERT);
751 if (!NT_SUCCESS(Status))
752 {
753 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
754 return(Status);
755 }
756
757 Status = NtReadFile(FileHandle,
758 NULL,
759 NULL,
760 NULL,
761 &IoStatusBlock,
762 OrigBootSector,
763 SECTORSIZE,
764 NULL,
765 NULL);
766 NtClose(FileHandle);
767 if (!NT_SUCCESS(Status))
768 {
769 CHECKPOINT1;
770 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
771 return(Status);
772 }
773
774 /* Allocate buffer for new bootsector (2 sectors) */
775 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
776 0,
777 2 * SECTORSIZE);
778 if (NewBootSector == NULL)
779 {
780 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
781 return(STATUS_INSUFFICIENT_RESOURCES);
782 }
783
784 /* Read new bootsector from SrcPath */
785 RtlInitUnicodeString(&Name,
786 SrcPath);
787
788 InitializeObjectAttributes(&ObjectAttributes,
789 &Name,
790 OBJ_CASE_INSENSITIVE,
791 NULL,
792 NULL);
793
794 Status = NtOpenFile(&FileHandle,
795 FILE_READ_ACCESS,
796 &ObjectAttributes,
797 &IoStatusBlock,
798 0,
799 FILE_SYNCHRONOUS_IO_ALERT);
800 if (!NT_SUCCESS(Status))
801 {
802 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
803 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
804 return(Status);
805 }
806
807 Status = NtReadFile(FileHandle,
808 NULL,
809 NULL,
810 NULL,
811 &IoStatusBlock,
812 NewBootSector,
813 2 * SECTORSIZE,
814 NULL,
815 NULL);
816 NtClose(FileHandle);
817 if (!NT_SUCCESS(Status))
818 {
819 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
820 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
821 return(Status);
822 }
823
824 /* Adjust bootsector (copy a part of the FAT32 BPB) */
825 memcpy((NewBootSector + 3),
826 (OrigBootSector + 3),
827 87); /* FAT32 BPB length */
828
829 /* Disable the backup boot sector */
830 NewBootSector[0x32] = 0xFF;
831 NewBootSector[0x33] = 0xFF;
832
833 /* Free the original boot sector */
834 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
835
836 /* Write the first sector of the new bootcode to DstPath */
837 RtlInitUnicodeString(&Name,
838 DstPath);
839
840 InitializeObjectAttributes(&ObjectAttributes,
841 &Name,
842 0,
843 NULL,
844 NULL);
845
846 Status = NtCreateFile(&FileHandle,
847 FILE_WRITE_ACCESS,
848 &ObjectAttributes,
849 &IoStatusBlock,
850 NULL,
851 FILE_ATTRIBUTE_NORMAL,
852 0,
853 FILE_SUPERSEDE,
854 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
855 NULL,
856 0);
857 if (!NT_SUCCESS(Status))
858 {
859 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
860 return(Status);
861 }
862
863 Status = NtWriteFile(FileHandle,
864 NULL,
865 NULL,
866 NULL,
867 &IoStatusBlock,
868 NewBootSector,
869 SECTORSIZE,
870 NULL,
871 NULL);
872 NtClose(FileHandle);
873 if (!NT_SUCCESS(Status))
874 {
875 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
876 return(Status);
877 }
878
879 /* Write the second sector of the new bootcode to boot disk sector 14 */
880 RtlInitUnicodeString(&Name,
881 RootPath);
882
883 InitializeObjectAttributes(&ObjectAttributes,
884 &Name,
885 0,
886 NULL,
887 NULL);
888
889 Status = NtOpenFile(&FileHandle,
890 FILE_WRITE_ACCESS,
891 &ObjectAttributes,
892 &IoStatusBlock,
893 0,
894 FILE_SYNCHRONOUS_IO_ALERT);
895 if (!NT_SUCCESS(Status))
896 {
897 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
898 return(Status);
899 }
900
901 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
902 Status = NtWriteFile(FileHandle,
903 NULL,
904 NULL,
905 NULL,
906 &IoStatusBlock,
907 (NewBootSector + SECTORSIZE),
908 SECTORSIZE,
909 &FileOffset,
910 NULL);
911 if (!NT_SUCCESS(Status))
912 {
913 }
914 NtClose(FileHandle);
915
916 /* Free the new boot sector */
917 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
918
919 return(Status);
920 }
921
922
923 NTSTATUS
924 InstallFat16BootCodeToDisk(PWSTR SrcPath,
925 PWSTR RootPath)
926 {
927 OBJECT_ATTRIBUTES ObjectAttributes;
928 IO_STATUS_BLOCK IoStatusBlock;
929 UNICODE_STRING Name;
930 HANDLE FileHandle;
931 NTSTATUS Status;
932 PUCHAR OrigBootSector;
933 PUCHAR NewBootSector;
934
935 /* Allocate buffer for original bootsector */
936 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
937 0,
938 SECTORSIZE);
939 if (OrigBootSector == NULL)
940 return(STATUS_INSUFFICIENT_RESOURCES);
941
942 /* Read current boot sector into buffer */
943 RtlInitUnicodeString(&Name,
944 RootPath);
945
946 InitializeObjectAttributes(&ObjectAttributes,
947 &Name,
948 OBJ_CASE_INSENSITIVE,
949 NULL,
950 NULL);
951
952 Status = NtOpenFile(&FileHandle,
953 FILE_READ_ACCESS,
954 &ObjectAttributes,
955 &IoStatusBlock,
956 0,
957 FILE_SYNCHRONOUS_IO_ALERT);
958 if (!NT_SUCCESS(Status))
959 {
960 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
961 return(Status);
962 }
963
964 Status = NtReadFile(FileHandle,
965 NULL,
966 NULL,
967 NULL,
968 &IoStatusBlock,
969 OrigBootSector,
970 SECTORSIZE,
971 NULL,
972 NULL);
973 NtClose(FileHandle);
974 if (!NT_SUCCESS(Status))
975 {
976 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
977 return(Status);
978 }
979
980
981 /* Allocate buffer for new bootsector */
982 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
983 0,
984 SECTORSIZE);
985 if (NewBootSector == NULL)
986 {
987 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
988 return(STATUS_INSUFFICIENT_RESOURCES);
989 }
990
991 /* Read new bootsector from SrcPath */
992 RtlInitUnicodeString(&Name,
993 SrcPath);
994
995 InitializeObjectAttributes(&ObjectAttributes,
996 &Name,
997 OBJ_CASE_INSENSITIVE,
998 NULL,
999 NULL);
1000
1001 Status = NtOpenFile(&FileHandle,
1002 FILE_READ_ACCESS,
1003 &ObjectAttributes,
1004 &IoStatusBlock,
1005 0,
1006 FILE_SYNCHRONOUS_IO_ALERT);
1007 if (!NT_SUCCESS(Status))
1008 {
1009 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1010 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1011 return(Status);
1012 }
1013
1014 Status = NtReadFile(FileHandle,
1015 NULL,
1016 NULL,
1017 NULL,
1018 &IoStatusBlock,
1019 NewBootSector,
1020 SECTORSIZE,
1021 NULL,
1022 NULL);
1023 NtClose(FileHandle);
1024 if (!NT_SUCCESS(Status))
1025 {
1026 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1027 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1028 return(Status);
1029 }
1030
1031 /* Adjust bootsector (copy a part of the FAT BPB) */
1032 memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
1033
1034 /* Free the original boot sector */
1035 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1036
1037 /* Write new bootsector to RootPath */
1038 RtlInitUnicodeString(&Name,
1039 RootPath);
1040
1041 InitializeObjectAttributes(&ObjectAttributes,
1042 &Name,
1043 0,
1044 NULL,
1045 NULL);
1046
1047 Status = NtCreateFile(&FileHandle,
1048 FILE_WRITE_ACCESS,
1049 &ObjectAttributes,
1050 &IoStatusBlock,
1051 NULL,
1052 FILE_ATTRIBUTE_NORMAL,
1053 0,
1054 FILE_OVERWRITE_IF,
1055 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
1056 NULL,
1057 0);
1058 if (!NT_SUCCESS(Status))
1059 {
1060 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1061 return(Status);
1062 }
1063
1064 #if 0
1065 FilePosition.QuadPart = 0;
1066 #endif
1067 Status = NtWriteFile(FileHandle,
1068 NULL,
1069 NULL,
1070 NULL,
1071 &IoStatusBlock,
1072 NewBootSector,
1073 SECTORSIZE,
1074 NULL,
1075 NULL);
1076 NtClose(FileHandle);
1077
1078 /* Free the new boot sector */
1079 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1080
1081 return(Status);
1082 }
1083
1084
1085 NTSTATUS
1086 InstallFat32BootCodeToDisk(PWSTR SrcPath,
1087 PWSTR RootPath)
1088 {
1089 OBJECT_ATTRIBUTES ObjectAttributes;
1090 IO_STATUS_BLOCK IoStatusBlock;
1091 UNICODE_STRING Name;
1092 HANDLE FileHandle;
1093 NTSTATUS Status;
1094 PUCHAR OrigBootSector;
1095 PUCHAR NewBootSector;
1096 LARGE_INTEGER FileOffset;
1097 USHORT BackupBootSector;
1098
1099 /* Allocate buffer for original bootsector */
1100 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1101 0,
1102 SECTORSIZE);
1103 if (OrigBootSector == NULL)
1104 return(STATUS_INSUFFICIENT_RESOURCES);
1105
1106 /* Read current boot sector into buffer */
1107 RtlInitUnicodeString(&Name,
1108 RootPath);
1109
1110 InitializeObjectAttributes(&ObjectAttributes,
1111 &Name,
1112 OBJ_CASE_INSENSITIVE,
1113 NULL,
1114 NULL);
1115
1116 Status = NtOpenFile(&FileHandle,
1117 FILE_READ_ACCESS,
1118 &ObjectAttributes,
1119 &IoStatusBlock,
1120 0,
1121 FILE_SYNCHRONOUS_IO_ALERT);
1122 if (!NT_SUCCESS(Status))
1123 {
1124 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1125 return(Status);
1126 }
1127
1128 Status = NtReadFile(FileHandle,
1129 NULL,
1130 NULL,
1131 NULL,
1132 &IoStatusBlock,
1133 OrigBootSector,
1134 SECTORSIZE,
1135 NULL,
1136 NULL);
1137 NtClose(FileHandle);
1138 if (!NT_SUCCESS(Status))
1139 {
1140 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1141 return(Status);
1142 }
1143
1144
1145 /* Allocate buffer for new bootsector (2 sectors) */
1146 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1147 0,
1148 2 * SECTORSIZE);
1149 if (NewBootSector == NULL)
1150 {
1151 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1152 return(STATUS_INSUFFICIENT_RESOURCES);
1153 }
1154
1155 /* Read new bootsector from SrcPath */
1156 RtlInitUnicodeString(&Name,
1157 SrcPath);
1158
1159 InitializeObjectAttributes(&ObjectAttributes,
1160 &Name,
1161 OBJ_CASE_INSENSITIVE,
1162 NULL,
1163 NULL);
1164
1165 Status = NtOpenFile(&FileHandle,
1166 FILE_READ_ACCESS,
1167 &ObjectAttributes,
1168 &IoStatusBlock,
1169 0,
1170 FILE_SYNCHRONOUS_IO_ALERT);
1171 if (!NT_SUCCESS(Status))
1172 {
1173 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1174 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1175 return(Status);
1176 }
1177
1178 Status = NtReadFile(FileHandle,
1179 NULL,
1180 NULL,
1181 NULL,
1182 &IoStatusBlock,
1183 NewBootSector,
1184 2 * SECTORSIZE,
1185 NULL,
1186 NULL);
1187 NtClose(FileHandle);
1188 if (!NT_SUCCESS(Status))
1189 {
1190 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1191 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1192 return(Status);
1193 }
1194
1195 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1196 memcpy((NewBootSector + 3),
1197 (OrigBootSector + 3),
1198 87); /* FAT32 BPB length */
1199
1200 /* Get the location of the backup boot sector */
1201 BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x33];
1202
1203 /* Free the original boot sector */
1204 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1205
1206 /* Write the first sector of the new bootcode to DstPath */
1207 RtlInitUnicodeString(&Name,
1208 RootPath);
1209
1210 InitializeObjectAttributes(&ObjectAttributes,
1211 &Name,
1212 0,
1213 NULL,
1214 NULL);
1215
1216 Status = NtOpenFile(&FileHandle,
1217 FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
1218 &ObjectAttributes,
1219 &IoStatusBlock,
1220 0,
1221 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1225 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1226 return(Status);
1227 }
1228
1229 /* Write sector 0 */
1230 FileOffset.QuadPart = 0ULL;
1231 Status = NtWriteFile(FileHandle,
1232 NULL,
1233 NULL,
1234 NULL,
1235 &IoStatusBlock,
1236 NewBootSector,
1237 SECTORSIZE,
1238 &FileOffset,
1239 NULL);
1240 if (!NT_SUCCESS(Status))
1241 {
1242 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1243 NtClose(FileHandle);
1244 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1245 return(Status);
1246 }
1247
1248 /* Write backup boot sector */
1249 if (BackupBootSector != 0xFFFF)
1250 {
1251 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1252 Status = NtWriteFile(FileHandle,
1253 NULL,
1254 NULL,
1255 NULL,
1256 &IoStatusBlock,
1257 NewBootSector,
1258 SECTORSIZE,
1259 &FileOffset,
1260 NULL);
1261 if (!NT_SUCCESS(Status))
1262 {
1263 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1264 NtClose(FileHandle);
1265 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1266 return(Status);
1267 }
1268 }
1269
1270 /* Write sector 14 */
1271 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1272 Status = NtWriteFile(FileHandle,
1273 NULL,
1274 NULL,
1275 NULL,
1276 &IoStatusBlock,
1277 (NewBootSector + SECTORSIZE),
1278 SECTORSIZE,
1279 &FileOffset,
1280 NULL);
1281 if (!NT_SUCCESS(Status))
1282 {
1283 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1284 }
1285 NtClose(FileHandle);
1286
1287 /* Free the new boot sector */
1288 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1289
1290 return(Status);
1291 }
1292
1293
1294 static NTSTATUS
1295 UnprotectBootIni(PWSTR FileName,
1296 PULONG Attributes)
1297 {
1298 UNICODE_STRING Name;
1299 OBJECT_ATTRIBUTES ObjectAttributes;
1300 IO_STATUS_BLOCK IoStatusBlock;
1301 FILE_BASIC_INFORMATION FileInfo;
1302 HANDLE FileHandle;
1303 NTSTATUS Status;
1304
1305 RtlInitUnicodeString(&Name,
1306 FileName);
1307
1308 InitializeObjectAttributes(&ObjectAttributes,
1309 &Name,
1310 OBJ_CASE_INSENSITIVE,
1311 NULL,
1312 NULL);
1313
1314 Status = NtOpenFile(&FileHandle,
1315 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1316 &ObjectAttributes,
1317 &IoStatusBlock,
1318 0,
1319 FILE_SYNCHRONOUS_IO_ALERT);
1320 if (Status == STATUS_NO_SUCH_FILE)
1321 {
1322 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1323 *Attributes = 0;
1324 return(STATUS_SUCCESS);
1325 }
1326 if (!NT_SUCCESS(Status))
1327 {
1328 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1329 return(Status);
1330 }
1331
1332 Status = NtQueryInformationFile(FileHandle,
1333 &IoStatusBlock,
1334 &FileInfo,
1335 sizeof(FILE_BASIC_INFORMATION),
1336 FileBasicInformation);
1337 if (!NT_SUCCESS(Status))
1338 {
1339 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1340 NtClose(FileHandle);
1341 return(Status);
1342 }
1343
1344 *Attributes = FileInfo.FileAttributes;
1345
1346 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1347 FileInfo.FileAttributes = FileInfo.FileAttributes &
1348 ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1349
1350 Status = NtSetInformationFile(FileHandle,
1351 &IoStatusBlock,
1352 &FileInfo,
1353 sizeof(FILE_BASIC_INFORMATION),
1354 FileBasicInformation);
1355 if (!NT_SUCCESS(Status))
1356 {
1357 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1358 }
1359
1360 NtClose(FileHandle);
1361 return(Status);
1362 }
1363
1364
1365 static NTSTATUS
1366 ProtectBootIni(PWSTR FileName,
1367 ULONG Attributes)
1368 {
1369 UNICODE_STRING Name;
1370 OBJECT_ATTRIBUTES ObjectAttributes;
1371 IO_STATUS_BLOCK IoStatusBlock;
1372 FILE_BASIC_INFORMATION FileInfo;
1373 HANDLE FileHandle;
1374 NTSTATUS Status;
1375
1376 RtlInitUnicodeString(&Name,
1377 FileName);
1378
1379 InitializeObjectAttributes(&ObjectAttributes,
1380 &Name,
1381 OBJ_CASE_INSENSITIVE,
1382 NULL,
1383 NULL);
1384
1385 Status = NtOpenFile(&FileHandle,
1386 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1387 &ObjectAttributes,
1388 &IoStatusBlock,
1389 0,
1390 FILE_SYNCHRONOUS_IO_ALERT);
1391 if (!NT_SUCCESS(Status))
1392 {
1393 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1394 return(Status);
1395 }
1396
1397 Status = NtQueryInformationFile(FileHandle,
1398 &IoStatusBlock,
1399 &FileInfo,
1400 sizeof(FILE_BASIC_INFORMATION),
1401 FileBasicInformation);
1402 if (!NT_SUCCESS(Status))
1403 {
1404 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1405 NtClose(FileHandle);
1406 return(Status);
1407 }
1408
1409 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1410
1411 Status = NtSetInformationFile(FileHandle,
1412 &IoStatusBlock,
1413 &FileInfo,
1414 sizeof(FILE_BASIC_INFORMATION),
1415 FileBasicInformation);
1416 if (!NT_SUCCESS(Status))
1417 {
1418 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1419 }
1420
1421 NtClose(FileHandle);
1422 return(Status);
1423 }
1424
1425
1426 NTSTATUS
1427 UpdateBootIni(PWSTR BootIniPath,
1428 PWSTR EntryName,
1429 PWSTR EntryValue)
1430 {
1431 UNICODE_STRING Name;
1432 PINICACHE Cache = NULL;
1433 PINICACHESECTION Section = NULL;
1434 NTSTATUS Status;
1435 ULONG FileAttribute;
1436
1437 RtlInitUnicodeString(&Name,
1438 BootIniPath);
1439
1440 Status = IniCacheLoad(&Cache,
1441 &Name);
1442 if (!NT_SUCCESS(Status))
1443 {
1444 CHECKPOINT1;
1445 return(Status);
1446 }
1447
1448 Section = IniCacheGetSection(Cache,
1449 L"operating systems");
1450 if (Section == NULL)
1451 {
1452 CHECKPOINT1;
1453 IniCacheDestroy(Cache);
1454 return(STATUS_UNSUCCESSFUL);
1455 }
1456
1457 IniCacheInsertKey(Section,
1458 NULL,
1459 INSERT_LAST,
1460 EntryName,
1461 EntryValue);
1462
1463 Status = UnprotectBootIni(BootIniPath,
1464 &FileAttribute);
1465 if (!NT_SUCCESS(Status))
1466 {
1467 CHECKPOINT1;
1468 IniCacheDestroy(Cache);
1469 return(Status);
1470 }
1471
1472 Status = IniCacheSave(Cache,
1473 BootIniPath);
1474 if (!NT_SUCCESS(Status))
1475 {
1476 CHECKPOINT1;
1477 IniCacheDestroy(Cache);
1478 return(Status);
1479 }
1480
1481 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1482 Status = ProtectBootIni(BootIniPath,
1483 FileAttribute);
1484
1485 IniCacheDestroy(Cache);
1486
1487 return(Status);
1488 }
1489
1490 /* EOF */