update for HEAD-2003050101
[reactos.git] / subsys / system / usetup / partlist.c
index 6181363..121a628 100644 (file)
@@ -22,6 +22,7 @@
  * FILE:            subsys/system/usetup/partlist.c
  * PURPOSE:         Partition list functions
  * PROGRAMMER:      Eric Kohl
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  */
 
 #include <ddk/ntddk.h>
@@ -47,7 +48,11 @@ AddPartitionList(ULONG DiskNumber,
   PPARTENTRY PartEntry;
   ULONG i;
   ULONG EntryCount;
-
+  BOOLEAN LastEntryWasUnused;
+  ULONGLONG LastStartingOffset;
+  ULONGLONG LastPartitionSize;
+  ULONGLONG LastUnusedPartitionSize;
+  ULONG LastUnusedEntry;
 
   /*
    * FIXME:
@@ -62,14 +67,6 @@ AddPartitionList(ULONG DiskNumber,
     }
   else
     {
-
-#if 0
-  for (i = 0; i < LayoutBuffer->PartitionCount; i++)
-    {
-
-    }
-#endif
-
       EntryCount = LayoutBuffer->PartitionCount;
     }
 
@@ -88,12 +85,21 @@ AddPartitionList(ULONG DiskNumber,
       PartEntry = &DiskEntry->PartArray[0];
 
       PartEntry->Unpartitioned = TRUE;
-      PartEntry->PartSize = 0; /* ?? */
-
-      PartEntry->Used = TRUE;
+      // Start partition at head 1, cylinder 0
+      PartEntry->StartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector;
+      PartEntry->PartSize = DiskEntry->DiskSize - PartEntry->StartingOffset;
+      PartEntry->Used = FALSE;
+      PartEntry->HidePartEntry = FALSE;
+      PartEntry->PartNumber = 1;
     }
   else
     {
+      LastEntryWasUnused = FALSE;
+      // Start partition at head 1, cylinder 0
+      LastStartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector;
+      LastPartitionSize = 0;
+      LastUnusedEntry = -1;
+      LastUnusedPartitionSize = 0;
       for (i = 0; i < LayoutBuffer->PartitionCount; i++)
        {
          PartEntry = &DiskEntry->PartArray[i];
@@ -101,6 +107,18 @@ AddPartitionList(ULONG DiskNumber,
          if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) &&
              (!IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType)))
            {
+        LastUnusedPartitionSize = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart
+          - (LastStartingOffset + LastPartitionSize);
+        if (LastUnusedEntry != -1)
+          {
+            DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize;
+            DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize;
+            DiskEntry->PartArray[LastUnusedEntry].PartNumber = LastUnusedEntry + 1; /* FIXME: Is this always correct? */
+          }
+        LastStartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart;
+        LastPartitionSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
+
+        PartEntry->StartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart;
              PartEntry->PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
              PartEntry->PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber,
              PartEntry->PartType = LayoutBuffer->PartitionEntry[i].PartitionType;
@@ -112,12 +130,37 @@ AddPartitionList(ULONG DiskNumber,
              PartEntry->Unpartitioned = FALSE;
 
              PartEntry->Used = TRUE;
+        PartEntry->HidePartEntry = FALSE;
+        LastEntryWasUnused = FALSE;
+        LastUnusedEntry = -1;
            }
          else
            {
+        if (LastEntryWasUnused)
+          {
+            /* Group unused entries into one unpartitioned disk space area */
+            PartEntry->HidePartEntry = TRUE;
+            PartEntry->PartSize = 0;
+          }
+        else
+          {
+            LastUnusedEntry = i;
+          }
+
+        PartEntry->Unpartitioned = TRUE;
+
              PartEntry->Used = FALSE;
+        LastEntryWasUnused = TRUE;
            }
        }
+      LastUnusedPartitionSize = DiskEntry->DiskSize
+        - (LastStartingOffset + LastPartitionSize);
+      if (LastUnusedEntry != -1)
+        {
+          DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize;
+          DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize;
+          DiskEntry->PartArray[LastUnusedEntry].PartNumber = LastUnusedEntry + 1; /* FIXME: Is this always correct? */
+        }
     }
 }
 
@@ -156,10 +199,7 @@ GetDriverName(PDISKENTRY DiskEntry)
 
 
 PPARTLIST
-CreatePartitionList(SHORT Left,
-                   SHORT Top,
-                   SHORT Right,
-                   SHORT Bottom)
+CreatePartitionListNoGUI()
 {
   PPARTLIST List;
   OBJECT_ATTRIBUTES ObjectAttributes;
@@ -179,10 +219,10 @@ CreatePartitionList(SHORT Left,
   if (List == NULL)
     return(NULL);
 
-  List->Left = Left;
-  List->Top = Top;
-  List->Right = Right;
-  List->Bottom = Bottom;
+  List->Left = 0;
+  List->Top = 0;
+  List->Right = 0;
+  List->Bottom = 0;
 
   List->Line = 0;
 
@@ -259,6 +299,16 @@ CreatePartitionList(SHORT Left,
                                                 sizeof(SCSI_ADDRESS));
 
 
+                 List->DiskArray[DiskNumber].Cylinders = DiskGeometry.Cylinders.QuadPart;
+                 List->DiskArray[DiskNumber].TracksPerCylinder = DiskGeometry.TracksPerCylinder;
+                 List->DiskArray[DiskNumber].SectorsPerTrack = DiskGeometry.SectorsPerTrack;
+                 List->DiskArray[DiskNumber].BytesPerSector = DiskGeometry.BytesPerSector;
+
+      DPRINT("Cylinders %d\n", List->DiskArray[DiskNumber].Cylinders);
+      DPRINT("TracksPerCylinder %d\n", List->DiskArray[DiskNumber].TracksPerCylinder);
+      DPRINT("SectorsPerTrack %d\n", List->DiskArray[DiskNumber].SectorsPerTrack);
+      DPRINT("BytesPerSector %d\n", List->DiskArray[DiskNumber].BytesPerSector);
+
                  List->DiskArray[DiskNumber].DiskSize = 
                    DiskGeometry.Cylinders.QuadPart *
                    (ULONGLONG)DiskGeometry.TracksPerCylinder *
@@ -314,12 +364,191 @@ CreatePartitionList(SHORT Left,
   List->CurrentDisk = 0;
   List->CurrentPartition = 0;
 
+  return(List);
+}
+
+PPARTLIST
+CreatePartitionList(SHORT Left,
+                   SHORT Top,
+                   SHORT Right,
+                   SHORT Bottom)
+{
+  PPARTLIST List;
+
+  List = CreatePartitionListNoGUI();
+  if (List == NULL)
+    return(NULL);
+
+  List->Left = Left;
+  List->Top = Top;
+  List->Right = Right;
+  List->Bottom = Bottom;
+
   DrawPartitionList(List);
 
   return(List);
 }
 
 
+PPARTENTRY
+GetPartitionInformation(PPARTLIST List,
+                       ULONG DiskNumber,
+                       ULONG PartitionNumber,
+                       PULONG PartEntryNumber)
+{
+  PPARTENTRY PartEntry;
+  ULONG i;
+
+  if (List->DiskArray == NULL)
+    {
+      return(FALSE);
+    }
+
+  if (DiskNumber >= List->DiskCount)
+    {
+      return(FALSE);
+    }
+
+  if (PartitionNumber >= List->DiskArray[DiskNumber].PartCount)
+    {
+      return(FALSE);
+    }
+
+  if (List->DiskArray[DiskNumber].FixedDisk != TRUE)
+    {
+      return(FALSE);
+    }
+
+  for (i = 0; i < List->DiskArray[DiskNumber].PartCount; i++)
+    {
+      PartEntry = &List->DiskArray[DiskNumber].PartArray[i];
+      if (PartEntry->PartNumber == PartitionNumber)
+        {
+          *PartEntryNumber = i;
+          return PartEntry;
+        }
+    }
+  return NULL;
+}
+
+BOOLEAN
+MarkPartitionActive(ULONG DiskNumber,
+                       ULONG PartitionNumber,
+                       PPARTDATA ActivePartition)
+{
+  PPARTLIST List;
+  PPARTENTRY PartEntry;
+  ULONG PartEntryNumber;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
+  IO_STATUS_BLOCK Iosb;
+  NTSTATUS Status;
+  WCHAR Buffer[MAX_PATH];
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+
+  List = CreatePartitionListNoGUI();
+  if (List == NULL)
+    {
+      return(FALSE);
+    }
+
+  PartEntry = GetPartitionInformation(List,
+                       DiskNumber,
+                       PartitionNumber,
+                       &PartEntryNumber);
+  if (List == NULL)
+    {
+      DestroyPartitionList(List);
+      return(FALSE);
+    }
+
+
+  swprintf(Buffer,
+    L"\\Device\\Harddisk%d\\Partition0",
+    DiskNumber);
+  RtlInitUnicodeString(&Name, Buffer);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+    &Name,
+    0,
+    NULL,
+    NULL);
+
+  Status = NtOpenFile(&FileHandle,
+    0x10001,
+    &ObjectAttributes,
+    &Iosb,
+    1,
+    FILE_SYNCHRONOUS_IO_NONALERT);
+  if (NT_SUCCESS(Status))
+    {
+         LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
+
+         Status = NtDeviceIoControlFile(FileHandle,
+               NULL,
+               NULL,
+               NULL,
+               &Iosb,
+               IOCTL_DISK_GET_DRIVE_LAYOUT,
+               NULL,
+               0,
+               LayoutBuffer,
+               8192);
+         if (!NT_SUCCESS(Status))
+           {
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          DestroyPartitionList(List);
+          return FALSE;
+        }
+
+
+      LayoutBuffer->PartitionEntry[PartEntryNumber].BootIndicator = TRUE;
+
+      Status = NtDeviceIoControlFile(FileHandle,
+        NULL,
+        NULL,
+        NULL,
+        &Iosb,
+        IOCTL_DISK_SET_DRIVE_LAYOUT,
+        LayoutBuffer,
+        8192,
+        NULL,
+        0);
+      if (!NT_SUCCESS(Status))
+        {
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          DestroyPartitionList(List);
+          return FALSE;
+        }
+    }
+  else
+    {
+      NtClose(FileHandle);
+      RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+      DestroyPartitionList(List);
+      return FALSE;
+    }
+
+  NtClose(FileHandle);
+  RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+
+  PartEntry->Active = TRUE;
+  if (!GetActiveBootPartition(List, ActivePartition))
+  {
+    DestroyPartitionList(List);
+    DPRINT("GetActiveBootPartition() failed\n");
+    return FALSE;
+  }
+
+  DestroyPartitionList(List);
+
+  return TRUE;
+}
+
+
 VOID
 DestroyPartitionList(PPARTLIST List)
 {
@@ -478,7 +707,7 @@ PrintPartitionData(PPARTLIST List,
   if (PartEntry->Unpartitioned == TRUE)
     {
       sprintf(LineBuffer,
-             "    Unpartitioned space              %I64u %s",
+             "    Unpartitioned space           %I64u %s",
              PartSize,
              Unit);
     }
@@ -640,12 +869,12 @@ PrintDiskData(PPARTLIST List,
   /* Print partition lines*/
   for (PartIndex = 0; PartIndex < DiskEntry->PartCount; PartIndex++)
     {
-      if (DiskEntry->PartArray[PartIndex].Used == TRUE)
-       {
-         PrintPartitionData(List,
-                            DiskIndex,
-                            PartIndex);
-       }
+      if (!DiskEntry->PartArray[PartIndex].HidePartEntry)
+        {
+         PrintPartitionData(List,
+                            DiskIndex,
+                            PartIndex);
+        }
     }
 
   /* Print separator line */
@@ -754,12 +983,12 @@ ScrollDownPartitionList(PPARTLIST List)
   /* check for next usable entry on current disk */
   for (i = List->CurrentPartition + 1; i < List->DiskArray[List->CurrentDisk].PartCount; i++)
     {
-      if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE)
-       {
-         List->CurrentPartition = i;
-         DrawPartitionList(List);
-         return;
-       }
+      if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry)
+        {
+         List->CurrentPartition = i;
+         DrawPartitionList(List);
+         return;
+        }
     }
 
   /* check for first usable entry on next disk */
@@ -767,13 +996,13 @@ ScrollDownPartitionList(PPARTLIST List)
     {
       for (i = 0; i < List->DiskArray[j].PartCount; i++)
        {
-         if (List->DiskArray[j].PartArray[i].Used == TRUE)
-           {
+    if (!List->DiskArray[j].PartArray[i].HidePartEntry)
+      {
              List->CurrentDisk = j;
              List->CurrentPartition = i;
              DrawPartitionList(List);
              return;
-           }
+      }
        }
     }
 }
@@ -792,7 +1021,7 @@ ScrollUpPartitionList(PPARTLIST List)
   /* check for previous usable entry on current disk */
   for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--)
     {
-      if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE)
+      if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry)
        {
          List->CurrentPartition = i;
          DrawPartitionList(List);
@@ -805,7 +1034,7 @@ ScrollUpPartitionList(PPARTLIST List)
     {
       for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--)
        {
-         if (List->DiskArray[j].PartArray[i].Used == TRUE)
+    if (!List->DiskArray[j].PartArray[i].HidePartEntry)
            {
              List->CurrentDisk = j;
              List->CurrentPartition = i;
@@ -838,7 +1067,9 @@ GetSelectedPartition(PPARTLIST List,
   PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
 
   if (PartEntry->Used == FALSE)
-    return(FALSE);
+    {
+      return(FALSE);
+    }
 
   /* Copy disk-specific data */
   Data->DiskSize = DiskEntry->DiskSize;
@@ -866,11 +1097,12 @@ GetSelectedPartition(PPARTLIST List,
     }
 
   /* Copy partition-specific data */
+  Data->CreatePartition = FALSE;
+  Data->NewPartSize = 0;
   Data->PartSize = PartEntry->PartSize;
   Data->PartNumber = PartEntry->PartNumber;
   Data->PartType = PartEntry->PartType;
   Data->DriveLetter = PartEntry->DriveLetter;
-
   return(TRUE);
 }
 
@@ -886,10 +1118,12 @@ GetActiveBootPartition(PPARTLIST List,
   if (List->CurrentDisk >= List->DiskCount)
     return(FALSE);
 
-  DiskEntry = &List->DiskArray[0];
+  DiskEntry = &List->DiskArray[List->CurrentDisk];
 
   if (DiskEntry->FixedDisk == FALSE)
+  {
     return(FALSE);
+  }
 
   for (i = 0; i < DiskEntry->PartCount; i++)
     {
@@ -898,7 +1132,9 @@ GetActiveBootPartition(PPARTLIST List,
          PartEntry = &DiskEntry->PartArray[i];
 
          if (PartEntry->Used == FALSE)
+      {
            return(FALSE);
+      }
 
          /* Copy disk-specific data */
          Data->DiskSize = DiskEntry->DiskSize;
@@ -939,4 +1175,221 @@ GetActiveBootPartition(PPARTLIST List,
 }
 
 
+BOOL
+CreateSelectedPartition(PPARTLIST List,
+  ULONG PartType,
+  ULONGLONG NewPartSize)
+{
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+  ULONG PartEntryNumber;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
+  IO_STATUS_BLOCK Iosb;
+  NTSTATUS Status;
+  WCHAR Buffer[MAX_PATH];
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  LARGE_INTEGER li;
+
+  DiskEntry = &List->DiskArray[List->CurrentDisk];
+  PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
+  PartEntry->PartType = PartType;
+  PartEntryNumber = List->CurrentPartition;
+
+  DPRINT("NewPartSize %d (%d MB)\n", NewPartSize, NewPartSize / (1024 * 1024));
+  DPRINT("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset);
+  DPRINT("PartEntry->PartSize %d\n", PartEntry->PartSize);
+  DPRINT("PartEntry->PartNumber %d\n", PartEntry->PartNumber);
+  DPRINT("PartEntry->PartType 0x%x\n", PartEntry->PartType);
+  DPRINT("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName);
+
+  swprintf(Buffer,
+    L"\\Device\\Harddisk%d\\Partition0",
+    DiskEntry->DiskNumber);
+  RtlInitUnicodeString(&Name, Buffer);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+    &Name,
+    0,
+    NULL,
+    NULL);
+
+  Status = NtOpenFile(&FileHandle,
+    0x10001,
+    &ObjectAttributes,
+    &Iosb,
+    1,
+    FILE_SYNCHRONOUS_IO_NONALERT);
+  if (NT_SUCCESS(Status))
+    {
+         LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
+
+         Status = NtDeviceIoControlFile(FileHandle,
+               NULL,
+               NULL,
+               NULL,
+               &Iosb,
+               IOCTL_DISK_GET_DRIVE_LAYOUT,
+               NULL,
+               0,
+               LayoutBuffer,
+               8192);
+         if (!NT_SUCCESS(Status))
+           {
+          DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          return FALSE;
+        }
+
+      li.QuadPart = PartEntry->StartingOffset;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li;
+      li.QuadPart = NewPartSize;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0;  /* FIXME: ? */
+      LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = PartType;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = TRUE;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE;
+
+      Status = NtDeviceIoControlFile(FileHandle,
+        NULL,
+        NULL,
+        NULL,
+        &Iosb,
+        IOCTL_DISK_SET_DRIVE_LAYOUT,
+        LayoutBuffer,
+        8192,
+        NULL,
+        0);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          return FALSE;
+        }
+    }
+  else
+    {
+      DPRINT("NtOpenFile failed() 0x%.08x\n", Status);
+      NtClose(FileHandle);
+      RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+      return FALSE;
+    }
+
+  NtClose(FileHandle);
+  RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+
+  return TRUE;
+}
+
+
+BOOL
+DeleteSelectedPartition(PPARTLIST List)
+{
+  PDISKENTRY DiskEntry;
+  PPARTENTRY PartEntry;
+  ULONG PartEntryNumber;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
+  IO_STATUS_BLOCK Iosb;
+  NTSTATUS Status;
+  WCHAR Buffer[MAX_PATH];
+  UNICODE_STRING Name;
+  HANDLE FileHandle;
+  LARGE_INTEGER li;
+
+  DiskEntry = &List->DiskArray[List->CurrentDisk];
+  PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
+  PartEntry->PartType = PARTITION_ENTRY_UNUSED;
+  PartEntryNumber = List->CurrentPartition;
+
+  DPRINT1("DeleteSelectedPartition(PartEntryNumber = %d)\n", PartEntryNumber);
+  DPRINT1("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset);
+  DPRINT1("PartEntry->PartSize %d\n", PartEntry->PartSize);
+  DPRINT1("PartEntry->PartNumber %d\n", PartEntry->PartNumber);
+  DPRINT1("PartEntry->PartType 0x%x\n", PartEntry->PartType);
+  DPRINT1("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName);
+
+  swprintf(Buffer,
+    L"\\Device\\Harddisk%d\\Partition0",
+    DiskEntry->DiskNumber);
+  RtlInitUnicodeString(&Name, Buffer);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+    &Name,
+    0,
+    NULL,
+    NULL);
+
+  Status = NtOpenFile(&FileHandle,
+    0x10001,
+    &ObjectAttributes,
+    &Iosb,
+    1,
+    FILE_SYNCHRONOUS_IO_NONALERT);
+  if (NT_SUCCESS(Status))
+    {
+         LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
+
+         Status = NtDeviceIoControlFile(FileHandle,
+               NULL,
+               NULL,
+               NULL,
+               &Iosb,
+               IOCTL_DISK_GET_DRIVE_LAYOUT,
+               NULL,
+               0,
+               LayoutBuffer,
+               8192);
+         if (!NT_SUCCESS(Status))
+           {
+          DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          return FALSE;
+        }
+
+      li.QuadPart = 0;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li;
+      li.QuadPart = 0;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = 0;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = FALSE;
+      LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE;
+
+      Status = NtDeviceIoControlFile(FileHandle,
+        NULL,
+        NULL,
+        NULL,
+        &Iosb,
+        IOCTL_DISK_SET_DRIVE_LAYOUT,
+        LayoutBuffer,
+        8192,
+        NULL,
+        0);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
+          NtClose(FileHandle);
+          RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+          return FALSE;
+        }
+    }
+  else
+    {
+      DPRINT("NtOpenFile failed() 0x%.08x\n", Status);
+      NtClose(FileHandle);
+      RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+      return FALSE;
+    }
+
+  NtClose(FileHandle);
+  RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+
+  return TRUE;
+}
+
 /* EOF */