3 * Copyright (C) 2002 ReactOS Team
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.
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.
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.
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
27 #include <ddk/ntddk.h>
28 #include <ntdll/rtl.h>
37 #define SECTORSIZE 512
39 /* FUNCTIONS ****************************************************************/
43 CreateCommonFreeLoaderSections(PINICACHE IniCache
)
45 PINICACHESECTION IniSection
;
47 /* Create "FREELOADER" section */
48 IniSection
= IniCacheAppendSection(IniCache
,
51 /* DefaultOS=ReactOS */
52 IniCacheInsertKey(IniSection
,
60 IniCacheInsertKey(IniSection
,
67 /* Create "Display" section */
68 IniSection
= IniCacheAppendSection(IniCache
,
71 /* TitleText=ReactOS Boot Manager */
72 IniCacheInsertKey(IniSection
,
76 L
"ReactOS Boot Manager");
78 /* StatusBarColor=Cyan */
79 IniCacheInsertKey(IniSection
,
85 /* StatusBarTextColor=Black */
86 IniCacheInsertKey(IniSection
,
89 L
"StatusBarTextColor",
92 /* BackdropTextColor=White */
93 IniCacheInsertKey(IniSection
,
99 /* BackdropColor=Blue */
100 IniCacheInsertKey(IniSection
,
106 /* BackdropFillStyle=Medium */
107 IniCacheInsertKey(IniSection
,
110 L
"BackdropFillStyle",
113 /* TitleBoxTextColor=White */
114 IniCacheInsertKey(IniSection
,
117 L
"TitleBoxTextColor",
120 /* TitleBoxColor=Red */
121 IniCacheInsertKey(IniSection
,
127 /* MessageBoxTextColor=White */
128 IniCacheInsertKey(IniSection
,
131 L
"MessageBoxTextColor",
134 /* MessageBoxColor=Blue */
135 IniCacheInsertKey(IniSection
,
141 /* MenuTextColor=White */
142 IniCacheInsertKey(IniSection
,
149 IniCacheInsertKey(IniSection
,
155 /* TextColor=Yellow */
156 IniCacheInsertKey(IniSection
,
162 /* SelectedTextColor=Black */
163 IniCacheInsertKey(IniSection
,
166 L
"SelectedTextColor",
169 /* SelectedColor=Gray */
170 IniCacheInsertKey(IniSection
,
179 CreateFreeLoaderIniForDos(PWCHAR IniPath
,
183 PINICACHESECTION IniSection
;
185 IniCache
= IniCacheCreate();
187 CreateCommonFreeLoaderSections(IniCache
);
189 /* Create "Operating Systems" section */
190 IniSection
= IniCacheAppendSection(IniCache
,
191 L
"Operating Systems");
193 /* REACTOS=ReactOS */
194 IniCacheInsertKey(IniSection
,
200 /* ReactOS_Debug="ReactOS (Debug)" */
201 IniCacheInsertKey(IniSection
,
205 L
"\"ReactOS (Debug)\"");
207 /* DOS=Dos/Windows */
208 IniCacheInsertKey(IniSection
,
214 /* Create "ReactOS" section */
215 IniSection
= IniCacheAppendSection(IniCache
,
218 /* BootType=ReactOS */
219 IniCacheInsertKey(IniSection
,
225 /* SystemPath=<ArcPath> */
226 IniCacheInsertKey(IniSection
,
232 /* Create "ReactOS_Debug" section */
233 IniSection
= IniCacheAppendSection(IniCache
,
236 /* BootType=ReactOS */
237 IniCacheInsertKey(IniSection
,
243 /* SystemPath=<ArcPath> */
244 IniCacheInsertKey(IniSection
,
250 /* Options=/DEBUGPORT=SCREEN */
251 IniCacheInsertKey(IniSection
,
255 L
"/DEBUGPORT=SCREEN");
257 /* Create "DOS" section */
258 IniSection
= IniCacheAppendSection(IniCache
,
261 /* BootType=BootSector */
262 IniCacheInsertKey(IniSection
,
269 IniCacheInsertKey(IniSection
,
275 /* BootPartition=1 */
276 IniCacheInsertKey(IniSection
,
282 /* BootSector=BOOTSECT.DOS */
283 IniCacheInsertKey(IniSection
,
289 IniCacheSave(IniCache
, IniPath
);
290 IniCacheDestroy(IniCache
);
292 return(STATUS_SUCCESS
);
297 CreateFreeLoaderIniForReactos(PWCHAR IniPath
,
301 PINICACHESECTION IniSection
;
303 IniCache
= IniCacheCreate();
305 CreateCommonFreeLoaderSections(IniCache
);
307 /* Create "Operating Systems" section */
308 IniSection
= IniCacheAppendSection(IniCache
,
309 L
"Operating Systems");
311 /* ReactOS="ReactOS" */
312 IniCacheInsertKey(IniSection
,
318 /* ReactOS_Debug="ReactOS (Debug)" */
319 IniCacheInsertKey(IniSection
,
323 L
"\"ReactOS (Debug)\"");
325 /* Create "ReactOS" section */
326 IniSection
= IniCacheAppendSection(IniCache
,
329 /* BootType=ReactOS */
330 IniCacheInsertKey(IniSection
,
336 /* SystemPath=<ArcPath> */
337 IniCacheInsertKey(IniSection
,
343 /* Create "ReactOS_Debug" section */
344 IniSection
= IniCacheAppendSection(IniCache
,
347 /* BootType=ReactOS */
348 IniCacheInsertKey(IniSection
,
354 /* SystemPath=<ArcPath> */
355 IniCacheInsertKey(IniSection
,
361 /* Options=/DEBUGPORT=SCREEN */
362 IniCacheInsertKey(IniSection
,
366 L
"/DEBUGPORT=SCREEN");
368 /* Save the ini file */
369 IniCacheSave(IniCache
, IniPath
);
370 IniCacheDestroy(IniCache
);
372 return(STATUS_SUCCESS
);
377 UpdateFreeLoaderIni(PWCHAR IniPath
,
382 PINICACHESECTION IniSection
;
383 WCHAR SectionName
[80];
389 RtlInitUnicodeString(&Name
,
392 Status
= IniCacheLoad(&IniCache
,
395 if (!NT_SUCCESS(Status
))
398 /* Get "Operating Systems" section */
399 IniSection
= IniCacheGetSection(IniCache
,
400 L
"Operating Systems");
401 if (IniSection
== NULL
)
402 return(STATUS_UNSUCCESSFUL
);
404 /* Find an unused section name */
406 wcscpy(SectionName
, L
"ReactOS");
407 wcscpy(OsName
, L
"\"ReactOS\"");
410 Status
= IniCacheGetKey(IniSection
,
413 if (!NT_SUCCESS(Status
))
416 swprintf(SectionName
, L
"ReactOS_%lu", i
);
417 swprintf(OsName
, L
"\"ReactOS %lu\"", i
);
421 /* <SectionName>=<OsName> */
422 IniCacheInsertKey(IniSection
,
428 /* Create <SectionName> section */
429 IniSection
= IniCacheAppendSection(IniCache
,
432 /* BootType=ReactOS */
433 IniCacheInsertKey(IniSection
,
439 /* SystemPath=<ArcPath> */
440 IniCacheInsertKey(IniSection
,
446 IniCacheSave(IniCache
, IniPath
);
447 IniCacheDestroy(IniCache
);
449 return(STATUS_SUCCESS
);
454 SaveCurrentBootSector(PWSTR RootPath
,
457 OBJECT_ATTRIBUTES ObjectAttributes
;
458 IO_STATUS_BLOCK IoStatusBlock
;
464 /* Allocate buffer for bootsector */
465 BootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
468 if (BootSector
== NULL
)
469 return(STATUS_INSUFFICIENT_RESOURCES
);
471 /* Read current boot sector into buffer */
472 RtlInitUnicodeString(&Name
,
475 InitializeObjectAttributes(&ObjectAttributes
,
477 OBJ_CASE_INSENSITIVE
,
481 Status
= NtOpenFile(&FileHandle
,
486 FILE_SYNCHRONOUS_IO_NONALERT
);
487 if (!NT_SUCCESS(Status
))
489 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
493 Status
= NtReadFile(FileHandle
,
503 if (!NT_SUCCESS(Status
))
505 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
509 /* Write bootsector to DstPath */
510 RtlInitUnicodeString(&Name
,
513 InitializeObjectAttributes(&ObjectAttributes
,
519 Status
= NtCreateFile(&FileHandle
,
524 FILE_ATTRIBUTE_NORMAL
,
527 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
530 if (!NT_SUCCESS(Status
))
532 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
536 Status
= NtWriteFile(FileHandle
,
547 /* Free the new boot sector */
548 RtlFreeHeap(ProcessHeap
, 0, BootSector
);
555 InstallFat16BootCodeToFile(PWSTR SrcPath
,
559 OBJECT_ATTRIBUTES ObjectAttributes
;
560 IO_STATUS_BLOCK IoStatusBlock
;
564 PUCHAR OrigBootSector
;
565 PUCHAR NewBootSector
;
567 /* Allocate buffer for original bootsector */
568 OrigBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
571 if (OrigBootSector
== NULL
)
572 return(STATUS_INSUFFICIENT_RESOURCES
);
574 /* Read current boot sector into buffer */
575 RtlInitUnicodeString(&Name
,
578 InitializeObjectAttributes(&ObjectAttributes
,
580 OBJ_CASE_INSENSITIVE
,
584 Status
= NtOpenFile(&FileHandle
,
589 FILE_SYNCHRONOUS_IO_NONALERT
);
590 if (!NT_SUCCESS(Status
))
592 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
596 Status
= NtReadFile(FileHandle
,
606 if (!NT_SUCCESS(Status
))
608 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
613 /* Allocate buffer for new bootsector */
614 NewBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
617 if (NewBootSector
== NULL
)
619 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
620 return(STATUS_INSUFFICIENT_RESOURCES
);
623 /* Read new bootsector from SrcPath */
624 RtlInitUnicodeString(&Name
,
627 InitializeObjectAttributes(&ObjectAttributes
,
629 OBJ_CASE_INSENSITIVE
,
633 Status
= NtOpenFile(&FileHandle
,
638 FILE_SYNCHRONOUS_IO_NONALERT
);
639 if (!NT_SUCCESS(Status
))
641 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
642 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
646 Status
= NtReadFile(FileHandle
,
656 if (!NT_SUCCESS(Status
))
658 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
659 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
663 /* Adjust bootsector (copy a part of the FAT BPB) */
664 memcpy((NewBootSector
+ 11), (OrigBootSector
+ 11), 51 /*fat BPB length*/);
666 /* Free the original boot sector */
667 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
669 /* Write new bootsector to DstPath */
670 RtlInitUnicodeString(&Name
,
673 InitializeObjectAttributes(&ObjectAttributes
,
679 Status
= NtCreateFile(&FileHandle
,
684 FILE_ATTRIBUTE_NORMAL
,
687 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
690 if (!NT_SUCCESS(Status
))
692 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
697 FilePosition
.QuadPart
= 0;
699 Status
= NtWriteFile(FileHandle
,
710 /* Free the new boot sector */
711 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
718 InstallFat32BootCodeToFile(PWSTR SrcPath
,
722 OBJECT_ATTRIBUTES ObjectAttributes
;
723 IO_STATUS_BLOCK IoStatusBlock
;
727 PUCHAR OrigBootSector
;
728 PUCHAR NewBootSector
;
729 LARGE_INTEGER FileOffset
;
731 /* Allocate buffer for original bootsector */
732 OrigBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
735 if (OrigBootSector
== NULL
)
736 return(STATUS_INSUFFICIENT_RESOURCES
);
738 /* Read current boot sector into buffer */
739 RtlInitUnicodeString(&Name
,
742 InitializeObjectAttributes(&ObjectAttributes
,
744 OBJ_CASE_INSENSITIVE
,
748 Status
= NtOpenFile(&FileHandle
,
753 FILE_SYNCHRONOUS_IO_NONALERT
);
754 if (!NT_SUCCESS(Status
))
756 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
760 Status
= NtReadFile(FileHandle
,
770 if (!NT_SUCCESS(Status
))
773 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
777 /* Allocate buffer for new bootsector (2 sectors) */
778 NewBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
781 if (NewBootSector
== NULL
)
783 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
784 return(STATUS_INSUFFICIENT_RESOURCES
);
787 /* Read new bootsector from SrcPath */
788 RtlInitUnicodeString(&Name
,
791 InitializeObjectAttributes(&ObjectAttributes
,
793 OBJ_CASE_INSENSITIVE
,
797 Status
= NtOpenFile(&FileHandle
,
802 FILE_SYNCHRONOUS_IO_NONALERT
);
803 if (!NT_SUCCESS(Status
))
805 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
806 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
810 Status
= NtReadFile(FileHandle
,
820 if (!NT_SUCCESS(Status
))
822 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
823 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
827 /* Adjust bootsector (copy a part of the FAT32 BPB) */
828 memcpy((NewBootSector
+ 3),
829 (OrigBootSector
+ 3),
830 87); /* FAT32 BPB length */
832 /* Disable the backup boot sector */
833 NewBootSector
[0x32] = 0x00;
834 NewBootSector
[0x33] = 0x00;
836 /* Free the original boot sector */
837 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
839 /* Write the first sector of the new bootcode to DstPath */
840 RtlInitUnicodeString(&Name
,
843 InitializeObjectAttributes(&ObjectAttributes
,
849 Status
= NtCreateFile(&FileHandle
,
854 FILE_ATTRIBUTE_NORMAL
,
857 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
860 if (!NT_SUCCESS(Status
))
862 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
866 Status
= NtWriteFile(FileHandle
,
876 if (!NT_SUCCESS(Status
))
878 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
882 /* Write the second sector of the new bootcode to boot disk sector 14 */
883 RtlInitUnicodeString(&Name
,
886 InitializeObjectAttributes(&ObjectAttributes
,
892 Status
= NtOpenFile(&FileHandle
,
897 FILE_SYNCHRONOUS_IO_NONALERT
);
898 if (!NT_SUCCESS(Status
))
900 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
904 FileOffset
.QuadPart
= (ULONGLONG
)(14 * SECTORSIZE
);
905 Status
= NtWriteFile(FileHandle
,
910 (NewBootSector
+ SECTORSIZE
),
914 if (!NT_SUCCESS(Status
))
919 /* Free the new boot sector */
920 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
927 InstallMbrBootCodeToDisk (PWSTR SrcPath
,
930 OBJECT_ATTRIBUTES ObjectAttributes
;
931 IO_STATUS_BLOCK IoStatusBlock
;
935 PUCHAR OrigBootSector
;
936 PUCHAR NewBootSector
;
938 /* Allocate buffer for original bootsector */
939 OrigBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
942 if (OrigBootSector
== NULL
)
943 return(STATUS_INSUFFICIENT_RESOURCES
);
945 /* Read current boot sector into buffer */
946 RtlInitUnicodeString(&Name
,
949 InitializeObjectAttributes(&ObjectAttributes
,
951 OBJ_CASE_INSENSITIVE
,
955 Status
= NtOpenFile(&FileHandle
,
960 FILE_SYNCHRONOUS_IO_NONALERT
);
961 if (!NT_SUCCESS(Status
))
963 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
967 Status
= NtReadFile(FileHandle
,
977 if (!NT_SUCCESS(Status
))
979 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
984 /* Allocate buffer for new bootsector */
985 NewBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
988 if (NewBootSector
== NULL
)
990 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
991 return(STATUS_INSUFFICIENT_RESOURCES
);
994 /* Read new bootsector from SrcPath */
995 RtlInitUnicodeString(&Name
,
998 InitializeObjectAttributes(&ObjectAttributes
,
1000 OBJ_CASE_INSENSITIVE
,
1004 Status
= NtOpenFile(&FileHandle
,
1009 FILE_SYNCHRONOUS_IO_NONALERT
);
1010 if (!NT_SUCCESS(Status
))
1012 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1013 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1017 Status
= NtReadFile(FileHandle
,
1026 NtClose(FileHandle
);
1027 if (!NT_SUCCESS(Status
))
1029 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1030 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1034 /* Copy partition table from old MBR to new */
1035 RtlCopyMemory ((NewBootSector
+ 446),
1036 (OrigBootSector
+ 446),
1037 4*16 /* Length of partition table */);
1039 /* Free the original boot sector */
1040 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1042 /* Write new bootsector to RootPath */
1043 RtlInitUnicodeString(&Name
,
1046 InitializeObjectAttributes(&ObjectAttributes
,
1052 Status
= NtCreateFile(&FileHandle
,
1057 FILE_ATTRIBUTE_NORMAL
,
1060 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1063 if (!NT_SUCCESS(Status
))
1065 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1069 Status
= NtWriteFile(FileHandle
,
1078 NtClose(FileHandle
);
1080 /* Free the new boot sector */
1081 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1088 InstallFat16BootCodeToDisk(PWSTR SrcPath
,
1091 OBJECT_ATTRIBUTES ObjectAttributes
;
1092 IO_STATUS_BLOCK IoStatusBlock
;
1093 UNICODE_STRING Name
;
1096 PUCHAR OrigBootSector
;
1097 PUCHAR NewBootSector
;
1099 /* Allocate buffer for original bootsector */
1100 OrigBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
1103 if (OrigBootSector
== NULL
)
1104 return(STATUS_INSUFFICIENT_RESOURCES
);
1106 /* Read current boot sector into buffer */
1107 RtlInitUnicodeString(&Name
,
1110 InitializeObjectAttributes(&ObjectAttributes
,
1112 OBJ_CASE_INSENSITIVE
,
1116 Status
= NtOpenFile(&FileHandle
,
1121 FILE_SYNCHRONOUS_IO_NONALERT
);
1122 if (!NT_SUCCESS(Status
))
1124 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1128 Status
= NtReadFile(FileHandle
,
1137 NtClose(FileHandle
);
1138 if (!NT_SUCCESS(Status
))
1140 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1145 /* Allocate buffer for new bootsector */
1146 NewBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
1149 if (NewBootSector
== NULL
)
1151 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1152 return(STATUS_INSUFFICIENT_RESOURCES
);
1155 /* Read new bootsector from SrcPath */
1156 RtlInitUnicodeString(&Name
,
1159 InitializeObjectAttributes(&ObjectAttributes
,
1161 OBJ_CASE_INSENSITIVE
,
1165 Status
= NtOpenFile(&FileHandle
,
1170 FILE_SYNCHRONOUS_IO_NONALERT
);
1171 if (!NT_SUCCESS(Status
))
1173 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1174 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1178 Status
= NtReadFile(FileHandle
,
1187 NtClose(FileHandle
);
1188 if (!NT_SUCCESS(Status
))
1190 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1191 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1195 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1196 memcpy((NewBootSector
+ 3),
1197 (OrigBootSector
+ 3),
1198 59); /* FAT16 BPB length*/
1200 /* Free the original boot sector */
1201 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1203 /* Write new bootsector to RootPath */
1204 RtlInitUnicodeString(&Name
,
1207 InitializeObjectAttributes(&ObjectAttributes
,
1213 Status
= NtCreateFile(&FileHandle
,
1218 FILE_ATTRIBUTE_NORMAL
,
1221 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
,
1224 if (!NT_SUCCESS(Status
))
1226 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1231 FilePosition
.QuadPart
= 0;
1233 Status
= NtWriteFile(FileHandle
,
1242 NtClose(FileHandle
);
1244 /* Free the new boot sector */
1245 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1252 InstallFat32BootCodeToDisk(PWSTR SrcPath
,
1255 OBJECT_ATTRIBUTES ObjectAttributes
;
1256 IO_STATUS_BLOCK IoStatusBlock
;
1257 UNICODE_STRING Name
;
1260 PUCHAR OrigBootSector
;
1261 PUCHAR NewBootSector
;
1262 LARGE_INTEGER FileOffset
;
1263 USHORT BackupBootSector
;
1265 /* Allocate buffer for original bootsector */
1266 OrigBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
1269 if (OrigBootSector
== NULL
)
1270 return(STATUS_INSUFFICIENT_RESOURCES
);
1272 /* Read current boot sector into buffer */
1273 RtlInitUnicodeString(&Name
,
1276 InitializeObjectAttributes(&ObjectAttributes
,
1278 OBJ_CASE_INSENSITIVE
,
1282 Status
= NtOpenFile(&FileHandle
,
1287 FILE_SYNCHRONOUS_IO_NONALERT
);
1288 if (!NT_SUCCESS(Status
))
1290 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1294 Status
= NtReadFile(FileHandle
,
1303 NtClose(FileHandle
);
1304 if (!NT_SUCCESS(Status
))
1306 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1311 /* Allocate buffer for new bootsector (2 sectors) */
1312 NewBootSector
= (PUCHAR
)RtlAllocateHeap(ProcessHeap
,
1315 if (NewBootSector
== NULL
)
1317 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1318 return(STATUS_INSUFFICIENT_RESOURCES
);
1321 /* Read new bootsector from SrcPath */
1322 RtlInitUnicodeString(&Name
,
1325 InitializeObjectAttributes(&ObjectAttributes
,
1327 OBJ_CASE_INSENSITIVE
,
1331 Status
= NtOpenFile(&FileHandle
,
1336 FILE_SYNCHRONOUS_IO_NONALERT
);
1337 if (!NT_SUCCESS(Status
))
1339 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1340 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1344 Status
= NtReadFile(FileHandle
,
1353 NtClose(FileHandle
);
1354 if (!NT_SUCCESS(Status
))
1356 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1357 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1361 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1362 memcpy((NewBootSector
+ 3),
1363 (OrigBootSector
+ 3),
1364 87); /* FAT32 BPB length */
1366 /* Get the location of the backup boot sector */
1367 BackupBootSector
= (OrigBootSector
[0x33] << 8) + OrigBootSector
[0x32];
1369 /* Free the original boot sector */
1370 RtlFreeHeap(ProcessHeap
, 0, OrigBootSector
);
1372 /* Write the first sector of the new bootcode to DstPath */
1373 RtlInitUnicodeString(&Name
,
1376 InitializeObjectAttributes(&ObjectAttributes
,
1382 Status
= NtOpenFile(&FileHandle
,
1383 FILE_WRITE_ACCESS
| FILE_WRITE_ATTRIBUTES
,
1387 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_SEQUENTIAL_ONLY
);
1388 if (!NT_SUCCESS(Status
))
1390 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1391 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1395 /* Write sector 0 */
1396 FileOffset
.QuadPart
= 0ULL;
1397 Status
= NtWriteFile(FileHandle
,
1406 if (!NT_SUCCESS(Status
))
1408 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1409 NtClose(FileHandle
);
1410 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1414 /* Write backup boot sector */
1415 if ((BackupBootSector
!= 0x0000) && (BackupBootSector
!= 0xFFFF))
1417 FileOffset
.QuadPart
= (ULONGLONG
)((ULONG
)BackupBootSector
* SECTORSIZE
);
1418 Status
= NtWriteFile(FileHandle
,
1427 if (!NT_SUCCESS(Status
))
1429 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1430 NtClose(FileHandle
);
1431 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1436 /* Write sector 14 */
1437 FileOffset
.QuadPart
= (ULONGLONG
)(14 * SECTORSIZE
);
1438 Status
= NtWriteFile(FileHandle
,
1443 (NewBootSector
+ SECTORSIZE
),
1447 if (!NT_SUCCESS(Status
))
1449 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
1451 NtClose(FileHandle
);
1453 /* Free the new boot sector */
1454 RtlFreeHeap(ProcessHeap
, 0, NewBootSector
);
1461 UnprotectBootIni(PWSTR FileName
,
1464 UNICODE_STRING Name
;
1465 OBJECT_ATTRIBUTES ObjectAttributes
;
1466 IO_STATUS_BLOCK IoStatusBlock
;
1467 FILE_BASIC_INFORMATION FileInfo
;
1471 RtlInitUnicodeString(&Name
,
1474 InitializeObjectAttributes(&ObjectAttributes
,
1476 OBJ_CASE_INSENSITIVE
,
1480 Status
= NtOpenFile(&FileHandle
,
1481 FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
1485 FILE_SYNCHRONOUS_IO_NONALERT
);
1486 if (Status
== STATUS_NO_SUCH_FILE
)
1488 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1490 return(STATUS_SUCCESS
);
1492 if (!NT_SUCCESS(Status
))
1494 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1498 Status
= NtQueryInformationFile(FileHandle
,
1501 sizeof(FILE_BASIC_INFORMATION
),
1502 FileBasicInformation
);
1503 if (!NT_SUCCESS(Status
))
1505 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status
);
1506 NtClose(FileHandle
);
1510 *Attributes
= FileInfo
.FileAttributes
;
1512 /* Delete attributes SYSTEM, HIDDEN and READONLY */
1513 FileInfo
.FileAttributes
= FileInfo
.FileAttributes
&
1514 ~(FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_READONLY
);
1516 Status
= NtSetInformationFile(FileHandle
,
1519 sizeof(FILE_BASIC_INFORMATION
),
1520 FileBasicInformation
);
1521 if (!NT_SUCCESS(Status
))
1523 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status
);
1526 NtClose(FileHandle
);
1532 ProtectBootIni(PWSTR FileName
,
1535 UNICODE_STRING Name
;
1536 OBJECT_ATTRIBUTES ObjectAttributes
;
1537 IO_STATUS_BLOCK IoStatusBlock
;
1538 FILE_BASIC_INFORMATION FileInfo
;
1542 RtlInitUnicodeString(&Name
,
1545 InitializeObjectAttributes(&ObjectAttributes
,
1547 OBJ_CASE_INSENSITIVE
,
1551 Status
= NtOpenFile(&FileHandle
,
1552 FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
,
1556 FILE_SYNCHRONOUS_IO_NONALERT
);
1557 if (!NT_SUCCESS(Status
))
1559 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
1563 Status
= NtQueryInformationFile(FileHandle
,
1566 sizeof(FILE_BASIC_INFORMATION
),
1567 FileBasicInformation
);
1568 if (!NT_SUCCESS(Status
))
1570 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status
);
1571 NtClose(FileHandle
);
1575 FileInfo
.FileAttributes
= FileInfo
.FileAttributes
| Attributes
;
1577 Status
= NtSetInformationFile(FileHandle
,
1580 sizeof(FILE_BASIC_INFORMATION
),
1581 FileBasicInformation
);
1582 if (!NT_SUCCESS(Status
))
1584 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status
);
1587 NtClose(FileHandle
);
1593 UpdateBootIni(PWSTR BootIniPath
,
1597 UNICODE_STRING Name
;
1598 PINICACHE Cache
= NULL
;
1599 PINICACHESECTION Section
= NULL
;
1601 ULONG FileAttribute
;
1603 RtlInitUnicodeString(&Name
,
1606 Status
= IniCacheLoad(&Cache
,
1609 if (!NT_SUCCESS(Status
))
1615 Section
= IniCacheGetSection(Cache
,
1616 L
"operating systems");
1617 if (Section
== NULL
)
1620 IniCacheDestroy(Cache
);
1621 return(STATUS_UNSUCCESSFUL
);
1624 IniCacheInsertKey(Section
,
1630 Status
= UnprotectBootIni(BootIniPath
,
1632 if (!NT_SUCCESS(Status
))
1635 IniCacheDestroy(Cache
);
1639 Status
= IniCacheSave(Cache
,
1641 if (!NT_SUCCESS(Status
))
1644 IniCacheDestroy(Cache
);
1648 FileAttribute
|= (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_READONLY
);
1649 Status
= ProtectBootIni(BootIniPath
,
1652 IniCacheDestroy(Cache
);