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