1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Setup Library 4 * FILE: base/setup/lib/bootsup.c 5 * PURPOSE: Bootloader support functions 6 * PROGRAMMERS: ... 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "precomp.h" 13 14 #include "bldrsup.h" 15 #include "filesup.h" 16 #include "fsutil.h" 17 #include "partlist.h" 18 19 #include "setuplib.h" // HAXX for IsUnattendedSetup!! 20 21 #include "bootsup.h" 22 23 #define NDEBUG 24 #include <debug.h> 25 26 27 /* TYPEDEFS *****************************************************************/ 28 29 /* 30 * BIG FIXME!! 31 * =========== 32 * 33 * All that stuff *MUST* go into the fsutil.c module. 34 * Indeed, all that relates to filesystem formatting details and as such 35 * *MUST* be abstracted out from this module (bootsup.c). 36 * However, bootsup.c can still deal with MBR code (actually it'll have 37 * at some point to share or give it to partlist.c, because when we'll 38 * support GPT disks, things will change a bit). 39 * And, bootsup.c can still manage initializing / adding boot entries 40 * into NTLDR and FREELDR, and installing the latter, and saving the old 41 * MBR / boot sectors in files. 42 */ 43 #define SECTORSIZE 512 44 45 #include <pshpack1.h> 46 typedef struct _FAT_BOOTSECTOR 47 { 48 UCHAR JumpBoot[3]; // Jump instruction to boot code 49 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes 50 USHORT BytesPerSector; // Bytes per sector 51 UCHAR SectorsPerCluster; // Number of sectors in a cluster 52 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) 53 UCHAR NumberOfFats; // Number of FAT tables 54 USHORT RootDirEntries; // Number of root directory entries (fat12/16) 55 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit 56 UCHAR MediaDescriptor; // Media descriptor byte 57 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) 58 USHORT SectorsPerTrack; // Number of sectors in a track 59 USHORT NumberOfHeads; // Number of heads on the disk 60 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) 61 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume 62 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) 63 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. 64 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. 65 ULONG VolumeSerialNumber; // Volume serial number 66 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory 67 CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " 68 69 UCHAR BootCodeAndData[448]; // The remainder of the boot sector 70 71 USHORT BootSectorMagic; // 0xAA55 72 73 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR; 74 75 typedef struct _FAT32_BOOTSECTOR 76 { 77 UCHAR JumpBoot[3]; // Jump instruction to boot code 78 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes 79 USHORT BytesPerSector; // Bytes per sector 80 UCHAR SectorsPerCluster; // Number of sectors in a cluster 81 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) 82 UCHAR NumberOfFats; // Number of FAT tables 83 USHORT RootDirEntries; // Number of root directory entries (fat12/16) 84 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit 85 UCHAR MediaDescriptor; // Media descriptor byte 86 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) 87 USHORT SectorsPerTrack; // Number of sectors in a track 88 USHORT NumberOfHeads; // Number of heads on the disk 89 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) 90 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume 91 ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 92 USHORT ExtendedFlags; // Extended flags (fat32) 93 USHORT FileSystemVersion; // File system version (fat32) 94 ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) 95 USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. 96 USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. 97 UCHAR Reserved[12]; // Reserved for future expansion 98 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) 99 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. 100 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. 101 ULONG VolumeSerialNumber; // Volume serial number 102 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory 103 CHAR FileSystemType[8]; // Always set to the string "FAT32 " 104 105 UCHAR BootCodeAndData[420]; // The remainder of the boot sector 106 107 USHORT BootSectorMagic; // 0xAA55 108 109 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR; 110 111 typedef struct _BTRFS_BOOTSECTOR 112 { 113 UCHAR JumpBoot[3]; 114 UCHAR ChunkMapSize; 115 UCHAR BootDrive; 116 ULONGLONG PartitionStartLBA; 117 UCHAR Fill[1521]; // 1536 - 15 118 USHORT BootSectorMagic; 119 } BTRFS_BOOTSECTOR, *PBTRFS_BOOTSECTOR; 120 C_ASSERT(sizeof(BTRFS_BOOTSECTOR) == 3 * 512); 121 122 // TODO: Add more bootsector structures! 123 124 #include <poppack.h> 125 126 /* End of BIG FIXME!! */ 127 128 129 /* FUNCTIONS ****************************************************************/ 130 131 static VOID 132 TrimTrailingPathSeparators_UStr( 133 IN OUT PUNICODE_STRING UnicodeString) 134 { 135 while (UnicodeString->Length >= sizeof(WCHAR) && 136 UnicodeString->Buffer[UnicodeString->Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR) 137 { 138 UnicodeString->Length -= sizeof(WCHAR); 139 } 140 } 141 142 143 static VOID 144 CreateFreeLoaderReactOSEntries( 145 IN PVOID BootStoreHandle, 146 IN PCWSTR ArcPath) 147 { 148 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 149 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 150 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 151 BOOT_STORE_OPTIONS BootOptions; 152 153 BootEntry->Version = FreeLdr; 154 BootEntry->BootFilePath = NULL; 155 156 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 157 RtlCopyMemory(Options->Signature, 158 NTOS_OPTIONS_SIGNATURE, 159 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 160 161 Options->OsLoadPath = ArcPath; 162 163 /* ReactOS */ 164 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS"); 165 BootEntry->FriendlyName = L"\"ReactOS\""; 166 Options->OsLoadOptions = NULL; // L""; 167 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS")); 168 169 /* ReactOS_Debug */ 170 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Debug"); 171 BootEntry->FriendlyName = L"\"ReactOS (Debug)\""; 172 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"; 173 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Debug")); 174 175 #ifdef _WINKD_ 176 /* ReactOS_VBoxDebug */ 177 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_VBoxDebug"); 178 BootEntry->FriendlyName = L"\"ReactOS (VBoxDebug)\""; 179 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=VBOX /SOS"; 180 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_VBoxDebug")); 181 #endif 182 #if DBG 183 #ifndef _WINKD_ 184 /* ReactOS_KdSerial */ 185 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial"); 186 BootEntry->FriendlyName = L"\"ReactOS (RosDbg)\""; 187 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL"; 188 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_KdSerial")); 189 #endif 190 191 /* ReactOS_Screen */ 192 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Screen"); 193 BootEntry->FriendlyName = L"\"ReactOS (Screen)\""; 194 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=SCREEN /SOS"; 195 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Screen")); 196 197 /* ReactOS_LogFile */ 198 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_LogFile"); 199 BootEntry->FriendlyName = L"\"ReactOS (Log file)\""; 200 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=FILE /SOS"; 201 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_LogFile")); 202 203 /* ReactOS_Ram */ 204 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_Ram"); 205 BootEntry->FriendlyName = L"\"ReactOS (RAM Disk)\""; 206 Options->OsLoadPath = L"ramdisk(0)\\ReactOS"; 207 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256"; 208 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_Ram")); 209 210 /* ReactOS_EMS */ 211 // BootEntry->BootEntryKey = MAKESTRKEY(L"ReactOS_EMS"); 212 BootEntry->FriendlyName = L"\"ReactOS (Emergency Management Services)\""; 213 Options->OsLoadPath = ArcPath; 214 Options->OsLoadOptions = L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200"; 215 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(L"ReactOS_EMS")); 216 #endif 217 218 219 #if DBG 220 if (IsUnattendedSetup) 221 { 222 /* DefaultOS=ReactOS */ 223 #ifndef _WINKD_ 224 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_KdSerial"); 225 #else 226 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS_Debug"); 227 #endif 228 } 229 else 230 #endif 231 { 232 /* DefaultOS=ReactOS */ 233 BootOptions.CurrentBootEntryKey = MAKESTRKEY(L"ReactOS"); 234 } 235 236 #if DBG 237 if (IsUnattendedSetup) 238 #endif 239 { 240 /* Timeout=0 for unattended or non debug */ 241 BootOptions.Timeout = 0; 242 } 243 #if DBG 244 else 245 { 246 /* Timeout=10 */ 247 BootOptions.Timeout = 10; 248 } 249 #endif 250 251 BootOptions.Version = FreeLdr; 252 SetBootStoreOptions(BootStoreHandle, &BootOptions, 2 | 1); 253 } 254 255 static NTSTATUS 256 CreateFreeLoaderIniForReactOS( 257 IN PCWSTR IniPath, 258 IN PCWSTR ArcPath) 259 { 260 NTSTATUS Status; 261 PVOID BootStoreHandle; 262 263 /* Initialize the INI file and create the common FreeLdr sections */ 264 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE); 265 if (!NT_SUCCESS(Status)) 266 return Status; 267 268 /* Add the ReactOS entries */ 269 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath); 270 271 /* Close the INI file */ 272 CloseBootStore(BootStoreHandle); 273 return STATUS_SUCCESS; 274 } 275 276 static NTSTATUS 277 CreateFreeLoaderIniForReactOSAndBootSector( 278 IN PCWSTR IniPath, 279 IN PCWSTR ArcPath, 280 IN PCWSTR Section, 281 IN PCWSTR Description, 282 IN PCWSTR BootDrive, 283 IN PCWSTR BootPartition, 284 IN PCWSTR BootSector) 285 { 286 NTSTATUS Status; 287 PVOID BootStoreHandle; 288 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)]; 289 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 290 PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions; 291 292 /* Initialize the INI file and create the common FreeLdr sections */ 293 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, TRUE); 294 if (!NT_SUCCESS(Status)) 295 return Status; 296 297 /* Add the ReactOS entries */ 298 CreateFreeLoaderReactOSEntries(BootStoreHandle, ArcPath); 299 300 BootEntry->Version = FreeLdr; 301 BootEntry->BootFilePath = NULL; 302 303 BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS); 304 RtlCopyMemory(Options->Signature, 305 BOOT_SECTOR_OPTIONS_SIGNATURE, 306 RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature)); 307 308 Options->Drive = BootDrive; 309 Options->Partition = BootPartition; 310 Options->BootSectorFileName = BootSector; 311 312 // BootEntry->BootEntryKey = MAKESTRKEY(Section); 313 BootEntry->FriendlyName = Description; 314 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Section)); 315 316 /* Close the INI file */ 317 CloseBootStore(BootStoreHandle); 318 return STATUS_SUCCESS; 319 } 320 321 // 322 // I think this function can be generalizable as: 323 // "find the corresponding 'ReactOS' boot entry in this loader config file 324 // (here abstraction comes there), and if none, add a new one". 325 // 326 327 typedef struct _ENUM_REACTOS_ENTRIES_DATA 328 { 329 ULONG i; 330 BOOLEAN UseExistingEntry; 331 PCWSTR ArcPath; 332 WCHAR SectionName[80]; 333 WCHAR OsName[80]; 334 } ENUM_REACTOS_ENTRIES_DATA, *PENUM_REACTOS_ENTRIES_DATA; 335 336 // PENUM_BOOT_ENTRIES_ROUTINE 337 static NTSTATUS 338 NTAPI 339 EnumerateReactOSEntries( 340 IN BOOT_STORE_TYPE Type, 341 IN PBOOT_STORE_ENTRY BootEntry, 342 IN PVOID Parameter OPTIONAL) 343 { 344 NTSTATUS Status; 345 PENUM_REACTOS_ENTRIES_DATA Data = (PENUM_REACTOS_ENTRIES_DATA)Parameter; 346 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 347 WCHAR SystemPath[MAX_PATH]; 348 349 /* We have a boot entry */ 350 351 /* Check for supported boot type "Windows2003" */ 352 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) || 353 RtlCompareMemory(&BootEntry->OsOptions /* Signature */, 354 NTOS_OPTIONS_SIGNATURE, 355 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) != 356 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)) 357 { 358 /* This is not a ReactOS entry */ 359 // DPRINT(" An installation '%S' of unsupported type '%S'\n", 360 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a"); 361 DPRINT(" An installation '%S' of unsupported type %lu\n", 362 BootEntry->FriendlyName, BootEntry->OsOptionsLength); 363 /* Continue the enumeration */ 364 goto SkipThisEntry; 365 } 366 367 /* BootType is Windows2003, now check OsLoadPath */ 368 if (!Options->OsLoadPath || !*Options->OsLoadPath) 369 { 370 /* Certainly not a ReactOS installation */ 371 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName); 372 /* Continue the enumeration */ 373 goto SkipThisEntry; 374 } 375 376 if (_wcsicmp(Options->OsLoadPath, Data->ArcPath) != 0) 377 { 378 /* Not found, retry with a quoted path */ 379 Status = RtlStringCchPrintfW(SystemPath, ARRAYSIZE(SystemPath), L"\"%s\"", Data->ArcPath); 380 if (!NT_SUCCESS(Status) || _wcsicmp(Options->OsLoadPath, SystemPath) != 0) 381 { 382 /* 383 * This entry is a ReactOS entry, but the SystemRoot 384 * does not match the one we are looking for. 385 */ 386 /* Continue the enumeration */ 387 goto SkipThisEntry; 388 } 389 } 390 391 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n", 392 BootEntry->FriendlyName, Options->OsLoadPath); 393 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n", 394 // BootEntry->FriendlyName, Options->OsLoadPath); 395 396 DPRINT("EnumerateReactOSEntries: OsLoadPath: '%S'\n", Options->OsLoadPath); 397 398 Data->UseExistingEntry = TRUE; 399 RtlStringCchCopyW(Data->OsName, ARRAYSIZE(Data->OsName), BootEntry->FriendlyName); 400 401 /* We have found our entry, stop the enumeration now! */ 402 return STATUS_NO_MORE_ENTRIES; 403 404 SkipThisEntry: 405 Data->UseExistingEntry = FALSE; 406 if (Type == FreeLdr && wcscmp(Data->SectionName, (PWSTR)BootEntry->BootEntryKey)== 0) 407 { 408 RtlStringCchPrintfW(Data->SectionName, ARRAYSIZE(Data->SectionName), 409 L"ReactOS_%lu", Data->i); 410 RtlStringCchPrintfW(Data->OsName, ARRAYSIZE(Data->OsName), 411 L"\"ReactOS %lu\"", Data->i); 412 Data->i++; 413 } 414 return STATUS_SUCCESS; 415 } 416 417 static 418 NTSTATUS 419 UpdateFreeLoaderIni( 420 IN PCWSTR IniPath, 421 IN PCWSTR ArcPath) 422 { 423 NTSTATUS Status; 424 PVOID BootStoreHandle; 425 ENUM_REACTOS_ENTRIES_DATA Data; 426 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 427 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 428 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 429 430 /* Open the INI file */ 431 Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr, /*TRUE*/ FALSE); 432 if (!NT_SUCCESS(Status)) 433 return Status; 434 435 /* Find an existing usable or an unused section name */ 436 Data.UseExistingEntry = TRUE; 437 Data.i = 1; 438 Data.ArcPath = ArcPath; 439 RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS"); 440 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\""); 441 442 // 443 // FIXME: We temporarily use EnumerateBootStoreEntries, until 444 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented. 445 // 446 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data); 447 448 /* Create a new "ReactOS" entry if there is none already existing that suits us */ 449 if (!Data.UseExistingEntry) 450 { 451 // RtlStringCchPrintfW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS_%lu", Data.i); 452 // RtlStringCchPrintfW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS %lu\"", Data.i); 453 454 BootEntry->Version = FreeLdr; 455 BootEntry->BootFilePath = NULL; 456 457 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 458 RtlCopyMemory(Options->Signature, 459 NTOS_OPTIONS_SIGNATURE, 460 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 461 462 Options->OsLoadPath = ArcPath; 463 464 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName); 465 BootEntry->FriendlyName = Data.OsName; 466 Options->OsLoadOptions = NULL; // L""; 467 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(Data.SectionName)); 468 } 469 470 /* Close the INI file */ 471 CloseBootStore(BootStoreHandle); 472 return STATUS_SUCCESS; 473 } 474 475 static 476 NTSTATUS 477 UpdateBootIni( 478 IN PCWSTR IniPath, 479 IN PCWSTR EntryName, // ~= ArcPath 480 IN PCWSTR EntryValue) 481 { 482 NTSTATUS Status; 483 PVOID BootStoreHandle; 484 ENUM_REACTOS_ENTRIES_DATA Data; 485 486 // NOTE: Technically it would be "BootSector"... 487 UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(NTOS_OPTIONS)]; 488 PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry; 489 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions; 490 491 /* Open the INI file */ 492 Status = OpenBootStore(&BootStoreHandle, IniPath, NtLdr, FALSE); 493 if (!NT_SUCCESS(Status)) 494 return Status; 495 496 /* Find an existing usable or an unused section name */ 497 Data.UseExistingEntry = TRUE; 498 // Data.i = 1; 499 Data.ArcPath = EntryName; 500 // RtlStringCchCopyW(Data.SectionName, ARRAYSIZE(Data.SectionName), L"ReactOS"); 501 RtlStringCchCopyW(Data.OsName, ARRAYSIZE(Data.OsName), L"\"ReactOS\""); 502 503 // 504 // FIXME: We temporarily use EnumerateBootStoreEntries, until 505 // both QueryBootStoreEntry and ModifyBootStoreEntry get implemented. 506 // 507 Status = EnumerateBootStoreEntries(BootStoreHandle, EnumerateReactOSEntries, &Data); 508 509 /* If either the key was not found, or contains something else, add a new one */ 510 if (!Data.UseExistingEntry /* || 511 ( (Status == STATUS_NO_MORE_ENTRIES) && wcscmp(Data.OsName, EntryValue) ) */) 512 { 513 BootEntry->Version = NtLdr; 514 BootEntry->BootFilePath = NULL; 515 516 BootEntry->OsOptionsLength = sizeof(NTOS_OPTIONS); 517 RtlCopyMemory(Options->Signature, 518 NTOS_OPTIONS_SIGNATURE, 519 RTL_FIELD_SIZE(NTOS_OPTIONS, Signature)); 520 521 Options->OsLoadPath = EntryName; 522 523 // BootEntry->BootEntryKey = MAKESTRKEY(Data.SectionName); 524 // BootEntry->FriendlyName = Data.OsName; 525 BootEntry->FriendlyName = EntryValue; 526 Options->OsLoadOptions = NULL; // L""; 527 AddBootStoreEntry(BootStoreHandle, BootEntry, MAKESTRKEY(0 /*Data.SectionName*/)); 528 } 529 530 /* Close the INI file */ 531 CloseBootStore(BootStoreHandle); 532 return STATUS_SUCCESS; // Status; 533 } 534 535 536 static 537 BOOLEAN 538 IsThereAValidBootSector( 539 IN PCWSTR RootPath) 540 { 541 /* 542 * We first demand that the bootsector has a valid signature at its end. 543 * We then check the first 3 bytes (as a ULONG) of the bootsector for a 544 * potential "valid" instruction (the BIOS starts execution of the bootsector 545 * at its beginning). Currently this criterium is that this ULONG must be 546 * non-zero. If both these tests pass, then the bootsector is valid; otherwise 547 * it is invalid and certainly needs to be overwritten. 548 */ 549 550 BOOLEAN IsValid = FALSE; 551 NTSTATUS Status; 552 UNICODE_STRING RootPartition; 553 OBJECT_ATTRIBUTES ObjectAttributes; 554 IO_STATUS_BLOCK IoStatusBlock; 555 HANDLE FileHandle; 556 LARGE_INTEGER FileOffset; 557 PUCHAR BootSector; 558 559 /* Allocate buffer for bootsector */ 560 BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 561 if (BootSector == NULL) 562 return FALSE; // STATUS_INSUFFICIENT_RESOURCES; 563 RtlZeroMemory(BootSector, SECTORSIZE); 564 565 /* Open the root partition - Remove any trailing backslash if needed */ 566 RtlInitUnicodeString(&RootPartition, RootPath); 567 TrimTrailingPathSeparators_UStr(&RootPartition); 568 569 InitializeObjectAttributes(&ObjectAttributes, 570 &RootPartition, 571 OBJ_CASE_INSENSITIVE, 572 NULL, 573 NULL); 574 575 Status = NtOpenFile(&FileHandle, 576 GENERIC_READ | SYNCHRONIZE, 577 &ObjectAttributes, 578 &IoStatusBlock, 579 FILE_SHARE_READ | FILE_SHARE_WRITE, 580 FILE_SYNCHRONOUS_IO_NONALERT); 581 if (!NT_SUCCESS(Status)) 582 goto Quit; 583 584 /* Read current boot sector into buffer */ 585 FileOffset.QuadPart = 0ULL; 586 Status = NtReadFile(FileHandle, 587 NULL, 588 NULL, 589 NULL, 590 &IoStatusBlock, 591 BootSector, 592 SECTORSIZE, 593 &FileOffset, 594 NULL); 595 NtClose(FileHandle); 596 if (!NT_SUCCESS(Status)) 597 goto Quit; 598 599 /* Check for the existence of the bootsector signature */ 600 IsValid = (*(PUSHORT)(BootSector + 0x1FE) == 0xAA55); 601 if (IsValid) 602 { 603 /* Check for the first instruction encoded on three bytes */ 604 IsValid = (((*(PULONG)BootSector) & 0x00FFFFFF) != 0x00000000); 605 } 606 607 Quit: 608 /* Free the boot sector */ 609 RtlFreeHeap(ProcessHeap, 0, BootSector); 610 return IsValid; 611 } 612 613 static 614 NTSTATUS 615 SaveBootSector( 616 IN PCWSTR RootPath, 617 IN PCWSTR DstPath, 618 IN ULONG Length) 619 { 620 NTSTATUS Status; 621 UNICODE_STRING Name; 622 OBJECT_ATTRIBUTES ObjectAttributes; 623 IO_STATUS_BLOCK IoStatusBlock; 624 HANDLE FileHandle; 625 LARGE_INTEGER FileOffset; 626 PUCHAR BootSector; 627 628 /* Allocate buffer for bootsector */ 629 BootSector = RtlAllocateHeap(ProcessHeap, 0, Length); 630 if (BootSector == NULL) 631 return STATUS_INSUFFICIENT_RESOURCES; 632 633 /* Open the root partition - Remove any trailing backslash if needed */ 634 RtlInitUnicodeString(&Name, RootPath); 635 TrimTrailingPathSeparators_UStr(&Name); 636 637 InitializeObjectAttributes(&ObjectAttributes, 638 &Name, 639 OBJ_CASE_INSENSITIVE, 640 NULL, 641 NULL); 642 643 Status = NtOpenFile(&FileHandle, 644 GENERIC_READ | SYNCHRONIZE, 645 &ObjectAttributes, 646 &IoStatusBlock, 647 FILE_SHARE_READ | FILE_SHARE_WRITE, 648 FILE_SYNCHRONOUS_IO_NONALERT); 649 if (!NT_SUCCESS(Status)) 650 { 651 RtlFreeHeap(ProcessHeap, 0, BootSector); 652 return Status; 653 } 654 655 /* Read current boot sector into buffer */ 656 FileOffset.QuadPart = 0ULL; 657 Status = NtReadFile(FileHandle, 658 NULL, 659 NULL, 660 NULL, 661 &IoStatusBlock, 662 BootSector, 663 Length, 664 &FileOffset, 665 NULL); 666 NtClose(FileHandle); 667 if (!NT_SUCCESS(Status)) 668 { 669 RtlFreeHeap(ProcessHeap, 0, BootSector); 670 return Status; 671 } 672 673 /* Write bootsector to DstPath */ 674 RtlInitUnicodeString(&Name, DstPath); 675 InitializeObjectAttributes(&ObjectAttributes, 676 &Name, 677 OBJ_CASE_INSENSITIVE, 678 NULL, 679 NULL); 680 681 Status = NtCreateFile(&FileHandle, 682 GENERIC_WRITE | SYNCHRONIZE, 683 &ObjectAttributes, 684 &IoStatusBlock, 685 NULL, 686 FILE_ATTRIBUTE_NORMAL, 687 0, 688 FILE_SUPERSEDE, 689 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 690 NULL, 691 0); 692 if (!NT_SUCCESS(Status)) 693 { 694 RtlFreeHeap(ProcessHeap, 0, BootSector); 695 return Status; 696 } 697 698 Status = NtWriteFile(FileHandle, 699 NULL, 700 NULL, 701 NULL, 702 &IoStatusBlock, 703 BootSector, 704 Length, 705 NULL, 706 NULL); 707 NtClose(FileHandle); 708 709 /* Free the boot sector */ 710 RtlFreeHeap(ProcessHeap, 0, BootSector); 711 712 return Status; 713 } 714 715 716 static 717 NTSTATUS 718 InstallMbrBootCodeToDiskHelper( 719 IN PCWSTR SrcPath, 720 IN PCWSTR RootPath) 721 { 722 NTSTATUS Status; 723 UNICODE_STRING Name; 724 OBJECT_ATTRIBUTES ObjectAttributes; 725 IO_STATUS_BLOCK IoStatusBlock; 726 HANDLE FileHandle; 727 LARGE_INTEGER FileOffset; 728 PPARTITION_SECTOR OrigBootSector; 729 PPARTITION_SECTOR NewBootSector; 730 731 /* Allocate buffer for original bootsector */ 732 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR)); 733 if (OrigBootSector == NULL) 734 return STATUS_INSUFFICIENT_RESOURCES; 735 736 /* Open the root partition - Remove any trailing backslash if needed */ 737 RtlInitUnicodeString(&Name, RootPath); 738 TrimTrailingPathSeparators_UStr(&Name); 739 740 InitializeObjectAttributes(&ObjectAttributes, 741 &Name, 742 OBJ_CASE_INSENSITIVE, 743 NULL, 744 NULL); 745 746 Status = NtOpenFile(&FileHandle, 747 GENERIC_READ | SYNCHRONIZE, 748 &ObjectAttributes, 749 &IoStatusBlock, 750 FILE_SHARE_READ | FILE_SHARE_WRITE, 751 FILE_SYNCHRONOUS_IO_NONALERT); 752 if (!NT_SUCCESS(Status)) 753 { 754 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 755 return Status; 756 } 757 758 /* Read current boot sector into buffer */ 759 FileOffset.QuadPart = 0ULL; 760 Status = NtReadFile(FileHandle, 761 NULL, 762 NULL, 763 NULL, 764 &IoStatusBlock, 765 OrigBootSector, 766 sizeof(PARTITION_SECTOR), 767 &FileOffset, 768 NULL); 769 NtClose(FileHandle); 770 if (!NT_SUCCESS(Status)) 771 { 772 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 773 return Status; 774 } 775 776 /* Allocate buffer for new bootsector */ 777 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR)); 778 if (NewBootSector == NULL) 779 { 780 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 781 return STATUS_INSUFFICIENT_RESOURCES; 782 } 783 784 /* Read new bootsector from SrcPath */ 785 RtlInitUnicodeString(&Name, SrcPath); 786 InitializeObjectAttributes(&ObjectAttributes, 787 &Name, 788 OBJ_CASE_INSENSITIVE, 789 NULL, 790 NULL); 791 792 Status = NtOpenFile(&FileHandle, 793 GENERIC_READ | SYNCHRONIZE, 794 &ObjectAttributes, 795 &IoStatusBlock, 796 FILE_SHARE_READ, 797 FILE_SYNCHRONOUS_IO_NONALERT); 798 if (!NT_SUCCESS(Status)) 799 { 800 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 801 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 802 return Status; 803 } 804 805 Status = NtReadFile(FileHandle, 806 NULL, 807 NULL, 808 NULL, 809 &IoStatusBlock, 810 NewBootSector, 811 sizeof(PARTITION_SECTOR), 812 NULL, 813 NULL); 814 NtClose(FileHandle); 815 if (!NT_SUCCESS(Status)) 816 { 817 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 818 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 819 return Status; 820 } 821 822 /* 823 * Copy the disk signature, the reserved fields and 824 * the partition table from the old MBR to the new one. 825 */ 826 RtlCopyMemory(&NewBootSector->Signature, 827 &OrigBootSector->Signature, 828 sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) 829 /* Length of partition table */); 830 831 /* Free the original boot sector */ 832 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 833 834 /* Open the root partition - Remove any trailing backslash if needed */ 835 RtlInitUnicodeString(&Name, RootPath); 836 TrimTrailingPathSeparators_UStr(&Name); 837 838 InitializeObjectAttributes(&ObjectAttributes, 839 &Name, 840 OBJ_CASE_INSENSITIVE, 841 NULL, 842 NULL); 843 844 Status = NtOpenFile(&FileHandle, 845 GENERIC_WRITE | SYNCHRONIZE, 846 &ObjectAttributes, 847 &IoStatusBlock, 848 FILE_SHARE_READ | FILE_SHARE_WRITE, 849 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); 850 if (!NT_SUCCESS(Status)) 851 { 852 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); 853 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 854 return Status; 855 } 856 857 /* Write new bootsector to RootPath */ 858 FileOffset.QuadPart = 0ULL; 859 Status = NtWriteFile(FileHandle, 860 NULL, 861 NULL, 862 NULL, 863 &IoStatusBlock, 864 NewBootSector, 865 sizeof(PARTITION_SECTOR), 866 &FileOffset, 867 NULL); 868 NtClose(FileHandle); 869 870 /* Free the new boot sector */ 871 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 872 873 return Status; 874 } 875 876 NTSTATUS 877 InstallMbrBootCodeToDisk( 878 IN PUNICODE_STRING SystemRootPath, 879 IN PUNICODE_STRING SourceRootPath, 880 IN PCWSTR DestinationDevicePathBuffer) 881 { 882 NTSTATUS Status; 883 WCHAR SourceMbrPathBuffer[MAX_PATH]; 884 WCHAR DstPath[MAX_PATH]; 885 886 #if 0 887 /* 888 * The DestinationDevicePathBuffer parameter has been built with 889 * the following instruction by the caller; I'm not yet sure whether 890 * I actually want this function to build the path instead, hence 891 * I keep this code here but disabled for now... 892 */ 893 WCHAR DestinationDevicePathBuffer[MAX_PATH]; 894 RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer), 895 L"\\Device\\Harddisk%d\\Partition0", 896 DiskNumber); 897 #endif 898 899 CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, 900 SourceRootPath->Buffer, L"\\loader\\dosmbr.bin"); 901 902 if (IsThereAValidBootSector(DestinationDevicePathBuffer)) 903 { 904 /* Save current MBR */ 905 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, 906 SystemRootPath->Buffer, L"mbr.old"); 907 908 DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath); 909 Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR)); 910 if (!NT_SUCCESS(Status)) 911 { 912 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 913 // Don't care if we succeeded or not saving the old MBR, just go ahead. 914 } 915 } 916 917 DPRINT1("Install MBR bootcode: %S ==> %S\n", 918 SourceMbrPathBuffer, DestinationDevicePathBuffer); 919 920 return InstallMbrBootCodeToDiskHelper(SourceMbrPathBuffer, 921 DestinationDevicePathBuffer); 922 } 923 924 925 static 926 NTSTATUS 927 InstallFat12BootCodeToFloppy( 928 IN PCWSTR SrcPath, 929 IN PCWSTR RootPath) 930 { 931 NTSTATUS Status; 932 UNICODE_STRING Name; 933 OBJECT_ATTRIBUTES ObjectAttributes; 934 IO_STATUS_BLOCK IoStatusBlock; 935 HANDLE FileHandle; 936 LARGE_INTEGER FileOffset; 937 PFAT_BOOTSECTOR OrigBootSector; 938 PFAT_BOOTSECTOR NewBootSector; 939 940 /* Allocate buffer for original bootsector */ 941 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 942 if (OrigBootSector == NULL) 943 return STATUS_INSUFFICIENT_RESOURCES; 944 945 /* Open the root partition - Remove any trailing backslash if needed */ 946 RtlInitUnicodeString(&Name, RootPath); 947 TrimTrailingPathSeparators_UStr(&Name); 948 949 InitializeObjectAttributes(&ObjectAttributes, 950 &Name, 951 OBJ_CASE_INSENSITIVE, 952 NULL, 953 NULL); 954 955 Status = NtOpenFile(&FileHandle, 956 GENERIC_READ | SYNCHRONIZE, 957 &ObjectAttributes, 958 &IoStatusBlock, 959 FILE_SHARE_READ | FILE_SHARE_WRITE, 960 FILE_SYNCHRONOUS_IO_NONALERT); 961 if (!NT_SUCCESS(Status)) 962 { 963 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 964 return Status; 965 } 966 967 /* Read current boot sector into buffer */ 968 FileOffset.QuadPart = 0ULL; 969 Status = NtReadFile(FileHandle, 970 NULL, 971 NULL, 972 NULL, 973 &IoStatusBlock, 974 OrigBootSector, 975 SECTORSIZE, 976 &FileOffset, 977 NULL); 978 NtClose(FileHandle); 979 if (!NT_SUCCESS(Status)) 980 { 981 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 982 return Status; 983 } 984 985 /* Allocate buffer for new bootsector */ 986 NewBootSector = RtlAllocateHeap(ProcessHeap, 987 0, 988 SECTORSIZE); 989 if (NewBootSector == NULL) 990 { 991 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 992 return STATUS_INSUFFICIENT_RESOURCES; 993 } 994 995 /* Read new bootsector from SrcPath */ 996 RtlInitUnicodeString(&Name, SrcPath); 997 998 InitializeObjectAttributes(&ObjectAttributes, 999 &Name, 1000 OBJ_CASE_INSENSITIVE, 1001 NULL, 1002 NULL); 1003 1004 Status = NtOpenFile(&FileHandle, 1005 GENERIC_READ | SYNCHRONIZE, 1006 &ObjectAttributes, 1007 &IoStatusBlock, 1008 FILE_SHARE_READ, 1009 FILE_SYNCHRONOUS_IO_NONALERT); 1010 if (!NT_SUCCESS(Status)) 1011 { 1012 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1013 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1014 return Status; 1015 } 1016 1017 Status = NtReadFile(FileHandle, 1018 NULL, 1019 NULL, 1020 NULL, 1021 &IoStatusBlock, 1022 NewBootSector, 1023 SECTORSIZE, 1024 NULL, 1025 NULL); 1026 NtClose(FileHandle); 1027 if (!NT_SUCCESS(Status)) 1028 { 1029 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1030 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1031 return Status; 1032 } 1033 1034 /* Adjust bootsector (copy a part of the FAT16 BPB) */ 1035 memcpy(&NewBootSector->OemName, 1036 &OrigBootSector->OemName, 1037 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - 1038 FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); 1039 1040 /* Free the original boot sector */ 1041 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1042 1043 /* Open the root partition - Remove any trailing backslash if needed */ 1044 RtlInitUnicodeString(&Name, RootPath); 1045 TrimTrailingPathSeparators_UStr(&Name); 1046 1047 InitializeObjectAttributes(&ObjectAttributes, 1048 &Name, 1049 OBJ_CASE_INSENSITIVE, 1050 NULL, 1051 NULL); 1052 1053 Status = NtOpenFile(&FileHandle, 1054 GENERIC_WRITE | SYNCHRONIZE, 1055 &ObjectAttributes, 1056 &IoStatusBlock, 1057 FILE_SHARE_READ | FILE_SHARE_WRITE, 1058 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); 1059 if (!NT_SUCCESS(Status)) 1060 { 1061 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); 1062 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1063 return Status; 1064 } 1065 1066 /* Write new bootsector to RootPath */ 1067 FileOffset.QuadPart = 0ULL; 1068 Status = NtWriteFile(FileHandle, 1069 NULL, 1070 NULL, 1071 NULL, 1072 &IoStatusBlock, 1073 NewBootSector, 1074 SECTORSIZE, 1075 &FileOffset, 1076 NULL); 1077 NtClose(FileHandle); 1078 1079 /* Free the new boot sector */ 1080 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1081 1082 return Status; 1083 } 1084 1085 static 1086 NTSTATUS 1087 InstallFat16BootCode( 1088 IN PCWSTR SrcPath, // FAT16 bootsector source file (on the installation medium) 1089 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information 1090 IN HANDLE RootPartition) // Partition holding the (old) FAT16 information 1091 { 1092 NTSTATUS Status; 1093 UNICODE_STRING Name; 1094 OBJECT_ATTRIBUTES ObjectAttributes; 1095 IO_STATUS_BLOCK IoStatusBlock; 1096 HANDLE FileHandle; 1097 LARGE_INTEGER FileOffset; 1098 PFAT_BOOTSECTOR OrigBootSector; 1099 PFAT_BOOTSECTOR NewBootSector; 1100 1101 /* Allocate a buffer for the original bootsector */ 1102 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 1103 if (OrigBootSector == NULL) 1104 return STATUS_INSUFFICIENT_RESOURCES; 1105 1106 /* Read the current partition boot sector into the buffer */ 1107 FileOffset.QuadPart = 0ULL; 1108 Status = NtReadFile(RootPartition, 1109 NULL, 1110 NULL, 1111 NULL, 1112 &IoStatusBlock, 1113 OrigBootSector, 1114 SECTORSIZE, 1115 &FileOffset, 1116 NULL); 1117 if (!NT_SUCCESS(Status)) 1118 { 1119 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1120 return Status; 1121 } 1122 1123 /* Allocate a buffer for the new bootsector */ 1124 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 1125 if (NewBootSector == NULL) 1126 { 1127 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1128 return STATUS_INSUFFICIENT_RESOURCES; 1129 } 1130 1131 /* Read the new bootsector from SrcPath */ 1132 RtlInitUnicodeString(&Name, SrcPath); 1133 InitializeObjectAttributes(&ObjectAttributes, 1134 &Name, 1135 OBJ_CASE_INSENSITIVE, 1136 NULL, 1137 NULL); 1138 1139 Status = NtOpenFile(&FileHandle, 1140 GENERIC_READ | SYNCHRONIZE, 1141 &ObjectAttributes, 1142 &IoStatusBlock, 1143 FILE_SHARE_READ, 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 FileOffset.QuadPart = 0ULL; 1153 Status = NtReadFile(FileHandle, 1154 NULL, 1155 NULL, 1156 NULL, 1157 &IoStatusBlock, 1158 NewBootSector, 1159 SECTORSIZE, 1160 &FileOffset, 1161 NULL); 1162 NtClose(FileHandle); 1163 if (!NT_SUCCESS(Status)) 1164 { 1165 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1166 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1167 return Status; 1168 } 1169 1170 /* Adjust the bootsector (copy a part of the FAT16 BPB) */ 1171 memcpy(&NewBootSector->OemName, 1172 &OrigBootSector->OemName, 1173 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - 1174 FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); 1175 1176 /* Free the original boot sector */ 1177 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1178 1179 /* Write the new bootsector to DstPath */ 1180 FileOffset.QuadPart = 0ULL; 1181 Status = NtWriteFile(DstPath, 1182 NULL, 1183 NULL, 1184 NULL, 1185 &IoStatusBlock, 1186 NewBootSector, 1187 SECTORSIZE, 1188 &FileOffset, 1189 NULL); 1190 1191 /* Free the new boot sector */ 1192 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1193 1194 return Status; 1195 } 1196 1197 static 1198 NTSTATUS 1199 InstallFat16BootCodeToFile( 1200 IN PCWSTR SrcPath, 1201 IN PCWSTR DstPath, 1202 IN PCWSTR RootPath) 1203 { 1204 NTSTATUS Status; 1205 UNICODE_STRING Name; 1206 OBJECT_ATTRIBUTES ObjectAttributes; 1207 IO_STATUS_BLOCK IoStatusBlock; 1208 HANDLE PartitionHandle, FileHandle; 1209 1210 /* 1211 * Open the root partition from which the boot sector 1212 * parameters will be obtained. 1213 * Remove any trailing backslash if needed. 1214 */ 1215 RtlInitUnicodeString(&Name, RootPath); 1216 TrimTrailingPathSeparators_UStr(&Name); 1217 1218 InitializeObjectAttributes(&ObjectAttributes, 1219 &Name, 1220 OBJ_CASE_INSENSITIVE, 1221 NULL, 1222 NULL); 1223 1224 Status = NtOpenFile(&PartitionHandle, 1225 GENERIC_READ | SYNCHRONIZE, 1226 &ObjectAttributes, 1227 &IoStatusBlock, 1228 FILE_SHARE_READ | FILE_SHARE_WRITE, 1229 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */); 1230 if (!NT_SUCCESS(Status)) 1231 return Status; 1232 1233 /* Open or create the file where the new bootsector will be saved */ 1234 RtlInitUnicodeString(&Name, DstPath); 1235 InitializeObjectAttributes(&ObjectAttributes, 1236 &Name, 1237 OBJ_CASE_INSENSITIVE, 1238 NULL, 1239 NULL); 1240 1241 Status = NtCreateFile(&FileHandle, 1242 GENERIC_WRITE | SYNCHRONIZE, 1243 &ObjectAttributes, 1244 &IoStatusBlock, 1245 NULL, 1246 FILE_ATTRIBUTE_NORMAL, 1247 0, 1248 FILE_OVERWRITE_IF, 1249 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 1250 NULL, 1251 0); 1252 if (!NT_SUCCESS(Status)) 1253 { 1254 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status); 1255 NtClose(PartitionHandle); 1256 return Status; 1257 } 1258 1259 /* Install the FAT16 boot sector */ 1260 Status = InstallFat16BootCode(SrcPath, FileHandle, PartitionHandle); 1261 1262 /* Close the file and the partition */ 1263 NtClose(FileHandle); 1264 NtClose(PartitionHandle); 1265 1266 return Status; 1267 } 1268 1269 static 1270 NTSTATUS 1271 InstallFat16BootCodeToDisk( 1272 IN PCWSTR SrcPath, 1273 IN PCWSTR RootPath) 1274 { 1275 NTSTATUS Status; 1276 UNICODE_STRING Name; 1277 OBJECT_ATTRIBUTES ObjectAttributes; 1278 IO_STATUS_BLOCK IoStatusBlock; 1279 HANDLE PartitionHandle; 1280 1281 /* 1282 * Open the root partition from which the boot sector parameters will be 1283 * obtained; this is also where we will write the updated boot sector. 1284 * Remove any trailing backslash if needed. 1285 */ 1286 RtlInitUnicodeString(&Name, RootPath); 1287 TrimTrailingPathSeparators_UStr(&Name); 1288 1289 InitializeObjectAttributes(&ObjectAttributes, 1290 &Name, 1291 OBJ_CASE_INSENSITIVE, 1292 NULL, 1293 NULL); 1294 1295 Status = NtOpenFile(&PartitionHandle, 1296 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1297 &ObjectAttributes, 1298 &IoStatusBlock, 1299 FILE_SHARE_READ | FILE_SHARE_WRITE, 1300 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); 1301 if (!NT_SUCCESS(Status)) 1302 return Status; 1303 1304 /* Install the FAT16 boot sector */ 1305 Status = InstallFat16BootCode(SrcPath, PartitionHandle, PartitionHandle); 1306 1307 /* Close the partition */ 1308 NtClose(PartitionHandle); 1309 1310 return Status; 1311 } 1312 1313 1314 static 1315 NTSTATUS 1316 InstallFat32BootCode( 1317 IN PCWSTR SrcPath, // FAT32 bootsector source file (on the installation medium) 1318 IN HANDLE DstPath, // Where to save the bootsector built from the source + partition information 1319 IN HANDLE RootPartition) // Partition holding the (old) FAT32 information 1320 { 1321 NTSTATUS Status; 1322 UNICODE_STRING Name; 1323 OBJECT_ATTRIBUTES ObjectAttributes; 1324 IO_STATUS_BLOCK IoStatusBlock; 1325 HANDLE FileHandle; 1326 LARGE_INTEGER FileOffset; 1327 PFAT32_BOOTSECTOR OrigBootSector; 1328 PFAT32_BOOTSECTOR NewBootSector; 1329 USHORT BackupBootSector; 1330 1331 /* Allocate a buffer for the original bootsector */ 1332 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 1333 if (OrigBootSector == NULL) 1334 return STATUS_INSUFFICIENT_RESOURCES; 1335 1336 /* Read the current boot sector into the buffer */ 1337 FileOffset.QuadPart = 0ULL; 1338 Status = NtReadFile(RootPartition, 1339 NULL, 1340 NULL, 1341 NULL, 1342 &IoStatusBlock, 1343 OrigBootSector, 1344 SECTORSIZE, 1345 &FileOffset, 1346 NULL); 1347 if (!NT_SUCCESS(Status)) 1348 { 1349 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1350 return Status; 1351 } 1352 1353 /* Allocate a buffer for the new bootsector (2 sectors) */ 1354 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE); 1355 if (NewBootSector == NULL) 1356 { 1357 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1358 return STATUS_INSUFFICIENT_RESOURCES; 1359 } 1360 1361 /* Read the new bootsector from SrcPath */ 1362 RtlInitUnicodeString(&Name, SrcPath); 1363 InitializeObjectAttributes(&ObjectAttributes, 1364 &Name, 1365 OBJ_CASE_INSENSITIVE, 1366 NULL, 1367 NULL); 1368 1369 Status = NtOpenFile(&FileHandle, 1370 GENERIC_READ | SYNCHRONIZE, 1371 &ObjectAttributes, 1372 &IoStatusBlock, 1373 FILE_SHARE_READ, 1374 FILE_SYNCHRONOUS_IO_NONALERT); 1375 if (!NT_SUCCESS(Status)) 1376 { 1377 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1378 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1379 return Status; 1380 } 1381 1382 FileOffset.QuadPart = 0ULL; 1383 Status = NtReadFile(FileHandle, 1384 NULL, 1385 NULL, 1386 NULL, 1387 &IoStatusBlock, 1388 NewBootSector, 1389 2 * SECTORSIZE, 1390 &FileOffset, 1391 NULL); 1392 NtClose(FileHandle); 1393 if (!NT_SUCCESS(Status)) 1394 { 1395 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1396 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1397 return Status; 1398 } 1399 1400 /* Adjust the bootsector (copy a part of the FAT32 BPB) */ 1401 memcpy(&NewBootSector->OemName, 1402 &OrigBootSector->OemName, 1403 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) - 1404 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName)); 1405 1406 /* 1407 * We know we copy the boot code to a file only when DstPath != RootPartition, 1408 * otherwise the boot code is copied to the specified root partition. 1409 */ 1410 if (DstPath != RootPartition) 1411 { 1412 /* Copy to a file: Disable the backup boot sector */ 1413 NewBootSector->BackupBootSector = 0; 1414 } 1415 else 1416 { 1417 /* Copy to a disk: Get the location of the backup boot sector */ 1418 BackupBootSector = OrigBootSector->BackupBootSector; 1419 } 1420 1421 /* Free the original boot sector */ 1422 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1423 1424 /* Write the first sector of the new bootcode to DstPath sector 0 */ 1425 FileOffset.QuadPart = 0ULL; 1426 Status = NtWriteFile(DstPath, 1427 NULL, 1428 NULL, 1429 NULL, 1430 &IoStatusBlock, 1431 NewBootSector, 1432 SECTORSIZE, 1433 &FileOffset, 1434 NULL); 1435 if (!NT_SUCCESS(Status)) 1436 { 1437 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1438 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1439 return Status; 1440 } 1441 1442 if (DstPath == RootPartition) 1443 { 1444 /* Copy to a disk: Write the backup boot sector */ 1445 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF)) 1446 { 1447 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE); 1448 Status = NtWriteFile(DstPath, 1449 NULL, 1450 NULL, 1451 NULL, 1452 &IoStatusBlock, 1453 NewBootSector, 1454 SECTORSIZE, 1455 &FileOffset, 1456 NULL); 1457 if (!NT_SUCCESS(Status)) 1458 { 1459 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1460 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1461 return Status; 1462 } 1463 } 1464 } 1465 1466 /* Write the second sector of the new bootcode to boot disk sector 14 */ 1467 // FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE); 1468 FileOffset.QuadPart = 14 * SECTORSIZE; 1469 Status = NtWriteFile(DstPath, // or really RootPartition ??? 1470 NULL, 1471 NULL, 1472 NULL, 1473 &IoStatusBlock, 1474 ((PUCHAR)NewBootSector + SECTORSIZE), 1475 SECTORSIZE, 1476 &FileOffset, 1477 NULL); 1478 if (!NT_SUCCESS(Status)) 1479 { 1480 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1481 } 1482 1483 /* Free the new boot sector */ 1484 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1485 1486 return Status; 1487 } 1488 1489 static 1490 NTSTATUS 1491 InstallFat32BootCodeToFile( 1492 IN PCWSTR SrcPath, 1493 IN PCWSTR DstPath, 1494 IN PCWSTR RootPath) 1495 { 1496 NTSTATUS Status; 1497 UNICODE_STRING Name; 1498 OBJECT_ATTRIBUTES ObjectAttributes; 1499 IO_STATUS_BLOCK IoStatusBlock; 1500 HANDLE PartitionHandle, FileHandle; 1501 1502 /* 1503 * Open the root partition from which the boot sector parameters 1504 * will be obtained. 1505 * FIXME? It might be possible that we need to also open it for writing 1506 * access in case we really need to still write the second portion of 1507 * the boot sector ???? 1508 * 1509 * Remove any trailing backslash if needed. 1510 */ 1511 RtlInitUnicodeString(&Name, RootPath); 1512 TrimTrailingPathSeparators_UStr(&Name); 1513 1514 InitializeObjectAttributes(&ObjectAttributes, 1515 &Name, 1516 OBJ_CASE_INSENSITIVE, 1517 NULL, 1518 NULL); 1519 1520 Status = NtOpenFile(&PartitionHandle, 1521 GENERIC_READ | SYNCHRONIZE, 1522 &ObjectAttributes, 1523 &IoStatusBlock, 1524 FILE_SHARE_READ | FILE_SHARE_WRITE, 1525 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */); 1526 if (!NT_SUCCESS(Status)) 1527 return Status; 1528 1529 /* Open or create the file where (the first sector of ????) the new bootsector will be saved */ 1530 RtlInitUnicodeString(&Name, DstPath); 1531 InitializeObjectAttributes(&ObjectAttributes, 1532 &Name, 1533 OBJ_CASE_INSENSITIVE, 1534 NULL, 1535 NULL); 1536 1537 Status = NtCreateFile(&FileHandle, 1538 GENERIC_WRITE | SYNCHRONIZE, 1539 &ObjectAttributes, 1540 &IoStatusBlock, 1541 NULL, 1542 FILE_ATTRIBUTE_NORMAL, 1543 0, 1544 FILE_SUPERSEDE, // FILE_OVERWRITE_IF, <- is used for FAT16 1545 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, 1546 NULL, 1547 0); 1548 if (!NT_SUCCESS(Status)) 1549 { 1550 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status); 1551 NtClose(PartitionHandle); 1552 return Status; 1553 } 1554 1555 /* Install the FAT32 boot sector */ 1556 Status = InstallFat32BootCode(SrcPath, FileHandle, PartitionHandle); 1557 1558 /* Close the file and the partition */ 1559 NtClose(FileHandle); 1560 NtClose(PartitionHandle); 1561 1562 return Status; 1563 } 1564 1565 static 1566 NTSTATUS 1567 InstallFat32BootCodeToDisk( 1568 IN PCWSTR SrcPath, 1569 IN PCWSTR RootPath) 1570 { 1571 NTSTATUS Status; 1572 UNICODE_STRING Name; 1573 OBJECT_ATTRIBUTES ObjectAttributes; 1574 IO_STATUS_BLOCK IoStatusBlock; 1575 HANDLE PartitionHandle; 1576 1577 /* 1578 * Open the root partition from which the boot sector parameters will be 1579 * obtained; this is also where we will write the updated boot sector. 1580 * Remove any trailing backslash if needed. 1581 */ 1582 RtlInitUnicodeString(&Name, RootPath); 1583 TrimTrailingPathSeparators_UStr(&Name); 1584 1585 InitializeObjectAttributes(&ObjectAttributes, 1586 &Name, 1587 OBJ_CASE_INSENSITIVE, 1588 NULL, 1589 NULL); 1590 1591 Status = NtOpenFile(&PartitionHandle, 1592 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1593 &ObjectAttributes, 1594 &IoStatusBlock, 1595 FILE_SHARE_READ | FILE_SHARE_WRITE, 1596 FILE_SYNCHRONOUS_IO_NONALERT /* | FILE_SEQUENTIAL_ONLY */); 1597 if (!NT_SUCCESS(Status)) 1598 return Status; 1599 1600 /* Install the FAT32 boot sector */ 1601 Status = InstallFat32BootCode(SrcPath, PartitionHandle, PartitionHandle); 1602 1603 /* Close the partition */ 1604 NtClose(PartitionHandle); 1605 1606 return Status; 1607 } 1608 1609 static 1610 NTSTATUS 1611 InstallBtrfsBootCodeToDisk( 1612 IN PCWSTR SrcPath, 1613 IN PCWSTR RootPath) 1614 { 1615 NTSTATUS Status; 1616 NTSTATUS LockStatus; 1617 UNICODE_STRING Name; 1618 OBJECT_ATTRIBUTES ObjectAttributes; 1619 IO_STATUS_BLOCK IoStatusBlock; 1620 HANDLE FileHandle; 1621 LARGE_INTEGER FileOffset; 1622 // PEXT2_BOOTSECTOR OrigBootSector; 1623 PBTRFS_BOOTSECTOR NewBootSector; 1624 // USHORT BackupBootSector; 1625 PARTITION_INFORMATION_EX PartInfo; 1626 1627 #if 0 1628 /* Allocate buffer for original bootsector */ 1629 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); 1630 if (OrigBootSector == NULL) 1631 return STATUS_INSUFFICIENT_RESOURCES; 1632 1633 /* Open the root partition - Remove any trailing backslash if needed */ 1634 RtlInitUnicodeString(&Name, RootPath); 1635 TrimTrailingPathSeparators_UStr(&Name); 1636 1637 InitializeObjectAttributes(&ObjectAttributes, 1638 &Name, 1639 OBJ_CASE_INSENSITIVE, 1640 NULL, 1641 NULL); 1642 1643 Status = NtOpenFile(&FileHandle, 1644 GENERIC_READ | SYNCHRONIZE, 1645 &ObjectAttributes, 1646 &IoStatusBlock, 1647 FILE_SHARE_READ | FILE_SHARE_WRITE, 1648 FILE_SYNCHRONOUS_IO_NONALERT); 1649 if (!NT_SUCCESS(Status)) 1650 { 1651 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1652 return Status; 1653 } 1654 1655 /* Read current boot sector into buffer */ 1656 FileOffset.QuadPart = 0ULL; 1657 Status = NtReadFile(FileHandle, 1658 NULL, 1659 NULL, 1660 NULL, 1661 &IoStatusBlock, 1662 OrigBootSector, 1663 SECTORSIZE, 1664 &FileOffset, 1665 NULL); 1666 NtClose(FileHandle); 1667 if (!NT_SUCCESS(Status)) 1668 { 1669 RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1670 return Status; 1671 } 1672 #endif 1673 1674 /* Allocate buffer for new bootsector */ 1675 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(BTRFS_BOOTSECTOR)); 1676 if (NewBootSector == NULL) 1677 { 1678 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1679 return STATUS_INSUFFICIENT_RESOURCES; 1680 } 1681 1682 /* Read new bootsector from SrcPath */ 1683 RtlInitUnicodeString(&Name, SrcPath); 1684 1685 InitializeObjectAttributes(&ObjectAttributes, 1686 &Name, 1687 OBJ_CASE_INSENSITIVE, 1688 NULL, 1689 NULL); 1690 1691 Status = NtOpenFile(&FileHandle, 1692 GENERIC_READ | SYNCHRONIZE, 1693 &ObjectAttributes, 1694 &IoStatusBlock, 1695 FILE_SHARE_READ, 1696 FILE_SYNCHRONOUS_IO_NONALERT); 1697 if (!NT_SUCCESS(Status)) 1698 { 1699 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1700 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1701 return Status; 1702 } 1703 1704 Status = NtReadFile(FileHandle, 1705 NULL, 1706 NULL, 1707 NULL, 1708 &IoStatusBlock, 1709 NewBootSector, 1710 sizeof(BTRFS_BOOTSECTOR), 1711 NULL, 1712 NULL); 1713 NtClose(FileHandle); 1714 if (!NT_SUCCESS(Status)) 1715 { 1716 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1717 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1718 return Status; 1719 } 1720 1721 #if 0 1722 /* Adjust bootsector (copy a part of the FAT32 BPB) */ 1723 memcpy(&NewBootSector->OemName, 1724 &OrigBootSector->OemName, 1725 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) - 1726 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName)); 1727 1728 /* Get the location of the backup boot sector */ 1729 BackupBootSector = OrigBootSector->BackupBootSector; 1730 1731 /* Free the original boot sector */ 1732 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector); 1733 #endif 1734 1735 /* Open the root partition - Remove any trailing backslash if needed */ 1736 RtlInitUnicodeString(&Name, RootPath); 1737 TrimTrailingPathSeparators_UStr(&Name); 1738 1739 InitializeObjectAttributes(&ObjectAttributes, 1740 &Name, 1741 OBJ_CASE_INSENSITIVE, 1742 NULL, 1743 NULL); 1744 1745 Status = NtOpenFile(&FileHandle, 1746 GENERIC_WRITE | SYNCHRONIZE, 1747 &ObjectAttributes, 1748 &IoStatusBlock, 1749 FILE_SHARE_READ | FILE_SHARE_WRITE, 1750 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); 1751 if (!NT_SUCCESS(Status)) 1752 { 1753 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); 1754 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1755 return Status; 1756 } 1757 1758 /* 1759 * The BTRFS driver requires the volume to be locked in order to modify 1760 * the first sectors of the partition, even though they are outside the 1761 * file-system space / in the reserved area (they are situated before 1762 * the super-block at 0x1000) and is in principle allowed by the NT 1763 * storage stack. 1764 * So we lock here in order to write the bootsector at sector 0. 1765 * If locking fails, we ignore and continue nonetheless. 1766 */ 1767 LockStatus = NtFsControlFile(FileHandle, 1768 NULL, 1769 NULL, 1770 NULL, 1771 &IoStatusBlock, 1772 FSCTL_LOCK_VOLUME, 1773 NULL, 1774 0, 1775 NULL, 1776 0); 1777 if (!NT_SUCCESS(LockStatus)) 1778 { 1779 DPRINT1("WARNING: Failed to lock BTRFS volume for writing bootsector! Operations may fail! (Status 0x%lx)\n", LockStatus); 1780 } 1781 1782 /* Obtaining partition info and writing it to bootsector */ 1783 Status = NtDeviceIoControlFile(FileHandle, 1784 NULL, 1785 NULL, 1786 NULL, 1787 &IoStatusBlock, 1788 IOCTL_DISK_GET_PARTITION_INFO_EX, 1789 NULL, 1790 0, 1791 &PartInfo, 1792 sizeof(PartInfo)); 1793 if (!NT_SUCCESS(Status)) 1794 { 1795 DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status); 1796 goto Quit; 1797 } 1798 1799 /* Write new bootsector to RootPath */ 1800 1801 NewBootSector->PartitionStartLBA = PartInfo.StartingOffset.QuadPart / SECTORSIZE; 1802 1803 /* Write sector 0 */ 1804 FileOffset.QuadPart = 0ULL; 1805 Status = NtWriteFile(FileHandle, 1806 NULL, 1807 NULL, 1808 NULL, 1809 &IoStatusBlock, 1810 NewBootSector, 1811 sizeof(BTRFS_BOOTSECTOR), 1812 &FileOffset, 1813 NULL); 1814 if (!NT_SUCCESS(Status)) 1815 { 1816 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1817 goto Quit; 1818 } 1819 1820 #if 0 1821 /* Write backup boot sector */ 1822 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF)) 1823 { 1824 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE); 1825 Status = NtWriteFile(FileHandle, 1826 NULL, 1827 NULL, 1828 NULL, 1829 &IoStatusBlock, 1830 NewBootSector, 1831 SECTORSIZE, 1832 &FileOffset, 1833 NULL); 1834 if (!NT_SUCCESS(Status)) 1835 { 1836 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1837 goto Quit; 1838 } 1839 } 1840 1841 /* Write sector 14 */ 1842 FileOffset.QuadPart = 14 * SECTORSIZE; 1843 Status = NtWriteFile(FileHandle, 1844 NULL, 1845 NULL, 1846 NULL, 1847 &IoStatusBlock, 1848 ((PUCHAR)NewBootSector + SECTORSIZE), 1849 SECTORSIZE, 1850 &FileOffset, 1851 NULL); 1852 if (!NT_SUCCESS(Status)) 1853 { 1854 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 1855 } 1856 #endif 1857 1858 Quit: 1859 /* Unlock the volume */ 1860 LockStatus = NtFsControlFile(FileHandle, 1861 NULL, 1862 NULL, 1863 NULL, 1864 &IoStatusBlock, 1865 FSCTL_UNLOCK_VOLUME, 1866 NULL, 1867 0, 1868 NULL, 1869 0); 1870 if (!NT_SUCCESS(LockStatus)) 1871 { 1872 DPRINT1("Failed to unlock BTRFS volume (Status 0x%lx)\n", LockStatus); 1873 } 1874 1875 /* Close the volume */ 1876 NtClose(FileHandle); 1877 1878 /* Free the new boot sector */ 1879 RtlFreeHeap(ProcessHeap, 0, NewBootSector); 1880 1881 return Status; 1882 } 1883 1884 1885 static 1886 NTSTATUS 1887 InstallFatBootcodeToPartition( 1888 IN PUNICODE_STRING SystemRootPath, 1889 IN PUNICODE_STRING SourceRootPath, 1890 IN PUNICODE_STRING DestinationArcPath, 1891 IN UCHAR PartitionType) 1892 { 1893 NTSTATUS Status; 1894 BOOLEAN DoesFreeLdrExist; 1895 WCHAR SrcPath[MAX_PATH]; 1896 WCHAR DstPath[MAX_PATH]; 1897 1898 /* FAT or FAT32 partition */ 1899 DPRINT("System path: '%wZ'\n", SystemRootPath); 1900 1901 /* Copy FreeLoader to the system partition, always overwriting the older version */ 1902 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 1903 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys"); 1904 1905 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 1906 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 1907 if (!NT_SUCCESS(Status)) 1908 { 1909 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 1910 return Status; 1911 } 1912 1913 /* Prepare for possibly updating 'freeldr.ini' */ 1914 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini"); 1915 if (DoesFreeLdrExist) 1916 { 1917 /* Update existing 'freeldr.ini' */ 1918 DPRINT1("Update existing 'freeldr.ini'\n"); 1919 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1920 if (!NT_SUCCESS(Status)) 1921 { 1922 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); 1923 return Status; 1924 } 1925 } 1926 1927 /* Check for NT and other bootloaders */ 1928 1929 // FIXME: Check for Vista+ bootloader! 1930 /*** Status = FindBootStore(PartitionHandle, NtLdr, &Version); ***/ 1931 /*** Status = FindBootStore(PartitionHandle, BootMgr, &Version); ***/ 1932 if (DoesFileExist_2(SystemRootPath->Buffer, L"NTLDR") == TRUE || 1933 DoesFileExist_2(SystemRootPath->Buffer, L"BOOT.INI") == TRUE) 1934 { 1935 /* Search root directory for 'NTLDR' and 'BOOT.INI' */ 1936 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n"); 1937 1938 /* Create or update 'freeldr.ini' */ 1939 if (DoesFreeLdrExist == FALSE) 1940 { 1941 /* Create new 'freeldr.ini' */ 1942 DPRINT1("Create new 'freeldr.ini'\n"); 1943 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 1944 if (!NT_SUCCESS(Status)) 1945 { 1946 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 1947 return Status; 1948 } 1949 1950 /* Install new bootcode into a file */ 1951 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"bootsect.ros"); 1952 1953 if (PartitionType == PARTITION_FAT32 || 1954 PartitionType == PARTITION_FAT32_XINT13) 1955 { 1956 /* Install FAT32 bootcode */ 1957 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin"); 1958 1959 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath); 1960 Status = InstallFat32BootCodeToFile(SrcPath, DstPath, 1961 SystemRootPath->Buffer); 1962 if (!NT_SUCCESS(Status)) 1963 { 1964 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status); 1965 return Status; 1966 } 1967 } 1968 else 1969 { 1970 /* Install FAT16 bootcode */ 1971 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 1972 1973 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); 1974 Status = InstallFat16BootCodeToFile(SrcPath, DstPath, 1975 SystemRootPath->Buffer); 1976 if (!NT_SUCCESS(Status)) 1977 { 1978 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status); 1979 return Status; 1980 } 1981 } 1982 } 1983 1984 /* Update 'boot.ini' */ 1985 /* Windows' NTLDR loads an external bootsector file when the specified drive 1986 letter is C:, otherwise it will interpret it as a boot DOS path specifier. */ 1987 DPRINT1("Update 'boot.ini'\n"); 1988 Status = UpdateBootIni(SystemRootPath->Buffer, 1989 L"C:\\bootsect.ros", 1990 L"\"ReactOS\""); 1991 if (!NT_SUCCESS(Status)) 1992 { 1993 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status); 1994 return Status; 1995 } 1996 } 1997 else 1998 { 1999 /* Non-NT bootloaders: install our own bootloader */ 2000 2001 PCWSTR Section; 2002 PCWSTR Description; 2003 PCWSTR BootDrive; 2004 PCWSTR BootPartition; 2005 PCWSTR BootSector; 2006 2007 /* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */ 2008 if (DoesFileExist_2(SystemRootPath->Buffer, L"IOSYS.COM") == TRUE || 2009 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.COM") == TRUE) 2010 { 2011 DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n"); 2012 2013 Section = L"CPQDOS"; 2014 Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\""; 2015 BootDrive = L"hd0"; 2016 BootPartition = L"1"; 2017 BootSector = L"BOOTSECT.DOS"; 2018 } 2019 else 2020 /* Search for Microsoft DOS or Windows 9x boot loader */ 2021 if (DoesFileExist_2(SystemRootPath->Buffer, L"IO.SYS") == TRUE || 2022 DoesFileExist_2(SystemRootPath->Buffer, L"MSDOS.SYS") == TRUE) 2023 // WINBOOT.SYS 2024 { 2025 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n"); 2026 2027 Section = L"MSDOS"; 2028 Description = L"\"MS-DOS/Windows\""; 2029 BootDrive = L"hd0"; 2030 BootPartition = L"1"; 2031 BootSector = L"BOOTSECT.DOS"; 2032 } 2033 else 2034 /* Search for IBM PC-DOS or DR-DOS 5.x boot loader */ 2035 if (DoesFileExist_2(SystemRootPath->Buffer, L"IBMIO.COM" ) == TRUE || // Some people refer to this file instead of IBMBIO.COM... 2036 DoesFileExist_2(SystemRootPath->Buffer, L"IBMBIO.COM") == TRUE || 2037 DoesFileExist_2(SystemRootPath->Buffer, L"IBMDOS.COM") == TRUE) 2038 { 2039 DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n"); 2040 2041 Section = L"IBMDOS"; 2042 Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\""; 2043 BootDrive = L"hd0"; 2044 BootPartition = L"1"; 2045 BootSector = L"BOOTSECT.DOS"; 2046 } 2047 else 2048 /* Search for DR-DOS 3.x boot loader */ 2049 if (DoesFileExist_2(SystemRootPath->Buffer, L"DRBIOS.SYS") == TRUE || 2050 DoesFileExist_2(SystemRootPath->Buffer, L"DRBDOS.SYS") == TRUE) 2051 { 2052 DPRINT1("Found DR-DOS 3.x\n"); 2053 2054 Section = L"DRDOS"; 2055 Description = L"\"DR-DOS 3.x\""; 2056 BootDrive = L"hd0"; 2057 BootPartition = L"1"; 2058 BootSector = L"BOOTSECT.DOS"; 2059 } 2060 else 2061 /* Search for Dell Real-Mode Kernel (DRMK) OS */ 2062 if (DoesFileExist_2(SystemRootPath->Buffer, L"DELLBIO.BIN") == TRUE || 2063 DoesFileExist_2(SystemRootPath->Buffer, L"DELLRMK.BIN") == TRUE) 2064 { 2065 DPRINT1("Found Dell Real-Mode Kernel OS\n"); 2066 2067 Section = L"DRMK"; 2068 Description = L"\"Dell Real-Mode Kernel OS\""; 2069 BootDrive = L"hd0"; 2070 BootPartition = L"1"; 2071 BootSector = L"BOOTSECT.DOS"; 2072 } 2073 else 2074 /* Search for MS OS/2 1.x */ 2075 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT.COM") == TRUE || 2076 DoesFileExist_2(SystemRootPath->Buffer, L"OS2BIO.COM" ) == TRUE || 2077 DoesFileExist_2(SystemRootPath->Buffer, L"OS2DOS.COM" ) == TRUE) 2078 { 2079 DPRINT1("Found MS OS/2 1.x\n"); 2080 2081 Section = L"MSOS2"; 2082 Description = L"\"MS OS/2 1.x\""; 2083 BootDrive = L"hd0"; 2084 BootPartition = L"1"; 2085 BootSector = L"BOOTSECT.OS2"; 2086 } 2087 else 2088 /* Search for MS or IBM OS/2 */ 2089 if (DoesFileExist_2(SystemRootPath->Buffer, L"OS2BOOT") == TRUE || 2090 DoesFileExist_2(SystemRootPath->Buffer, L"OS2LDR" ) == TRUE || 2091 DoesFileExist_2(SystemRootPath->Buffer, L"OS2KRNL") == TRUE) 2092 { 2093 DPRINT1("Found MS/IBM OS/2\n"); 2094 2095 Section = L"IBMOS2"; 2096 Description = L"\"MS/IBM OS/2\""; 2097 BootDrive = L"hd0"; 2098 BootPartition = L"1"; 2099 BootSector = L"BOOTSECT.OS2"; 2100 } 2101 else 2102 /* Search for FreeDOS boot loader */ 2103 if (DoesFileExist_2(SystemRootPath->Buffer, L"kernel.sys") == TRUE) 2104 { 2105 DPRINT1("Found FreeDOS boot loader\n"); 2106 2107 Section = L"FDOS"; 2108 Description = L"\"FreeDOS\""; 2109 BootDrive = L"hd0"; 2110 BootPartition = L"1"; 2111 BootSector = L"BOOTSECT.DOS"; 2112 } 2113 else 2114 { 2115 /* No or unknown boot loader */ 2116 DPRINT1("No or unknown boot loader found\n"); 2117 2118 Section = L"Unknown"; 2119 Description = L"\"Unknown Operating System\""; 2120 BootDrive = L"hd0"; 2121 BootPartition = L"1"; 2122 BootSector = L"BOOTSECT.OLD"; 2123 } 2124 2125 /* Create or update 'freeldr.ini' */ 2126 if (DoesFreeLdrExist == FALSE) 2127 { 2128 /* Create new 'freeldr.ini' */ 2129 DPRINT1("Create new 'freeldr.ini'\n"); 2130 2131 if (IsThereAValidBootSector(SystemRootPath->Buffer)) 2132 { 2133 Status = CreateFreeLoaderIniForReactOSAndBootSector( 2134 SystemRootPath->Buffer, DestinationArcPath->Buffer, 2135 Section, Description, 2136 BootDrive, BootPartition, BootSector); 2137 if (!NT_SUCCESS(Status)) 2138 { 2139 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status); 2140 return Status; 2141 } 2142 2143 /* Save current bootsector */ 2144 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector); 2145 2146 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath); 2147 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE); 2148 if (!NT_SUCCESS(Status)) 2149 { 2150 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 2151 return Status; 2152 } 2153 } 2154 else 2155 { 2156 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 2157 if (!NT_SUCCESS(Status)) 2158 { 2159 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 2160 return Status; 2161 } 2162 } 2163 2164 /* Install new bootsector on the disk */ 2165 if (PartitionType == PARTITION_FAT32 || 2166 PartitionType == PARTITION_FAT32_XINT13) 2167 { 2168 /* Install FAT32 bootcode */ 2169 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat32.bin"); 2170 2171 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 2172 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer); 2173 if (!NT_SUCCESS(Status)) 2174 { 2175 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status); 2176 return Status; 2177 } 2178 } 2179 else 2180 { 2181 /* Install FAT16 bootcode */ 2182 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 2183 2184 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 2185 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer); 2186 if (!NT_SUCCESS(Status)) 2187 { 2188 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); 2189 return Status; 2190 } 2191 } 2192 } 2193 } 2194 2195 return STATUS_SUCCESS; 2196 } 2197 2198 static 2199 NTSTATUS 2200 InstallBtrfsBootcodeToPartition( 2201 IN PUNICODE_STRING SystemRootPath, 2202 IN PUNICODE_STRING SourceRootPath, 2203 IN PUNICODE_STRING DestinationArcPath, 2204 IN UCHAR PartitionType) 2205 { 2206 NTSTATUS Status; 2207 BOOLEAN DoesFreeLdrExist; 2208 WCHAR SrcPath[MAX_PATH]; 2209 WCHAR DstPath[MAX_PATH]; 2210 2211 /* BTRFS partition */ 2212 DPRINT("System path: '%wZ'\n", SystemRootPath); 2213 2214 /* Copy FreeLoader to the system partition, always overwriting the older version */ 2215 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 2216 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, L"freeldr.sys"); 2217 2218 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 2219 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 2220 if (!NT_SUCCESS(Status)) 2221 { 2222 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 2223 return Status; 2224 } 2225 2226 /* Prepare for possibly updating 'freeldr.ini' */ 2227 DoesFreeLdrExist = DoesFileExist_2(SystemRootPath->Buffer, L"freeldr.ini"); 2228 if (DoesFreeLdrExist) 2229 { 2230 /* Update existing 'freeldr.ini' */ 2231 DPRINT1("Update existing 'freeldr.ini'\n"); 2232 Status = UpdateFreeLoaderIni(SystemRootPath->Buffer, DestinationArcPath->Buffer); 2233 if (!NT_SUCCESS(Status)) 2234 { 2235 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); 2236 return Status; 2237 } 2238 } 2239 2240 /* Check for *nix bootloaders */ 2241 2242 /* Create or update 'freeldr.ini' */ 2243 if (DoesFreeLdrExist == FALSE) 2244 { 2245 /* Create new 'freeldr.ini' */ 2246 DPRINT1("Create new 'freeldr.ini'\n"); 2247 2248 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */ 2249 DPRINT1("*nix or unknown boot loader found\n"); 2250 2251 if (IsThereAValidBootSector(SystemRootPath->Buffer)) 2252 { 2253 PCWSTR BootSector = L"BOOTSECT.OLD"; 2254 2255 Status = CreateFreeLoaderIniForReactOSAndBootSector( 2256 SystemRootPath->Buffer, DestinationArcPath->Buffer, 2257 L"Linux", L"\"Linux\"", 2258 L"hd0", L"1", BootSector); 2259 if (!NT_SUCCESS(Status)) 2260 { 2261 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status); 2262 return Status; 2263 } 2264 2265 /* Save current bootsector */ 2266 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath->Buffer, BootSector); 2267 2268 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath); 2269 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(BTRFS_BOOTSECTOR)); 2270 if (!NT_SUCCESS(Status)) 2271 { 2272 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status); 2273 return Status; 2274 } 2275 } 2276 else 2277 { 2278 Status = CreateFreeLoaderIniForReactOS(SystemRootPath->Buffer, DestinationArcPath->Buffer); 2279 if (!NT_SUCCESS(Status)) 2280 { 2281 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 2282 return Status; 2283 } 2284 } 2285 2286 /* Install new bootsector on the disk */ 2287 // if (PartitionType == PARTITION_EXT2) 2288 { 2289 /* Install BTRFS bootcode */ 2290 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\btrfs.bin"); 2291 2292 DPRINT1("Install BTRFS bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); 2293 Status = InstallBtrfsBootCodeToDisk(SrcPath, SystemRootPath->Buffer); 2294 if (!NT_SUCCESS(Status)) 2295 { 2296 DPRINT1("InstallBtrfsBootCodeToDisk() failed (Status %lx)\n", Status); 2297 return Status; 2298 } 2299 } 2300 } 2301 2302 return STATUS_SUCCESS; 2303 } 2304 2305 2306 NTSTATUS 2307 InstallVBRToPartition( 2308 IN PUNICODE_STRING SystemRootPath, 2309 IN PUNICODE_STRING SourceRootPath, 2310 IN PUNICODE_STRING DestinationArcPath, 2311 IN UCHAR PartitionType) 2312 { 2313 switch (PartitionType) 2314 { 2315 case PARTITION_FAT_12: 2316 case PARTITION_FAT_16: 2317 case PARTITION_HUGE: 2318 case PARTITION_XINT13: 2319 case PARTITION_FAT32: 2320 case PARTITION_FAT32_XINT13: 2321 { 2322 return InstallFatBootcodeToPartition(SystemRootPath, 2323 SourceRootPath, 2324 DestinationArcPath, 2325 PartitionType); 2326 } 2327 2328 case PARTITION_LINUX: 2329 { 2330 return InstallBtrfsBootcodeToPartition(SystemRootPath, 2331 SourceRootPath, 2332 DestinationArcPath, 2333 PartitionType); 2334 } 2335 2336 case PARTITION_IFS: 2337 DPRINT1("Partitions of type NTFS or HPFS are not supported yet!\n"); 2338 break; 2339 2340 default: 2341 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType); 2342 break; 2343 } 2344 2345 return STATUS_UNSUCCESSFUL; 2346 } 2347 2348 2349 NTSTATUS 2350 InstallFatBootcodeToFloppy( 2351 IN PUNICODE_STRING SourceRootPath, 2352 IN PUNICODE_STRING DestinationArcPath) 2353 { 2354 static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\"; 2355 2356 NTSTATUS Status; 2357 WCHAR SrcPath[MAX_PATH]; 2358 WCHAR DstPath[MAX_PATH]; 2359 2360 /* Verify that the floppy disk is accessible */ 2361 if (DoesDirExist(NULL, FloppyDevice) == FALSE) 2362 return STATUS_DEVICE_NOT_READY; 2363 2364 /* Format the floppy disk */ 2365 // FormatPartition(...) 2366 Status = FormatFileSystem(FloppyDevice, 2367 L"FAT", 2368 FMIFS_FLOPPY, 2369 NULL, 2370 TRUE, 2371 0, 2372 NULL); 2373 if (!NT_SUCCESS(Status)) 2374 { 2375 if (Status == STATUS_NOT_SUPPORTED) 2376 DPRINT1("FAT FS non existent on this system?!\n"); 2377 else 2378 DPRINT1("VfatFormat() failed (Status %lx)\n", Status); 2379 2380 return Status; 2381 } 2382 2383 /* Copy FreeLoader to the boot partition */ 2384 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); 2385 CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice, L"freeldr.sys"); 2386 2387 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); 2388 Status = SetupCopyFile(SrcPath, DstPath, FALSE); 2389 if (!NT_SUCCESS(Status)) 2390 { 2391 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); 2392 return Status; 2393 } 2394 2395 /* Create new 'freeldr.ini' */ 2396 DPRINT("Create new 'freeldr.ini'\n"); 2397 Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer); 2398 if (!NT_SUCCESS(Status)) 2399 { 2400 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); 2401 return Status; 2402 } 2403 2404 /* Install FAT12 boosector */ 2405 CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); 2406 CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice); 2407 2408 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); 2409 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath); 2410 if (!NT_SUCCESS(Status)) 2411 { 2412 DPRINT1("InstallFat12BootCodeToFloppy() failed (Status %lx)\n", Status); 2413 return Status; 2414 } 2415 2416 return STATUS_SUCCESS; 2417 } 2418 2419 /* EOF */ 2420