#define NDEBUG
#include <debug.h>
+#define DUMP_PARTITION_TABLE
+
/* FUNCTIONS ****************************************************************/
-static VOID
-GetDriverName (PDISKENTRY DiskEntry)
+#ifdef DUMP_PARTITION_TABLE
+static
+VOID
+DumpPartitionTable(
+ PDISKENTRY DiskEntry)
{
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- WCHAR KeyName[32];
- NTSTATUS Status;
+ PPARTITION_INFORMATION PartitionInfo;
+ ULONG i;
- RtlInitUnicodeString (&DiskEntry->DriverName,
- NULL);
+ for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
+ {
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
+ DbgPrint("%lu: %12I64u %12I64u %10lu %2lu %2x %c %c\n",
+ i,
+ PartitionInfo->StartingOffset.QuadPart,
+ PartitionInfo->PartitionLength.QuadPart,
+ PartitionInfo->HiddenSectors,
+ PartitionInfo->PartitionNumber,
+ PartitionInfo->PartitionType,
+ PartitionInfo->BootIndicator ? '*': ' ',
+ PartitionInfo->RewritePartition ? 'Y': 'N');
+ }
+}
+#endif
- swprintf (KeyName,
- L"\\Scsi\\Scsi Port %lu",
- DiskEntry->Port);
- RtlZeroMemory (&QueryTable,
- sizeof(QueryTable));
+ULONGLONG
+Align(
+ IN ULONGLONG Value,
+ IN ULONG Alignment)
+{
+ ULONGLONG Temp;
- QueryTable[0].Name = L"Driver";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
- QueryTable[0].EntryContext = &DiskEntry->DriverName;
+ Temp = Value / Alignment;
- Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP,
- KeyName,
- QueryTable,
- NULL,
- NULL);
- if (!NT_SUCCESS (Status))
- {
- DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
- }
+ return Temp * Alignment;
}
-static VOID
-AssignDriverLetters (PPARTLIST List)
+ULONGLONG
+RoundingDivide(
+ IN ULONGLONG Dividend,
+ IN ULONGLONG Divisor)
+{
+ return (Dividend + Divisor / 2) / Divisor;
+}
+
+
+static
+VOID
+GetDriverName(
+ PDISKENTRY DiskEntry)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- //PLIST_ENTRY Entry2;
- CHAR Letter;
- UCHAR i;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ WCHAR KeyName[32];
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&DiskEntry->DriverName,
+ NULL);
- Letter = 'C';
+ swprintf(KeyName,
+ L"\\Scsi\\Scsi Port %lu",
+ DiskEntry->Port);
- /* Assign drive letters to primary partitions */
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+ RtlZeroMemory(&QueryTable,
+ sizeof(QueryTable));
- if (!IsListEmpty (&DiskEntry->PartListHead))
+ QueryTable[0].Name = L"Driver";
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].EntryContext = &DiskEntry->DriverName;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
+ KeyName,
+ QueryTable,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
- PARTENTRY,
- ListEntry);
+ DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+ }
+}
- for (i=0; i<4; i++)
- PartEntry->DriveLetter[i] = 0;
- if (PartEntry->Unpartitioned == FALSE)
- {
- for (i=0; i<4; i++)
+static
+VOID
+AssignDriveLetters(
+ PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ CHAR Letter;
+
+ Letter = 'C';
+
+ /* Assign drive letters to primary partitions */
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
{
- if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
- continue;
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (IsRecognizedPartition (PartEntry->PartInfo[i].PartitionType) ||
- (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0LL))
- {
- if (Letter <= 'Z')
+ PartEntry->DriveLetter = 0;
+
+ if (PartEntry->IsPartitioned &&
+ !IsContainerPartition(PartEntry->PartitionType))
{
- PartEntry->DriveLetter[i] = Letter;
- Letter++;
+ if (IsRecognizedPartition(PartEntry->PartitionType) ||
+ (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry->SectorCount.QuadPart != 0LL))
+ {
+ if (Letter <= 'Z')
+ {
+ PartEntry->DriveLetter = Letter;
+ Letter++;
+ }
+ }
}
- }
+
+ Entry2 = Entry2->Flink;
}
- }
- }
- Entry1 = Entry1->Flink;
- }
+ Entry1 = Entry1->Flink;
+ }
- /* Assign drive letters to logical drives */
+ /* Assign drive letters to logical drives */
#if 0
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
-
- Entry2 = DiskEntry->PartListHead.Flink;
- if (Entry2 != &DiskEntry->PartListHead)
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
{
- Entry2 = Entry2->Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2,
- PARTENTRY,
- ListEntry);
-
- PartEntry->DriveLetter = 0;
+ DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
- if (PartEntry->Unpartitioned == FALSE &&
- !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
+ Entry2 = DiskEntry->PartListHead.Flink;
+ if (Entry2 != &DiskEntry->PartListHead)
{
- if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
- {
- if (Letter <= 'Z')
+ Entry2 = Entry2->Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
{
- PartEntry->DriveLetter = Letter;
- Letter++;
+ PartEntry = CONTAINING_RECORD(Entry2,
+ PARTENTRY,
+ ListEntry);
+
+ PartEntry->DriveLetter = 0;
+
+ if (PartEntry->Unpartitioned == FALSE &&
+ !IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
+ {
+ if (IsRecognizedPartition(PartEntry->PartInfo[0].PartitionType) ||
+ (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
+ {
+ if (Letter <= 'Z')
+ {
+ PartEntry->DriveLetter = Letter;
+ Letter++;
+ }
+ }
+ }
+
+ Entry2 = Entry2->Flink;
}
- }
}
- Entry2 = Entry2->Flink;
- }
+ Entry1 = Entry1->Flink;
}
-
- Entry1 = Entry1->Flink;
- }
#endif
}
-static VOID
-UpdatePartitionNumbers (PDISKENTRY DiskEntry)
+static
+VOID
+UpdatePartitionNumbers(
+ PDISKENTRY DiskEntry)
{
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry;
- ULONG PartNumber;
- ULONG i;
-
- PartNumber = 1;
- Entry = DiskEntry->PartListHead.Flink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry,
- PARTENTRY,
- ListEntry);
-
- if (PartEntry->Unpartitioned == TRUE)
- {
- for (i = 0; i < 4; i++)
- {
- PartEntry->PartInfo[i].PartitionNumber = 0;
- }
- }
- else
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+// ULONG PartitionNumber = 1;
+ ULONG PartitionIndex = 0;
+
+ Entry = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry != &DiskEntry->PrimaryPartListHead)
{
- for (i = 0; i < 4; i++)
- {
- if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
- {
- PartEntry->PartInfo[i].PartitionNumber = 0;
- }
- else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
+ PartEntry = CONTAINING_RECORD(Entry,
+ PARTENTRY,
+ ListEntry);
+
+ if (PartEntry->IsPartitioned == FALSE)
{
- PartEntry->PartInfo[i].PartitionNumber = 0;
+// PartEntry->PartitionNumber = 0;
+ PartEntry->PartitionIndex = (ULONG)-1;
}
else
{
- PartEntry->PartInfo[i].PartitionNumber = PartNumber;
- PartNumber++;
+ if (IsContainerPartition(PartEntry->PartitionType))
+ {
+// PartEntry->PartitionNumber = 0;
+ }
+ else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry->SectorCount.QuadPart == 0ULL)
+ {
+// PartEntry->PartitionNumber = 0;
+ }
+ else
+ {
+// PartEntry->PartitionNumber = PartitionNumber++;
+ }
+
+ PartEntry->PartitionIndex = PartitionIndex++;
}
- }
- }
- Entry = Entry->Flink;
- }
+ Entry = Entry->Flink;
+ }
}
-static VOID
-AddPartitionToList (ULONG DiskNumber,
- PDISKENTRY DiskEntry,
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
+NTSTATUS
+NTAPI
+DiskIdentifierQueryRoutine(
+ PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength,
+ PVOID Context,
+ PVOID EntryContext)
{
- PPARTENTRY PartEntry;
- ULONG i;
- ULONG j;
+ PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
+ UNICODE_STRING NameU;
- for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
- {
- for (j = 0; j < 4; j++)
+ if (ValueType == REG_SZ &&
+ ValueLength == 20 * sizeof(WCHAR))
{
- if (LayoutBuffer->PartitionEntry[i+j].PartitionType != PARTITION_ENTRY_UNUSED ||
- LayoutBuffer->PartitionEntry[i+j].PartitionLength.QuadPart != 0ULL)
- {
- break;
- }
- }
- if (j >= 4)
- {
- continue;
- }
-
- PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (PartEntry == NULL)
- {
- return;
- }
-
- RtlZeroMemory (PartEntry,
- sizeof(PARTENTRY));
+ NameU.Buffer = (PWCHAR)ValueData;
+ NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
+ RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
- PartEntry->Unpartitioned = FALSE;
+ NameU.Buffer = (PWCHAR)ValueData + 9;
+ RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
- for (j = 0; j < 4; j++)
- {
- RtlCopyMemory (&PartEntry->PartInfo[j],
- &LayoutBuffer->PartitionEntry[i+j],
- sizeof(PARTITION_INFORMATION));
- }
-
- if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
- {
- PartEntry->FormatState = Unformatted;
- }
- else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
- (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
- {
-#if 0
- if (CheckFatFormat())
- {
- PartEntry->FormatState = Preformatted;
- }
- else
- {
- PartEntry->FormatState = Unformatted;
- }
-#endif
- PartEntry->FormatState = Preformatted;
- }
- else if (PartEntry->PartInfo[0].PartitionType == PARTITION_EXT2)
- {
-#if 0
- if (CheckExt2Format())
- {
- PartEntry->FormatState = Preformatted;
- }
- else
- {
- PartEntry->FormatState = Unformatted;
- }
-#endif
- PartEntry->FormatState = Preformatted;
- }
- else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
- {
-#if 0
- if (CheckNtfsFormat())
- {
- PartEntry->FormatState = Preformatted;
- }
- else if (CheckHpfsFormat())
- {
- PartEntry->FormatState = Preformatted;
- }
- else
- {
- PartEntry->FormatState = Unformatted;
- }
-#endif
- PartEntry->FormatState = Preformatted;
- }
- else
- {
- PartEntry->FormatState = UnknownFormat;
+ return STATUS_SUCCESS;
}
- InsertTailList (&DiskEntry->PartListHead,
- &PartEntry->ListEntry);
- }
+ return STATUS_UNSUCCESSFUL;
}
-static VOID
-ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
+NTSTATUS
+NTAPI
+DiskConfigurationDataQueryRoutine(
+ PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength,
+ PVOID Context,
+ PVOID EntryContext)
{
- ULONGLONG LastStartingOffset;
- ULONGLONG LastPartitionLength;
- ULONGLONG LastUnusedPartitionLength;
- PPARTENTRY PartEntry;
- PPARTENTRY NewPartEntry;
- PLIST_ENTRY Entry;
- ULONG i;
- ULONG j;
-
- if (IsListEmpty (&DiskEntry->PartListHead))
- {
- /* Create a partition table that represents the empty disk */
- PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (PartEntry == NULL)
- return;
-
- RtlZeroMemory (PartEntry,
- sizeof(PARTENTRY));
-
- PartEntry->Unpartitioned = TRUE;
- PartEntry->UnpartitionedOffset = 0ULL;
- PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
-
- PartEntry->FormatState = Unformatted;
-
- InsertTailList (&DiskEntry->PartListHead,
- &PartEntry->ListEntry);
- }
- else
- {
- /* Start partition at head 1, cylinder 0 */
- LastStartingOffset = DiskEntry->TrackSize;
- LastPartitionLength = 0ULL;
- LastUnusedPartitionLength = 0ULL;
-
- i = 0;
- Entry = DiskEntry->PartListHead.Flink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
-
- for (j = 0; j < 4; j++)
- {
- if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
- (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
- PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
- {
- LastUnusedPartitionLength =
- PartEntry->PartInfo[j].StartingOffset.QuadPart -
- (LastStartingOffset + LastPartitionLength);
-
- if (PartEntry->PartInfo[j].StartingOffset.QuadPart > (LastStartingOffset + LastPartitionLength) &&
- LastUnusedPartitionLength >= DiskEntry->CylinderSize)
- {
- DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
-
- NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (NewPartEntry == NULL)
- return;
-
- RtlZeroMemory (NewPartEntry,
- sizeof(PARTENTRY));
-
- NewPartEntry->Unpartitioned = TRUE;
- NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
- NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
- if (j == 0)
- NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;
-
- NewPartEntry->FormatState = Unformatted;
+ PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
+ PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
+ PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
+ ULONG i;
- /* Insert the table into the list */
- InsertTailList (&PartEntry->ListEntry,
- &NewPartEntry->ListEntry);
- }
+ if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
+ ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
+ return STATUS_UNSUCCESSFUL;
- LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
- LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
- }
- }
+ FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
- i += 4;
- Entry = Entry->Flink;
- }
+ /* Hm. Version and Revision are not set on Microsoft Windows XP... */
+#if 0
+ if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
+ FullResourceDescriptor->PartialResourceList.Revision != 1)
+ return STATUS_UNSUCCESSFUL;
+#endif
- /* Check for trailing unpartitioned disk space */
- if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
+ for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
{
- /* Round-down to cylinder size */
- LastUnusedPartitionLength =
- (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength))
- & ~(DiskEntry->CylinderSize - 1);
-
- if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
- {
- DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
-
- NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (NewPartEntry == NULL)
- return;
-
- RtlZeroMemory (NewPartEntry,
- sizeof(PARTENTRY));
+ if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
+ FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
+ continue;
- NewPartEntry->Unpartitioned = TRUE;
- NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
- NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
+ DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
+ BiosDiskEntry->DiskGeometry = *DiskGeometry;
- /* Append the table to the list */
- InsertTailList (&DiskEntry->PartListHead,
- &NewPartEntry->ListEntry);
- }
+ return STATUS_SUCCESS;
}
- }
-}
-NTSTATUS
-NTAPI
-DiskIdentifierQueryRoutine(PWSTR ValueName,
- ULONG ValueType,
- PVOID ValueData,
- ULONG ValueLength,
- PVOID Context,
- PVOID EntryContext)
-{
- PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
- UNICODE_STRING NameU;
-
- if (ValueType == REG_SZ &&
- ValueLength == 20 * sizeof(WCHAR))
- {
- NameU.Buffer = (PWCHAR)ValueData;
- NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
- RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
-
- NameU.Buffer = (PWCHAR)ValueData + 9;
- RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
-
- return STATUS_SUCCESS;
- }
- return STATUS_UNSUCCESSFUL;
+ return STATUS_UNSUCCESSFUL;
}
+
NTSTATUS
NTAPI
-DiskConfigurationDataQueryRoutine(PWSTR ValueName,
- ULONG ValueType,
- PVOID ValueData,
- ULONG ValueLength,
- PVOID Context,
- PVOID EntryContext)
+SystemConfigurationDataQueryRoutine(
+ PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength,
+ PVOID Context,
+ PVOID EntryContext)
{
- PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
- PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
- PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
- ULONG i;
+ PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
+ PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
+ ULONG i;
- if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
- ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
- return STATUS_UNSUCCESSFUL;
+ if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
+ ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR))
+ return STATUS_UNSUCCESSFUL;
- FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
- /* Hm. Version and Revision are not set on Microsoft Windows XP... */
- /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
- FullResourceDescriptor->PartialResourceList.Revision != 1)
- return STATUS_UNSUCCESSFUL;*/
+ FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
- for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
- {
- if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
- FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
- continue;
+ /* Hm. Version and Revision are not set on Microsoft Windows XP... */
+#if 0
+ if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
+ FullResourceDescriptor->PartialResourceList.Revision != 1)
+ return STATUS_UNSUCCESSFUL;
+#endif
- DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
- BiosDiskEntry->DiskGeometry = *DiskGeometry;
+ for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
+ {
+ if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
+ FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
+ continue;
- return STATUS_SUCCESS;
- }
- return STATUS_UNSUCCESSFUL;
-}
+ *Int13Drives = (CM_INT13_DRIVE_PARAMETER*) RtlAllocateHeap(ProcessHeap, 0, FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
+ if (*Int13Drives == NULL)
+ return STATUS_NO_MEMORY;
-NTSTATUS
-NTAPI
-SystemConfigurationDataQueryRoutine(PWSTR ValueName,
- ULONG ValueType,
- PVOID ValueData,
- ULONG ValueLength,
- PVOID Context,
- PVOID EntryContext)
-{
- PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
- PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
- ULONG i;
+ memcpy(*Int13Drives,
+ &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
+ FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
+ return STATUS_SUCCESS;
+ }
- if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
- ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR))
return STATUS_UNSUCCESSFUL;
-
- FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
- /* Hm. Version and Revision are not set on Microsoft Windows XP... */
- /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
- FullResourceDescriptor->PartialResourceList.Revision != 1)
- return STATUS_UNSUCCESSFUL;*/
-
- for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
- {
- if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
- FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
- continue;
-
- *Int13Drives = (CM_INT13_DRIVE_PARAMETER*) RtlAllocateHeap(ProcessHeap, 0, FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
- if (*Int13Drives == NULL)
- return STATUS_NO_MEMORY;
- memcpy(*Int13Drives,
- &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
- FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
- return STATUS_SUCCESS;
- }
- return STATUS_UNSUCCESSFUL;
}
+
+
#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
static VOID
-EnumerateBiosDiskEntries(PPARTLIST PartList)
+EnumerateBiosDiskEntries(
+ PPARTLIST PartList)
{
- RTL_QUERY_REGISTRY_TABLE QueryTable[3];
- WCHAR Name[120];
- ULONG AdapterCount;
- ULONG DiskCount;
- NTSTATUS Status;
- PCM_INT13_DRIVE_PARAMETER Int13Drives;
- PBIOSDISKENTRY BiosDiskEntry;
-
- memset(QueryTable, 0, sizeof(QueryTable));
-
- QueryTable[1].Name = L"Configuration Data";
- QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
- Int13Drives = NULL;
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
- &QueryTable[1],
- (PVOID)&Int13Drives,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
- return;
- }
-
- AdapterCount = 0;
- while (1)
- {
- swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
+ RTL_QUERY_REGISTRY_TABLE QueryTable[3];
+ WCHAR Name[120];
+ ULONG AdapterCount;
+ ULONG DiskCount;
+ NTSTATUS Status;
+ PCM_INT13_DRIVE_PARAMETER Int13Drives;
+ PBIOSDISKENTRY BiosDiskEntry;
+
+ memset(QueryTable, 0, sizeof(QueryTable));
+
+ QueryTable[1].Name = L"Configuration Data";
+ QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
+ Int13Drives = NULL;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[2],
- NULL,
+ L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
+ &QueryTable[1],
+ (PVOID)&Int13Drives,
NULL);
if (!NT_SUCCESS(Status))
{
- break;
+ DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
+ return;
}
- swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- &QueryTable[2],
- NULL,
- NULL);
- if (NT_SUCCESS(Status))
+ AdapterCount = 0;
+ while (1)
{
- while (1)
- {
- swprintf(Name, L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
+ swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[2],
NULL);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap, 0, Int13Drives);
- return;
+ break;
}
- swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
+ swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[2],
NULL);
if (NT_SUCCESS(Status))
{
- QueryTable[0].Name = L"Identifier";
- QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
- QueryTable[1].Name = L"Configuration Data";
- QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
- DiskCount = 0;
- while (1)
- {
- BiosDiskEntry = (BIOSDISKENTRY*) RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
- if (BiosDiskEntry == NULL)
- {
- break;
- }
- swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- Name,
- QueryTable,
- (PVOID)BiosDiskEntry,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
- break;
- }
- BiosDiskEntry->DiskNumber = DiskCount;
- BiosDiskEntry->Recognized = FALSE;
-
- if (DiskCount < Int13Drives[0].NumberDrives)
- {
- BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
- }
- else
+ while (1)
{
- DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
+ swprintf(Name, L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[2],
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+ return;
+ }
+
+ swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[2],
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ QueryTable[0].Name = L"Identifier";
+ QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
+ QueryTable[1].Name = L"Configuration Data";
+ QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
+
+ DiskCount = 0;
+ while (1)
+ {
+ BiosDiskEntry = (BIOSDISKENTRY*) RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
+ if (BiosDiskEntry == NULL)
+ {
+ break;
+ }
+
+ swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ QueryTable,
+ (PVOID)BiosDiskEntry,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
+ break;
+ }
+
+ BiosDiskEntry->DiskNumber = DiskCount;
+ BiosDiskEntry->Recognized = FALSE;
+
+ if (DiskCount < Int13Drives[0].NumberDrives)
+ {
+ BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
+ }
+ else
+ {
+ DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
+ }
+
+ InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
+
+ DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
+ DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
+ DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
+ DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
+ DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
+ DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
+ DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
+ DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
+ DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
+ DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
+ DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
+
+ DiskCount++;
+ }
+ }
+
+ RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+ return;
}
-
-
- InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
-
- DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
- DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
- DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
- DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
- DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
- DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
- DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
- DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
- DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
- DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
- DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
-
- DiskCount++;
- }
}
- RtlFreeHeap(ProcessHeap, 0, Int13Drives);
- return;
- }
+
+ AdapterCount++;
}
- AdapterCount++;
- }
- RtlFreeHeap(ProcessHeap, 0, Int13Drives);
-}
-static VOID
-AddDiskToList (HANDLE FileHandle,
- ULONG DiskNumber,
- PPARTLIST List)
-{
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
- DISK_GEOMETRY DiskGeometry;
- SCSI_ADDRESS ScsiAddress;
- PDISKENTRY DiskEntry;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
- PPARTITION_SECTOR Mbr;
- PULONG Buffer;
- LARGE_INTEGER FileOffset;
- WCHAR Identifier[20];
- ULONG Checksum;
- ULONG Signature;
- ULONG i;
- PLIST_ENTRY ListEntry;
- PBIOSDISKENTRY BiosDiskEntry;
- ULONG LayoutBufferSize;
-
- Status = NtDeviceIoControlFile (FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_GET_DRIVE_GEOMETRY,
- NULL,
- 0,
- &DiskGeometry,
- sizeof(DISK_GEOMETRY));
- if (!NT_SUCCESS (Status))
- {
- return;
- }
-
- if (DiskGeometry.MediaType != FixedMedia &&
- DiskGeometry.MediaType != RemovableMedia)
- {
- return;
- }
-
- Status = NtDeviceIoControlFile (FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_SCSI_GET_ADDRESS,
- NULL,
- 0,
- &ScsiAddress,
- sizeof(SCSI_ADDRESS));
- if (!NT_SUCCESS(Status))
- {
- return;
- }
-
- Mbr = (PARTITION_SECTOR*) RtlAllocateHeap(ProcessHeap,
- 0,
- DiskGeometry.BytesPerSector);
-
- if (Mbr == NULL)
- {
- return;
- }
-
- FileOffset.QuadPart = 0;
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- (PVOID)Mbr,
- DiskGeometry.BytesPerSector,
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(ProcessHeap,
- 0,
- Mbr);
- DPRINT1("NtReadFile failed, status=%x\n", Status);
- return;
- }
- Signature = Mbr->Signature;
-
- /* Calculate the MBR checksum */
- Checksum = 0;
- Buffer = (PULONG)Mbr;
- for (i = 0; i < 128; i++)
- {
- Checksum += Buffer[i];
- }
- Checksum = ~Checksum + 1;
-
- swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
- DPRINT("Identifier: %S\n", Identifier);
-
- DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(DISKENTRY));
- if (DiskEntry == NULL)
- {
- return;
- }
-
- DiskEntry->Checksum = Checksum;
- DiskEntry->Signature = Signature;
- if (Signature == 0)
- {
- /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
- DiskEntry->Modified = TRUE;
- }
- DiskEntry->BiosFound = FALSE;
-
- /* Check if this disk has a valid MBR */
- if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
- DiskEntry->NoMbr = TRUE;
- else
- DiskEntry->NoMbr = FALSE;
-
- /* Free Mbr sector buffer */
- RtlFreeHeap (ProcessHeap,
- 0,
- Mbr);
-
- ListEntry = List->BiosDiskListHead.Flink;
- while(ListEntry != &List->BiosDiskListHead)
- {
- BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
- /* FIXME:
- * Compare the size from bios and the reported size from driver.
- * If we have more than one disk with a zero or with the same signatur
- * we must create new signatures and reboot. After the reboot,
- * it is possible to identify the disks.
- */
- if (BiosDiskEntry->Signature == Signature &&
- BiosDiskEntry->Checksum == Checksum &&
- !BiosDiskEntry->Recognized)
- {
- if (!DiskEntry->BiosFound)
- {
- DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
- DiskEntry->BiosFound = TRUE;
- BiosDiskEntry->Recognized = TRUE;
- }
- else
- {
- }
- }
- ListEntry = ListEntry->Flink;
- }
-
- if (!DiskEntry->BiosFound)
- {
-#if 0
- RtlFreeHeap(ProcessHeap, 0, DiskEntry);
- return;
-#else
- DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
-#endif
- }
-
- InitializeListHead (&DiskEntry->PartListHead);
-
- DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
- DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
- DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
- DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
-
- DPRINT ("Cylinders %I64u\n", DiskEntry->Cylinders);
- DPRINT ("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
- DPRINT ("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
- DPRINT ("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
-
- DiskEntry->TrackSize =
- (ULONGLONG)DiskGeometry.SectorsPerTrack *
- (ULONGLONG)DiskGeometry.BytesPerSector;
- DiskEntry->CylinderSize =
- (ULONGLONG)DiskGeometry.TracksPerCylinder *
- DiskEntry->TrackSize;
- DiskEntry->DiskSize =
- DiskGeometry.Cylinders.QuadPart *
- DiskEntry->CylinderSize;
-
- DiskEntry->DiskNumber = DiskNumber;
- DiskEntry->Port = ScsiAddress.PortNumber;
- DiskEntry->Bus = ScsiAddress.PathId;
- DiskEntry->Id = ScsiAddress.TargetId;
-
- GetDriverName (DiskEntry);
-
- InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
-
- /*
- * Allocate a buffer for 26 logical drives (2 entries each == 52)
- * plus the main partiton table (4 entries). Total 56 entries.
- */
- LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
- ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
- LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
- 0,
- LayoutBufferSize);
- if (LayoutBuffer == NULL)
- {
- return;
- }
-
- Status = NtDeviceIoControlFile (FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_GET_DRIVE_LAYOUT,
- NULL,
- 0,
- LayoutBuffer,
- LayoutBufferSize);
- if (NT_SUCCESS (Status))
- {
- if (LayoutBuffer->PartitionCount == 0)
- {
- DiskEntry->NewDisk = TRUE;
- }
-
- AddPartitionToList (DiskNumber,
- DiskEntry,
- LayoutBuffer);
-
- ScanForUnpartitionedDiskSpace (DiskEntry);
- }
-
- RtlFreeHeap (ProcessHeap,
- 0,
- LayoutBuffer);
+ RtlFreeHeap(ProcessHeap, 0, Int13Drives);
}
-PPARTLIST
-CreatePartitionList (SHORT Left,
- SHORT Top,
- SHORT Right,
- SHORT Bottom)
+static
+VOID
+AddPartitionToDisk(
+ ULONG DiskNumber,
+ PDISKENTRY DiskEntry,
+ ULONG PartitionIndex,
+ BOOLEAN LogicalPartition)
{
- PPARTLIST List;
- OBJECT_ATTRIBUTES ObjectAttributes;
- SYSTEM_DEVICE_INFORMATION Sdi;
- IO_STATUS_BLOCK Iosb;
- ULONG ReturnSize;
- NTSTATUS Status;
- ULONG DiskNumber;
- WCHAR Buffer[MAX_PATH];
- UNICODE_STRING Name;
- HANDLE FileHandle;
-
- List = (PPARTLIST)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof (PARTLIST));
- if (List == NULL)
- return NULL;
+ PPARTITION_INFORMATION PartitionInfo;
+ PPARTENTRY PartEntry;
- List->Left = Left;
- List->Top = Top;
- List->Right = Right;
- List->Bottom = Bottom;
-
- List->Line = 0;
- List->Offset = 0;
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
+ if (PartitionInfo->PartitionType == 0 ||
+ (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType)))
+ return;
- List->TopDisk = (ULONG)-1;
- List->TopPartition = (ULONG)-1;
+ PartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (PartEntry == NULL)
+ {
+ return;
+ }
- List->CurrentDisk = NULL;
- List->CurrentPartition = NULL;
- List->CurrentPartitionNumber = 0;
+ PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
+ PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
- InitializeListHead (&List->DiskListHead);
- InitializeListHead (&List->BiosDiskListHead);
+ PartEntry->BootIndicator = PartitionInfo->BootIndicator;
+ PartEntry->PartitionType = PartitionInfo->PartitionType;
+ PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
- EnumerateBiosDiskEntries(List);
+ PartEntry->LogicalPartition = LogicalPartition;
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ PartEntry->PartitionIndex = PartitionIndex;
- Status = NtQuerySystemInformation (SystemDeviceInformation,
- &Sdi,
- sizeof(SYSTEM_DEVICE_INFORMATION),
- &ReturnSize);
- if (!NT_SUCCESS (Status))
- {
- RtlFreeHeap (ProcessHeap, 0, List);
- return NULL;
- }
-
- for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
- {
- swprintf (Buffer,
- L"\\Device\\Harddisk%d\\Partition0",
- DiskNumber);
- RtlInitUnicodeString (&Name,
- Buffer);
-
- InitializeObjectAttributes (&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
-
- Status = NtOpenFile (&FileHandle,
- FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
- &ObjectAttributes,
- &Iosb,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (NT_SUCCESS(Status))
+ if (IsContainerPartition(PartEntry->PartitionType))
{
- AddDiskToList (FileHandle,
- DiskNumber,
- List);
+ PartEntry->FormatState = Unformatted;
- NtClose(FileHandle);
+ if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
+ DiskEntry->ExtendedPartition = PartEntry;
}
- }
-
- AssignDriverLetters (List);
-
- List->TopDisk = 0;
- List->TopPartition = 0;
-
- /* Search for first usable disk and partition */
- if (IsListEmpty (&List->DiskListHead))
- {
- List->CurrentDisk = NULL;
- List->CurrentPartition = NULL;
- List->CurrentPartitionNumber = 0;
- }
- else
- {
- List->CurrentDisk =
- CONTAINING_RECORD (List->DiskListHead.Flink,
- DISKENTRY,
- ListEntry);
-
- if (IsListEmpty (&List->CurrentDisk->PartListHead))
+ else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+ (PartEntry->PartitionType == PARTITION_FAT_16) ||
+ (PartEntry->PartitionType == PARTITION_HUGE) ||
+ (PartEntry->PartitionType == PARTITION_XINT13) ||
+ (PartEntry->PartitionType == PARTITION_FAT32) ||
+ (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
+ {
+#if 0
+ if (CheckFatFormat())
+ {
+ PartEntry->FormatState = Preformatted;
+ }
+ else
+ {
+ PartEntry->FormatState = Unformatted;
+ }
+#endif
+ PartEntry->FormatState = Preformatted;
+ }
+ else if (PartEntry->PartitionType == PARTITION_EXT2)
+ {
+#if 0
+ if (CheckExt2Format())
+ {
+ PartEntry->FormatState = Preformatted;
+ }
+ else
+ {
+ PartEntry->FormatState = Unformatted;
+ }
+#endif
+ PartEntry->FormatState = Preformatted;
+ }
+ else if (PartEntry->PartitionType == PARTITION_IFS)
{
- List->CurrentPartition = 0;
- List->CurrentPartitionNumber = 0;
+#if 0
+ if (CheckNtfsFormat())
+ {
+ PartEntry->FormatState = Preformatted;
+ }
+ else if (CheckHpfsFormat())
+ {
+ PartEntry->FormatState = Preformatted;
+ }
+ else
+ {
+ PartEntry->FormatState = Unformatted;
+ }
+#endif
+ PartEntry->FormatState = Preformatted;
}
else
{
- List->CurrentPartition =
- CONTAINING_RECORD (List->CurrentDisk->PartListHead.Flink,
- PARTENTRY,
- ListEntry);
- List->CurrentPartitionNumber = 0;
+ PartEntry->FormatState = UnknownFormat;
}
- }
- return List;
+ if (LogicalPartition)
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &PartEntry->ListEntry);
+ else
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &PartEntry->ListEntry);
}
+static
VOID
-DestroyPartitionList (PPARTLIST List)
+ScanForUnpartitionedDiskSpace(
+ PDISKENTRY DiskEntry)
{
- PDISKENTRY DiskEntry;
- PBIOSDISKENTRY BiosDiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry;
+ ULONGLONG LastStartSector;
+ ULONGLONG LastSectorCount;
+ ULONGLONG LastUnusedSectorCount;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
+ PLIST_ENTRY Entry;
- /* Release disk and partition info */
- while (!IsListEmpty (&List->DiskListHead))
- {
- Entry = RemoveHeadList (&List->DiskListHead);
- DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
+ DPRINT1("ScanForUnpartitionedDiskSpace()\n");
- /* Release driver name */
- RtlFreeUnicodeString(&DiskEntry->DriverName);
-
- /* Release partition array */
- while (!IsListEmpty (&DiskEntry->PartListHead))
+ if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
{
- Entry = RemoveHeadList (&DiskEntry->PartListHead);
- PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
+ DPRINT1("No primary partition!\n");
+
+ /* Create a partition table that represents the empty disk */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorsPerTrack;
+ NewPartEntry->SectorCount.QuadPart = Align(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
+ DiskEntry->SectorsPerTrack;
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
- RtlFreeHeap (ProcessHeap,
- 0,
- PartEntry);
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &NewPartEntry->ListEntry);
+
+ return;
}
- /* Release disk entry */
- RtlFreeHeap (ProcessHeap, 0, DiskEntry);
- }
+ /* Start partition at head 1, cylinder 0 */
+ LastStartSector = DiskEntry->SectorsPerTrack;
+ LastSectorCount = 0ULL;
+ LastUnusedSectorCount = 0ULL;
- /* release the bios disk info */
- while(!IsListEmpty(&List->BiosDiskListHead))
- {
- Entry = RemoveHeadList(&List->BiosDiskListHead);
- BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
+ Entry = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
- }
+ if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
+ PartEntry->SectorCount.QuadPart != 0ULL)
+ {
+ LastUnusedSectorCount =
+ PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
- /* Release list head */
- RtlFreeHeap (ProcessHeap, 0, List);
-}
+ if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
+ LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+ {
+ DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
-static VOID
-PrintEmptyLine (PPARTLIST List)
-{
- COORD coPos;
- DWORD Written;
- USHORT Width;
- USHORT Height;
+ NewPartEntry->DiskEntry = DiskEntry;
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+ NewPartEntry->FormatState = Unformatted;
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ /* Insert the table into the list */
+ InsertTailList(&PartEntry->ListEntry,
+ &NewPartEntry->ListEntry);
+ }
- if (List->Line >= 0 && List->Line <= Height)
- {
- FillConsoleOutputAttribute (StdOutput,
- FOREGROUND_WHITE | BACKGROUND_BLUE,
- Width,
- coPos,
- &Written);
+ LastStartSector = PartEntry->StartSector.QuadPart;
+ LastSectorCount = PartEntry->SectorCount.QuadPart;
+ }
- FillConsoleOutputCharacterA (StdOutput,
- ' ',
- Width,
- coPos,
- &Written);
- }
- List->Line++;
-}
+ Entry = Entry->Flink;
+ }
+ /* Check for trailing unpartitioned disk space */
+ if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
+ {
+ LastUnusedSectorCount = Align(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
-static VOID
-PrintPartitionData (PPARTLIST List,
- PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry,
- ULONG PartNumber)
-{
- CHAR LineBuffer[128];
- COORD coPos;
- DWORD Written;
- USHORT Width;
- USHORT Height;
+ if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+ {
+ DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
- LARGE_INTEGER PartSize;
- PCHAR Unit;
- UCHAR Attribute;
- PCHAR PartType;
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ NewPartEntry->FormatState = Unformatted;
- if (PartEntry->Unpartitioned == TRUE)
- {
-#if 0
- if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
- {
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
- Unit = MUIGetString(STRING_GB);
+ /* Append the table to the list */
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &NewPartEntry->ListEntry);
+ }
}
- else
-#endif
- if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
- {
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
- Unit = MUIGetString(STRING_MB);
- }
- else
- {
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
- Unit = MUIGetString(STRING_KB);
- }
-
- sprintf (LineBuffer,
- MUIGetString(STRING_UNPSPACE),
- PartSize.u.LowPart,
- Unit);
- }
- else
- {
- /* Determine partition type */
- PartType = NULL;
- if (PartEntry->New == TRUE)
- {
- PartType = MUIGetString(STRING_UNFORMATTED);
- }
- else if (PartEntry->Unpartitioned == FALSE)
- {
- if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
- (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
- (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
- (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
- {
- PartType = "FAT";
- }
- else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
- (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
- {
- PartType = "FAT32";
- }
- else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
- {
- PartType = "EXT2";
- }
- else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
- {
- PartType = "NTFS"; /* FIXME: Not quite correct! */
- }
+
+ if (DiskEntry->ExtendedPartition != NULL)
+ {
+ if (IsListEmpty(&DiskEntry->LogicalPartListHead))
+ {
+ DPRINT1("No logical partition!\n");
+
+ /* Create a partition table entry that represents the empty extended partition */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->LogicalPartition = TRUE;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+ NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack;
+
+ DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
+
+ return;
+ }
+
+ /* Start partition at head 1, cylinder 0 */
+ LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+ LastSectorCount = 0ULL;
+ LastUnusedSectorCount = 0ULL;
+
+ Entry = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry != &DiskEntry->LogicalPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
+ PartEntry->SectorCount.QuadPart != 0ULL)
+ {
+ LastUnusedSectorCount =
+ PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack - (LastStartSector + LastSectorCount);
+
+ if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack) > (LastStartSector + LastSectorCount) &&
+ LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+ {
+ DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
+
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->LogicalPartition = TRUE;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+
+ /* Insert the table into the list */
+ InsertTailList(&PartEntry->ListEntry,
+ &NewPartEntry->ListEntry);
+ }
+
+ LastStartSector = PartEntry->StartSector.QuadPart;
+ LastSectorCount = PartEntry->SectorCount.QuadPart;
+ }
+
+ Entry = Entry->Flink;
+ }
+
+ /* Check for trailing unpartitioned disk space */
+ if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
+ {
+ LastUnusedSectorCount = Align(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
+
+ if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+ {
+ DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
+
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->LogicalPartition = TRUE;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+
+ /* Append the table to the list */
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
+ }
+ }
+ }
+
+ DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
+}
+
+
+static
+VOID
+SetDiskSignature(
+ IN PPARTLIST List,
+ IN PDISKENTRY DiskEntry)
+{
+ LARGE_INTEGER SystemTime;
+ TIME_FIELDS TimeFields;
+ PLIST_ENTRY Entry2;
+ PDISKENTRY DiskEntry2;
+ PUCHAR Buffer;
+
+ Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
+
+ while (1)
+ {
+ NtQuerySystemTime(&SystemTime);
+ RtlTimeToTimeFields(&SystemTime, &TimeFields);
+
+ Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
+ Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
+ Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
+ Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
+
+ if (DiskEntry->LayoutBuffer->Signature == 0)
+ {
+ continue;
+ }
+
+ /* check if the signature already exist */
+ /* FIXME:
+ * Check also signatures from disks, which are
+ * not visible (bootable) by the bios.
+ */
+ Entry2 = List->DiskListHead.Flink;
+ while (Entry2 != &List->DiskListHead)
+ {
+ DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
+
+ if (DiskEntry != DiskEntry2 &&
+ DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
+ break;
+
+ Entry2 = Entry2->Flink;
+ }
+
+ if (Entry2 == &List->DiskListHead)
+ break;
+ }
+}
+
+
+static
+VOID
+UpdateDiskSignatures(
+ PPARTLIST List)
+{
+ PLIST_ENTRY Entry;
+ PDISKENTRY DiskEntry;
+
+ /* Print partition lines*/
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+ if (DiskEntry->LayoutBuffer &&
+ DiskEntry->LayoutBuffer->Signature == 0)
+ {
+ SetDiskSignature(List, DiskEntry);
+ DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
+ }
+
+ Entry = Entry->Flink;
+ }
+}
+
+
+static
+VOID
+AddDiskToList(
+ HANDLE FileHandle,
+ ULONG DiskNumber,
+ PPARTLIST List)
+{
+ DISK_GEOMETRY DiskGeometry;
+ SCSI_ADDRESS ScsiAddress;
+ PDISKENTRY DiskEntry;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ PPARTITION_SECTOR Mbr;
+ PULONG Buffer;
+ LARGE_INTEGER FileOffset;
+ WCHAR Identifier[20];
+ ULONG Checksum;
+ ULONG Signature;
+ ULONG i;
+ PLIST_ENTRY ListEntry;
+ PBIOSDISKENTRY BiosDiskEntry;
+ ULONG LayoutBufferSize;
+
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &DiskGeometry,
+ sizeof(DISK_GEOMETRY));
+ if (!NT_SUCCESS(Status))
+ {
+ return;
+ }
+
+ if (DiskGeometry.MediaType != FixedMedia &&
+ DiskGeometry.MediaType != RemovableMedia)
+ {
+ return;
+ }
+
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_SCSI_GET_ADDRESS,
+ NULL,
+ 0,
+ &ScsiAddress,
+ sizeof(SCSI_ADDRESS));
+ if (!NT_SUCCESS(Status))
+ {
+ return;
+ }
+
+ Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
+ 0,
+ DiskGeometry.BytesPerSector);
+ if (Mbr == NULL)
+ {
+ return;
+ }
+
+ FileOffset.QuadPart = 0;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ (PVOID)Mbr,
+ DiskGeometry.BytesPerSector,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Mbr);
+ DPRINT1("NtReadFile failed, status=%x\n", Status);
+ return;
+ }
+ Signature = Mbr->Signature;
+
+ /* Calculate the MBR checksum */
+ Checksum = 0;
+ Buffer = (PULONG)Mbr;
+ for (i = 0; i < 128; i++)
+ {
+ Checksum += Buffer[i];
+ }
+ Checksum = ~Checksum + 1;
+
+ swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
+ DPRINT("Identifier: %S\n", Identifier);
+
+ DiskEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(DISKENTRY));
+ if (DiskEntry == NULL)
+ {
+ return;
+ }
+
+// DiskEntry->Checksum = Checksum;
+// DiskEntry->Signature = Signature;
+ DiskEntry->BiosFound = FALSE;
+
+ /* Check if this disk has a valid MBR */
+ if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
+ DiskEntry->NoMbr = TRUE;
+ else
+ DiskEntry->NoMbr = FALSE;
+
+ /* Free Mbr sector buffer */
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Mbr);
+
+ ListEntry = List->BiosDiskListHead.Flink;
+ while(ListEntry != &List->BiosDiskListHead)
+ {
+ BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+ /* FIXME:
+ * Compare the size from bios and the reported size from driver.
+ * If we have more than one disk with a zero or with the same signatur
+ * we must create new signatures and reboot. After the reboot,
+ * it is possible to identify the disks.
+ */
+ if (BiosDiskEntry->Signature == Signature &&
+ BiosDiskEntry->Checksum == Checksum &&
+ !BiosDiskEntry->Recognized)
+ {
+ if (!DiskEntry->BiosFound)
+ {
+ DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+ DiskEntry->BiosFound = TRUE;
+ BiosDiskEntry->Recognized = TRUE;
+ }
+ else
+ {
+ }
+ }
+ ListEntry = ListEntry->Flink;
+ }
+
+ if (!DiskEntry->BiosFound)
+ {
+#if 0
+ RtlFreeHeap(ProcessHeap, 0, DiskEntry);
+ return;
+#else
+ DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
+#endif
+ }
+
+ InitializeListHead(&DiskEntry->PrimaryPartListHead);
+ InitializeListHead(&DiskEntry->LogicalPartListHead);
+
+ DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
+ DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
+ DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
+ DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
+
+ DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
+ DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
+ DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
+ DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
+
+ DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
+ (ULONGLONG)DiskGeometry.TracksPerCylinder *
+ (ULONGLONG)DiskGeometry.SectorsPerTrack;
+
+ DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
+
+ DPRINT1("SectorCount %I64u\n", DiskEntry->SectorCount);
+ DPRINT1("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
+
+ DiskEntry->DiskNumber = DiskNumber;
+ DiskEntry->Port = ScsiAddress.PortNumber;
+ DiskEntry->Bus = ScsiAddress.PathId;
+ DiskEntry->Id = ScsiAddress.TargetId;
+
+ GetDriverName(DiskEntry);
+
+ InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
+
+ /*
+ * Allocate a buffer for 26 logical drives (2 entries each == 52)
+ * plus the main partiton table (4 entries). Total 56 entries.
+ */
+ LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+ ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+ DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ LayoutBufferSize);
+ if (DiskEntry->LayoutBuffer == NULL)
+ {
+ return;
+ }
+
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_DISK_GET_DRIVE_LAYOUT,
+ NULL,
+ 0,
+ DiskEntry->LayoutBuffer,
+ LayoutBufferSize);
+ if (NT_SUCCESS(Status))
+ {
+#ifdef DUMP_PARTITION_TABLE
+ DumpPartitionTable(DiskEntry);
+#endif
+
+ if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
+ DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
+ DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
+ {
+ if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
+ {
+ DPRINT1("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
+ }
+ else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % 1048756 == 0)
+ {
+ DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+ }
+ else
+ {
+ DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
+ }
+ }
+ else
+ {
+ DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+ }
+
+
+ if (DiskEntry->LayoutBuffer->PartitionCount == 0)
+ {
+ DiskEntry->NewDisk = TRUE;
+ DiskEntry->LayoutBuffer->PartitionCount = 4;
+
+ for (i = 0; i < 4; i++)
+ DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+ }
+ else
+ {
+ for (i = 0; i < 4; i++)
+ {
+ AddPartitionToDisk(DiskNumber,
+ DiskEntry,
+ i,
+ FALSE);
+ }
+
+ for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
+ {
+ AddPartitionToDisk(DiskNumber,
+ DiskEntry,
+ i,
+ TRUE);
+ }
+ }
+ }
+
+ ScanForUnpartitionedDiskSpace(DiskEntry);
+}
+
+
+PPARTLIST
+CreatePartitionList(
+ SHORT Left,
+ SHORT Top,
+ SHORT Right,
+ SHORT Bottom)
+{
+ PPARTLIST List;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ SYSTEM_DEVICE_INFORMATION Sdi;
+ IO_STATUS_BLOCK Iosb;
+ ULONG ReturnSize;
+ NTSTATUS Status;
+ ULONG DiskNumber;
+ WCHAR Buffer[MAX_PATH];
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+
+ List = (PPARTLIST)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof (PARTLIST));
+ if (List == NULL)
+ return NULL;
+
+ List->Left = Left;
+ List->Top = Top;
+ List->Right = Right;
+ List->Bottom = Bottom;
+
+ List->Line = 0;
+ List->Offset = 0;
+
+ List->TopDisk = (ULONG)-1;
+ List->TopPartition = (ULONG)-1;
+
+ List->CurrentDisk = NULL;
+ List->CurrentPartition = NULL;
+
+ InitializeListHead(&List->DiskListHead);
+ InitializeListHead(&List->BiosDiskListHead);
+
+ EnumerateBiosDiskEntries(List);
+
+ Status = NtQuerySystemInformation(SystemDeviceInformation,
+ &Sdi,
+ sizeof(SYSTEM_DEVICE_INFORMATION),
+ &ReturnSize);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, List);
+ return NULL;
+ }
+
+ for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
+ {
+ swprintf(Buffer,
+ L"\\Device\\Harddisk%d\\Partition0",
+ DiskNumber);
+ RtlInitUnicodeString(&Name,
+ Buffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes,
+ &Iosb,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (NT_SUCCESS(Status))
+ {
+ AddDiskToList(FileHandle,
+ DiskNumber,
+ List);
+
+ NtClose(FileHandle);
+ }
+ }
+
+ UpdateDiskSignatures(List);
+
+ AssignDriveLetters(List);
+
+ List->TopDisk = 0;
+ List->TopPartition = 0;
+
+ /* Search for first usable disk and partition */
+ if (IsListEmpty(&List->DiskListHead))
+ {
+ List->CurrentDisk = NULL;
+ List->CurrentPartition = NULL;
+ }
+ else
+ {
+ List->CurrentDisk = CONTAINING_RECORD(List->DiskListHead.Flink,
+ DISKENTRY,
+ ListEntry);
+
+ if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
+ {
+ List->CurrentPartition = 0;
+ }
+ else
+ {
+ List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
+ PARTENTRY,
+ ListEntry);
+ }
+ }
+
+ return List;
+}
+
+
+VOID
+DestroyPartitionList(
+ PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PBIOSDISKENTRY BiosDiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+
+ /* Release disk and partition info */
+ while (!IsListEmpty(&List->DiskListHead))
+ {
+ Entry = RemoveHeadList(&List->DiskListHead);
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+ /* Release driver name */
+ RtlFreeUnicodeString(&DiskEntry->DriverName);
+
+ /* Release primary partition list */
+ while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
+ {
+ Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ }
+
+ /* Release logical partition list */
+ while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
+ {
+ Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ }
+
+ /* Release layout buffer */
+ if (DiskEntry->LayoutBuffer != NULL)
+ RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
+
+
+ /* Release disk entry */
+ RtlFreeHeap(ProcessHeap, 0, DiskEntry);
+ }
+
+ /* release the bios disk info */
+ while(!IsListEmpty(&List->BiosDiskListHead))
+ {
+ Entry = RemoveHeadList(&List->BiosDiskListHead);
+ BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
+
+ RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
+ }
+
+ /* Release list head */
+ RtlFreeHeap(ProcessHeap, 0, List);
+}
+
+
+static
+VOID
+PrintEmptyLine(
+ PPARTLIST List)
+{
+ COORD coPos;
+ DWORD Written;
+ USHORT Width;
+ USHORT Height;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute(StdOutput,
+ FOREGROUND_WHITE | BACKGROUND_BLUE,
+ Width,
+ coPos,
+ &Written);
+
+ FillConsoleOutputCharacterA(StdOutput,
+ ' ',
+ Width,
+ coPos,
+ &Written);
+ }
+
+ List->Line++;
+}
+
+
+static
+VOID
+PrintPartitionData(
+ PPARTLIST List,
+ PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
+{
+ CHAR LineBuffer[128];
+ COORD coPos;
+ DWORD Written;
+ USHORT Width;
+ USHORT Height;
+ LARGE_INTEGER PartSize;
+ PCHAR Unit;
+ UCHAR Attribute;
+ PCHAR PartType;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+ if (PartEntry->IsPartitioned == FALSE)
+ {
+ PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+#if 0
+ if (PartSize.QuadPart >= 10737418240) /* 10 GB */
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
+ Unit = MUIGetString(STRING_GB);
+ }
+ else
+#endif
+ if (PartSize.QuadPart >= 10485760) /* 10 MB */
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
+ Unit = MUIGetString(STRING_MB);
+ }
+ else
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
+ Unit = MUIGetString(STRING_KB);
+ }
+
+ sprintf(LineBuffer,
+ MUIGetString(STRING_UNPSPACE),
+ PartEntry->LogicalPartition ? " " : "",
+ PartEntry->LogicalPartition ? "" : " ",
+ PartSize.u.LowPart,
+ Unit);
+ }
+ else
+ {
+ /* Determine partition type */
+ PartType = NULL;
+ if (PartEntry->New == TRUE)
+ {
+ PartType = MUIGetString(STRING_UNFORMATTED);
+ }
+ else if (PartEntry->IsPartitioned == TRUE)
+ {
+ if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+ (PartEntry->PartitionType == PARTITION_FAT_16) ||
+ (PartEntry->PartitionType == PARTITION_HUGE) ||
+ (PartEntry->PartitionType == PARTITION_XINT13))
+ {
+ PartType = "FAT";
+ }
+ else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
+ (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
+ {
+ PartType = "FAT32";
+ }
+ else if (PartEntry->PartitionType == PARTITION_EXT2)
+ {
+ PartType = "EXT2";
+ }
+ else if (PartEntry->PartitionType == PARTITION_IFS)
+ {
+ PartType = "NTFS"; /* FIXME: Not quite correct! */
+ }
+ else if ((PartEntry->PartitionType == PARTITION_EXTENDED) ||
+ (PartEntry->PartitionType == PARTITION_XINT13_EXTENDED))
+ {
+ PartType = MUIGetString(STRING_EXTENDED_PARTITION);
+ }
+ }
+
+ PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+#if 0
+ if (PartSize.QuadPart >= 10737418240) /* 10 GB */
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
+ Unit = MUIGetString(STRING_GB);
+ }
+ else
+#endif
+ if (PartSize.QuadPart >= 10485760) /* 10 MB */
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
+ Unit = MUIGetString(STRING_MB);
+ }
+ else
+ {
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
+ Unit = MUIGetString(STRING_KB);
+ }
+
+ if (PartType == NULL)
+ {
+ sprintf(LineBuffer,
+ MUIGetString(STRING_HDDINFOUNK5),
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartEntry->LogicalPartition ? " " : "",
+ PartEntry->PartitionType,
+ PartEntry->LogicalPartition ? "" : " ",
+ PartSize.u.LowPart,
+ Unit);
+ }
+ else
+ {
+ sprintf(LineBuffer,
+ "%c%c %s%-24s%s %6lu %s",
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartEntry->LogicalPartition ? " " : "",
+ PartType,
+ PartEntry->LogicalPartition ? "" : " ",
+ PartSize.u.LowPart,
+ Unit);
+ }
}
-#if 0
- if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
+ Attribute = (List->CurrentDisk == DiskEntry &&
+ List->CurrentPartition == PartEntry) ?
+ FOREGROUND_BLUE | BACKGROUND_WHITE :
+ FOREGROUND_WHITE | BACKGROUND_BLUE;
+
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputCharacterA(StdOutput,
+ ' ',
+ Width,
+ coPos,
+ &Written);
+ }
+ coPos.X += 4;
+ Width -= 8;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute(StdOutput,
+ Attribute,
+ Width,
+ coPos,
+ &Written);
+ }
+ coPos.X++;
+ Width -= 2;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ WriteConsoleOutputCharacterA(StdOutput,
+ LineBuffer,
+ min(strlen(LineBuffer), Width),
+ coPos,
+ &Written);
+ }
+
+ List->Line++;
+}
+
+
+static
+VOID
+PrintDiskData(
+ PPARTLIST List,
+ PDISKENTRY DiskEntry)
+{
+ PPARTENTRY PrimaryPartEntry, LogicalPartEntry;
+ PLIST_ENTRY PrimaryEntry, LogicalEntry;
+ CHAR LineBuffer[128];
+ COORD coPos;
+ DWORD Written;
+ USHORT Width;
+ USHORT Height;
+ ULARGE_INTEGER DiskSize;
+ PCHAR Unit;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+ DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
- Unit = MUIGetString(STRING_GB);
+ DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1073741824);
+ Unit = MUIGetString(STRING_GB);
}
else
-#endif
- if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
- Unit = MUIGetString(STRING_MB);
+ DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1048576);
+ if (DiskSize.QuadPart == 0)
+ DiskSize.QuadPart = 1;
+ Unit = MUIGetString(STRING_MB);
+ }
+
+ if (DiskEntry->DriverName.Length > 0)
+ {
+ sprintf(LineBuffer,
+ MUIGetString(STRING_HDINFOPARTSELECT),
+ DiskSize.u.LowPart,
+ Unit,
+ DiskEntry->DiskNumber,
+ DiskEntry->Port,
+ DiskEntry->Bus,
+ DiskEntry->Id,
+ DiskEntry->DriverName.Buffer);
+ }
+ else
+ {
+ sprintf(LineBuffer,
+ MUIGetString(STRING_HDDINFOUNK6),
+ DiskSize.u.LowPart,
+ Unit,
+ DiskEntry->DiskNumber,
+ DiskEntry->Port,
+ DiskEntry->Bus,
+ DiskEntry->Id);
+ }
+
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute(StdOutput,
+ FOREGROUND_WHITE | BACKGROUND_BLUE,
+ Width,
+ coPos,
+ &Written);
+
+ FillConsoleOutputCharacterA(StdOutput,
+ ' ',
+ Width,
+ coPos,
+ &Written);
+ }
+
+ coPos.X++;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ WriteConsoleOutputCharacterA(StdOutput,
+ LineBuffer,
+ min((USHORT)strlen(LineBuffer), Width - 2),
+ coPos,
+ &Written);
+ }
+
+ List->Line++;
+
+ /* Print separator line */
+ PrintEmptyLine(List);
+
+ /* Print partition lines*/
+ PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (PrimaryEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
+
+ PrintPartitionData(List,
+ DiskEntry,
+ PrimaryPartEntry);
+
+ if (IsContainerPartition(PrimaryPartEntry->PartitionType))
+ {
+ LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
+ while (LogicalEntry != &DiskEntry->LogicalPartListHead)
+ {
+ LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
+
+ PrintPartitionData(List,
+ DiskEntry,
+ LogicalPartEntry);
+
+ LogicalEntry = LogicalEntry->Flink;
+ }
+ }
+
+ PrimaryEntry = PrimaryEntry->Flink;
+ }
+
+ /* Print separator line */
+ PrintEmptyLine(List);
+}
+
+
+VOID
+DrawPartitionList(
+ PPARTLIST List)
+{
+ PLIST_ENTRY Entry, Entry2;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry = NULL;
+ COORD coPos;
+ DWORD Written;
+ SHORT i;
+ SHORT CurrentDiskLine;
+ SHORT CurrentPartLine;
+ SHORT LastLine;
+ BOOL CurrentPartLineFound = FALSE;
+ BOOL CurrentDiskLineFound = FALSE;
+
+ /* Calculate the line of the current disk and partition */
+ CurrentDiskLine = 0;
+ CurrentPartLine = 0;
+ LastLine = 0;
+
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+ LastLine += 2;
+ if (CurrentPartLineFound == FALSE)
+ {
+ CurrentPartLine += 2;
+ }
+
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry == List->CurrentPartition)
+ {
+ CurrentPartLineFound = TRUE;
+ }
+
+ Entry2 = Entry2->Flink;
+ if (CurrentPartLineFound == FALSE)
+ {
+ CurrentPartLine++;
+ }
+
+ LastLine++;
+ }
+
+ if (DiskEntry == List->CurrentDisk)
+ {
+ CurrentDiskLineFound = TRUE;
+ }
+
+ Entry = Entry->Flink;
+ if (Entry != &List->DiskListHead)
+ {
+ if (CurrentDiskLineFound == FALSE)
+ {
+ CurrentPartLine ++;
+ CurrentDiskLine = CurrentPartLine;
+ }
+
+ LastLine++;
+ }
+ else
+ {
+ LastLine--;
+ }
+ }
+
+ /* If it possible, make the disk name visible */
+ if (CurrentPartLine < List->Offset)
+ {
+ List->Offset = CurrentPartLine;
+ }
+ else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
+ {
+ List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
+ }
+
+ if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
+ {
+ List->Offset = CurrentDiskLine;
+ }
+
+ /* draw upper left corner */
+ coPos.X = List->Left;
+ coPos.Y = List->Top;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xDA, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw upper edge */
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top;
+ if (List->Offset == 0)
+ {
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ List->Right - List->Left - 1,
+ coPos,
+ &Written);
}
else
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
- Unit = MUIGetString(STRING_KB);
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ List->Right - List->Left - 5,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 5;
+ WriteConsoleOutputCharacterA(StdOutput,
+ "(\x18)", // "(up)"
+ 3,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 2;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ 2,
+ coPos,
+ &Written);
+ }
+
+ /* draw upper right corner */
+ coPos.X = List->Right;
+ coPos.Y = List->Top;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xBF, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw left and right edge */
+ for (i = List->Top + 1; i < List->Bottom; i++)
+ {
+ coPos.X = List->Left;
+ coPos.Y = i;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xB3, // '|',
+ 1,
+ coPos,
+ &Written);
+
+ coPos.X = List->Right;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xB3, //'|',
+ 1,
+ coPos,
+ &Written);
}
- if (PartType == NULL)
+ /* draw lower left corner */
+ coPos.X = List->Left;
+ coPos.Y = List->Bottom;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC0, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw lower edge */
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Bottom;
+ if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
{
- sprintf (LineBuffer,
- MUIGetString(STRING_HDDINFOUNK5),
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
- PartEntry->PartInfo[PartNumber].PartitionType,
- PartSize.u.LowPart,
- Unit);
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ List->Right - List->Left - 1,
+ coPos,
+ &Written);
}
else
{
- sprintf (LineBuffer,
- "%c%c %-24s %6lu %s",
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
- PartType,
- PartSize.u.LowPart,
- Unit);
- }
- }
-
- Attribute = (List->CurrentDisk == DiskEntry &&
- List->CurrentPartition == PartEntry &&
- List->CurrentPartitionNumber == PartNumber) ?
- FOREGROUND_BLUE | BACKGROUND_WHITE :
- FOREGROUND_WHITE | BACKGROUND_BLUE;
-
- if (List->Line >= 0 && List->Line <= Height)
- {
- FillConsoleOutputCharacterA (StdOutput,
- ' ',
- Width,
- coPos,
- &Written);
- }
- coPos.X += 4;
- Width -= 8;
- if (List->Line >= 0 && List->Line <= Height)
- {
- FillConsoleOutputAttribute (StdOutput,
- Attribute,
- Width,
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ List->Right - List->Left - 5,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 5;
+ WriteConsoleOutputCharacterA(StdOutput,
+ "(\x19)", // "(down)"
+ 3,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 2;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xC4, // '-',
+ 2,
+ coPos,
+ &Written);
+ }
+
+ /* draw lower right corner */
+ coPos.X = List->Right;
+ coPos.Y = List->Bottom;
+ FillConsoleOutputCharacterA(StdOutput,
+ 0xD9, // '+',
+ 1,
coPos,
&Written);
- }
- coPos.X++;
- Width -= 2;
- if (List->Line >= 0 && List->Line <= Height)
- {
- WriteConsoleOutputCharacterA (StdOutput,
- LineBuffer,
- min (strlen (LineBuffer), Width),
- coPos,
- &Written);
- }
- List->Line++;
+
+ /* print list entries */
+ List->Line = - List->Offset;
+
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+ /* Print disk entry */
+ PrintDiskData(List,
+ DiskEntry);
+
+ Entry = Entry->Flink;
+ }
}
-static VOID
-PrintDiskData (PPARTLIST List,
- PDISKENTRY DiskEntry)
+DWORD
+SelectPartition(
+ PPARTLIST List,
+ ULONG DiskNumber,
+ ULONG PartitionNumber)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+
+ /* Check for empty disks */
+ if (IsListEmpty(&List->DiskListHead))
+ return FALSE;
+
+ /* Check for first usable entry on next disk */
+ Entry1 = List->CurrentDisk->ListEntry.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+
+ if (DiskEntry->DiskNumber == DiskNumber)
+ {
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+
+ if (PartEntry->PartitionNumber == PartitionNumber)
+ {
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ DrawPartitionList(List);
+ return TRUE;
+ }
+
+ Entry2 = Entry2->Flink;
+ }
+
+ return FALSE;
+ }
+
+ Entry1 = Entry1->Flink;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+ScrollDownPartitionList(
+ PPARTLIST List)
{
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry;
- CHAR LineBuffer[128];
- COORD coPos;
- DWORD Written;
- USHORT Width;
- USHORT Height;
- ULARGE_INTEGER DiskSize;
- PCHAR Unit;
- ULONG i;
+// PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+
+ /* Check for empty disks */
+ if (IsListEmpty(&List->DiskListHead))
+ return FALSE;
+
+
+ /* Check for next usable entry on current disk */
+ if (List->CurrentPartition != NULL)
+ {
+ if (List->CurrentPartition->LogicalPartition)
+ {
+ /* Logical partition */
+
+ Entry = List->CurrentPartition->ListEntry.Flink;
+ if (Entry != &List->CurrentDisk->LogicalPartListHead)
+ {
+ /* Next logical partition */
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+ else
+ {
+ Entry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
+ if (Entry != &List->CurrentDisk->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ /* Primary or extended partition */
+ if (IsContainerPartition(List->CurrentPartition->PartitionType))
+ {
+ /* First logical partition */
+ Entry = List->CurrentDisk->LogicalPartListHead.Flink;
+ if (Entry != &List->CurrentDisk->LogicalPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* Next primary partition */
+ Entry = List->CurrentPartition->ListEntry.Flink;
+ if (Entry != &List->CurrentDisk->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+ }
+ }
+ }
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ DPRINT1("TODO: Check the next drive!\n");
#if 0
- if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
- {
- DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 29)) >> 30;
- Unit = MUIGetString(STRING_GB);
- }
- else
+ /* Check for first usable entry on next disk */
+ if (List->CurrentDisk != NULL)
+ {
+ Entry1 = List->CurrentDisk->ListEntry.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+
+ Entry2 = DiskEntry->PartListHead.Flink;
+ if (Entry2 != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ DrawPartitionList(List);
+ return;
+ }
+
+ Entry1 = Entry1->Flink;
+ }
+ }
#endif
- {
- DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 19)) >> 20;
- if (DiskSize.QuadPart == 0)
- DiskSize.QuadPart = 1;
- Unit = MUIGetString(STRING_MB);
- }
-
- if (DiskEntry->DriverName.Length > 0)
- {
- sprintf (LineBuffer,
- MUIGetString(STRING_HDINFOPARTSELECT),
- DiskSize.u.LowPart,
- Unit,
- DiskEntry->DiskNumber,
- DiskEntry->Port,
- DiskEntry->Bus,
- DiskEntry->Id,
- DiskEntry->DriverName.Buffer);
- }
- else
- {
- sprintf (LineBuffer,
- MUIGetString(STRING_HDDINFOUNK6),
- DiskSize.u.LowPart,
- Unit,
- DiskEntry->DiskNumber,
- DiskEntry->Port,
- DiskEntry->Bus,
- DiskEntry->Id);
- }
- if (List->Line >= 0 && List->Line <= Height)
- {
- FillConsoleOutputAttribute (StdOutput,
- FOREGROUND_WHITE | BACKGROUND_BLUE,
- Width,
- coPos,
- &Written);
- FillConsoleOutputCharacterA (StdOutput,
- ' ',
- Width,
- coPos,
- &Written);
- }
-
- coPos.X++;
- if (List->Line >= 0 && List->Line <= Height)
- {
- WriteConsoleOutputCharacterA (StdOutput,
- LineBuffer,
- min ((USHORT)strlen (LineBuffer), Width - 2),
- coPos,
- &Written);
- }
- List->Line++;
-
- /* Print separator line */
- PrintEmptyLine (List);
-
- /* Print partition lines*/
- Entry = DiskEntry->PartListHead.Flink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-
- /* Print disk entry */
- for (i=0; i<4; i++)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED ||
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
- {
- PrintPartitionData (List,
- DiskEntry,
- PartEntry,
- i);
- }
- }
-
- /* Print unpartitioned entry */
- if (PartEntry->Unpartitioned)
- {
- PrintPartitionData (List,
- DiskEntry,
- PartEntry,
- 0);
- }
-
- Entry = Entry->Flink;
- }
-
- /* Print separator line */
- PrintEmptyLine (List);
+ return FALSE;
+}
+
+
+BOOL
+ScrollUpPartitionList(
+ PPARTLIST List)
+{
+// PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+
+ /* Check for empty disks */
+ if (IsListEmpty(&List->DiskListHead))
+ return FALSE;
+
+ /* Check for previous usable entry on current disk */
+ if (List->CurrentPartition != NULL)
+ {
+ if (List->CurrentPartition->LogicalPartition)
+ {
+ /* Logical partition */
+ Entry = List->CurrentPartition->ListEntry.Blink;
+ if (Entry != &List->CurrentDisk->LogicalPartListHead)
+ {
+ /* Previous logical partition */
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ }
+ else
+ {
+ /* Extended partition*/
+ PartEntry = List->CurrentDisk->ExtendedPartition;
+ }
+
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+ else
+ {
+ /* Primary or extended partition */
+
+ Entry = List->CurrentPartition->ListEntry.Blink;
+ if (Entry != &List->CurrentDisk->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ if (IsContainerPartition(PartEntry->PartitionType))
+ {
+ Entry = List->CurrentDisk->LogicalPartListHead.Blink;
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ }
+
+ List->CurrentPartition = PartEntry;
+ return TRUE;
+ }
+
+ }
+ }
+
+ DPRINT1("TODO: Check the previous drive!\n");
+
+#if 0
+ /* check for last usable entry on previous disk */
+ if (List->CurrentDisk != NULL)
+ {
+ Entry1 = List->CurrentDisk->ListEntry.Blink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+
+ Entry2 = DiskEntry->PrimaryPartListHead.Blink;
+ if (Entry2 != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+
+ /* Draw partition list and return */
+ DrawPartitionList(List);
+ return;
+ }
+
+ Entry1 = Entry1->Blink;
+ }
+ }
+#endif
+
+ return FALSE;
+}
+
+
+static
+BOOLEAN
+IsEmptyLayoutEntry(
+ PPARTITION_INFORMATION PartitionInfo)
+{
+ if (PartitionInfo->StartingOffset.QuadPart == 0 &&
+ PartitionInfo->PartitionLength.QuadPart == 0)
+// PartitionInfo->PartitionType == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static
+BOOLEAN
+IsSamePrimaryLayoutEntry(
+ IN PPARTITION_INFORMATION PartitionInfo,
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry)
+{
+ if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
+ PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
+// PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
+// PartitionInfo->PartitionType == PartEntry->PartitionType
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static
+VOID
+UpdateDiskLayout(
+ IN PDISKENTRY DiskEntry)
+{
+ PPARTITION_INFORMATION PartitionInfo;
+ PLIST_ENTRY ListEntry;
+ PPARTENTRY PartEntry;
+ ULONG Index = 0;
+ ULONG PartitionNumber = 1;
+
+DPRINT1("UpdateDiskLayout()\n");
+
+ ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (ListEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ if (PartEntry->IsPartitioned == TRUE)
+ {
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+
+ if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
+ {
+DPRINT1("Updating partition entry %lu\n", Index);
+ PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->HiddenSectors = 0;
+ PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+ PartitionInfo->PartitionType = PartEntry->PartitionType;
+ PartitionInfo->BootIndicator = PartEntry->BootIndicator;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
+
+ PartEntry->PartitionNumber = PartitionNumber;
+ PartEntry->PartitionIndex = Index;
+
+ PartitionNumber++;
+ }
+ else if (!IsEmptyLayoutEntry(PartitionInfo))
+ {
+ PartitionNumber++;
+ }
+
+ Index++;
+ }
+
+ ListEntry = ListEntry->Flink;
+ }
+
+ for (;Index < 4; Index++)
+ {
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+
+ if (!IsEmptyLayoutEntry(PartitionInfo))
+ {
+DPRINT1("Wiping partition entry %lu\n", Index);
+ PartitionInfo->StartingOffset.QuadPart = 0;
+ PartitionInfo->PartitionLength.QuadPart = 0;
+ PartitionInfo->HiddenSectors = 0;
+ PartitionInfo->PartitionNumber = 0;
+ PartitionInfo->PartitionType = 0;
+ PartitionInfo->BootIndicator = FALSE;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
+ }
+ }
+
+#ifdef DUMP_PARTITION_TABLE
+ DumpPartitionTable(DiskEntry);
+#endif
}
-VOID
-DrawPartitionList (PPARTLIST List)
+static
+PPARTENTRY
+GetPrevUnpartitionedEntry(
+ PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
{
- PLIST_ENTRY Entry, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry = NULL;
- COORD coPos;
- DWORD Written;
- SHORT i;
- SHORT CurrentDiskLine;
- SHORT CurrentPartLine;
- SHORT LastLine;
- BOOL CurrentPartLineFound = FALSE;
- BOOL CurrentDiskLineFound = FALSE;
-
- /* Calculate the line of the current disk and partition */
- CurrentDiskLine = 0;
- CurrentPartLine = 0;
- LastLine = 0;
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
- LastLine += 2;
- if (CurrentPartLineFound == FALSE)
- {
- CurrentPartLine += 2;
- }
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
- if (PartEntry == List->CurrentPartition)
- {
- CurrentPartLineFound = TRUE;
- }
- Entry2 = Entry2->Flink;
- if (CurrentPartLineFound == FALSE)
- {
- CurrentPartLine++;
- }
- LastLine++;
- }
- if (DiskEntry == List->CurrentDisk)
- {
- CurrentDiskLineFound = TRUE;
- }
- Entry = Entry->Flink;
- if (Entry != &List->DiskListHead)
- {
- if (CurrentDiskLineFound == FALSE)
- {
- CurrentPartLine ++;
- CurrentDiskLine = CurrentPartLine;
- }
- LastLine++;
- }
- else
+ PPARTENTRY PrevPartEntry;
+
+ if (PartEntry->ListEntry.Blink != &DiskEntry->PrimaryPartListHead)
{
- LastLine--;
- }
- }
-
- /* If it possible, make the disk name visible */
- if (CurrentPartLine < List->Offset)
- {
- List->Offset = CurrentPartLine;
- }
- else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
- {
- List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
- }
- if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
- {
- List->Offset = CurrentDiskLine;
- }
-
-
- /* draw upper left corner */
- coPos.X = List->Left;
- coPos.Y = List->Top;
- FillConsoleOutputCharacterA (StdOutput,
- 0xDA, // '+',
- 1,
- coPos,
- &Written);
-
- /* draw upper edge */
- coPos.X = List->Left + 1;
- coPos.Y = List->Top;
- if (List->Offset == 0)
- {
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- List->Right - List->Left - 1,
- coPos,
- &Written);
- }
- else
- {
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- List->Right - List->Left - 5,
- coPos,
- &Written);
- coPos.X = List->Right - 5;
- WriteConsoleOutputCharacterA (StdOutput,
- "(\x18)", // "(up)"
- 3,
- coPos,
- &Written);
- coPos.X = List->Right - 2;
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- 2,
- coPos,
- &Written);
- }
-
- /* draw upper right corner */
- coPos.X = List->Right;
- coPos.Y = List->Top;
- FillConsoleOutputCharacterA (StdOutput,
- 0xBF, // '+',
- 1,
- coPos,
- &Written);
-
- /* draw left and right edge */
- for (i = List->Top + 1; i < List->Bottom; i++)
- {
- coPos.X = List->Left;
- coPos.Y = i;
- FillConsoleOutputCharacterA (StdOutput,
- 0xB3, // '|',
- 1,
- coPos,
- &Written);
+ PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
+ PARTENTRY,
+ ListEntry);
+ if (PrevPartEntry->IsPartitioned == FALSE)
+ return PrevPartEntry;
+ }
- coPos.X = List->Right;
- FillConsoleOutputCharacterA (StdOutput,
- 0xB3, //'|',
- 1,
- coPos,
- &Written);
- }
-
- /* draw lower left corner */
- coPos.X = List->Left;
- coPos.Y = List->Bottom;
- FillConsoleOutputCharacterA (StdOutput,
- 0xC0, // '+',
- 1,
- coPos,
- &Written);
-
- /* draw lower edge */
- coPos.X = List->Left + 1;
- coPos.Y = List->Bottom;
- if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
- {
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- List->Right - List->Left - 1,
- coPos,
- &Written);
- }
- else
- {
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- List->Right - List->Left - 5,
- coPos,
- &Written);
- coPos.X = List->Right - 5;
- WriteConsoleOutputCharacterA (StdOutput,
- "(\x19)", // "(down)"
- 3,
- coPos,
- &Written);
- coPos.X = List->Right - 2;
- FillConsoleOutputCharacterA (StdOutput,
- 0xC4, // '-',
- 2,
- coPos,
- &Written);
- }
-
- /* draw lower right corner */
- coPos.X = List->Right;
- coPos.Y = List->Bottom;
- FillConsoleOutputCharacterA (StdOutput,
- 0xD9, // '+',
- 1,
- coPos,
- &Written);
-
- /* print list entries */
- List->Line = - List->Offset;
-
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
-
- /* Print disk entry */
- PrintDiskData (List,
- DiskEntry);
-
- Entry = Entry->Flink;
- }
+ return NULL;
}
-DWORD
-SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber)
+static
+PPARTENTRY
+GetNextUnpartitionedEntry(
+ PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
-
- /* Check for empty disks */
- if (IsListEmpty (&List->DiskListHead))
- return FALSE;
+ PPARTENTRY NextPartEntry;
- /* Check for first usable entry on next disk */
- Entry1 = List->CurrentDisk->ListEntry.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
-
- if (DiskEntry->DiskNumber == DiskNumber)
+ if (PartEntry->ListEntry.Flink != &DiskEntry->PrimaryPartListHead)
{
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
-
- for (i = 0; i < 4; i++)
- {
- if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
- {
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = i;
- DrawPartitionList (List);
- return TRUE;
- }
- }
- Entry2 = Entry2->Flink;
- }
- return FALSE;
+ NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
+ PARTENTRY,
+ ListEntry);
+ if (NextPartEntry->IsPartitioned == FALSE)
+ return NextPartEntry;
}
- Entry1 = Entry1->Flink;
- }
- return FALSE;
+
+ return NULL;
}
VOID
-ScrollDownPartitionList (PPARTLIST List)
+CreatePrimaryPartition(
+ PPARTLIST List,
+ ULONGLONG SectorCount,
+ BOOLEAN AutoCreate)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
-
- /* Check for empty disks */
- if (IsListEmpty (&List->DiskListHead))
- return;
-
- /* Check for next usable entry on current disk */
- if (List->CurrentPartition != NULL)
- {
- Entry2 = &List->CurrentPartition->ListEntry;
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
-
- /* Check if we can move inside primary partitions */
- for (i = List->CurrentPartitionNumber + 1; i < 4; i++)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
- }
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
- if (i == 4)
- {
- /* We're out of partitions in the current partition table.
- Try to move to the next one if possible. */
- Entry2 = Entry2->Flink;
- }
- else
+ DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
+
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->IsPartitioned == TRUE)
{
- /* Just advance to the next partition */
- List->CurrentPartitionNumber = i;
- DrawPartitionList (List);
return;
}
- while (Entry2 != &List->CurrentDisk->PartListHead)
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+ if (AutoCreate == TRUE ||
+ Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
{
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+DPRINT1("Convert existing partition entry\n");
+ /* Convert current entry to 'new (unformatted)' */
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartEntry->FormatState = Unformatted;
+ PartEntry->AutoCreate = AutoCreate;
+ PartEntry->New = TRUE;
+ PartEntry->BootIndicator = FALSE; /* FIXME */
-// if (PartEntry->HidePartEntry == FALSE)
- {
- List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = 0;
- DrawPartitionList (List);
- return;
- }
- Entry2 = Entry2->Flink;
+DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
}
- }
-
- /* Check for first usable entry on next disk */
- if (List->CurrentDisk != NULL)
- {
- Entry1 = List->CurrentDisk->ListEntry.Flink;
- while (Entry1 != &List->DiskListHead)
+ else
{
- DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+DPRINT1("Add new partition entry\n");
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+ /* Insert and initialize a new partition entry */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
-// if (PartEntry->HidePartEntry == FALSE)
- {
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = 0;
- DrawPartitionList (List);
- return;
- }
+ /* Insert the new entry into the list */
+ InsertTailList(&PartEntry->ListEntry,
+ &NewPartEntry->ListEntry);
+
+ NewPartEntry->DiskEntry = DiskEntry;
+
+ NewPartEntry->IsPartitioned = TRUE;
+ NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+ NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
- Entry2 = Entry2->Flink;
- }
+ NewPartEntry->New = TRUE;
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->BootIndicator = FALSE; /* FIXME */
- Entry1 = Entry1->Flink;
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
}
- }
+
+ UpdateDiskLayout(DiskEntry);
+
+ DiskEntry->Dirty = TRUE;
+
+ UpdatePartitionNumbers(DiskEntry);
+
+ AssignDriveLetters(List);
}
+static
VOID
-ScrollUpPartitionList (PPARTLIST List)
+AddLogicalDiskSpace(
+ PDISKENTRY DiskEntry)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
+ PPARTENTRY NewPartEntry;
- /* Check for empty disks */
- if (IsListEmpty (&List->DiskListHead))
- return;
+ DPRINT1("AddLogicalDiskSpace()\n");
- /* check for previous usable entry on current disk */
- if (List->CurrentPartition != NULL)
- {
- Entry2 = &List->CurrentPartition->ListEntry;
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+ /* Create a partition table entry that represents the empty space in the container partition */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
- /* Check if we can move inside primary partitions */
- if (List->CurrentPartitionNumber > 0)
- {
- /* Find a previous partition */
- for (i = List->CurrentPartitionNumber - 1; i > 0; i--)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
- }
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->LogicalPartition = TRUE;
- /* Move to it and return */
- List->CurrentPartitionNumber = i;
- DrawPartitionList (List);
- return;
- }
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+ NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack;
- /* Move to the previous entry */
- Entry2 = Entry2->Blink;
+ DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
- while (Entry2 != &List->CurrentDisk->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+ NewPartEntry->FormatState = Unformatted;
-// if (PartEntry->HidePartEntry == FALSE)
- {
- List->CurrentPartition = PartEntry;
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
+}
- /* Find last existing partition in the table */
- for (i = 3; i > 0; i--)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
- }
- /* Move to it */
- List->CurrentPartitionNumber = i;
+VOID
+CreateExtendedPartition(
+ PPARTLIST List,
+ ULONGLONG SectorCount)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
+
+ DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
- /* Draw partition list and return */
- DrawPartitionList (List);
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->IsPartitioned == TRUE)
+ {
return;
- }
- Entry2 = Entry2->Blink;
}
- }
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
- /* check for last usable entry on previous disk */
- if (List->CurrentDisk != NULL)
- {
- Entry1 = List->CurrentDisk->ListEntry.Blink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
-
- Entry2 = DiskEntry->PartListHead.Blink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
-// if (PartEntry->HidePartEntry == FALSE)
+ if (Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
+ {
+DPRINT1("Convert existing partition entry\n");
+ /* Convert current entry to 'new (unformatted)' */
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->FormatState = Formatted;
+ PartEntry->AutoCreate = FALSE;
+ PartEntry->New = FALSE;
+ PartEntry->BootIndicator = FALSE; /* FIXME */
+
+ if (PartEntry->StartSector.QuadPart < 1450560)
{
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
-
- /* Find last existing partition in the table */
- for (i = 3; i > 0; i--)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
- }
-
- /* Move to it */
- List->CurrentPartitionNumber = i;
-
- /* Draw partition list and return */
- DrawPartitionList (List);
- return;
+ /* Partition starts below the 8.4GB boundary ==> CHS partition */
+ PartEntry->PartitionType = PARTITION_EXTENDED;
+ }
+ else
+ {
+ /* Partition starts above the 8.4GB boundary ==> LBA partition */
+ PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
}
- Entry2 = Entry2->Blink;
- }
+ DiskEntry->ExtendedPartition = PartEntry;
- Entry1 = Entry1->Blink;
+DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
}
- }
-}
-
-
-static PPARTENTRY
-GetPrevPartitionedEntry (PDISKENTRY DiskEntry,
- PPARTENTRY CurrentEntry)
-{
- PPARTENTRY PrevEntry;
- PLIST_ENTRY Entry;
+ else
+ {
+DPRINT1("Add new partition entry\n");
- if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
- return NULL;
+ /* Insert and initialize a new partition entry */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
- Entry = CurrentEntry->ListEntry.Blink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PrevEntry = CONTAINING_RECORD (Entry,
- PARTENTRY,
- ListEntry);
- if (PrevEntry->Unpartitioned == FALSE)
- return PrevEntry;
+ /* Insert the new entry into the list */
+ InsertTailList(&PartEntry->ListEntry,
+ &NewPartEntry->ListEntry);
- Entry = Entry->Blink;
- }
+ NewPartEntry->DiskEntry = DiskEntry;
- return NULL;
-}
+ NewPartEntry->IsPartitioned = TRUE;
+ NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+ NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+ NewPartEntry->New = FALSE;
+ NewPartEntry->FormatState = Formatted;
+ NewPartEntry->BootIndicator = FALSE; /* FIXME */
-static PPARTENTRY
-GetNextPartitionedEntry (PDISKENTRY DiskEntry,
- PPARTENTRY CurrentEntry)
-{
- PPARTENTRY NextEntry;
- PLIST_ENTRY Entry;
+ if (NewPartEntry->StartSector.QuadPart < 1450560)
+ {
+ /* Partition starts below the 8.4GB boundary ==> CHS partition */
+ NewPartEntry->PartitionType = PARTITION_EXTENDED;
+ }
+ else
+ {
+ /* Partition starts above the 8.4GB boundary ==> LBA partition */
+ NewPartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
+ }
- if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
- return NULL;
+ DiskEntry->ExtendedPartition = NewPartEntry;
- Entry = CurrentEntry->ListEntry.Flink;
- while (Entry != &DiskEntry->PartListHead)
- {
- NextEntry = CONTAINING_RECORD (Entry,
- PARTENTRY,
- ListEntry);
- if (NextEntry->Unpartitioned == FALSE)
- return NextEntry;
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
- Entry = Entry->Flink;
- }
+DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+ }
- return NULL;
-}
+ AddLogicalDiskSpace(DiskEntry);
+ UpdateDiskLayout(DiskEntry);
-static PPARTENTRY
-GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry)
-{
- PPARTENTRY PrevPartEntry;
-
- if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
- {
- PrevPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Blink,
- PARTENTRY,
- ListEntry);
- if (PrevPartEntry->Unpartitioned == TRUE)
- return PrevPartEntry;
- }
-
- return NULL;
-}
+ DiskEntry->Dirty = TRUE;
+ UpdatePartitionNumbers(DiskEntry);
-static PPARTENTRY
-GetNextUnpartitionedEntry (PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry)
-{
- PPARTENTRY NextPartEntry;
-
- if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
- {
- NextPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Flink,
- PARTENTRY,
- ListEntry);
- if (NextPartEntry->Unpartitioned == TRUE)
- return NextPartEntry;
- }
-
- return NULL;
+ AssignDriveLetters(List);
}
VOID
-CreateNewPartition (PPARTLIST List,
- ULONGLONG PartitionSize,
- BOOLEAN AutoCreate)
+DeleteCurrentPartition(
+ PPARTLIST List)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PPARTENTRY PrevPartEntry;
- PPARTENTRY NextPartEntry;
- PPARTENTRY NewPartEntry;
-
- if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->Unpartitioned == FALSE)
- {
- return;
- }
-
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- if (AutoCreate == TRUE ||
- PartitionSize == PartEntry->UnpartitionedLength)
- {
- /* Convert current entry to 'new (unformatted)' */
- PartEntry->FormatState = Unformatted;
- PartEntry->PartInfo[0].StartingOffset.QuadPart =
- PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
- PartEntry->PartInfo[0].HiddenSectors =
- (ULONG)(PartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
- PartEntry->PartInfo[0].PartitionLength.QuadPart =
- PartEntry->UnpartitionedLength - DiskEntry->TrackSize;
- PartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
- PartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
- PartEntry->PartInfo[0].RewritePartition = TRUE;
- PartEntry->PartInfo[1].RewritePartition = TRUE;
- PartEntry->PartInfo[2].RewritePartition = TRUE;
- PartEntry->PartInfo[3].RewritePartition = TRUE;
-
- /* Get previous and next partition entries */
- PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
- PartEntry);
- NextPartEntry = GetNextPartitionedEntry (DiskEntry,
- PartEntry);
-
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY PrevPartEntry;
+ PPARTENTRY NextPartEntry;
+ PPARTENTRY LogicalPartEntry;
+ PLIST_ENTRY Entry;
+
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->IsPartitioned == FALSE)
{
- /* Current entry is in the middle of the list */
-
- /* Copy previous container partition data to current entry */
- RtlCopyMemory (&PartEntry->PartInfo[1],
- &PrevPartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- PartEntry->PartInfo[1].RewritePartition = TRUE;
+ return;
+ }
- /* Update previous container partition data */
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
- PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
- PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PrevPartEntry->PartInfo[1].HiddenSectors =
- (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
+ /* Delete all logical partiton entries if an extended partition will be deleted */
+ if (DiskEntry->ExtendedPartition == PartEntry)
+ {
+ while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
+ {
+ Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
+ LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
- {
- /* Special case - previous partition is first partition */
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
- }
+ RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
+ }
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
- else if (PrevPartEntry == NULL && NextPartEntry != NULL)
- {
- /* Current entry is the first entry */
- return;
+ DiskEntry->ExtendedPartition = NULL;
}
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
- {
- /* Current entry is the last entry */
-
- PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
- PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PrevPartEntry->PartInfo[1].HiddenSectors =
- (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
- if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
- {
- /* Special case - previous partition is first partition */
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
- }
-
- if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
- PartEntry->PartInfo[1].PartitionLength.QuadPart) <
- (1024LL * 255LL * 63LL * 512LL))
- {
- PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
- }
-
- PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
-
- PartEntry->AutoCreate = AutoCreate;
- PartEntry->New = TRUE;
- PartEntry->Unpartitioned = FALSE;
- PartEntry->UnpartitionedOffset = 0ULL;
- PartEntry->UnpartitionedLength = 0ULL;
- }
- else
- {
- /* Insert an initialize a new partition entry */
- NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (NewPartEntry == NULL)
- return;
-
- RtlZeroMemory (NewPartEntry,
- sizeof(PARTENTRY));
- /* Insert the new entry into the list */
- InsertTailList (&PartEntry->ListEntry,
- &NewPartEntry->ListEntry);
+ /* Adjust unpartitioned disk space entries */
- NewPartEntry->New = TRUE;
+ /* Get pointer to previous and next unpartitioned entries */
+ PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry,
+ PartEntry);
- NewPartEntry->FormatState = Unformatted;
- NewPartEntry->PartInfo[0].StartingOffset.QuadPart =
- PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
- NewPartEntry->PartInfo[0].HiddenSectors =
- (ULONG)(NewPartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
- NewPartEntry->PartInfo[0].PartitionLength.QuadPart =
- PartitionSize - DiskEntry->TrackSize;
- NewPartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
- NewPartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
- NewPartEntry->PartInfo[0].RewritePartition = TRUE;
- NewPartEntry->PartInfo[1].RewritePartition = TRUE;
- NewPartEntry->PartInfo[2].RewritePartition = TRUE;
- NewPartEntry->PartInfo[3].RewritePartition = TRUE;
-
- /* Get previous and next partition entries */
- PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
- NewPartEntry);
- NextPartEntry = GetNextPartitionedEntry (DiskEntry,
- NewPartEntry);
+ NextPartEntry = GetNextUnpartitionedEntry(DiskEntry,
+ PartEntry);
if (PrevPartEntry != NULL && NextPartEntry != NULL)
{
- /* Current entry is in the middle of the list */
+ /* Merge previous, current and next unpartitioned entry */
+
+ /* Adjust the previous entries length */
+ PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
- /* Copy previous container partition data to current entry */
- RtlCopyMemory (&NewPartEntry->PartInfo[1],
- &PrevPartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- NewPartEntry->PartInfo[1].RewritePartition = TRUE;
+ /* Remove the current entry */
+ RemoveEntryList(&PartEntry->ListEntry);
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
- /* Update previous container partition data */
+ /* Remove the next entry */
+ RemoveEntryList (&NextPartEntry->ListEntry);
+ RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
+
+ /* Update current partition */
+ List->CurrentPartition = PrevPartEntry;
+ }
+ else if (PrevPartEntry != NULL && NextPartEntry == NULL)
+ {
+ /* Merge current and previous unpartitioned entry */
- PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
- NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PrevPartEntry->PartInfo[1].HiddenSectors =
- (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
+ /* Adjust the previous entries length */
+ PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
- if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
- {
- /* Special case - previous partition is first partition */
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
- }
+ /* Remove the current entry */
+ RemoveEntryList(&PartEntry->ListEntry);
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
+ /* Update current partition */
+ List->CurrentPartition = PrevPartEntry;
}
else if (PrevPartEntry == NULL && NextPartEntry != NULL)
{
- /* Current entry is the first entry */
- return;
+ /* Merge current and next unpartitioned entry */
+
+ /* Adjust the next entries offset and length */
+ NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+ NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
+
+ /* Remove the current entry */
+ RemoveEntryList(&PartEntry->ListEntry);
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
+
+ /* Update current partition */
+ List->CurrentPartition = NextPartEntry;
}
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
+ else
{
- /* Current entry is the last entry */
-
- PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
- NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PrevPartEntry->PartInfo[1].HiddenSectors =
- (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
- if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
- {
- /* Special case - previous partition is first partition */
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
- }
-
- if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
- PartEntry->PartInfo[1].PartitionLength.QuadPart) <
- (1024LL * 255LL * 63LL * 512LL))
- {
- PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
- }
- else
- {
- PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
- }
-
- PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
-
- /* Update offset and size of the remaining unpartitioned disk space */
- PartEntry->UnpartitionedOffset += PartitionSize;
- PartEntry->UnpartitionedLength -= PartitionSize;
- }
-
- DiskEntry->Modified = TRUE;
-
- UpdatePartitionNumbers (DiskEntry);
-
- AssignDriverLetters (List);
-}
+ /* Nothing to merge but change current entry */
+ PartEntry->IsPartitioned = FALSE;
+ PartEntry->FormatState = Unformatted;
+ PartEntry->DriveLetter = 0;
+ }
+ UpdateDiskLayout(DiskEntry);
-VOID
-DeleteCurrentPartition (PPARTLIST List)
-{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PPARTENTRY PrevPartEntry;
- PPARTENTRY NextPartEntry;
-
- if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->Unpartitioned == TRUE)
- {
- return;
- }
-
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- /* Adjust container partition entries */
-
- /* Get previous and next partition entries */
- PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
- PartEntry);
- NextPartEntry = GetNextPartitionedEntry (DiskEntry,
- PartEntry);
-
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
- {
- /* Current entry is in the middle of the list */
+ DiskEntry->Dirty = TRUE;
- /*
- * The first extended partition can not be deleted
- * as long as other extended partitions are present.
- */
- if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
- return;
-
- /* Copy previous container partition data to current entry */
- RtlCopyMemory (&PrevPartEntry->PartInfo[1],
- &PartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
- else if (PrevPartEntry == NULL && NextPartEntry != NULL)
- {
- /*
- * A primary partition can not be deleted as long as
- * extended partitions are present.
- */
- return;
- }
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
- {
- /* Current entry is the last entry */
- RtlZeroMemory (&PrevPartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
-
-
- /* Adjust unpartitioned disk space entries */
-
- /* Get pointer to previous and next unpartitioned entries */
- PrevPartEntry = GetPrevUnpartitionedEntry (DiskEntry,
- PartEntry);
-
- NextPartEntry = GetNextUnpartitionedEntry (DiskEntry,
- PartEntry);
-
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
- {
- /* Merge previous, current and next unpartitioned entry */
-
- /* Adjust the previous entries length */
- PrevPartEntry->UnpartitionedLength +=
- (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
- NextPartEntry->UnpartitionedLength);
-
- /* Remove the current entry */
- RemoveEntryList (&PartEntry->ListEntry);
- RtlFreeHeap (ProcessHeap,
- 0,
- PartEntry);
-
- /* Remove the next entry */
- RemoveEntryList (&NextPartEntry->ListEntry);
- RtlFreeHeap (ProcessHeap,
- 0,
- NextPartEntry);
-
- /* Update current partition */
- List->CurrentPartition = PrevPartEntry;
- }
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
- {
- /* Merge current and previous unpartitioned entry */
-
- /* Adjust the previous entries length */
- PrevPartEntry->UnpartitionedLength +=
- (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
-
- /* Remove the current entry */
- RemoveEntryList (&PartEntry->ListEntry);
- RtlFreeHeap (ProcessHeap,
- 0,
- PartEntry);
-
- /* Update current partition */
- List->CurrentPartition = PrevPartEntry;
- }
- else if (PrevPartEntry == NULL && NextPartEntry != NULL)
- {
- /* Merge current and next unpartitioned entry */
-
- /* Adjust the next entries offset and length */
- NextPartEntry->UnpartitionedOffset =
- PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- NextPartEntry->UnpartitionedLength +=
- (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
-
- /* Remove the current entry */
- RemoveEntryList (&PartEntry->ListEntry);
- RtlFreeHeap (ProcessHeap,
- 0,
- PartEntry);
-
- /* Update current partition */
- List->CurrentPartition = NextPartEntry;
- }
- else
- {
- /* Nothing to merge but change current entry */
- PartEntry->New = FALSE;
- PartEntry->Unpartitioned = TRUE;
- PartEntry->UnpartitionedOffset =
- PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PartEntry->UnpartitionedLength =
- PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-
- /* Wipe the partition table */
- RtlZeroMemory (&PartEntry->PartInfo,
- sizeof(PartEntry->PartInfo));
- }
-
- DiskEntry->Modified = TRUE;
-
- UpdatePartitionNumbers (DiskEntry);
-
- AssignDriverLetters (List);
+ UpdatePartitionNumbers(DiskEntry);
+
+ AssignDriveLetters(List);
}
VOID
-CheckActiveBootPartition (PPARTLIST List)
+CheckActiveBootPartition(
+ PPARTLIST List)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY ListEntry;
- UCHAR i;
-
- /* Check for empty disk list */
- if (IsListEmpty (&List->DiskListHead))
- {
- List->ActiveBootDisk = NULL;
- List->ActiveBootPartition = NULL;
- List->ActiveBootPartitionNumber = 0;
- return;
- }
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY ListEntry;
+
+ /* Check for empty disk list */
+ if (IsListEmpty (&List->DiskListHead))
+ {
+ List->ActiveBootDisk = NULL;
+ List->ActiveBootPartition = NULL;
+ return;
+ }
#if 0
- if (List->ActiveBootDisk != NULL &&
- List->ActiveBootPartition != NULL)
- {
- /* We already have an active boot partition */
- return;
- }
+ if (List->ActiveBootDisk != NULL &&
+ List->ActiveBootPartition != NULL)
+ {
+ /* We already have an active boot partition */
+ return;
+ }
#endif
- /* Choose the currently selected disk */
- DiskEntry = List->CurrentDisk;
+ /* Choose the currently selected disk */
+ DiskEntry = List->CurrentDisk;
- /* Check for empty partition list */
- if (IsListEmpty (&DiskEntry->PartListHead))
- {
- List->ActiveBootDisk = NULL;
- List->ActiveBootPartition = NULL;
- List->ActiveBootPartitionNumber = 0;
- return;
- }
-
- PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
- PARTENTRY,
- ListEntry);
-
- /* Set active boot partition */
- if ((DiskEntry->NewDisk == TRUE) ||
- (PartEntry->PartInfo[0].BootIndicator == FALSE &&
- PartEntry->PartInfo[1].BootIndicator == FALSE &&
- PartEntry->PartInfo[2].BootIndicator == FALSE &&
- PartEntry->PartInfo[3].BootIndicator == FALSE))
- {
- PartEntry->PartInfo[0].BootIndicator = TRUE;
- PartEntry->PartInfo[0].RewritePartition = TRUE;
- DiskEntry->Modified = TRUE;
-
- /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
- List->ActiveBootDisk = DiskEntry;
- List->ActiveBootPartition = PartEntry;
- List->ActiveBootPartitionNumber = 0;
-
- return;
- }
-
- /* Disk is not new, scan all partitions to find a bootable one */
- List->ActiveBootDisk = NULL;
- List->ActiveBootPartition = NULL;
- List->ActiveBootPartitionNumber = 0;
-
- ListEntry = DiskEntry->PartListHead.Flink;
- while (ListEntry != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD(ListEntry,
+ /* Check for empty partition list */
+ if (IsListEmpty (&DiskEntry->PrimaryPartListHead))
+ {
+ List->ActiveBootDisk = NULL;
+ List->ActiveBootPartition = NULL;
+ return;
+ }
+
+ PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
PARTENTRY,
ListEntry);
- /* Check if it's partitioned */
- if (!PartEntry->Unpartitioned)
+ /* Set active boot partition */
+ if ((DiskEntry->NewDisk == TRUE) ||
+ (PartEntry->BootIndicator == FALSE))
{
- /* Go through all of its 4 partitions */
- for (i=0; i<4; i++)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED &&
- PartEntry->PartInfo[i].BootIndicator)
- {
- /* Yes, we found it */
- List->ActiveBootDisk = DiskEntry;
- List->ActiveBootPartition = PartEntry;
- List->ActiveBootPartitionNumber = i;
+ PartEntry->BootIndicator = TRUE;
+ DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
+ DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
+ DiskEntry->Dirty = TRUE;
+
+ /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
+ List->ActiveBootDisk = DiskEntry;
+ List->ActiveBootPartition = PartEntry;
+
+ return;
+ }
+
+ /* Disk is not new, scan all partitions to find a bootable one */
+ List->ActiveBootDisk = NULL;
+ List->ActiveBootPartition = NULL;
+
+ ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (ListEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(ListEntry,
+ PARTENTRY,
+ ListEntry);
- DPRINT("Found bootable partition disk %d, drive letter %c\n",
- DiskEntry->DiskNumber, PartEntry->DriveLetter[i]);
+ /* Check if it is partitioned */
+ if (PartEntry->IsPartitioned)
+ {
+ if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED &&
+ PartEntry->BootIndicator)
+ {
+ /* Yes, we found it */
+ List->ActiveBootDisk = DiskEntry;
+ List->ActiveBootPartition = PartEntry;
- break;
+ DPRINT("Found bootable partition disk %d, drive letter %c\n",
+ DiskEntry->DiskNumber, PartEntry->DriveLetter);
+ break;
+ }
}
- }
+
+ /* Go to the next one */
+ ListEntry = ListEntry->Flink;
}
- /* Go to the next one */
- ListEntry = ListEntry->Flink;
- }
}
BOOLEAN
-CheckForLinuxFdiskPartitions (PPARTLIST List)
+CheckForLinuxFdiskPartitions(
+ PPARTLIST List)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- ULONG PartitionCount;
- ULONG i;
-
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1,
- DISKENTRY,
- ListEntry);
-
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+#if 0
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ ULONG PartitionCount;
+ ULONG i;
+
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
{
- PartEntry = CONTAINING_RECORD (Entry2,
- PARTENTRY,
- ListEntry);
+ DiskEntry = CONTAINING_RECORD(Entry1,
+ DISKENTRY,
+ ListEntry);
- if (PartEntry->Unpartitioned == FALSE)
- {
- PartitionCount = 0;
-
- for (i = 0; i < 4; i++)
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
{
- if (!IsContainerPartition (PartEntry->PartInfo[i].PartitionType) &&
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
- {
- PartitionCount++;
- }
- }
+ PartEntry = CONTAINING_RECORD(Entry2,
+ PARTENTRY,
+ ListEntry);
- if (PartitionCount > 1)
- {
- return TRUE;
+ if (PartEntry->Unpartitioned == FALSE)
+ {
+ PartitionCount = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!IsContainerPartition(PartEntry->PartInfo[i].PartitionType) &&
+ PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
+ {
+ PartitionCount++;
+ }
+ }
+
+ if (PartitionCount > 1)
+ {
+ return TRUE;
+ }
+ }
+
+ Entry2 = Entry2->Flink;
}
- }
- Entry2 = Entry2->Flink;
+ Entry1 = Entry1->Flink;
+ }
+#endif
+
+ return FALSE;
+}
+
+
+static
+NTSTATUS
+WritePartitons(
+ IN PPARTLIST List,
+ IN PDISKENTRY DiskEntry)
+{
+ WCHAR DstPath[MAX_PATH];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK Iosb;
+ UNICODE_STRING Name;
+ ULONG BufferSize;
+ HANDLE FileHandle = NULL;
+ NTSTATUS Status;
+
+ DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
+
+ swprintf(DstPath,
+ L"\\Device\\Harddisk%d\\Partition0",
+ DiskEntry->DiskNumber);
+ RtlInitUnicodeString(&Name,
+ DstPath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &Iosb,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+#ifdef DUMP_PARTITION_TABLE
+ DumpPartitionTable(DiskEntry);
+#endif
+
+ BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+ ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_DISK_SET_DRIVE_LAYOUT,
+ DiskEntry->LayoutBuffer,
+ BufferSize,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
}
- Entry1 = Entry1->Flink;
- }
+ if (FileHandle != NULL)
+ NtClose(FileHandle);
- return FALSE;
+ return Status;
}
BOOLEAN
-WritePartitionsToDisk (PPARTLIST List)
+WritePartitionsToDisk(
+ PPARTLIST List)
{
- PDRIVE_LAYOUT_INFORMATION DriveLayout;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK Iosb;
- WCHAR DstPath[MAX_PATH];
- UNICODE_STRING Name;
- HANDLE FileHandle;
- PDISKENTRY DiskEntry1;
- PDISKENTRY DiskEntry2;
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- ULONG PartitionCount;
- ULONG DriveLayoutSize;
- ULONG Index;
- NTSTATUS Status;
-
- if (List == NULL)
- {
+ PLIST_ENTRY Entry;
+ PDISKENTRY DiskEntry;
+
+ if (List == NULL)
+ return TRUE;
+
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+ if (DiskEntry->Dirty == TRUE)
+ {
+ WritePartitons(List, DiskEntry);
+ }
+
+ Entry = Entry->Flink;
+ }
+
return TRUE;
- }
-
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry1 = CONTAINING_RECORD (Entry1,
- DISKENTRY,
- ListEntry);
-
- if (DiskEntry1->Modified == TRUE)
- {
- /* Count partitioned entries */
- PartitionCount = 0;
- Entry2 = DiskEntry1->PartListHead.Flink;
- while (Entry2 != &DiskEntry1->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2,
- PARTENTRY,
- ListEntry);
- if (PartEntry->Unpartitioned == FALSE)
- {
- PartitionCount += 4;
- }
-
- Entry2 = Entry2->Flink;
- }
- if (PartitionCount == 0)
- {
- DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
- ((4 - 1) * sizeof (PARTITION_INFORMATION));
- }
- else
- {
- DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
- ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION));
- }
- DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap (ProcessHeap,
- 0,
- DriveLayoutSize);
- if (DriveLayout == NULL)
- {
- DPRINT1 ("RtlAllocateHeap() failed\n");
+}
+
+
+BOOL
+SetMountedDeviceValues(
+ PPARTLIST List)
+{
+ PLIST_ENTRY Entry1, Entry2;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ LARGE_INTEGER StartingOffset;
+
+ if (List == NULL)
+ {
return FALSE;
- }
-
- RtlZeroMemory (DriveLayout,
- DriveLayoutSize);
-
- if (PartitionCount == 0)
- {
- /* delete all partitions in the mbr */
- DriveLayout->PartitionCount = 4;
- for (Index = 0; Index < 4; Index++)
- {
- DriveLayout->PartitionEntry[Index].RewritePartition = TRUE;
- }
- }
- else
- {
- DriveLayout->PartitionCount = PartitionCount;
-
- Index = 0;
- Entry2 = DiskEntry1->PartListHead.Flink;
- while (Entry2 != &DiskEntry1->PartListHead)
- {
- PartEntry = CONTAINING_RECORD (Entry2,
- PARTENTRY,
- ListEntry);
- if (PartEntry->Unpartitioned == FALSE)
- {
- RtlCopyMemory (&DriveLayout->PartitionEntry[Index],
- &PartEntry->PartInfo[0],
- 4 * sizeof (PARTITION_INFORMATION));
- Index += 4;
- }
-
- Entry2 = Entry2->Flink;
- }
- }
- if (DiskEntry1->Signature == 0)
- {
- LARGE_INTEGER SystemTime;
- TIME_FIELDS TimeFields;
- PUCHAR Buffer;
- Buffer = (PUCHAR)&DiskEntry1->Signature;
-
- while (1)
- {
- NtQuerySystemTime (&SystemTime);
- RtlTimeToTimeFields (&SystemTime, &TimeFields);
-
- Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
- Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
- Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
- Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
-
- if (DiskEntry1->Signature == 0)
- {
- continue;
- }
-
- /* check if the signature already exist */
- /* FIXME:
- * Check also signatures from disks, which are
- * not visible (bootable) by the bios.
- */
- Entry2 = List->DiskListHead.Flink;
- while (Entry2 != &List->DiskListHead)
- {
- DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
- if (DiskEntry1 != DiskEntry2 &&
- DiskEntry1->Signature == DiskEntry2->Signature)
+ }
+
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1,
+ DISKENTRY,
+ ListEntry);
+
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned)
{
- break;
+ if (PartEntry->DriveLetter)
+ {
+ StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ if (!SetMountedDeviceValue(PartEntry->DriveLetter,
+ DiskEntry->LayoutBuffer->Signature,
+ StartingOffset))
+ {
+ return FALSE;
+ }
+ }
}
+
Entry2 = Entry2->Flink;
- }
- if (Entry2 == &List->DiskListHead)
- {
- break;
- }
}
- /* set one partition entry to dirty, this will update the signature */
- DriveLayout->PartitionEntry[0].RewritePartition = TRUE;
+ Entry1 = Entry1->Flink;
+ }
+
+ return TRUE;
+}
- }
- DriveLayout->Signature = DiskEntry1->Signature;
+static
+BOOLEAN
+IsLastPrimaryPartiton(
+ IN PPARTENTRY PartEntry)
+{
+ return (PartEntry->ListEntry.Flink == &PartEntry->DiskEntry->PrimaryPartListHead);
+}
- swprintf (DstPath,
- L"\\Device\\Harddisk%d\\Partition0",
- DiskEntry1->DiskNumber);
- RtlInitUnicodeString (&Name,
- DstPath);
- InitializeObjectAttributes (&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
+static
+BOOLEAN
+IsPreviousPartitionExtended(
+ IN PPARTENTRY PartEntry,
+ IN PDISKENTRY DiskEntry)
+{
+ PPARTENTRY PrevPartEntry;
+ PLIST_ENTRY Entry;
- Status = NtOpenFile (&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
+ Entry = PartEntry->ListEntry.Blink;
- if (!NT_SUCCESS (Status))
- {
- DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status);
- return FALSE;
- }
-
- Status = NtDeviceIoControlFile (FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_SET_DRIVE_LAYOUT,
- DriveLayout,
- DriveLayoutSize,
- NULL,
- 0);
- if (!NT_SUCCESS (Status))
- {
- DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
- NtClose (FileHandle);
- return FALSE;
- }
+ while (Entry != &DiskEntry->PrimaryPartListHead)
+ {
+ PrevPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- RtlFreeHeap (ProcessHeap,
- 0,
- DriveLayout);
+ if (IsContainerPartition(PrevPartEntry->PartitionType))
+ return TRUE;
- NtClose (FileHandle);
+ Entry = Entry->Blink;
}
- Entry1 = Entry1->Flink;
- }
+ return FALSE;
- return TRUE;
}
-BOOL SetMountedDeviceValues(PPARTLIST List)
+
+static
+ULONG
+GetPrimaryPartitionCount(
+ IN PDISKENTRY DiskEntry)
{
- PLIST_ENTRY Entry1, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- UCHAR i;
+ PLIST_ENTRY Entry;
+ PPARTENTRY PartEntry;
+ UINT nCount = 0;
- if (List == NULL)
- {
- return FALSE;
- }
-
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
- {
- DiskEntry = CONTAINING_RECORD (Entry1,
- DISKENTRY,
- ListEntry);
-
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (!PartEntry->Unpartitioned)
- {
- for (i=0; i<4; i++)
- {
- if (PartEntry->DriveLetter[i])
- {
- if (!SetMountedDeviceValue(PartEntry->DriveLetter[i], DiskEntry->Signature, PartEntry->PartInfo[i].StartingOffset))
- {
- return FALSE;
- }
- }
- }
- }
- Entry2 = Entry2->Flink;
+ Entry = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned == TRUE)
+ nCount++;
+
+ Entry = Entry->Flink;
}
- Entry1 = Entry1->Flink;
- }
- return TRUE;
+
+ return nCount;
+}
+
+
+ULONG
+PrimaryPartitionCreationChecks(
+ IN PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ /* Fail if partition is already in use */
+ if (PartEntry->IsPartitioned == TRUE)
+ return ERROR_NEW_PARTITION;
+
+ /* Fail if there are more than 4 partitions in the list */
+ if (GetPrimaryPartitionCount(DiskEntry) > 4)
+ return ERROR_PARTITION_TABLE_FULL;
+
+ /* Fail if this partiton is located behind an extended partition */
+ if (IsPreviousPartitionExtended(PartEntry, DiskEntry))
+ return ERROR_NOT_BEHIND_EXTENDED;
+
+ return ERROR_SUCCESS;
}
+ULONG
+ExtendedPartitionCreationChecks(
+ IN PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ /* Fail if partition is already in use */
+ if (PartEntry->IsPartitioned == TRUE)
+ return ERROR_NEW_PARTITION;
+
+ /* Fail if there are more than 4 partitions in the list */
+ if (GetPrimaryPartitionCount(DiskEntry) > 4)
+ return ERROR_PARTITION_TABLE_FULL;
+
+ /* Fail if there is another extended partition in the list */
+ if (DiskEntry->ExtendedPartition != NULL)
+ return ERROR_ONLY_ONE_EXTENDED;
+
+ /* Fail if the partition is not the last list entry */
+ if (!IsLastPrimaryPartiton(PartEntry))
+ return ERROR_EXTENDED_NOT_LAST;
+
+ return ERROR_SUCCESS;
+}
/* EOF */