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