+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Adjust bootsector (copy a part of the FAT BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to DstPath */
+ RtlInitUnicodeString(&Name, DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+#if 0
+ FilePosition.QuadPart = 0;
+#endif
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToFile(
+ PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PFAT32_BOOTSECTOR OrigBootSector;
+ PFAT32_BOOTSECTOR NewBootSector;
+ LARGE_INTEGER FileOffset;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
+
+ /* Disable the backup boot sector */
+ NewBootSector->BackupBootSector = 0;
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath */
+ RtlInitUnicodeString(&Name, DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Write the second sector of the new bootcode to boot disk sector 14 */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ ((PUCHAR)NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+NTSTATUS
+InstallMbrBootCodeToDisk(
+ PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PPARTITION_SECTOR OrigBootSector;
+ PPARTITION_SECTOR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(PARTITION_SECTOR));
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(PARTITION_SECTOR));
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ sizeof(PARTITION_SECTOR),
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Copy partition table from old MBR to new */
+ RtlCopyMemory (&NewBootSector->Signature,
+ &OrigBootSector->Signature,
+ sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */);
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to RootPath */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+NTSTATUS
+InstallFat12BootCodeToFloppy(
+ PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PFAT_BOOTSECTOR OrigBootSector;
+ PFAT_BOOTSECTOR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Adjust bootsector (copy a part of the FAT16 BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to RootPath */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+#if 0
+ FilePosition.QuadPart = 0;
+#endif
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToDisk(
+ PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PFAT_BOOTSECTOR OrigBootSector;
+ PFAT_BOOTSECTOR NewBootSector;
+ PARTITION_INFORMATION *PartInfo;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Adjust bootsector (copy a part of the FAT16 BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
+
+ PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
+ NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to RootPath */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+#if 0
+ FilePosition.QuadPart = 0;
+#endif
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToDisk(
+ PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PFAT32_BOOTSECTOR OrigBootSector;
+ PFAT32_BOOTSECTOR NewBootSector;
+ LARGE_INTEGER FileOffset;
+ USHORT BackupBootSector;
+ PARTITION_INFORMATION *PartInfo;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return Status;
+ }
+
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name, SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy(&NewBootSector->OemName,
+ &OrigBootSector->OemName,
+ FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
+ FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
+
+ PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
+ NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
+
+ /* Get the location of the backup boot sector */
+ BackupBootSector = OrigBootSector->BackupBootSector;
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath */
+ RtlInitUnicodeString(&Name, RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Write sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+
+ /* Write backup boot sector */
+ if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
+ {
+ FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return Status;
+ }
+ }
+
+ /* Write sector 14 */
+ FileOffset.QuadPart = 14 * SECTORSIZE;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ ((PUCHAR)NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+UnprotectBootIni(
+ PWSTR FileName,
+ PULONG Attributes)
+{
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileInfo;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&Name, FileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (Status == STATUS_NO_SUCH_FILE)
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ *Attributes = 0;
+ return STATUS_SUCCESS;
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return Status;
+ }