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