2003-04-28 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / subsys / system / usetup / bootsup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/bootsup.c
23 * PURPOSE: Bootloader support functions
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include <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 FALSE);
393 if (!NT_SUCCESS(Status))
394 return(Status);
395
396 /* Get "Operating Systems" section */
397 IniSection = IniCacheGetSection(IniCache,
398 L"Operating Systems");
399 if (IniSection == NULL)
400 return(STATUS_UNSUCCESSFUL);
401
402 /* Find an unused section name */
403 i = 1;
404 wcscpy(SectionName, L"ReactOS");
405 wcscpy(OsName, L"\"ReactOS\"");
406 while(TRUE)
407 {
408 Status = IniCacheGetKey(IniSection,
409 SectionName,
410 &KeyData);
411 if (!NT_SUCCESS(Status))
412 break;
413
414 swprintf(SectionName, L"ReactOS_%lu", i);
415 swprintf(OsName, L"\"ReactOS %lu\"", i);
416 i++;
417 }
418
419 /* <SectionName>=<OsName> */
420 IniCacheInsertKey(IniSection,
421 NULL,
422 INSERT_LAST,
423 SectionName,
424 OsName);
425
426 /* Create <SectionName> section */
427 IniSection = IniCacheAppendSection(IniCache,
428 SectionName);
429
430 /* BootType=ReactOS */
431 IniCacheInsertKey(IniSection,
432 NULL,
433 INSERT_LAST,
434 L"BootType",
435 L"ReactOS");
436
437 /* SystemPath=<ArcPath> */
438 IniCacheInsertKey(IniSection,
439 NULL,
440 INSERT_LAST,
441 L"SystemPath",
442 ArcPath);
443
444 IniCacheSave(IniCache, IniPath);
445 IniCacheDestroy(IniCache);
446
447 return(STATUS_SUCCESS);
448 }
449
450
451 NTSTATUS
452 SaveCurrentBootSector(PWSTR RootPath,
453 PWSTR DstPath)
454 {
455 OBJECT_ATTRIBUTES ObjectAttributes;
456 IO_STATUS_BLOCK IoStatusBlock;
457 UNICODE_STRING Name;
458 HANDLE FileHandle;
459 NTSTATUS Status;
460 PUCHAR BootSector;
461
462 /* Allocate buffer for bootsector */
463 BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
464 0,
465 SECTORSIZE);
466 if (BootSector == NULL)
467 return(STATUS_INSUFFICIENT_RESOURCES);
468
469 /* Read current boot sector into buffer */
470 RtlInitUnicodeString(&Name,
471 RootPath);
472
473 InitializeObjectAttributes(&ObjectAttributes,
474 &Name,
475 OBJ_CASE_INSENSITIVE,
476 NULL,
477 NULL);
478
479 Status = NtOpenFile(&FileHandle,
480 FILE_READ_ACCESS,
481 &ObjectAttributes,
482 &IoStatusBlock,
483 0,
484 FILE_SYNCHRONOUS_IO_ALERT);
485 if (!NT_SUCCESS(Status))
486 {
487 RtlFreeHeap(ProcessHeap, 0, BootSector);
488 return(Status);
489 }
490
491 Status = NtReadFile(FileHandle,
492 NULL,
493 NULL,
494 NULL,
495 &IoStatusBlock,
496 BootSector,
497 SECTORSIZE,
498 NULL,
499 NULL);
500 NtClose(FileHandle);
501 if (!NT_SUCCESS(Status))
502 {
503 RtlFreeHeap(ProcessHeap, 0, BootSector);
504 return(Status);
505 }
506
507 /* Write bootsector to DstPath */
508 RtlInitUnicodeString(&Name,
509 DstPath);
510
511 InitializeObjectAttributes(&ObjectAttributes,
512 &Name,
513 0,
514 NULL,
515 NULL);
516
517 Status = NtCreateFile(&FileHandle,
518 FILE_WRITE_ACCESS,
519 &ObjectAttributes,
520 &IoStatusBlock,
521 NULL,
522 FILE_ATTRIBUTE_NORMAL,
523 0,
524 FILE_SUPERSEDE,
525 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
526 NULL,
527 0);
528 if (!NT_SUCCESS(Status))
529 {
530 RtlFreeHeap(ProcessHeap, 0, BootSector);
531 return(Status);
532 }
533
534 Status = NtWriteFile(FileHandle,
535 NULL,
536 NULL,
537 NULL,
538 &IoStatusBlock,
539 BootSector,
540 SECTORSIZE,
541 NULL,
542 NULL);
543 NtClose(FileHandle);
544
545 /* Free the new boot sector */
546 RtlFreeHeap(ProcessHeap, 0, BootSector);
547
548 return(Status);
549 }
550
551
552 NTSTATUS
553 InstallFat16BootCodeToFile(PWSTR SrcPath,
554 PWSTR DstPath,
555 PWSTR RootPath)
556 {
557 OBJECT_ATTRIBUTES ObjectAttributes;
558 IO_STATUS_BLOCK IoStatusBlock;
559 UNICODE_STRING Name;
560 HANDLE FileHandle;
561 NTSTATUS Status;
562 PUCHAR OrigBootSector;
563 PUCHAR NewBootSector;
564
565 /* Allocate buffer for original bootsector */
566 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
567 0,
568 SECTORSIZE);
569 if (OrigBootSector == NULL)
570 return(STATUS_INSUFFICIENT_RESOURCES);
571
572 /* Read current boot sector into buffer */
573 RtlInitUnicodeString(&Name,
574 RootPath);
575
576 InitializeObjectAttributes(&ObjectAttributes,
577 &Name,
578 OBJ_CASE_INSENSITIVE,
579 NULL,
580 NULL);
581
582 Status = NtOpenFile(&FileHandle,
583 FILE_READ_ACCESS,
584 &ObjectAttributes,
585 &IoStatusBlock,
586 0,
587 FILE_SYNCHRONOUS_IO_ALERT);
588 if (!NT_SUCCESS(Status))
589 {
590 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
591 return(Status);
592 }
593
594 Status = NtReadFile(FileHandle,
595 NULL,
596 NULL,
597 NULL,
598 &IoStatusBlock,
599 OrigBootSector,
600 SECTORSIZE,
601 NULL,
602 NULL);
603 NtClose(FileHandle);
604 if (!NT_SUCCESS(Status))
605 {
606 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
607 return(Status);
608 }
609
610
611 /* Allocate buffer for new bootsector */
612 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
613 0,
614 SECTORSIZE);
615 if (NewBootSector == NULL)
616 {
617 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
618 return(STATUS_INSUFFICIENT_RESOURCES);
619 }
620
621 /* Read new bootsector from SrcPath */
622 RtlInitUnicodeString(&Name,
623 SrcPath);
624
625 InitializeObjectAttributes(&ObjectAttributes,
626 &Name,
627 OBJ_CASE_INSENSITIVE,
628 NULL,
629 NULL);
630
631 Status = NtOpenFile(&FileHandle,
632 FILE_READ_ACCESS,
633 &ObjectAttributes,
634 &IoStatusBlock,
635 0,
636 FILE_SYNCHRONOUS_IO_ALERT);
637 if (!NT_SUCCESS(Status))
638 {
639 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
640 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
641 return(Status);
642 }
643
644 Status = NtReadFile(FileHandle,
645 NULL,
646 NULL,
647 NULL,
648 &IoStatusBlock,
649 NewBootSector,
650 SECTORSIZE,
651 NULL,
652 NULL);
653 NtClose(FileHandle);
654 if (!NT_SUCCESS(Status))
655 {
656 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
657 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
658 return(Status);
659 }
660
661 /* Adjust bootsector (copy a part of the FAT BPB) */
662 memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
663
664 /* Free the original boot sector */
665 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
666
667 /* Write new bootsector to DstPath */
668 RtlInitUnicodeString(&Name,
669 DstPath);
670
671 InitializeObjectAttributes(&ObjectAttributes,
672 &Name,
673 0,
674 NULL,
675 NULL);
676
677 Status = NtCreateFile(&FileHandle,
678 FILE_WRITE_ACCESS,
679 &ObjectAttributes,
680 &IoStatusBlock,
681 NULL,
682 FILE_ATTRIBUTE_NORMAL,
683 0,
684 FILE_OVERWRITE_IF,
685 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
686 NULL,
687 0);
688 if (!NT_SUCCESS(Status))
689 {
690 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
691 return(Status);
692 }
693
694 #if 0
695 FilePosition.QuadPart = 0;
696 #endif
697 Status = NtWriteFile(FileHandle,
698 NULL,
699 NULL,
700 NULL,
701 &IoStatusBlock,
702 NewBootSector,
703 SECTORSIZE,
704 NULL,
705 NULL);
706 NtClose(FileHandle);
707
708 /* Free the new boot sector */
709 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
710
711 return(Status);
712 }
713
714
715 NTSTATUS
716 InstallFat32BootCodeToFile(PWSTR SrcPath,
717 PWSTR DstPath,
718 PWSTR RootPath)
719 {
720 OBJECT_ATTRIBUTES ObjectAttributes;
721 IO_STATUS_BLOCK IoStatusBlock;
722 UNICODE_STRING Name;
723 HANDLE FileHandle;
724 NTSTATUS Status;
725 PUCHAR OrigBootSector;
726 PUCHAR NewBootSector;
727 LARGE_INTEGER FileOffset;
728
729 /* Allocate buffer for original bootsector */
730 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
731 0,
732 SECTORSIZE);
733 if (OrigBootSector == NULL)
734 return(STATUS_INSUFFICIENT_RESOURCES);
735
736 /* Read current boot sector into buffer */
737 RtlInitUnicodeString(&Name,
738 RootPath);
739
740 InitializeObjectAttributes(&ObjectAttributes,
741 &Name,
742 OBJ_CASE_INSENSITIVE,
743 NULL,
744 NULL);
745
746 Status = NtOpenFile(&FileHandle,
747 FILE_READ_ACCESS,
748 &ObjectAttributes,
749 &IoStatusBlock,
750 0,
751 FILE_SYNCHRONOUS_IO_ALERT);
752 if (!NT_SUCCESS(Status))
753 {
754 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
755 return(Status);
756 }
757
758 Status = NtReadFile(FileHandle,
759 NULL,
760 NULL,
761 NULL,
762 &IoStatusBlock,
763 OrigBootSector,
764 SECTORSIZE,
765 NULL,
766 NULL);
767 NtClose(FileHandle);
768 if (!NT_SUCCESS(Status))
769 {
770 CHECKPOINT1;
771 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
772 return(Status);
773 }
774
775 /* Allocate buffer for new bootsector (2 sectors) */
776 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
777 0,
778 2 * SECTORSIZE);
779 if (NewBootSector == NULL)
780 {
781 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
782 return(STATUS_INSUFFICIENT_RESOURCES);
783 }
784
785 /* Read new bootsector from SrcPath */
786 RtlInitUnicodeString(&Name,
787 SrcPath);
788
789 InitializeObjectAttributes(&ObjectAttributes,
790 &Name,
791 OBJ_CASE_INSENSITIVE,
792 NULL,
793 NULL);
794
795 Status = NtOpenFile(&FileHandle,
796 FILE_READ_ACCESS,
797 &ObjectAttributes,
798 &IoStatusBlock,
799 0,
800 FILE_SYNCHRONOUS_IO_ALERT);
801 if (!NT_SUCCESS(Status))
802 {
803 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
804 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
805 return(Status);
806 }
807
808 Status = NtReadFile(FileHandle,
809 NULL,
810 NULL,
811 NULL,
812 &IoStatusBlock,
813 NewBootSector,
814 2 * SECTORSIZE,
815 NULL,
816 NULL);
817 NtClose(FileHandle);
818 if (!NT_SUCCESS(Status))
819 {
820 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
821 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
822 return(Status);
823 }
824
825 /* Adjust bootsector (copy a part of the FAT32 BPB) */
826 memcpy((NewBootSector + 3),
827 (OrigBootSector + 3),
828 87); /* FAT32 BPB length */
829
830 /* Disable the backup boot sector */
831 NewBootSector[0x32] = 0x00;
832 NewBootSector[0x33] = 0x00;
833
834 /* Free the original boot sector */
835 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
836
837 /* Write the first sector of the new bootcode to DstPath */
838 RtlInitUnicodeString(&Name,
839 DstPath);
840
841 InitializeObjectAttributes(&ObjectAttributes,
842 &Name,
843 0,
844 NULL,
845 NULL);
846
847 Status = NtCreateFile(&FileHandle,
848 FILE_WRITE_ACCESS,
849 &ObjectAttributes,
850 &IoStatusBlock,
851 NULL,
852 FILE_ATTRIBUTE_NORMAL,
853 0,
854 FILE_SUPERSEDE,
855 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
856 NULL,
857 0);
858 if (!NT_SUCCESS(Status))
859 {
860 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
861 return(Status);
862 }
863
864 Status = NtWriteFile(FileHandle,
865 NULL,
866 NULL,
867 NULL,
868 &IoStatusBlock,
869 NewBootSector,
870 SECTORSIZE,
871 NULL,
872 NULL);
873 NtClose(FileHandle);
874 if (!NT_SUCCESS(Status))
875 {
876 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
877 return(Status);
878 }
879
880 /* Write the second sector of the new bootcode to boot disk sector 14 */
881 RtlInitUnicodeString(&Name,
882 RootPath);
883
884 InitializeObjectAttributes(&ObjectAttributes,
885 &Name,
886 0,
887 NULL,
888 NULL);
889
890 Status = NtOpenFile(&FileHandle,
891 FILE_WRITE_ACCESS,
892 &ObjectAttributes,
893 &IoStatusBlock,
894 0,
895 FILE_SYNCHRONOUS_IO_ALERT);
896 if (!NT_SUCCESS(Status))
897 {
898 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
899 return(Status);
900 }
901
902 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
903 Status = NtWriteFile(FileHandle,
904 NULL,
905 NULL,
906 NULL,
907 &IoStatusBlock,
908 (NewBootSector + SECTORSIZE),
909 SECTORSIZE,
910 &FileOffset,
911 NULL);
912 if (!NT_SUCCESS(Status))
913 {
914 }
915 NtClose(FileHandle);
916
917 /* Free the new boot sector */
918 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
919
920 return(Status);
921 }
922
923
924 NTSTATUS
925 InstallMBRBootCodeToDisk(PWSTR SrcPath,
926 PWSTR RootPath)
927 {
928 OBJECT_ATTRIBUTES ObjectAttributes;
929 IO_STATUS_BLOCK IoStatusBlock;
930 UNICODE_STRING Name;
931 HANDLE FileHandle;
932 NTSTATUS Status;
933 PUCHAR OrigBootSector;
934 PUCHAR NewBootSector;
935
936 /* Allocate buffer for original bootsector */
937 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
938 0,
939 SECTORSIZE);
940 if (OrigBootSector == NULL)
941 return(STATUS_INSUFFICIENT_RESOURCES);
942
943 /* Read current boot sector into buffer */
944 RtlInitUnicodeString(&Name,
945 RootPath);
946
947 InitializeObjectAttributes(&ObjectAttributes,
948 &Name,
949 OBJ_CASE_INSENSITIVE,
950 NULL,
951 NULL);
952
953 Status = NtOpenFile(&FileHandle,
954 FILE_READ_ACCESS,
955 &ObjectAttributes,
956 &IoStatusBlock,
957 0,
958 FILE_SYNCHRONOUS_IO_ALERT);
959 if (!NT_SUCCESS(Status))
960 {
961 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
962 return(Status);
963 }
964
965 Status = NtReadFile(FileHandle,
966 NULL,
967 NULL,
968 NULL,
969 &IoStatusBlock,
970 OrigBootSector,
971 SECTORSIZE,
972 NULL,
973 NULL);
974 NtClose(FileHandle);
975 if (!NT_SUCCESS(Status))
976 {
977 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
978 return(Status);
979 }
980
981
982 /* Allocate buffer for new bootsector */
983 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
984 0,
985 SECTORSIZE);
986 if (NewBootSector == NULL)
987 {
988 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
989 return(STATUS_INSUFFICIENT_RESOURCES);
990 }
991
992 /* Read new bootsector from SrcPath */
993 RtlInitUnicodeString(&Name,
994 SrcPath);
995
996 InitializeObjectAttributes(&ObjectAttributes,
997 &Name,
998 OBJ_CASE_INSENSITIVE,
999 NULL,
1000 NULL);
1001
1002 Status = NtOpenFile(&FileHandle,
1003 FILE_READ_ACCESS,
1004 &ObjectAttributes,
1005 &IoStatusBlock,
1006 0,
1007 FILE_SYNCHRONOUS_IO_ALERT);
1008 if (!NT_SUCCESS(Status))
1009 {
1010 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1011 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1012 return(Status);
1013 }
1014
1015 Status = NtReadFile(FileHandle,
1016 NULL,
1017 NULL,
1018 NULL,
1019 &IoStatusBlock,
1020 NewBootSector,
1021 SECTORSIZE,
1022 NULL,
1023 NULL);
1024 NtClose(FileHandle);
1025 if (!NT_SUCCESS(Status))
1026 {
1027 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1028 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1029 return(Status);
1030 }
1031
1032 /* Copy partition table from old MBR to new */
1033 memcpy((NewBootSector + 446), (OrigBootSector + 446), 4*16 /* Length of partition table */);
1034
1035 /* Free the original boot sector */
1036 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1037
1038 /* Write new bootsector to RootPath */
1039 RtlInitUnicodeString(&Name,
1040 RootPath);
1041
1042 InitializeObjectAttributes(&ObjectAttributes,
1043 &Name,
1044 0,
1045 NULL,
1046 NULL);
1047
1048 Status = NtCreateFile(&FileHandle,
1049 FILE_WRITE_ACCESS,
1050 &ObjectAttributes,
1051 &IoStatusBlock,
1052 NULL,
1053 FILE_ATTRIBUTE_NORMAL,
1054 0,
1055 FILE_OVERWRITE_IF,
1056 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
1057 NULL,
1058 0);
1059 if (!NT_SUCCESS(Status))
1060 {
1061 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1062 return(Status);
1063 }
1064
1065 Status = NtWriteFile(FileHandle,
1066 NULL,
1067 NULL,
1068 NULL,
1069 &IoStatusBlock,
1070 NewBootSector,
1071 SECTORSIZE,
1072 NULL,
1073 NULL);
1074 NtClose(FileHandle);
1075
1076 /* Free the new boot sector */
1077 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1078
1079 return(Status);
1080 }
1081
1082
1083 NTSTATUS
1084 InstallFat16BootCodeToDisk(PWSTR SrcPath,
1085 PWSTR RootPath)
1086 {
1087 OBJECT_ATTRIBUTES ObjectAttributes;
1088 IO_STATUS_BLOCK IoStatusBlock;
1089 UNICODE_STRING Name;
1090 HANDLE FileHandle;
1091 NTSTATUS Status;
1092 PUCHAR OrigBootSector;
1093 PUCHAR NewBootSector;
1094
1095 /* Allocate buffer for original bootsector */
1096 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1097 0,
1098 SECTORSIZE);
1099 if (OrigBootSector == NULL)
1100 return(STATUS_INSUFFICIENT_RESOURCES);
1101
1102 /* Read current boot sector into buffer */
1103 RtlInitUnicodeString(&Name,
1104 RootPath);
1105
1106 InitializeObjectAttributes(&ObjectAttributes,
1107 &Name,
1108 OBJ_CASE_INSENSITIVE,
1109 NULL,
1110 NULL);
1111
1112 Status = NtOpenFile(&FileHandle,
1113 FILE_READ_ACCESS,
1114 &ObjectAttributes,
1115 &IoStatusBlock,
1116 0,
1117 FILE_SYNCHRONOUS_IO_ALERT);
1118 if (!NT_SUCCESS(Status))
1119 {
1120 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1121 return(Status);
1122 }
1123
1124 Status = NtReadFile(FileHandle,
1125 NULL,
1126 NULL,
1127 NULL,
1128 &IoStatusBlock,
1129 OrigBootSector,
1130 SECTORSIZE,
1131 NULL,
1132 NULL);
1133 NtClose(FileHandle);
1134 if (!NT_SUCCESS(Status))
1135 {
1136 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1137 return(Status);
1138 }
1139
1140
1141 /* Allocate buffer for new bootsector */
1142 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1143 0,
1144 SECTORSIZE);
1145 if (NewBootSector == NULL)
1146 {
1147 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1148 return(STATUS_INSUFFICIENT_RESOURCES);
1149 }
1150
1151 /* Read new bootsector from SrcPath */
1152 RtlInitUnicodeString(&Name,
1153 SrcPath);
1154
1155 InitializeObjectAttributes(&ObjectAttributes,
1156 &Name,
1157 OBJ_CASE_INSENSITIVE,
1158 NULL,
1159 NULL);
1160
1161 Status = NtOpenFile(&FileHandle,
1162 FILE_READ_ACCESS,
1163 &ObjectAttributes,
1164 &IoStatusBlock,
1165 0,
1166 FILE_SYNCHRONOUS_IO_ALERT);
1167 if (!NT_SUCCESS(Status))
1168 {
1169 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1170 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1171 return(Status);
1172 }
1173
1174 Status = NtReadFile(FileHandle,
1175 NULL,
1176 NULL,
1177 NULL,
1178 &IoStatusBlock,
1179 NewBootSector,
1180 SECTORSIZE,
1181 NULL,
1182 NULL);
1183 NtClose(FileHandle);
1184 if (!NT_SUCCESS(Status))
1185 {
1186 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1187 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1188 return(Status);
1189 }
1190
1191 /* Adjust bootsector (copy a part of the FAT BPB) */
1192 memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
1193
1194 /* Free the original boot sector */
1195 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1196
1197 /* Write new bootsector to RootPath */
1198 RtlInitUnicodeString(&Name,
1199 RootPath);
1200
1201 InitializeObjectAttributes(&ObjectAttributes,
1202 &Name,
1203 0,
1204 NULL,
1205 NULL);
1206
1207 Status = NtCreateFile(&FileHandle,
1208 FILE_WRITE_ACCESS,
1209 &ObjectAttributes,
1210 &IoStatusBlock,
1211 NULL,
1212 FILE_ATTRIBUTE_NORMAL,
1213 0,
1214 FILE_OVERWRITE_IF,
1215 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
1216 NULL,
1217 0);
1218 if (!NT_SUCCESS(Status))
1219 {
1220 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1221 return(Status);
1222 }
1223
1224 #if 0
1225 FilePosition.QuadPart = 0;
1226 #endif
1227 Status = NtWriteFile(FileHandle,
1228 NULL,
1229 NULL,
1230 NULL,
1231 &IoStatusBlock,
1232 NewBootSector,
1233 SECTORSIZE,
1234 NULL,
1235 NULL);
1236 NtClose(FileHandle);
1237
1238 /* Free the new boot sector */
1239 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1240
1241 return(Status);
1242 }
1243
1244
1245 NTSTATUS
1246 InstallFat32BootCodeToDisk(PWSTR SrcPath,
1247 PWSTR RootPath)
1248 {
1249 OBJECT_ATTRIBUTES ObjectAttributes;
1250 IO_STATUS_BLOCK IoStatusBlock;
1251 UNICODE_STRING Name;
1252 HANDLE FileHandle;
1253 NTSTATUS Status;
1254 PUCHAR OrigBootSector;
1255 PUCHAR NewBootSector;
1256 LARGE_INTEGER FileOffset;
1257 USHORT BackupBootSector;
1258
1259 /* Allocate buffer for original bootsector */
1260 OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1261 0,
1262 SECTORSIZE);
1263 if (OrigBootSector == NULL)
1264 return(STATUS_INSUFFICIENT_RESOURCES);
1265
1266 /* Read current boot sector into buffer */
1267 RtlInitUnicodeString(&Name,
1268 RootPath);
1269
1270 InitializeObjectAttributes(&ObjectAttributes,
1271 &Name,
1272 OBJ_CASE_INSENSITIVE,
1273 NULL,
1274 NULL);
1275
1276 Status = NtOpenFile(&FileHandle,
1277 FILE_READ_ACCESS,
1278 &ObjectAttributes,
1279 &IoStatusBlock,
1280 0,
1281 FILE_SYNCHRONOUS_IO_ALERT);
1282 if (!NT_SUCCESS(Status))
1283 {
1284 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1285 return(Status);
1286 }
1287
1288 Status = NtReadFile(FileHandle,
1289 NULL,
1290 NULL,
1291 NULL,
1292 &IoStatusBlock,
1293 OrigBootSector,
1294 SECTORSIZE,
1295 NULL,
1296 NULL);
1297 NtClose(FileHandle);
1298 if (!NT_SUCCESS(Status))
1299 {
1300 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1301 return(Status);
1302 }
1303
1304
1305 /* Allocate buffer for new bootsector (2 sectors) */
1306 NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
1307 0,
1308 2 * SECTORSIZE);
1309 if (NewBootSector == NULL)
1310 {
1311 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1312 return(STATUS_INSUFFICIENT_RESOURCES);
1313 }
1314
1315 /* Read new bootsector from SrcPath */
1316 RtlInitUnicodeString(&Name,
1317 SrcPath);
1318
1319 InitializeObjectAttributes(&ObjectAttributes,
1320 &Name,
1321 OBJ_CASE_INSENSITIVE,
1322 NULL,
1323 NULL);
1324
1325 Status = NtOpenFile(&FileHandle,
1326 FILE_READ_ACCESS,
1327 &ObjectAttributes,
1328 &IoStatusBlock,
1329 0,
1330 FILE_SYNCHRONOUS_IO_ALERT);
1331 if (!NT_SUCCESS(Status))
1332 {
1333 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1334 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1335 return(Status);
1336 }
1337
1338 Status = NtReadFile(FileHandle,
1339 NULL,
1340 NULL,
1341 NULL,
1342 &IoStatusBlock,
1343 NewBootSector,
1344 2 * SECTORSIZE,
1345 NULL,
1346 NULL);
1347 NtClose(FileHandle);
1348 if (!NT_SUCCESS(Status))
1349 {
1350 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1351 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1352 return(Status);
1353 }
1354
1355 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1356 memcpy((NewBootSector + 3),
1357 (OrigBootSector + 3),
1358 87); /* FAT32 BPB length */
1359
1360 /* Get the location of the backup boot sector */
1361 BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x32];
1362
1363 /* Free the original boot sector */
1364 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1365
1366 /* Write the first sector of the new bootcode to DstPath */
1367 RtlInitUnicodeString(&Name,
1368 RootPath);
1369
1370 InitializeObjectAttributes(&ObjectAttributes,
1371 &Name,
1372 0,
1373 NULL,
1374 NULL);
1375
1376 Status = NtOpenFile(&FileHandle,
1377 FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
1378 &ObjectAttributes,
1379 &IoStatusBlock,
1380 0,
1381 FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
1382 if (!NT_SUCCESS(Status))
1383 {
1384 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1385 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1386 return(Status);
1387 }
1388
1389 /* Write sector 0 */
1390 FileOffset.QuadPart = 0ULL;
1391 Status = NtWriteFile(FileHandle,
1392 NULL,
1393 NULL,
1394 NULL,
1395 &IoStatusBlock,
1396 NewBootSector,
1397 SECTORSIZE,
1398 &FileOffset,
1399 NULL);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1403 NtClose(FileHandle);
1404 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1405 return(Status);
1406 }
1407
1408 /* Write backup boot sector */
1409 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1410 {
1411 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1412 Status = NtWriteFile(FileHandle,
1413 NULL,
1414 NULL,
1415 NULL,
1416 &IoStatusBlock,
1417 NewBootSector,
1418 SECTORSIZE,
1419 &FileOffset,
1420 NULL);
1421 if (!NT_SUCCESS(Status))
1422 {
1423 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1424 NtClose(FileHandle);
1425 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1426 return(Status);
1427 }
1428 }
1429
1430 /* Write sector 14 */
1431 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1432 Status = NtWriteFile(FileHandle,
1433 NULL,
1434 NULL,
1435 NULL,
1436 &IoStatusBlock,
1437 (NewBootSector + SECTORSIZE),
1438 SECTORSIZE,
1439 &FileOffset,
1440 NULL);
1441 if (!NT_SUCCESS(Status))
1442 {
1443 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1444 }
1445 NtClose(FileHandle);
1446
1447 /* Free the new boot sector */
1448 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1449
1450 return(Status);
1451 }
1452
1453
1454 static NTSTATUS
1455 UnprotectBootIni(PWSTR FileName,
1456 PULONG Attributes)
1457 {
1458 UNICODE_STRING Name;
1459 OBJECT_ATTRIBUTES ObjectAttributes;
1460 IO_STATUS_BLOCK IoStatusBlock;
1461 FILE_BASIC_INFORMATION FileInfo;
1462 HANDLE FileHandle;
1463 NTSTATUS Status;
1464
1465 RtlInitUnicodeString(&Name,
1466 FileName);
1467
1468 InitializeObjectAttributes(&ObjectAttributes,
1469 &Name,
1470 OBJ_CASE_INSENSITIVE,
1471 NULL,
1472 NULL);
1473
1474 Status = NtOpenFile(&FileHandle,
1475 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1476 &ObjectAttributes,
1477 &IoStatusBlock,
1478 0,
1479 FILE_SYNCHRONOUS_IO_ALERT);
1480 if (Status == STATUS_NO_SUCH_FILE)
1481 {
1482 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1483 *Attributes = 0;
1484 return(STATUS_SUCCESS);
1485 }
1486 if (!NT_SUCCESS(Status))
1487 {
1488 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1489 return(Status);
1490 }
1491
1492 Status = NtQueryInformationFile(FileHandle,
1493 &IoStatusBlock,
1494 &FileInfo,
1495 sizeof(FILE_BASIC_INFORMATION),
1496 FileBasicInformation);
1497 if (!NT_SUCCESS(Status))
1498 {
1499 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1500 NtClose(FileHandle);
1501 return(Status);
1502 }
1503
1504 *Attributes = FileInfo.FileAttributes;
1505
1506 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1507 FileInfo.FileAttributes = FileInfo.FileAttributes &
1508 ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1509
1510 Status = NtSetInformationFile(FileHandle,
1511 &IoStatusBlock,
1512 &FileInfo,
1513 sizeof(FILE_BASIC_INFORMATION),
1514 FileBasicInformation);
1515 if (!NT_SUCCESS(Status))
1516 {
1517 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1518 }
1519
1520 NtClose(FileHandle);
1521 return(Status);
1522 }
1523
1524
1525 static NTSTATUS
1526 ProtectBootIni(PWSTR FileName,
1527 ULONG Attributes)
1528 {
1529 UNICODE_STRING Name;
1530 OBJECT_ATTRIBUTES ObjectAttributes;
1531 IO_STATUS_BLOCK IoStatusBlock;
1532 FILE_BASIC_INFORMATION FileInfo;
1533 HANDLE FileHandle;
1534 NTSTATUS Status;
1535
1536 RtlInitUnicodeString(&Name,
1537 FileName);
1538
1539 InitializeObjectAttributes(&ObjectAttributes,
1540 &Name,
1541 OBJ_CASE_INSENSITIVE,
1542 NULL,
1543 NULL);
1544
1545 Status = NtOpenFile(&FileHandle,
1546 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
1547 &ObjectAttributes,
1548 &IoStatusBlock,
1549 0,
1550 FILE_SYNCHRONOUS_IO_ALERT);
1551 if (!NT_SUCCESS(Status))
1552 {
1553 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1554 return(Status);
1555 }
1556
1557 Status = NtQueryInformationFile(FileHandle,
1558 &IoStatusBlock,
1559 &FileInfo,
1560 sizeof(FILE_BASIC_INFORMATION),
1561 FileBasicInformation);
1562 if (!NT_SUCCESS(Status))
1563 {
1564 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
1565 NtClose(FileHandle);
1566 return(Status);
1567 }
1568
1569 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
1570
1571 Status = NtSetInformationFile(FileHandle,
1572 &IoStatusBlock,
1573 &FileInfo,
1574 sizeof(FILE_BASIC_INFORMATION),
1575 FileBasicInformation);
1576 if (!NT_SUCCESS(Status))
1577 {
1578 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
1579 }
1580
1581 NtClose(FileHandle);
1582 return(Status);
1583 }
1584
1585
1586 NTSTATUS
1587 UpdateBootIni(PWSTR BootIniPath,
1588 PWSTR EntryName,
1589 PWSTR EntryValue)
1590 {
1591 UNICODE_STRING Name;
1592 PINICACHE Cache = NULL;
1593 PINICACHESECTION Section = NULL;
1594 NTSTATUS Status;
1595 ULONG FileAttribute;
1596
1597 RtlInitUnicodeString(&Name,
1598 BootIniPath);
1599
1600 Status = IniCacheLoad(&Cache,
1601 &Name,
1602 FALSE);
1603 if (!NT_SUCCESS(Status))
1604 {
1605 CHECKPOINT1;
1606 return(Status);
1607 }
1608
1609 Section = IniCacheGetSection(Cache,
1610 L"operating systems");
1611 if (Section == NULL)
1612 {
1613 CHECKPOINT1;
1614 IniCacheDestroy(Cache);
1615 return(STATUS_UNSUCCESSFUL);
1616 }
1617
1618 IniCacheInsertKey(Section,
1619 NULL,
1620 INSERT_LAST,
1621 EntryName,
1622 EntryValue);
1623
1624 Status = UnprotectBootIni(BootIniPath,
1625 &FileAttribute);
1626 if (!NT_SUCCESS(Status))
1627 {
1628 CHECKPOINT1;
1629 IniCacheDestroy(Cache);
1630 return(Status);
1631 }
1632
1633 Status = IniCacheSave(Cache,
1634 BootIniPath);
1635 if (!NT_SUCCESS(Status))
1636 {
1637 CHECKPOINT1;
1638 IniCacheDestroy(Cache);
1639 return(Status);
1640 }
1641
1642 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
1643 Status = ProtectBootIni(BootIniPath,
1644 FileAttribute);
1645
1646 IniCacheDestroy(Cache);
1647
1648 return(Status);
1649 }
1650
1651 /* EOF */