* FILE: subsys/system/usetup/partlist.c
* PURPOSE: Partition list functions
* PROGRAMMER: Eric Kohl
+ * Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#include <ddk/ntddk.h>
PPARTENTRY PartEntry;
ULONG i;
ULONG EntryCount;
-
+ BOOLEAN LastEntryWasUnused;
+ ULONGLONG LastStartingOffset;
+ ULONGLONG LastPartitionSize;
+ ULONGLONG LastUnusedPartitionSize;
+ ULONG LastUnusedEntry;
/*
* FIXME:
}
else
{
-
-#if 0
- for (i = 0; i < LayoutBuffer->PartitionCount; i++)
- {
-
- }
-#endif
-
EntryCount = LayoutBuffer->PartitionCount;
}
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];
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;
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? */
+ }
}
}
PPARTLIST
-CreatePartitionList(SHORT Left,
- SHORT Top,
- SHORT Right,
- SHORT Bottom)
+CreatePartitionListNoGUI()
{
PPARTLIST List;
OBJECT_ATTRIBUTES ObjectAttributes;
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;
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 *
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)
{
if (PartEntry->Unpartitioned == TRUE)
{
sprintf(LineBuffer,
- " Unpartitioned space %I64u %s",
+ " Unpartitioned space %I64u %s",
PartSize,
Unit);
}
/* 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 */
/* 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 */
{
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;
- }
+ }
}
}
}
/* 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);
{
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;
PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
if (PartEntry->Used == FALSE)
- return(FALSE);
+ {
+ return(FALSE);
+ }
/* Copy disk-specific data */
Data->DiskSize = DiskEntry->DiskSize;
}
/* 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);
}
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++)
{
PartEntry = &DiskEntry->PartArray[i];
if (PartEntry->Used == FALSE)
+ {
return(FALSE);
+ }
/* Copy disk-specific data */
Data->DiskSize = DiskEntry->DiskSize;
}
+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 */