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