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