[NTOS:MM] Fix ViewSize parameter passed to MiInsertVadEx() from MiCreatePebOrTeb()
[reactos.git] / ntoskrnl / fstub / fstubex.c
index 6035ed8..b9be7fa 100644 (file)
@@ -53,27 +53,6 @@ typedef struct _EFI_PARTITION_ENTRY
     WCHAR Name[0x24];      // 56
 } EFI_PARTITION_ENTRY, *PEFI_PARTITION_ENTRY;
 
-typedef struct _CREATE_DISK_MBR
-{
-    ULONG Signature;
-} CREATE_DISK_MBR, *PCREATE_DISK_MBR;
-
-typedef struct _CREATE_DISK_GPT
-{
-    GUID DiskId;
-    ULONG MaxPartitionCount;
-} CREATE_DISK_GPT, *PCREATE_DISK_GPT;
-
-typedef struct _CREATE_DISK
-{
-    PARTITION_STYLE PartitionStyle;
-    union
-    {
-        CREATE_DISK_MBR Mbr;
-        CREATE_DISK_GPT Gpt;
-    };
-} CREATE_DISK, *PCREATE_DISK;
-
 typedef struct _PARTITION_TABLE_ENTRY
 {
     UCHAR BootIndicator;
@@ -105,8 +84,10 @@ typedef struct _MASTER_BOOT_RECORD
 #define EFI_HEADER_SIGNATURE  0x5452415020494645ULL
 /* Defines version 1.0 */
 #define EFI_HEADER_REVISION_1 0x00010000
-/* Defines system type for MBR showing that a GPT is following */ 
+/* Defines system type for MBR showing that a GPT is following */
 #define EFI_PMBR_OSTYPE_EFI 0xEE
+/* Defines size to store a complete GUID + null char */
+#define EFI_GUID_STRING_SIZE 0x27
 
 #define IS_VALID_DISK_INFO(Disk) \
   (Disk)               &&        \
@@ -151,6 +132,17 @@ NTAPI
 FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk
 );
 
+NTSTATUS
+NTAPI
+FstubWriteHeaderEFI(IN PDISK_INFORMATION Disk,
+                    IN ULONG PartitionsSizeSector,
+                    IN GUID DiskGUID,
+                    IN ULONG NumberOfEntries,
+                    IN ULONGLONG FirstUsableLBA,
+                    IN ULONGLONG LastUsableLBA,
+                    IN ULONG PartitionEntryCRC32,
+                    IN BOOLEAN WriteBackupTable);
+
 NTSTATUS
 NTAPI
 FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk,
@@ -239,7 +231,7 @@ FstubAllocateDiskInformation(IN PDEVICE_OBJECT DeviceObject,
     }
     else
     {
-        DiskInformation->DiskGeometry = *DiskGeometry;
+        RtlCopyMemory(&DiskInformation->DiskGeometry, DiskGeometry, sizeof(DISK_GEOMETRY_EX));
     }
 
     /* Ensure read/received information are correct */
@@ -290,7 +282,7 @@ FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
     DriveLayout = ExAllocatePoolWithTag(NonPagedPool,
                                         FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
                                         LayoutEx->PartitionCount * sizeof(PARTITION_INFORMATION),
-                                        'BtsF');
+                                        TAG_FSTUB);
     if (!DriveLayout)
     {
         return NULL;
@@ -555,7 +547,7 @@ NTAPI
 FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
 {
     ULONG i;
-    CHAR Guid[38];
+    CHAR Guid[EFI_GUID_STRING_SIZE];
     PAGED_CODE();
 
     DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
@@ -564,7 +556,7 @@ FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
         case PARTITION_STYLE_MBR:
             if (DriveLayout->PartitionCount % 4 != 0)
             {
-                DPRINT("Warning: Partition count isn't a 4-factor: %ld!\n", DriveLayout->PartitionCount);
+                DPRINT("Warning: Partition count isn't a 4-factor: %lu!\n", DriveLayout->PartitionCount);
             }
 
             DPRINT("Signature: %8.8x\n", DriveLayout->Mbr.Signature);
@@ -579,7 +571,7 @@ FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
             DPRINT("DiskId: %s\n", Guid);
             DPRINT("StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
             DPRINT("UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
-            DPRINT("MaxPartitionCount: %ld\n", DriveLayout->Gpt.MaxPartitionCount);
+            DPRINT("MaxPartitionCount: %lu\n", DriveLayout->Gpt.MaxPartitionCount);
             for (i = 0; i < DriveLayout->PartitionCount; i++)
             {
                 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
@@ -587,7 +579,7 @@ FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
 
             break;
         default:
-            DPRINT("Unsupported partition style: %ld\n", DriveLayout->PartitionStyle);
+            DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
     }
 }
 
@@ -596,32 +588,32 @@ NTAPI
 FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
                          IN ULONG PartitionNumber)
 {
-    CHAR Guid[38];
+    CHAR Guid[EFI_GUID_STRING_SIZE];
     PAGED_CODE();
 
-    DPRINT("Printing partition %ld\n", PartitionNumber);
+    DPRINT("Printing partition %lu\n", PartitionNumber);
 
     switch (PartitionEntry[PartitionNumber].PartitionStyle)
     {
         case PARTITION_STYLE_MBR:
             DPRINT("  StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
             DPRINT("  PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
-            DPRINT("  RewritePartition: %d\n", PartitionEntry[PartitionNumber].RewritePartition);
+            DPRINT("  RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
             DPRINT("  PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
-            DPRINT("  BootIndicator: %d\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
-            DPRINT("  RecognizedPartition: %d\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
-            DPRINT("  HiddenSectors: %ld\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
+            DPRINT("  BootIndicator: %u\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
+            DPRINT("  RecognizedPartition: %u\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
+            DPRINT("  HiddenSectors: %lu\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
 
             break;
         case PARTITION_STYLE_GPT:
             DPRINT("  StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
             DPRINT("  PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
-            DPRINT("  RewritePartition: %d\n", PartitionEntry[PartitionNumber].RewritePartition);
+            DPRINT("  RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
             FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionType), Guid);
             DPRINT("  PartitionType: %s\n", Guid);
             FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionId), Guid);
             DPRINT("  PartitionId: %s\n", Guid);
-            DPRINT("  Attributes: %16x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
+            DPRINT("  Attributes: %I64x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
             DPRINT("  Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
 
             break;
@@ -635,11 +627,11 @@ NTAPI
 FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
                             IN ULONG PartitionNumber)
 {
-    CHAR Guid[38];
+    CHAR Guid[EFI_GUID_STRING_SIZE];
     PAGED_CODE();
 
     DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
-    DPRINT("Modifying partition %ld\n", PartitionNumber);
+    DPRINT("Modifying partition %lu\n", PartitionNumber);
     switch (PartitionEntry->PartitionStyle)
     {
         case PARTITION_STYLE_MBR:
@@ -651,7 +643,7 @@ FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
             DPRINT("  PartitionType: %s\n", Guid);
             FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionId), Guid);
             DPRINT("  PartitionId: %s\n", Guid);
-            DPRINT("  Attributes: %16x\n", PartitionEntry->Gpt.Attributes);
+            DPRINT("  Attributes: %I64x\n", PartitionEntry->Gpt.Attributes);
             DPRINT("  Name: %ws\n", PartitionEntry->Gpt.Name);
 
             break;
@@ -818,7 +810,7 @@ NTSTATUS
 NTAPI
 FstubReadHeaderEFI(IN PDISK_INFORMATION Disk,
                    IN BOOLEAN ReadBackupTable,
-                   PEFI_PARTITION_HEADER HeaderBuffer)
+                   PEFI_PARTITION_HEADER HeaderBuffer)
 {
     NTSTATUS Status;
     PUCHAR Sector = NULL;
@@ -950,7 +942,7 @@ FstubReadHeaderEFI(IN PDISK_INFORMATION Disk,
     if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
     {
         /* In case of a success, return read header */
-        *HeaderBuffer = *EFIHeader;
+        *HeaderBuffer = EFIHeader;
         return STATUS_SUCCESS;
     }
     else
@@ -968,10 +960,15 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
                            OUT struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout)
 {
     NTSTATUS Status;
-    EFI_PARTITION_HEADER EfiHeader;
-    ULONGLONG SectorsForPartitions;
+    ULONG NumberOfEntries;
+    PEFI_PARTITION_HEADER EfiHeader;
     EFI_PARTITION_ENTRY PartitionEntry;
+#if 0
     BOOLEAN UpdatedPartitionTable = FALSE;
+    ULONGLONG SectorsForPartitions, PartitionEntryLBA;
+#else
+    ULONGLONG PartitionEntryLBA;
+#endif
     PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
     ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
     PAGED_CODE();
@@ -990,44 +987,58 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
         return Status;
     }
 
+    /* Backup the number of entries, will be used later on */
+    NumberOfEntries = EfiHeader->NumberOfEntries;
+
     /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
     DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
                                           FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
-                                          EfiHeader.NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
+                                          EfiHeader->NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
                                           TAG_FSTUB);
     if (!DriveLayoutEx)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    if (ReadBackupTable)
+#if 0
+    if (!ReadBackupTable)
     {
-        /* If we read backup but if it doesn't match with current geometry */
-        if ((Disk->SectorCount - 1ULL) != EfiHeader.AlternateLBA)
+        /* If we weren't ask to read backup table,
+         * check the status of the backup table.
+         * In case it's not where we're expecting it, move it and ask
+         * for a partition table rewrite.
+         */
+        if ((Disk->SectorCount - 1ULL) != EfiHeader->AlternateLBA)
         {
             /* We'll update it. First, count number of sectors needed to store partitions */
-            SectorsForPartitions = (EfiHeader.NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
+            SectorsForPartitions = ((ULONGLONG)EfiHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
             /* Then set first usable LBA: Legacy MBR + GPT header + Partitions entries */
-            EfiHeader.FirstUsableLBA = SectorsForPartitions + 2;
+            EfiHeader->FirstUsableLBA = SectorsForPartitions + 2;
             /* Then set last usable LBA: Last sector - GPT header - Partitions entries */
-            EfiHeader.LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
+            EfiHeader->LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
             /* Inform that we'll rewrite partition table */
             UpdatedPartitionTable = TRUE;
         }
     }
+#endif
 
     DriveLayoutEx->PartitionStyle = PARTITION_STYLE_GPT;
     /* Translate LBA -> Offset */
-    DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader.FirstUsableLBA * Disk->SectorSize;
-    DriveLayoutEx->Gpt.UsableLength.QuadPart = EfiHeader.LastUsableLBA - EfiHeader.FirstUsableLBA * Disk->SectorSize;
-    DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader.NumberOfEntries;
-    DriveLayoutEx->Gpt.DiskId = EfiHeader.DiskGUID;
+    DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader->FirstUsableLBA * Disk->SectorSize;
+    DriveLayoutEx->Gpt.UsableLength.QuadPart = EfiHeader->LastUsableLBA - EfiHeader->FirstUsableLBA * Disk->SectorSize;
+    DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader->NumberOfEntries;
+    DriveLayoutEx->Gpt.DiskId = EfiHeader->DiskGUID;
 
+    /* Backup partition entry position */
+    PartitionEntryLBA = EfiHeader->PartitionEntryLBA;
     /* Count number of partitions per sector */
     PartitionsPerSector = (Disk->SectorSize / PARTITION_ENTRY_SIZE);
-    /* Read all partitions and fill in structure */
+    /* Read all partitions and fill in structure
+     * BEWARE! Past that point EfiHeader IS NOT VALID ANYMORE
+     * It will be erased by the reading of the partition entry
+     */
     for (i = 0, PartitionCount = 0, PartitionIndex = PartitionsPerSector;
-         i < EfiHeader.NumberOfEntries;
+         i < NumberOfEntries;
          i++)
     {
         /* Only read following sector if we finished with previous sector */
@@ -1035,7 +1046,7 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
         {
             Status = FstubReadSector(Disk->DeviceObject,
                                      Disk->SectorSize,
-                                     EfiHeader.PartitionEntryLBA + (i / PartitionsPerSector),
+                                     PartitionEntryLBA + (i / PartitionsPerSector),
                                      Disk->Buffer);
             if (!NT_SUCCESS(Status))
             {
@@ -1078,12 +1089,14 @@ FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
     }
     DriveLayoutEx->PartitionCount = PartitionCount;
 
-    /* If we updated partition table using backup table, rewrite partition table */ 
+#if 0
+    /* If we updated partition table using backup table, rewrite partition table */
     if (UpdatedPartitionTable)
     {
         IoWritePartitionTableEx(Disk->DeviceObject,
                                 DriveLayoutEx);
     }
+#endif
 
     /* Finally, return read data */
     *DriveLayout = DriveLayoutEx;
@@ -1264,9 +1277,9 @@ FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk,
                              IN BOOLEAN FixErrors)
 {
     NTSTATUS Status;
-    PEFI_PARTITION_HEADER EFIHeader;
-    EFI_PARTITION_HEADER ReadEFIHeader;
-    BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE;
+    PEFI_PARTITION_HEADER EFIHeader, ReadEFIHeader;
+    BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE, WriteBackup;
+    ULONGLONG ReadPosition, WritePosition, SectorsForPartitions, PartitionIndex;
     PAGED_CODE();
 
     EFIHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(EFI_PARTITION_HEADER), TAG_FSTUB);
@@ -1279,43 +1292,112 @@ FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk,
     if (NT_SUCCESS(Status))
     {
         PrimaryValid = TRUE;
+        ASSERT(ReadEFIHeader);
+        RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
     }
 
     Status = FstubReadHeaderEFI(Disk, TRUE, &ReadEFIHeader);
     if (NT_SUCCESS(Status))
     {
         BackupValid = TRUE;
+        ASSERT(ReadEFIHeader);
+        RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
     }
 
-    if (!PrimaryValid)
+    /* If both are sane, just return */
+    if (PrimaryValid && BackupValid)
     {
-        if (!BackupValid || !FixErrors)
-        {
-            ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
-            return STATUS_DISK_CORRUPT_ERROR;
-        }
+        ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
+        return STATUS_SUCCESS;
+    }
 
-        DPRINT1("EFI::Partition table fixing not yet supported!\n");
+    /* If both are damaged OR if we have not been ordered to fix
+     * Then, quit and warn about disk corruption
+     */
+    if ((!PrimaryValid && !BackupValid) || !FixErrors)
+    {
         ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
-        return STATUS_NOT_IMPLEMENTED;
+        return STATUS_DISK_CORRUPT_ERROR;
     }
-    else if (!BackupValid)
+
+    /* Compute sectors taken by partitions */
+    SectorsForPartitions = (((ULONGLONG)EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) + Disk->SectorSize - 1) / Disk->SectorSize;
+    if (PrimaryValid)
     {
-        if (!PrimaryValid || !FixErrors)
-        {
-            ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
-            return STATUS_DISK_CORRUPT_ERROR;
-        }
+        WriteBackup = TRUE;
+        /* Take position at backup table for writing */
+        WritePosition = Disk->SectorCount - SectorsForPartitions;
+        /* And read from primary table */
+        ReadPosition = 2ULL;
 
-        DPRINT1("EFI::Partition table fixing not yet supported!\n");
-        ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
-        return STATUS_NOT_IMPLEMENTED;
+        DPRINT("EFI::Will repair backup table from primary\n");
     }
     else
     {
-        ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
-        return STATUS_SUCCESS;
+        ASSERT(BackupValid);
+        WriteBackup = FALSE;
+        /* Take position at primary table for writing */
+        WritePosition = 2ULL;
+        /* And read from backup table */
+        ReadPosition = Disk->SectorCount - SectorsForPartitions;
+
+        DPRINT("EFI::Will repair primary table from backup\n");
     }
+
+    PartitionIndex = 0ULL;
+
+    /* If no partitions are to be copied, just restore header */
+    if (SectorsForPartitions <= 0)
+    {
+        Status = FstubWriteHeaderEFI(Disk,
+                                     SectorsForPartitions,
+                                     EFIHeader->DiskGUID,
+                                     EFIHeader->NumberOfEntries,
+                                     EFIHeader->FirstUsableLBA,
+                                     EFIHeader->LastUsableLBA,
+                                     EFIHeader->PartitionEntryCRC32,
+                                     WriteBackup);
+
+        goto Cleanup;
+    }
+
+    /* Copy all the partitions */
+    for (; PartitionIndex < SectorsForPartitions; ++PartitionIndex)
+    {
+        /* First, read the partition from the first table */
+        Status = FstubReadSector(Disk->DeviceObject,
+                                 Disk->SectorSize,
+                                 ReadPosition + PartitionIndex,
+                                 Disk->Buffer);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
+
+        /* Then, write it in the other table */
+        Status = FstubWriteSector(Disk->DeviceObject,
+                                  Disk->SectorSize,
+                                  WritePosition + PartitionIndex,
+                                  Disk->Buffer);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
+    }
+
+    /* Now we're done, write the header */
+    Status = FstubWriteHeaderEFI(Disk,
+                                 SectorsForPartitions,
+                                 EFIHeader->DiskGUID,
+                                 EFIHeader->NumberOfEntries,
+                                 EFIHeader->FirstUsableLBA,
+                                 EFIHeader->LastUsableLBA,
+                                 EFIHeader->PartitionEntryCRC32,
+                                 WriteBackup);
+
+Cleanup:
+    ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
+    return Status;
 }
 
 NTSTATUS
@@ -1403,7 +1485,7 @@ FstubWriteEntryEFI(IN PDISK_INFORMATION Disk,
     /* Copy the entry at the proper place into the buffer
      * That way, we don't erase previous entries
      */
-    RtlCopyMemory(Disk->Buffer + (((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize) / sizeof(PUSHORT)),
+    RtlCopyMemory((PVOID)((ULONG_PTR)Disk->Buffer + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize)),
                   PartitionEntry,
                   sizeof(EFI_PARTITION_ENTRY));
     /* Compute size of buffer */
@@ -1422,6 +1504,7 @@ FstubWriteEntryEFI(IN PDISK_INFORMATION Disk,
         {
             return Status;
         }
+
         /* We clean buffer */
         RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
     }
@@ -1503,13 +1586,18 @@ FstubWriteHeaderEFI(IN PDISK_INFORMATION Disk,
 
     /* Debug the way we'll break disk, to let user pray */
     DPRINT("FSTUB: About to write the following header for %s table\n", (WriteBackupTable ? "backup" : "primary"));
-    DPRINT(" Signature: %I64x\n Revision: %x\n HeaderSize: %x\n HeaderCRC32: %x\n",
-           EFIHeader->Signature, EFIHeader->Revision, EFIHeader->HeaderSize, EFIHeader->HeaderCRC32);
-    DPRINT(" MyLBA: %I64x\n AlternateLBA: %I64x\n FirstUsableLBA: %I64x\n LastUsableLBA: %I64x\n",
-           EFIHeader->MyLBA, EFIHeader->AlternateLBA, EFIHeader->FirstUsableLBA, EFIHeader->LastUsableLBA);
-    DPRINT(" PartitionEntryLBA: %I64x\n NumberOfEntries: %x\n SizeOfPartitionEntry: %x\n PartitionEntryCRC32: %x\n",
-           EFIHeader->PartitionEntryLBA, EFIHeader->NumberOfEntries,
-           EFIHeader->SizeOfPartitionEntry, EFIHeader->PartitionEntryCRC32);
+    DPRINT(" Signature: %I64x\n", EFIHeader->Signature);
+    DPRINT(" Revision: %x\n", EFIHeader->Revision);
+    DPRINT(" HeaderSize: %x\n", EFIHeader->HeaderSize);
+    DPRINT(" HeaderCRC32: %x\n", EFIHeader->HeaderCRC32);
+    DPRINT(" MyLBA: %I64x\n", EFIHeader->MyLBA);
+    DPRINT(" AlternateLBA: %I64x\n", EFIHeader->AlternateLBA);
+    DPRINT(" FirstUsableLBA: %I64x\n", EFIHeader->FirstUsableLBA);
+    DPRINT(" LastUsableLBA: %I64x\n", EFIHeader->LastUsableLBA);
+    DPRINT(" PartitionEntryLBA: %I64x\n", EFIHeader->PartitionEntryLBA);
+    DPRINT(" NumberOfEntries: %x\n", EFIHeader->NumberOfEntries);
+    DPRINT(" SizeOfPartitionEntry: %x\n", EFIHeader->SizeOfPartitionEntry);
+    DPRINT(" PartitionEntryCRC32: %x\n", EFIHeader->PartitionEntryCRC32);
 
     /* Write header to disk */
     return FstubWriteSector(Disk->DeviceObject,
@@ -1626,7 +1714,7 @@ FstubWritePartitionTableMBR(IN PDISK_INFORMATION Disk,
                                    DriveLayout);
 
     /* Free allocated structure and return */
-    ExFreePool(DriveLayout);
+    ExFreePoolWithTag(DriveLayout, TAG_FSTUB);
     return Status;
 }
 
@@ -1798,6 +1886,7 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
         }
 
         /* Prepare for getting disk geometry */
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
         Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                             DeviceObject,
                                             NULL,
@@ -1814,7 +1903,6 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
         }
 
         /* Then, call the drive, and wait for it if needed */
-        KeInitializeEvent(&Event, NotificationEvent, FALSE);
         Status = IoCallDriver(DeviceObject, Irp);
         if (Status == STATUS_PENDING)
         {
@@ -1907,6 +1995,7 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
                         }
 
                         /* And call the drive to get information about partition */
+                        KeInitializeEvent(&Event, NotificationEvent, FALSE);
                         Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
                                                             DeviceObject,
                                                             NULL,
@@ -1924,7 +2013,6 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
                         }
 
                         /* Call & wait if needed */
-                        KeInitializeEvent(&Event, NotificationEvent, FALSE);
                         Status = IoCallDriver(DeviceObject, Irp);
                         if (Status == STATUS_PENDING)
                         {
@@ -1978,6 +2066,7 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
                         }
 
                         /* And call the drive to get information about partition */
+                        KeInitializeEvent(&Event, NotificationEvent, FALSE);
                         Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
                                                             DeviceObject,
                                                             NULL,
@@ -1995,7 +2084,6 @@ IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
                         }
 
                         /* Call & wait if needed */
-                        KeInitializeEvent(&Event, NotificationEvent, FALSE);
                         Status = IoCallDriver(DeviceObject, Irp);
                         if (Status == STATUS_PENDING)
                         {
@@ -2343,10 +2431,12 @@ NTAPI
 IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
                         IN struct _DRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
 {
+    GUID DiskGuid;
     NTSTATUS Status;
+    ULONG NumberOfEntries;
     PDISK_INFORMATION Disk;
-    ULONGLONG SectorsForPartitions;
-    EFI_PARTITION_HEADER EfiHeader;
+    PEFI_PARTITION_HEADER EfiHeader;
+    ULONGLONG SectorsForPartitions, FirstUsableLBA, LastUsableLBA;
     PAGED_CODE();
 
     ASSERT(DeviceObject);
@@ -2386,20 +2476,23 @@ IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
             if (NT_SUCCESS(Status))
             {
                 /* Check if there are enough places for the partitions to be written */
-                if (DriveLayout->PartitionCount <= EfiHeader.NumberOfEntries)
+                if (DriveLayout->PartitionCount <= EfiHeader->NumberOfEntries)
                 {
+                    /* Backup data */
+                    NumberOfEntries = EfiHeader->NumberOfEntries;
+                    RtlCopyMemory(&DiskGuid, &EfiHeader->DiskGUID, sizeof(GUID));
                     /* Count number of sectors needed to store partitions */
-                    SectorsForPartitions = (EfiHeader.NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
+                    SectorsForPartitions = ((ULONGLONG)NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
                     /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
-                    EfiHeader.FirstUsableLBA = SectorsForPartitions + 2;
+                    FirstUsableLBA = SectorsForPartitions + 2;
                     /* Set last usable LBA: Last sector - GPT header - Partitions entries */
-                    EfiHeader.LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
+                    LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
                     /* Write primary table */
                     Status = FstubWritePartitionTableEFI(Disk,
-                                                         EfiHeader.DiskGUID,
-                                                         EfiHeader.NumberOfEntries,
-                                                         EfiHeader.FirstUsableLBA,
-                                                         EfiHeader.LastUsableLBA,
+                                                         DiskGuid,
+                                                         NumberOfEntries,
+                                                         FirstUsableLBA,
+                                                         LastUsableLBA,
                                                          FALSE,
                                                          DriveLayout->PartitionCount,
                                                          DriveLayout->PartitionEntry);
@@ -2407,20 +2500,24 @@ IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
                     if (NT_SUCCESS(Status))
                     {
                         Status = FstubWritePartitionTableEFI(Disk,
-                                                             EfiHeader.DiskGUID,
-                                                             EfiHeader.NumberOfEntries,
-                                                             EfiHeader.FirstUsableLBA,
-                                                             EfiHeader.LastUsableLBA,
+                                                             DiskGuid,
+                                                             NumberOfEntries,
+                                                             FirstUsableLBA,
+                                                             LastUsableLBA,
                                                              TRUE,
                                                              DriveLayout->PartitionCount,
                                                              DriveLayout->PartitionEntry);
                     }
                 }
+                else
+                {
+                    Status = STATUS_INVALID_PARAMETER;
+                }
             }
             break;
 
         default:
-            DPRINT("Unsupported partition style: %ld\n", DriveLayout->PartitionStyle);
+            DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
             Status = STATUS_NOT_SUPPORTED;
     }