update for HEAD-2003091401
[reactos.git] / ntoskrnl / io / xhaldrv.c
index 0404f76..593d42e 100644 (file)
@@ -5,6 +5,7 @@
  * FILE:            ntoskrnl/io/xhaldrv.c
  * PURPOSE:         Hal drive routines
  * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  * UPDATE HISTORY:
  *                  Created 19/06/2000
  */
@@ -134,7 +135,7 @@ xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
   DPRINT("DiskGeometry.BytesPerSector: %d\n",
         DiskGeometry.BytesPerSector);
 
-  /* read the partition table */
+  /* Read the partition table */
   Status = IoReadPartitionTable(DeviceObject,
                                DiskGeometry.BytesPerSector,
                                FALSE,
@@ -171,39 +172,26 @@ xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
 
 
 static NTSTATUS
-xHalpReadSector(IN PDEVICE_OBJECT DeviceObject,
-               IN ULONG SectorSize,
-               IN PLARGE_INTEGER SectorOffset,
-               OUT PVOID *Buffer)
+xHalpReadSector (IN PDEVICE_OBJECT DeviceObject,
+                IN ULONG SectorSize,
+                IN PLARGE_INTEGER SectorOffset,
+                IN PVOID Sector)
 {
-  KEVENT Event;
   IO_STATUS_BLOCK StatusBlock;
-  PUCHAR Sector;
+  KEVENT Event;
   PIRP Irp;
   NTSTATUS Status;
 
-  DPRINT("xHalReadMBR()\n");
+  DPRINT("xHalpReadSector() called\n");
 
   assert(DeviceObject);
-  assert(Buffer);
-
-  *Buffer = NULL;
-
-  if (SectorSize < 512)
-    SectorSize = 512;
-  if (SectorSize > 4096)
-    SectorSize = 4096;
-
-  Sector = (PUCHAR)ExAllocatePool(PagedPool,
-                                 SectorSize);
-  if (Sector == NULL)
-    return STATUS_NO_MEMORY;
+  assert(Sector);
 
   KeInitializeEvent(&Event,
                    NotificationEvent,
                    FALSE);
 
-  /* Read MBR (Master Boot Record) */
+  /* Read the sector */
   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
                                     DeviceObject,
                                     Sector,
@@ -226,40 +214,33 @@ xHalpReadSector(IN PDEVICE_OBJECT DeviceObject,
 
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("Reading MBR failed (Status 0x%08lx)\n",
+      DPRINT("Reading sector failed (Status 0x%08lx)\n",
             Status);
-      ExFreePool(Sector);
       return Status;
     }
 
-  *Buffer = (PVOID)Sector;
   return Status;
 }
 
 
 static NTSTATUS
-xHalpWriteSector(IN PDEVICE_OBJECT DeviceObject,
-                IN ULONG SectorSize,
-                IN PLARGE_INTEGER SectorOffset,
-                OUT PVOID Sector)
+xHalpWriteSector (IN PDEVICE_OBJECT DeviceObject,
+                 IN ULONG SectorSize,
+                 IN PLARGE_INTEGER SectorOffset,
+                 IN PVOID Sector)
 {
-  KEVENT Event;
   IO_STATUS_BLOCK StatusBlock;
+  KEVENT Event;
   PIRP Irp;
   NTSTATUS Status;
 
-  DPRINT("xHalWriteMBR()\n");
-
-  if (SectorSize < 512)
-    SectorSize = 512;
-  if (SectorSize > 4096)
-    SectorSize = 4096;
+  DPRINT("xHalpWriteSector() called\n");
 
   KeInitializeEvent(&Event,
                    NotificationEvent,
                    FALSE);
 
-  /* Write MBR (Master Boot Record) */
+  /* Write the sector */
   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
                                     DeviceObject,
                                     Sector,
@@ -282,9 +263,8 @@ xHalpWriteSector(IN PDEVICE_OBJECT DeviceObject,
 
   if (!NT_SUCCESS(Status))
     {
-      DPRINT("Writing MBR failed (Status 0x%08lx)\n",
+      DPRINT("Writing sector failed (Status 0x%08lx)\n",
             Status);
-      return Status;
     }
 
   return Status;
@@ -299,21 +279,34 @@ xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
 {
   LARGE_INTEGER SectorOffset;
   PPARTITION_SECTOR Sector;
-  PULONG Shift;
   NTSTATUS Status;
 
   DPRINT("xHalExamineMBR()\n");
 
   *Buffer = NULL;
 
-  SectorOffset.QuadPart = 0ULL;
-  Status = xHalpReadSector(DeviceObject,
-                          SectorSize,
-                          &SectorOffset,
-                          (PVOID *)&Sector);
+  if (SectorSize < 512)
+    SectorSize = 512;
+  if (SectorSize > 4096)
+    SectorSize = 4096;
+
+  Sector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
+                                              SectorSize);
+  if (Sector == NULL)
+    {
+      DPRINT ("Partition sector allocation failed\n");
+      return;
+    }
+
+  SectorOffset.QuadPart = 0LL;
+  Status = xHalpReadSector (DeviceObject,
+                           SectorSize,
+                           &SectorOffset,
+                           (PVOID)Sector);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT1("xHalpReadSector() failed (Status %lx)\n", Status);
+      DPRINT("xHalpReadSector() failed (Status %lx)\n", Status);
+      ExFreePool(Sector);
       return;
     }
 
@@ -335,8 +328,7 @@ xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
     {
       /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
       DPRINT("Found 'Ontrack Disk Manager'!\n");
-      Shift = (PULONG)Sector;
-      *Shift = 63;
+      *((PULONG)Sector) = 63;
     }
 
   *Buffer = (PVOID)Sector;
@@ -663,8 +655,8 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
     }
 
   /* Assign cdrom drives */
-  DPRINT("CD-Rom drives: %d\n", ConfigInfo->CDRomCount);
-  for (i = 0; i < ConfigInfo->CDRomCount; i++)
+  DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount);
+  for (i = 0; i < ConfigInfo->CdRomCount; i++)
     {
       swprintf(Buffer1,
               L"\\Device\\CdRom%d",
@@ -679,7 +671,7 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
                      DOSDEVICE_DRIVE_CDROM);
     }
 
-  /* Anything else ?? */
+  /* Anything else to do? */
 
   ExFreePool(Buffer2);
   ExFreePool(Buffer1);
@@ -692,13 +684,10 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
                         BOOLEAN ReturnRecognizedPartitions,
                         PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
 {
-  KEVENT Event;
-  IO_STATUS_BLOCK StatusBlock;
-  ULARGE_INTEGER PartitionOffset;
-  ULARGE_INTEGER RealPartitionOffset;
-  ULARGE_INTEGER nextPartitionOffset;
-  ULARGE_INTEGER containerOffset;
-  PIRP Irp;
+  LARGE_INTEGER RealPartitionOffset;
+  ULONGLONG PartitionOffset;
+  ULONGLONG nextPartitionOffset;
+  ULONGLONG containerOffset;
   NTSTATUS Status;
   PPARTITION_SECTOR PartitionSector;
   PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
@@ -717,6 +706,12 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
 
   *PartitionBuffer = NULL;
 
+  /* Check sector size */
+  if (SectorSize < 512)
+    SectorSize = 512;
+  if (SectorSize > 4096)
+    SectorSize = 4096;
+
   /* Check for 'Ontrack Disk Manager' */
   xHalExamineMBR(DeviceObject,
                 SectorSize,
@@ -759,64 +754,53 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
   RtlZeroMemory(LayoutBuffer,
                0x1000);
 
-  PartitionOffset.QuadPart = (ULONGLONG)0;
-  containerOffset.QuadPart = (ULONGLONG)0;
+  PartitionOffset = 0ULL;
+  containerOffset = 0ULL;
 
   do
     {
-      DPRINT("PartitionOffset: %I64u\n", PartitionOffset.QuadPart / SectorSize);
+      DPRINT("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
 
+      /* Handle disk managers */
       if (DiskManager == OntrackDiskManager)
        {
-         RealPartitionOffset.QuadPart = PartitionOffset.QuadPart + (ULONGLONG)(63 * SectorSize);
+         /* Shift offset by 63 sectors */
+         RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
        }
-      else
+      else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
        {
-         RealPartitionOffset.QuadPart = PartitionOffset.QuadPart;
+         /* Use sector 1 instead of sector 0 */
+         RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
        }
-
-      DPRINT("RealPartitionOffset: %I64u\n", RealPartitionOffset.QuadPart / SectorSize);
-
-      KeInitializeEvent(&Event,
-                       NotificationEvent,
-                       FALSE);
-
-      Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
-                                        DeviceObject,
-                                        PartitionSector, //SectorBuffer,
-                                        SectorSize,
-                                        (PLARGE_INTEGER)&RealPartitionOffset,
-                                        &Event,
-                                        &StatusBlock);
-      Status = IoCallDriver(DeviceObject,
-                           Irp);
-      if (Status == STATUS_PENDING)
+      else
        {
-         KeWaitForSingleObject(&Event,
-                               Executive,
-                               KernelMode,
-                               FALSE,
-                               NULL);
-         Status = StatusBlock.Status;
+         RealPartitionOffset.QuadPart = PartitionOffset;
        }
 
+      DPRINT ("RealPartitionOffset: %I64u\n",
+             RealPartitionOffset.QuadPart / SectorSize);
+
+      Status = xHalpReadSector (DeviceObject,
+                               SectorSize,
+                               &RealPartitionOffset,
+                               PartitionSector);
       if (!NT_SUCCESS(Status))
        {
-         DPRINT("Failed to read partition table sector (Status = 0x%08lx)\n",
-                Status);
-         ExFreePool(PartitionSector);
-         ExFreePool(LayoutBuffer);
-         return(Status);
+         DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
+                 Status);
+         ExFreePool (PartitionSector);
+         ExFreePool (LayoutBuffer);
+         return Status;
        }
 
-      /* check the boot sector id */
+      /* Check the boot sector id */
       DPRINT("Magic %x\n", PartitionSector->Magic);
       if (PartitionSector->Magic != PARTITION_MAGIC)
        {
-         DbgPrint("Invalid partition sector magic\n");
-         ExFreePool(PartitionSector);
+         DPRINT ("Invalid partition sector magic\n");
+         ExFreePool (PartitionSector);
          *PartitionBuffer = LayoutBuffer;
-         return(STATUS_SUCCESS);
+         return STATUS_SUCCESS;
        }
 
 #ifndef NDEBUG
@@ -831,14 +815,15 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
                  (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
                     PartitionSector->Partition[i].StartingCylinder,
                  PartitionSector->Partition[i].EndingHead,
-                 PartitionSector->Partition[i].EndingSector,
-                 PartitionSector->Partition[i].EndingCylinder,
+                 PartitionSector->Partition[i].EndingSector & 0x3f,
+                 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
+                    PartitionSector->Partition[i].EndingCylinder,
                  PartitionSector->Partition[i].StartingBlock,
                  PartitionSector->Partition[i].SectorCount);
        }
 #endif
 
-      if (PartitionOffset.QuadPart == 0ULL)
+      if (PartitionOffset == 0ULL)
        {
          LayoutBuffer->Signature = PartitionSector->Signature;
          DPRINT("Disk signature: %lx\n", LayoutBuffer->Signature);
@@ -848,6 +833,18 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
 
       for (i = 0; i < PARTITION_TBL_SIZE; i++)
        {
+         if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
+           {
+             ExtendedFound = TRUE;
+             if ((ULONGLONG) containerOffset == (ULONGLONG) 0)
+               {
+                 containerOffset = PartitionOffset;
+               }
+             nextPartitionOffset = (ULONGLONG) containerOffset +
+               (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
+               (ULONGLONG) SectorSize;
+           }
+
          if ((ReturnRecognizedPartitions == FALSE) ||
               ((ReturnRecognizedPartitions == TRUE) &&
                IsRecognizedPartition(PartitionSector->Partition[i].PartitionType)))
@@ -856,6 +853,7 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
              DPRINT("Partition %u: Normal Partition\n", i);
              Count = LayoutBuffer->PartitionCount;
              DPRINT("Logical Partition %u\n", Count);
+
              if (PartitionSector->Partition[i].StartingBlock == 0)
                {
                  LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
@@ -863,17 +861,20 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
              else if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
                {
                  LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
-                   (ULONGLONG)PartitionOffset.QuadPart;
+                   (ULONGLONG) containerOffset +
+                   (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
+                   (ULONGLONG) SectorSize;
                }
              else
                {
                  LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
-                   (ULONGLONG)PartitionOffset.QuadPart +
+                   (ULONGLONG)PartitionOffset +
                    ((ULONGLONG)PartitionSector->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
                }
              LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
                (ULONGLONG)PartitionSector->Partition[i].SectorCount * (ULONGLONG)SectorSize;
-             LayoutBuffer->PartitionEntry[Count].HiddenSectors = 0;
+             LayoutBuffer->PartitionEntry[Count].HiddenSectors =
+               PartitionSector->Partition[i].StartingBlock;
 
              if (IsRecognizedPartition(PartitionSector->Partition[i].PartitionType))
                {
@@ -903,19 +904,8 @@ xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
 
              LayoutBuffer->PartitionCount++;
            }
-
-         if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
-           {
-             ExtendedFound = TRUE;
-             if ((ULONGLONG) containerOffset.QuadPart == (ULONGLONG) 0)
-               {
-                 containerOffset = PartitionOffset;
-               }
-             nextPartitionOffset.QuadPart = (ULONGLONG) containerOffset.QuadPart +
-               (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
-               (ULONGLONG) SectorSize;
-           }
        }
+
       PartitionOffset = nextPartitionOffset;
     }
   while (ExtendedFound == TRUE);
@@ -933,114 +923,107 @@ xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
                              IN ULONG PartitionNumber,
                              IN ULONG PartitionType)
 {
-  return(STATUS_NOT_IMPLEMENTED);
-}
-
-
-NTSTATUS FASTCALL
-xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
-                         IN ULONG SectorSize,
-                         IN ULONG SectorsPerTrack,
-                         IN ULONG NumberOfHeads,
-                         IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
-{
   PPARTITION_SECTOR PartitionSector;
-  LARGE_INTEGER SectorOffset;
+  LARGE_INTEGER RealPartitionOffset;
+  ULONGLONG PartitionOffset;
+  ULONGLONG nextPartitionOffset;
+  ULONGLONG containerOffset;
   NTSTATUS Status;
   ULONG i;
+  ULONG Number = 1;
+  BOOLEAN ExtendedFound = FALSE;
+  DISK_MANAGER DiskManager = NoDiskManager;
 
-  DPRINT("xHalIoWritePartitionTable(%p %lu %lu %p)\n",
-        DeviceObject,
-        SectorSize,
-        SectorsPerTrack,
-        PartitionBuffer);
+  DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
+         DeviceObject,
+         SectorSize,
+         PartitionNumber,
+         PartitionType);
 
-  assert(DeviceObject);
-  assert(PartitionBuffer);
+  /* Check sector size */
+  if (SectorSize < 512)
+    SectorSize = 512;
+  if (SectorSize > 4096)
+    SectorSize = 4096;
 
   /* Check for 'Ontrack Disk Manager' */
-  xHalExamineMBR(DeviceObject,
-                SectorSize,
-                0x54,
-                (PVOID *) &PartitionSector);
+  xHalExamineMBR (DeviceObject,
+                 SectorSize,
+                 0x54,
+                 (PVOID*) &PartitionSector);
   if (PartitionSector != NULL)
     {
-      DPRINT1("Ontrack Disk Manager is not supported\n");
-      ExFreePool(PartitionSector);
-      return STATUS_UNSUCCESSFUL;
+      DPRINT ("Found 'Ontrack Disk Manager'\n");
+      DiskManager = OntrackDiskManager;
+      ExFreePool (PartitionSector);
     }
 
   /* Check for 'EZ-Drive' */
-  xHalExamineMBR(DeviceObject,
-                SectorSize,
-                0x55,
-                (PVOID *) &PartitionSector);
+  xHalExamineMBR (DeviceObject,
+                 SectorSize,
+                 0x55,
+                 (PVOID*) &PartitionSector);
   if (PartitionSector != NULL)
     {
-      DPRINT1("EZ-Drive is not supported\n");
-      ExFreePool(PartitionSector);
-      return STATUS_UNSUCCESSFUL;
+      DPRINT ("Found 'EZ-Drive'\n");
+      DiskManager = EZ_Drive;
+      ExFreePool (PartitionSector);
     }
 
-
-  for (i = 0; i < PartitionBuffer->PartitionCount; i++)
+  /* Allocate partition sector */
+  PartitionSector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
+                                                       SectorSize);
+  if (PartitionSector == NULL)
     {
-      if (IsContainerPartition(PartitionBuffer->PartitionEntry[i].PartitionType))
-        {
-          /* FIXME: Implement */
-          DPRINT1("Writing MBRs with extended partitions is not implemented\n");
-          return STATUS_UNSUCCESSFUL;
-        }
+      return STATUS_INSUFFICIENT_RESOURCES;
     }
 
+  PartitionOffset = 0ULL;
+  containerOffset = 0ULL;
 
-  SectorOffset.QuadPart = 0ULL;
-  Status = xHalpReadSector(DeviceObject,
-                          SectorSize,
-                          &SectorOffset,
-                          (PVOID *) &PartitionSector);
-    if (!NT_SUCCESS(Status))
+  do
     {
-      DPRINT1("xHalpReadSector() failed (Status %lx)\n", Status);
-      return Status;
-    }
-
-  DPRINT1("WARNING: Only 'BootFlags' is implemented\n");
+      DPRINT ("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
 
-
-  for (i = 0; i < PartitionBuffer->PartitionCount; i++)
-    {
-      //= PartitionBuffer->PartitionEntry[i].StartingOffset;
-      //= PartitionBuffer->PartitionEntry[i].PartitionLength;
-      //= PartitionBuffer->PartitionEntry[i].HiddenSectors;
-      //= PartitionBuffer->PartitionEntry[i].PartitionType;
-      //= PartitionBuffer->PartitionEntry[i].PartitionType;
-
-      if (PartitionBuffer->PartitionEntry[i].BootIndicator)
-        {
-          PartitionSector->Partition[i].BootFlags |= 0x80;
-        }
+      /* Handle disk managers */
+      if (DiskManager == OntrackDiskManager)
+       {
+         /* Shift offset by 63 sectors */
+         RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
+       }
+      else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
+       {
+         /* Use sector 1 instead of sector 0 */
+         RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
+       }
       else
-        {
-          PartitionSector->Partition[i].BootFlags &= ~0x80;
-        }
+       {
+         RealPartitionOffset.QuadPart = PartitionOffset;
+       }
 
-      //= PartitionBuffer->PartitionEntry[i].RecognizedPartition;
-      //= PartitionBuffer->PartitionEntry[i].RewritePartition;
-    }
+      DPRINT ("RealPartitionOffset: %I64u\n",
+             RealPartitionOffset.QuadPart / SectorSize);
 
+      Status = xHalpReadSector (DeviceObject,
+                               SectorSize,
+                               &RealPartitionOffset,
+                               PartitionSector);
+      if (!NT_SUCCESS (Status))
+       {
+         DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
+                 Status);
+         ExFreePool (PartitionSector);
+         return Status;
+       }
 
-  SectorOffset.QuadPart = 0ULL;
-  Status = xHalpWriteSector(DeviceObject,
-                           SectorSize,
-                           &SectorOffset,
-                           (PVOID) PartitionSector);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
-      ExFreePool(PartitionSector);
-      return Status;
-    }
+      /* Check the boot sector id */
+      DPRINT("Magic %x\n", PartitionSector->Magic);
+      if (PartitionSector->Magic != PARTITION_MAGIC)
+       {
+         DPRINT ("Invalid partition sector magic\n");
+         ExFreePool (PartitionSector);
+         return STATUS_UNSUCCESSFUL;
+       }
 
 #ifndef NDEBUG
       for (i = 0; i < PARTITION_TBL_SIZE; i++)
@@ -1054,16 +1037,320 @@ xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
                  (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
                     PartitionSector->Partition[i].StartingCylinder,
                  PartitionSector->Partition[i].EndingHead,
-                 PartitionSector->Partition[i].EndingSector,
-                 PartitionSector->Partition[i].EndingCylinder,
+                 PartitionSector->Partition[i].EndingSector & 0x3f,
+                 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
+                    PartitionSector->Partition[i].EndingCylinder,
                  PartitionSector->Partition[i].StartingBlock,
                  PartitionSector->Partition[i].SectorCount);
        }
 #endif
 
+      ExtendedFound = FALSE;
+      for (i = 0; i < PARTITION_TBL_SIZE; i++)
+       {
+         if (IsContainerPartition (PartitionSector->Partition[i].PartitionType))
+           {
+             ExtendedFound = TRUE;
+             if (containerOffset == 0ULL)
+               {
+                 containerOffset = PartitionOffset;
+               }
+             nextPartitionOffset = containerOffset +
+               (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
+               (ULONGLONG) SectorSize;
+           }
+
+         /* Handle recognized partition */
+         if (IsRecognizedPartition (PartitionSector->Partition[i].PartitionType))
+           {
+             if (Number == PartitionNumber)
+               {
+                 /* Set partition type */
+                 PartitionSector->Partition[i].PartitionType = PartitionType;
+
+                 /* Write partition sector */
+                 Status = xHalpWriteSector (DeviceObject,
+                                            SectorSize,
+                                            &RealPartitionOffset,
+                                            PartitionSector);
+                 if (!NT_SUCCESS(Status))
+                   {
+                     DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
+                   }
+
+                 ExFreePool (PartitionSector);
+                 return Status;
+               }
+             Number++;
+           }
+       }
+
+      PartitionOffset = nextPartitionOffset;
+    }
+  while (ExtendedFound == TRUE);
+
   ExFreePool(PartitionSector);
 
-  return(STATUS_SUCCESS);
+  return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS FASTCALL
+xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
+                         IN ULONG SectorSize,
+                         IN ULONG SectorsPerTrack,
+                         IN ULONG NumberOfHeads,
+                         IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
+{
+  PPARTITION_SECTOR PartitionSector;
+  LARGE_INTEGER RealPartitionOffset;
+  ULONGLONG PartitionOffset;
+  ULONGLONG NextPartitionOffset;
+  ULONGLONG ContainerOffset;
+  BOOLEAN ContainerEntry;
+  DISK_MANAGER DiskManager;
+  ULONG i;
+  ULONG j;
+  ULONG StartBlock;
+  ULONG SectorCount;
+  ULONG StartCylinder;
+  ULONG StartSector;
+  ULONG StartHead;
+  ULONG EndCylinder;
+  ULONG EndSector;
+  ULONG EndHead;
+  ULONG lba;
+  ULONG x;
+  NTSTATUS Status;
+
+  DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
+         DeviceObject,
+         SectorSize,
+         SectorsPerTrack,
+         NumberOfHeads,
+         PartitionBuffer);
+
+  assert(DeviceObject);
+  assert(PartitionBuffer);
+
+  DiskManager = NoDiskManager;
+
+  /* Check sector size */
+  if (SectorSize < 512)
+    SectorSize = 512;
+  if (SectorSize > 4096)
+    SectorSize = 4096;
+
+  /* Check for 'Ontrack Disk Manager' */
+  xHalExamineMBR (DeviceObject,
+                 SectorSize,
+                 0x54,
+                 (PVOID *) &PartitionSector);
+  if (PartitionSector != NULL)
+    {
+      DPRINT ("Found 'Ontrack Disk Manager'\n");
+      DiskManager = OntrackDiskManager;
+      ExFreePool (PartitionSector);
+    }
+
+  /* Check for 'EZ-Drive' */
+  xHalExamineMBR (DeviceObject,
+                 SectorSize,
+                 0x55,
+                 (PVOID *) &PartitionSector);
+  if (PartitionSector != NULL)
+    {
+      DPRINT ("Found 'EZ-Drive'\n");
+      DiskManager = EZ_Drive;
+      ExFreePool (PartitionSector);
+    }
+
+  /* Allocate partition sector */
+  PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
+                                                     SectorSize);
+  if (PartitionSector == NULL)
+    {
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+  Status = STATUS_SUCCESS;
+  PartitionOffset = 0ULL;
+  ContainerOffset = 0ULL;
+  for (i = 0; i < PartitionBuffer->PartitionCount; i += 4)
+    {
+      DPRINT ("PartitionOffset: %I64u\n", PartitionOffset);
+      DPRINT ("ContainerOffset: %I64u\n", ContainerOffset);
+
+      /* Handle disk managers */
+      if (DiskManager == OntrackDiskManager)
+       {
+         /* Shift offset by 63 sectors */
+         RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
+       }
+      else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
+       {
+         /* Use sector 1 instead of sector 0 */
+         RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
+       }
+      else
+       {
+         RealPartitionOffset.QuadPart = PartitionOffset;
+       }
+
+      /* Write modified partition tables */
+      if (PartitionBuffer->PartitionEntry[i].RewritePartition == TRUE ||
+         PartitionBuffer->PartitionEntry[i + 1].RewritePartition == TRUE ||
+         PartitionBuffer->PartitionEntry[i + 2].RewritePartition == TRUE ||
+         PartitionBuffer->PartitionEntry[i + 3].RewritePartition == TRUE)
+       {
+         /* Read partition sector */
+         Status = xHalpReadSector (DeviceObject,
+                                   SectorSize,
+                                   &RealPartitionOffset,
+                                   PartitionSector);
+         if (!NT_SUCCESS(Status))
+           {
+             DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status);
+             break;
+           }
+
+         /* Initialize a new partition sector */
+         if (PartitionSector->Magic != PARTITION_MAGIC)
+           {
+             /* Create empty partition sector */
+             RtlZeroMemory (PartitionSector,
+                            SectorSize);
+             PartitionSector->Magic = PARTITION_MAGIC;
+           }
+
+         /* Update partition sector entries */
+         for (j = 0; j < 4; j++)
+           {
+             if (PartitionBuffer->PartitionEntry[i + j].RewritePartition == TRUE)
+               {
+                 /* Set partition boot flag */
+                 if (PartitionBuffer->PartitionEntry[i + j].BootIndicator)
+                   {
+                     PartitionSector->Partition[j].BootFlags |= 0x80;
+                   }
+                 else
+                   {
+                     PartitionSector->Partition[j].BootFlags &= ~0x80;
+                   }
+
+                 /* Set partition type */
+                 PartitionSector->Partition[j].PartitionType =
+                   PartitionBuffer->PartitionEntry[i + j].PartitionType;
+
+                 /* Set partition data */
+                 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0ULL &&
+                     PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0ULL)
+                   {
+                     PartitionSector->Partition[j].StartingBlock = 0;
+                     PartitionSector->Partition[j].SectorCount = 0;
+                     PartitionSector->Partition[j].StartingCylinder = 0;
+                     PartitionSector->Partition[j].StartingHead = 0;
+                     PartitionSector->Partition[j].StartingSector = 0;
+                     PartitionSector->Partition[j].EndingCylinder = 0;
+                     PartitionSector->Partition[j].EndingHead = 0;
+                     PartitionSector->Partition[j].EndingSector = 0;
+                   }
+                 else
+                   {
+                     /*
+                      * CHS formulas:
+                      * x = LBA DIV SectorsPerTrack
+                      * cylinder = (x DIV NumberOfHeads) % 1024
+                      * head = x MOD NumberOfHeads
+                      * sector = (LBA MOD SectorsPerTrack) + 1
+                      */
+
+                     /* Compute starting CHS values */
+                     lba = (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart) / SectorSize;
+                     x = lba / SectorsPerTrack;
+                     StartCylinder = (x / NumberOfHeads) %1024;
+                     StartHead = x % NumberOfHeads;
+                     StartSector = (lba % SectorsPerTrack) + 1;
+                     DPRINT ("StartingOffset (LBA:%d  C:%d  H:%d  S:%d)\n",
+                             lba, StartCylinder, StartHead, StartSector);
+
+                     /* Compute ending CHS values */
+                     lba = (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart +
+                            (PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart - 1)) / SectorSize;
+                     x = lba / SectorsPerTrack;
+                     EndCylinder = (x / NumberOfHeads) % 1024;
+                     EndHead = x % NumberOfHeads;
+                     EndSector = (lba % SectorsPerTrack) + 1;
+                     DPRINT ("EndingOffset (LBA:%d  C:%d  H:%d  S:%d)\n",
+                             lba, EndCylinder, EndHead, EndSector);
+
+                     /* Set starting CHS values */
+                     PartitionSector->Partition[j].StartingCylinder = StartCylinder & 0xff;
+                     PartitionSector->Partition[j].StartingHead = StartHead;
+                     PartitionSector->Partition[j].StartingSector =
+                       ((StartCylinder & 0x0300) >> 2) + (StartSector & 0x3f);
+
+                     /* Set ending CHS values */
+                     PartitionSector->Partition[j].EndingCylinder = EndCylinder & 0xff;
+                     PartitionSector->Partition[j].EndingHead = EndHead;
+                     PartitionSector->Partition[j].EndingSector = 
+                       ((EndCylinder & 0x0300) >> 2) + (EndSector & 0x3f);
+
+                     /* Calculate start sector and sector count */
+                     StartBlock =
+                       (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - ContainerOffset) / SectorSize;
+                     SectorCount =
+                       PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart / SectorSize;
+                     DPRINT ("LBA (StartBlock:%lu  SectorCount:%lu)\n",
+                             StartBlock, SectorCount);
+
+                     /* Set start sector and sector count */
+                     PartitionSector->Partition[j].StartingBlock = StartBlock;
+                     PartitionSector->Partition[j].SectorCount = SectorCount;
+                   }
+               }
+           }
+
+         /* Write partition sector */
+         Status = xHalpWriteSector (DeviceObject,
+                                    SectorSize,
+                                    &RealPartitionOffset,
+                                    PartitionSector);
+         if (!NT_SUCCESS(Status))
+           {
+             DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
+             break;
+           }
+       }
+
+      ContainerEntry = FALSE;
+      for (j = 0; j < 4; j++)
+       {
+         if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
+           {
+             ContainerEntry = TRUE;
+             NextPartitionOffset = 
+               PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart;
+
+             if (ContainerOffset == 0ULL)
+               {
+                 ContainerOffset = NextPartitionOffset;
+               }
+           }
+       }
+
+      if (ContainerEntry == FALSE)
+       {
+         DPRINT ("No container entry in partition sector!\n");
+         break;
+       }
+
+      PartitionOffset = NextPartitionOffset;
+    }
+
+  ExFreePool (PartitionSector);
+
+  return Status;
 }
 
 /* EOF */