*/
/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
- * FILE: subsys/system/usetup/partlist.c
+ * FILE: base/setup/usetup/partlist.c
* PURPOSE: Partition list functions
* PROGRAMMER: Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
#define NDEBUG
#include <debug.h>
+//#define DUMP_PARTITION_TABLE
+
+/* HELPERS FOR PARTITION TYPES **********************************************/
+
+typedef struct _PARTITION_TYPE
+{
+ UCHAR Type;
+ PCHAR Description;
+} PARTITION_TYPE, *PPARTITION_TYPE;
+
+/*
+ * This partition type list was ripped off the kernelDisk.c module from:
+ *
+ * Visopsys Operating System
+ * Copyright (C) 1998-2015 J. Andrew McLaughlin
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
+ * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
+ * for a complete list.
+ */
+
+/* This is a table for keeping known partition type codes and descriptions */
+static PARTITION_TYPE PartitionTypes[] =
+{
+ { 0x00, "(Empty)" },
+ { 0x01, "FAT12" },
+ { 0x02, "XENIX root" },
+ { 0x03, "XENIX /usr" },
+ { 0x04, "FAT16 (small)" },
+ { 0x05, "Extended" },
+ { 0x06, "FAT16" },
+ { 0x07, "NTFS/HPFS/exFAT" },
+ { 0x08, "OS/2 or AIX boot" },
+ { 0x09, "AIX data" },
+ { 0x0A, "OS/2 Boot Manager" },
+ { 0x0B, "FAT32" },
+ { 0x0C, "FAT32 (LBA)" },
+ { 0x0E, "FAT16 (LBA)" },
+ { 0x0F, "Extended (LBA)" },
+ { 0x11, "Hidden FAT12" },
+ { 0x12, "FAT diagnostic" },
+ { 0x14, "Hidden FAT16 (small)" },
+ { 0x16, "Hidden FAT16" },
+ { 0x17, "Hidden HPFS or NTFS" },
+ { 0x1B, "Hidden FAT32" },
+ { 0x1C, "Hidden FAT32 (LBA)" },
+ { 0x1E, "Hidden FAT16 (LBA)" },
+ { 0x35, "JFS" },
+ { 0x39, "Plan 9" },
+ { 0x3C, "PartitionMagic" },
+ { 0x3D, "Hidden Netware" },
+ { 0x41, "PowerPC PReP" },
+ { 0x42, "Win2K dynamic extended" },
+ { 0x43, "Old Linux" },
+ { 0x44, "GoBack" },
+ { 0x4D, "QNX4.x" },
+ { 0x4D, "QNX4.x 2nd" },
+ { 0x4D, "QNX4.x 3rd" },
+ { 0x50, "Ontrack R/O" },
+ { 0x51, "Ontrack R/W or Novell" },
+ { 0x52, "CP/M" },
+ { 0x63, "GNU HURD or UNIX SysV" },
+ { 0x64, "Netware 2" },
+ { 0x65, "Netware 3/4" },
+ { 0x66, "Netware SMS" },
+ { 0x67, "Novell" },
+ { 0x68, "Novell" },
+ { 0x69, "Netware 5+" },
+ { 0x7E, "Veritas VxVM public" },
+ { 0x7F, "Veritas VxVM private" },
+ { 0x80, "Minix" },
+ { 0x81, "Linux or Minix" },
+ { 0x82, "Linux swap or Solaris" },
+ { 0x83, "Linux" },
+ { 0x84, "Hibernation" },
+ { 0x85, "Linux extended" },
+ { 0x86, "HPFS or NTFS mirrored" },
+ { 0x87, "HPFS or NTFS mirrored" },
+ { 0x8E, "Linux LVM" },
+ { 0x93, "Hidden Linux" },
+ { 0x96, "CDFS/ISO-9660" },
+ { 0x9F, "BSD/OS" },
+ { 0xA0, "Laptop hibernation" },
+ { 0xA1, "Laptop hibernation" },
+ { 0xA5, "BSD, NetBSD, FreeBSD" },
+ { 0xA6, "OpenBSD" },
+ { 0xA7, "NeXTSTEP" },
+ { 0xA8, "OS-X UFS" },
+ { 0xA9, "NetBSD" },
+ { 0xAB, "OS-X boot" },
+ { 0xAF, "OS-X HFS" },
+ { 0xB6, "NT corrupt mirror" },
+ { 0xB7, "BSDI" },
+ { 0xB8, "BSDI swap" },
+ { 0xBE, "Solaris 8 boot" },
+ { 0xBF, "Solaris x86" },
+ { 0xC0, "NTFT" },
+ { 0xC1, "DR-DOS FAT12" },
+ { 0xC2, "Hidden Linux" },
+ { 0xC3, "Hidden Linux swap" },
+ { 0xC4, "DR-DOS FAT16 (small)" },
+ { 0xC5, "DR-DOS Extended" },
+ { 0xC6, "DR-DOS FAT16" },
+ { 0xC7, "HPFS mirrored" },
+ { 0xCB, "DR-DOS FAT32" },
+ { 0xCC, "DR-DOS FAT32 (LBA)" },
+ { 0xCE, "DR-DOS FAT16 (LBA)" },
+ { 0xD0, "MDOS" },
+ { 0xD1, "MDOS FAT12" },
+ { 0xD4, "MDOS FAT16 (small)" },
+ { 0xD5, "MDOS Extended" },
+ { 0xD6, "MDOS FAT16" },
+ { 0xD8, "CP/M-86" },
+ { 0xDF, "BootIt EMBRM(FAT16/32)" },
+ { 0xEB, "BeOS BFS" },
+ { 0xEE, "EFI GPT protective" },
+ { 0xEF, "EFI filesystem" },
+ { 0xF0, "Linux/PA-RISC boot" },
+ { 0xF2, "DOS 3.3+ second" },
+ { 0xFA, "Bochs" },
+ { 0xFB, "VmWare" },
+ { 0xFC, "VmWare swap" },
+ { 0xFD, "Linux RAID" },
+ { 0xFE, "NT hidden" },
+};
+
+VOID
+GetPartTypeStringFromPartitionType(
+ IN UCHAR partitionType,
+ OUT PCHAR strPartType,
+ IN ULONG cchPartType)
+{
+ /* Determine partition type */
+
+ if (IsContainerPartition(partitionType))
+ {
+ RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_EXTENDED_PARTITION));
+ }
+ else if (partitionType == PARTITION_ENTRY_UNUSED)
+ {
+ RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_FORMATUNUSED));
+ }
+ else
+ {
+ UINT i;
+
+ /* Do the table lookup */
+ for (i = 0; i < ARRAYSIZE(PartitionTypes); i++)
+ {
+ if (partitionType == PartitionTypes[i].Type)
+ {
+ RtlStringCchCopyA(strPartType, cchPartType, PartitionTypes[i].Description);
+ return;
+ }
+ }
+
+ /* We are here because the partition type is unknown */
+ RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_FORMATUNKNOWN));
+ }
+}
+
/* FUNCTIONS ****************************************************************/
+#ifdef DUMP_PARTITION_TABLE
static
VOID
-GetDriverName(
+DumpPartitionTable(
PDISKENTRY DiskEntry)
+{
+ PPARTITION_INFORMATION PartitionInfo;
+ ULONG i;
+
+ DbgPrint("\n");
+ DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
+ DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
+
+ for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
+ {
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
+ DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
+ i,
+ PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
+ PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
+ PartitionInfo->HiddenSectors,
+ PartitionInfo->PartitionNumber,
+ PartitionInfo->PartitionType,
+ PartitionInfo->BootIndicator ? '*': ' ',
+ PartitionInfo->RewritePartition ? 'Y': 'N');
+ }
+
+ DbgPrint("\n");
+}
+#endif
+
+
+ULONGLONG
+AlignDown(
+ IN ULONGLONG Value,
+ IN ULONG Alignment)
+{
+ ULONGLONG Temp;
+
+ Temp = Value / Alignment;
+
+ return Temp * Alignment;
+}
+
+ULONGLONG
+AlignUp(
+ IN ULONGLONG Value,
+ IN ULONG Alignment)
+{
+ ULONGLONG Temp, Result;
+
+ Temp = Value / Alignment;
+
+ Result = Temp * Alignment;
+ if (Value % Alignment)
+ Result += Alignment;
+
+ return Result;
+}
+
+ULONGLONG
+RoundingDivide(
+ IN ULONGLONG Dividend,
+ IN ULONGLONG Divisor)
+{
+ return (Dividend + Divisor / 2) / Divisor;
+}
+
+
+static
+VOID
+GetDriverName(
+ IN PDISKENTRY DiskEntry)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
WCHAR KeyName[32];
NULL);
swprintf(KeyName,
- L"\\Scsi\\Scsi Port %lu",
+ L"\\Scsi\\Scsi Port %hu",
DiskEntry->Port);
RtlZeroMemory(&QueryTable,
static
VOID
-AssignDriverLetters(
- PPARTLIST List)
+AssignDriveLetters(
+ IN PPARTLIST List)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
PLIST_ENTRY Entry1;
- //PLIST_ENTRY Entry2;
+ PLIST_ENTRY Entry2;
CHAR Letter;
- UCHAR i;
Letter = 'C';
{
DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
- if (!IsListEmpty(&DiskEntry->PartListHead))
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(DiskEntry->PartListHead.Flink,
- PARTENTRY,
- ListEntry);
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- for (i = 0; i < 4; i++)
- PartEntry->DriveLetter[i] = 0;
+ PartEntry->DriveLetter = 0;
- if (PartEntry->Unpartitioned == FALSE)
+ if (PartEntry->IsPartitioned &&
+ !IsContainerPartition(PartEntry->PartitionType))
{
- for (i = 0; i < 4; i++)
+ if (IsRecognizedPartition(PartEntry->PartitionType) ||
+ (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry->SectorCount.QuadPart != 0LL))
{
- if (IsContainerPartition(PartEntry->PartInfo[i].PartitionType))
- continue;
-
- if (IsRecognizedPartition(PartEntry->PartInfo[i].PartitionType) ||
- (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0LL))
+ if (Letter <= 'Z')
{
- if (Letter <= 'Z')
- {
- PartEntry->DriveLetter[i] = Letter;
- Letter++;
- }
+ PartEntry->DriveLetter = Letter;
+ Letter++;
}
}
}
+
+ Entry2 = Entry2->Flink;
}
Entry1 = Entry1->Flink;
}
/* 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)
- {
- Entry2 = Entry2->Flink;
- while (Entry2 != &DiskEntry->PartListHead)
- {
- 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;
- }
- }
-
- Entry1 = Entry1->Flink;
- }
-#endif
-}
-
-
-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
- {
- 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->PartInfo[i].PartitionNumber = 0;
- }
- else
- {
- PartEntry->PartInfo[i].PartitionNumber = PartNumber;
- PartNumber++;
- }
- }
- }
-
- Entry = Entry->Flink;
- }
-}
-
-
-static
-VOID
-AddPartitionToList(
- ULONG DiskNumber,
- PDISKENTRY DiskEntry,
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
-{
- PPARTENTRY PartEntry;
- ULONG i;
- ULONG j;
-
- for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
- {
- for (j = 0; j < 4; j++)
- {
- 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));
-
- PartEntry->Unpartitioned = FALSE;
-
- 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
+ Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry2 != &DiskEntry->LogicalPartListHead)
{
- PartEntry->FormatState = UnknownFormat;
- }
-
- InsertTailList(&DiskEntry->PartListHead,
- &PartEntry->ListEntry);
- }
-}
-
-
-static
-VOID
-ScanForUnpartitionedDiskSpace(
- PDISKENTRY DiskEntry)
-{
- 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;
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- i = 0;
- Entry = DiskEntry->PartListHead.Flink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ PartEntry->DriveLetter = 0;
- for (j = 0; j < 4; j++)
+ if (PartEntry->IsPartitioned)
{
- if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
- (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
- PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
+ if (IsRecognizedPartition(PartEntry->PartitionType) ||
+ (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry->SectorCount.QuadPart != 0LL))
{
- LastUnusedPartitionLength =
- PartEntry->PartInfo[j].StartingOffset.QuadPart -
- (LastStartingOffset + LastPartitionLength);
-
- if (PartEntry->PartInfo[j].StartingOffset.QuadPart > (LastStartingOffset + LastPartitionLength) &&
- LastUnusedPartitionLength >= DiskEntry->CylinderSize)
+ if (Letter <= 'Z')
{
- 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;
-
- /* Insert the table into the list */
- InsertTailList(&PartEntry->ListEntry,
- &NewPartEntry->ListEntry);
+ PartEntry->DriveLetter = Letter;
+ Letter++;
}
-
- LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
- LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
}
}
- i += 4;
- Entry = Entry->Flink;
+ Entry2 = Entry2->Flink;
}
- /* Check for trailing unpartitioned disk space */
- if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
- {
- /* 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));
-
- NewPartEntry->Unpartitioned = TRUE;
- NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
- NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
-
- /* Append the table to the list */
- InsertTailList(&DiskEntry->PartListHead,
- &NewPartEntry->ListEntry);
- }
- }
+ Entry1 = Entry1->Flink;
}
}
-NTSTATUS
+static NTSTATUS
NTAPI
DiskIdentifierQueryRoutine(
PWSTR ValueName,
}
-NTSTATUS
+static NTSTATUS
NTAPI
DiskConfigurationDataQueryRoutine(
PWSTR ValueName,
}
-NTSTATUS
+static NTSTATUS
NTAPI
SystemConfigurationDataQueryRoutine(
PWSTR ValueName,
ULONG i;
if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
- ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR))
+ ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
return STATUS_UNSUCCESSFUL;
FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
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);
+ *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(ProcessHeap, 0,
+ FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
if (*Int13Drives == NULL)
return STATUS_NO_MEMORY;
static VOID
EnumerateBiosDiskEntries(
- PPARTLIST PartList)
+ IN PPARTLIST PartList)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
WCHAR Name[120];
DiskCount = 0;
while (1)
{
- BiosDiskEntry = (BIOSDISKENTRY*) RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
+ BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
if (BiosDiskEntry == NULL)
{
break;
static
VOID
-AddDiskToList(
- HANDLE FileHandle,
- ULONG DiskNumber,
- PPARTLIST List)
+AddPartitionToDisk(
+ IN ULONG DiskNumber,
+ IN PDISKENTRY DiskEntry,
+ IN ULONG PartitionIndex,
+ IN BOOLEAN LogicalPartition)
{
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
- DISK_GEOMETRY DiskGeometry;
- SCSI_ADDRESS ScsiAddress;
- PDISKENTRY DiskEntry;
+ PPARTITION_INFORMATION PartitionInfo;
+ PPARTENTRY PartEntry;
+
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
+ if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED ||
+ ((LogicalPartition != FALSE) && IsContainerPartition(PartitionInfo->PartitionType)))
+ return;
+
+ PartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (PartEntry == NULL)
+ {
+ return;
+ }
+
+ PartEntry->DiskEntry = DiskEntry;
+
+ PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
+ PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
+
+ PartEntry->BootIndicator = PartitionInfo->BootIndicator;
+ PartEntry->PartitionType = PartitionInfo->PartitionType;
+ PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
+
+ PartEntry->LogicalPartition = LogicalPartition;
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ PartEntry->PartitionIndex = PartitionIndex;
+
+ if (IsContainerPartition(PartEntry->PartitionType))
+ {
+ PartEntry->FormatState = Unformatted;
+ PartEntry->FileSystem = NULL;
+
+ if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
+ DiskEntry->ExtendedPartition = PartEntry;
+ }
+#if 0
+ else if (IsRecognizedPartition(PartEntry->PartitionType))
+ {
+ // FIXME FIXME! We should completely rework how we get this 'FileSystemList' available...
+ PartEntry->FileSystem = GetFileSystem(FileSystemList, PartEntry);
+ if (!PartEntry->FileSystem)
+ PartEntry->FormatState = Preformatted;
+ else
+ PartEntry->FormatState = Unformatted;
+ // PartEntry->FormatState = UnknownFormat;
+ }
+ else
+ {
+ /* Unknown partition, so unknown partition format (may or may not be actually formatted) */
+ PartEntry->FormatState = UnknownFormat;
+ }
+#endif
+ 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)
+ {
+#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;
+ }
+
+ if (LogicalPartition)
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &PartEntry->ListEntry);
+ else
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &PartEntry->ListEntry);
+}
+
+
+static
+VOID
+ScanForUnpartitionedDiskSpace(
+ IN PDISKENTRY DiskEntry)
+{
+ ULONGLONG LastStartSector;
+ ULONGLONG LastSectorCount;
+ ULONGLONG LastUnusedSectorCount;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
+ PLIST_ENTRY Entry;
+
+ DPRINT("ScanForUnpartitionedDiskSpace()\n");
+
+ if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+ {
+ DPRINT1("No primary partition!\n");
+
+ /* Create a partition entry 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->SectorAlignment;
+ NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, 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;
+ NewPartEntry->FileSystem = NULL;
+
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &NewPartEntry->ListEntry);
+
+ return;
+ }
+
+ /* Start partition at head 1, cylinder 0 */
+ LastStartSector = DiskEntry->SectorAlignment;
+ LastSectorCount = 0ULL;
+ LastUnusedSectorCount = 0ULL;
+
+ Entry = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
+ PartEntry->SectorCount.QuadPart != 0ULL)
+ {
+ LastUnusedSectorCount =
+ PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
+
+ 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;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = AlignDown(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;
+ NewPartEntry->FileSystem = NULL;
+
+ /* 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->SectorCount.QuadPart)
+ {
+ LastUnusedSectorCount = AlignDown(DiskEntry->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->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+ NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+
+ DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
+
+ /* Append the table to the list */
+ InsertTailList(&DiskEntry->PrimaryPartListHead,
+ &NewPartEntry->ListEntry);
+ }
+ }
+
+ if (DiskEntry->ExtendedPartition != NULL)
+ {
+ if (IsListEmpty(&DiskEntry->LogicalPartListHead))
+ {
+ DPRINT1("No logical partition!\n");
+
+ /* Create a partition 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->SectorAlignment;
+ NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
+
+ 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;
+ NewPartEntry->FileSystem = NULL;
+
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
+
+ return;
+ }
+
+ /* Start partition at head 1, cylinder 0 */
+ LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+ 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->SectorAlignment - (LastStartSector + LastSectorCount);
+
+ if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (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 = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+
+ DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
+
+ /* 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 = AlignDown(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 = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+
+ DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
+
+ /* Append the table to the list */
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
+ }
+ }
+ }
+
+ DPRINT("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(
+ IN 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(
+ IN HANDLE FileHandle,
+ IN ULONG DiskNumber,
+ IN PPARTLIST List)
+{
+ DISK_GEOMETRY DiskGeometry;
+ SCSI_ADDRESS ScsiAddress;
+ PDISKENTRY DiskEntry;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
PPARTITION_SECTOR Mbr;
PLIST_ENTRY ListEntry;
PBIOSDISKENTRY BiosDiskEntry;
ULONG LayoutBufferSize;
+ PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
Status = NtDeviceIoControlFile(FileHandle,
NULL,
&DiskGeometry,
sizeof(DISK_GEOMETRY));
if (!NT_SUCCESS(Status))
- {
return;
- }
if (DiskGeometry.MediaType != FixedMedia &&
DiskGeometry.MediaType != RemovableMedia)
&ScsiAddress,
sizeof(SCSI_ADDRESS));
if (!NT_SUCCESS(Status))
- {
return;
- }
+
+ /*
+ * Check whether the disk is initialized, by looking at its MBR.
+ * NOTE that this must be generalized to GPT disks as well!
+ */
Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
0,
DiskGeometry.BytesPerSector);
if (Mbr == NULL)
- {
return;
- }
FileOffset.QuadPart = 0;
Status = NtReadFile(FileHandle,
NULL);
if (!NT_SUCCESS(Status))
{
- RtlFreeHeap(ProcessHeap,
- 0,
- Mbr);
+ RtlFreeHeap(ProcessHeap, 0, Mbr);
DPRINT1("NtReadFile failed, status=%x\n", Status);
return;
}
swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
DPRINT("Identifier: %S\n", Identifier);
- DiskEntry = (PDISKENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(DISKENTRY));
+ DiskEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ 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->Checksum = Checksum;
+// DiskEntry->Signature = Signature;
DiskEntry->BiosFound = FALSE;
/* Check if this disk has a valid MBR */
+ // FIXME: Check for the MBR signature as well, etc...
if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
DiskEntry->NoMbr = TRUE;
else
DiskEntry->NoMbr = FALSE;
- /* Free Mbr sector buffer */
- RtlFreeHeap(ProcessHeap,
- 0,
- Mbr);
+ /* Free the MBR sector buffer */
+ RtlFreeHeap(ProcessHeap, 0, Mbr);
+
ListEntry = List->BiosDiskListHead.Flink;
- while(ListEntry != &List->BiosDiskListHead)
+ 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
+ * If we have more than one disk with a zero or with the same signature
* we must create new signatures and reboot. After the reboot,
* it is possible to identify the disks.
*/
#endif
}
- InitializeListHead(&DiskEntry->PartListHead);
+ 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->TrackSize =
- (ULONGLONG)DiskGeometry.SectorsPerTrack *
- (ULONGLONG)DiskGeometry.BytesPerSector;
- DiskEntry->CylinderSize =
- (ULONGLONG)DiskGeometry.TracksPerCylinder *
- DiskEntry->TrackSize;
- DiskEntry->DiskSize =
- DiskGeometry.Cylinders.QuadPart *
- DiskEntry->CylinderSize;
+ DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
+ DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
+ DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
+ DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
- DiskEntry->DiskNumber = DiskNumber;
+ DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
+ (ULONGLONG)DiskGeometry.TracksPerCylinder *
+ (ULONGLONG)DiskGeometry.SectorsPerTrack;
+
+ DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
+ DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
+ DiskGeometry.SectorsPerTrack;
+
+ DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
+ DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
+
+ DiskEntry->DiskNumber = DiskNumber;
DiskEntry->Port = ScsiAddress.PortNumber;
DiskEntry->Bus = ScsiAddress.PathId;
DiskEntry->Id = ScsiAddress.TargetId;
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.
- */
+ /* Allocate a layout buffer with 4 partition entries first */
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
- ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
- LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap,
- 0,
- LayoutBufferSize);
- if (LayoutBuffer == NULL)
+ ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+ DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ LayoutBufferSize);
+ if (DiskEntry->LayoutBuffer == NULL)
{
+ DPRINT1("Failed to allocate the disk layout buffer!\n");
return;
}
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_GET_DRIVE_LAYOUT,
- NULL,
- 0,
- LayoutBuffer,
- LayoutBufferSize);
- if (NT_SUCCESS(Status))
+ for (;;)
{
- if (LayoutBuffer->PartitionCount == 0)
+ DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
+ Status = NtDeviceIoControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_DISK_GET_DRIVE_LAYOUT,
+ NULL,
+ 0,
+ DiskEntry->LayoutBuffer,
+ LayoutBufferSize);
+ if (NT_SUCCESS(Status))
+ break;
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
{
- DiskEntry->NewDisk = TRUE;
+ DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
+ return;
}
- AddPartitionToList(DiskNumber,
- DiskEntry,
- LayoutBuffer);
+ LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
+ NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ DiskEntry->LayoutBuffer,
+ LayoutBufferSize);
+ if (NewLayoutBuffer == NULL)
+ {
+ DPRINT1("Failed to reallocate the disk layout buffer!\n");
+ return;
+ }
+
+ DiskEntry->LayoutBuffer = NewLayoutBuffer;
+ }
+
+ DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
+
+#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 != PARTITION_ENTRY_UNUSED)
+ {
+ if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
+ {
+ DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
+ }
+ else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
+ {
+ DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
+ }
+ else
+ {
+ DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
+ }
+ }
+ else
+ {
+ DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / 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);
+ }
- ScanForUnpartitionedDiskSpace(DiskEntry);
+ for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
+ {
+ AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
+ }
}
- RtlFreeHeap(ProcessHeap,
- 0,
- LayoutBuffer);
+ ScanForUnpartitionedDiskSpace(DiskEntry);
}
PPARTLIST
-CreatePartitionList(
- SHORT Left,
- SHORT Top,
- SHORT Right,
- SHORT Bottom)
+CreatePartitionList(VOID)
{
PPARTLIST List;
OBJECT_ATTRIBUTES ObjectAttributes;
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;
- List->CurrentPartitionNumber = 0;
+
+ List->SystemPartition = NULL;
+ List->OriginalSystemPartition = NULL;
+
+ List->TempPartition = NULL;
+ List->FormatState = Start;
InitializeListHead(&List->DiskListHead);
InitializeListHead(&List->BiosDiskListHead);
Status = NtQuerySystemInformation(SystemDeviceInformation,
&Sdi,
- sizeof(SYSTEM_DEVICE_INFORMATION),
+ sizeof(Sdi),
&ReturnSize);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status);
RtlFreeHeap(ProcessHeap, 0, List);
return NULL;
}
FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(Status))
{
- AddDiskToList(FileHandle,
- DiskNumber,
- List);
+ AddDiskToList(FileHandle, DiskNumber, List);
NtClose(FileHandle);
}
}
- AssignDriverLetters(List);
+ UpdateDiskSignatures(List);
- List->TopDisk = 0;
- List->TopPartition = 0;
+ AssignDriveLetters(List);
/* Search for first usable disk and partition */
if (IsListEmpty(&List->DiskListHead))
{
List->CurrentDisk = NULL;
List->CurrentPartition = NULL;
- List->CurrentPartitionNumber = 0;
}
else
{
DISKENTRY,
ListEntry);
- if (IsListEmpty(&List->CurrentDisk->PartListHead))
+ if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
{
- List->CurrentPartition = 0;
- List->CurrentPartitionNumber = 0;
+ List->CurrentPartition = NULL;
}
else
{
- List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PartListHead.Flink,
+ List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
PARTENTRY,
ListEntry);
- List->CurrentPartitionNumber = 0;
}
}
VOID
DestroyPartitionList(
- PPARTLIST List)
+ IN PPARTLIST List)
{
PDISKENTRY DiskEntry;
PBIOSDISKENTRY BiosDiskEntry;
/* Release driver name */
RtlFreeUnicodeString(&DiskEntry->DriverName);
- /* Release partition array */
- while (!IsListEmpty(&DiskEntry->PartListHead))
+ /* Release primary partition list */
+ while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
{
- Entry = RemoveHeadList(&DiskEntry->PartListHead);
+ Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- RtlFreeHeap(ProcessHeap,
- 0,
- PartEntry);
+ 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))
+ /* Release the bios disk info */
+ while (!IsListEmpty(&List->BiosDiskListHead))
{
Entry = RemoveHeadList(&List->BiosDiskListHead);
BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
}
+VOID
+InitPartitionListUi(
+ IN OUT PPARTLIST_UI ListUi,
+ IN PPARTLIST List,
+ IN SHORT Left,
+ IN SHORT Top,
+ IN SHORT Right,
+ IN SHORT Bottom)
+{
+ ListUi->List = List;
+ // ListUi->FirstShown = NULL;
+ // ListUi->LastShown = NULL;
+
+ ListUi->Left = Left;
+ ListUi->Top = Top;
+ ListUi->Right = Right;
+ ListUi->Bottom = Bottom;
+
+ ListUi->Line = 0;
+ ListUi->Offset = 0;
+
+ // ListUi->Redraw = TRUE;
+}
+
static
VOID
PrintEmptyLine(
- PPARTLIST List)
+ IN PPARTLIST_UI ListUi)
{
COORD coPos;
- DWORD Written;
+ ULONG Written;
USHORT Width;
USHORT Height;
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ Width = ListUi->Right - ListUi->Left - 1;
+ Height = ListUi->Bottom - ListUi->Top - 2;
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ coPos.X = ListUi->Left + 1;
+ coPos.Y = ListUi->Top + 1 + ListUi->Line;
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
FillConsoleOutputAttribute(StdOutput,
FOREGROUND_WHITE | BACKGROUND_BLUE,
&Written);
}
- List->Line++;
+ ListUi->Line++;
}
static
VOID
PrintPartitionData(
- PPARTLIST List,
- PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry,
- ULONG PartNumber)
+ IN PPARTLIST_UI ListUi,
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry)
{
+ PPARTLIST List = ListUi->List;
CHAR LineBuffer[128];
COORD coPos;
- DWORD Written;
+ ULONG Written;
USHORT Width;
USHORT Height;
LARGE_INTEGER PartSize;
PCHAR Unit;
UCHAR Attribute;
- PCHAR PartType;
+ CHAR PartTypeString[32];
+ PCHAR PartType = PartTypeString;
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ Width = ListUi->Right - ListUi->Left - 1;
+ Height = ListUi->Bottom - ListUi->Top - 2;
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ coPos.X = ListUi->Left + 1;
+ coPos.Y = ListUi->Top + 1 + ListUi->Line;
- if (PartEntry->Unpartitioned == TRUE)
+ if (PartEntry->IsPartitioned == FALSE)
{
+ PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
#if 0
- if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
+ if (PartSize.QuadPart >= 10737418240) /* 10 GB */
{
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
Unit = MUIGetString(STRING_GB);
}
else
#endif
- if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
+ if (PartSize.QuadPart >= 10485760) /* 10 MB */
{
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
Unit = MUIGetString(STRING_MB);
}
else
{
- PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
+ 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)
+ PartTypeString[0] = '\0';
+ if (PartEntry->New != FALSE)
{
PartType = MUIGetString(STRING_UNFORMATTED);
}
- else if (PartEntry->Unpartitioned == FALSE)
+ else if (PartEntry->IsPartitioned != 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! */
- }
+ GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
+ PartTypeString,
+ ARRAYSIZE(PartTypeString));
+ PartType = PartTypeString;
}
+ PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
#if 0
- if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
+ if (PartSize.QuadPart >= 10737418240) /* 10 GB */
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
Unit = MUIGetString(STRING_GB);
}
else
#endif
- if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
+ if (PartSize.QuadPart >= 10485760) /* 10 MB */
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
Unit = MUIGetString(STRING_MB);
}
else
{
- PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
+ PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
Unit = MUIGetString(STRING_KB);
}
- if (PartType == NULL)
+ if (strcmp(PartType, MUIGetString(STRING_FORMATUNKNOWN)) == 0)
{
sprintf(LineBuffer,
MUIGetString(STRING_HDDINFOUNK5),
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
- PartEntry->PartInfo[PartNumber].PartitionType,
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartEntry->BootIndicator ? '*' : ' ',
+ PartEntry->LogicalPartition ? " " : "",
+ PartEntry->PartitionType,
+ PartEntry->LogicalPartition ? "" : " ",
PartSize.u.LowPart,
Unit);
}
else
{
sprintf(LineBuffer,
- "%c%c %-24s %6lu %s",
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
- (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
+ "%c%c %c %s%-24s%s %6lu %s",
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartEntry->BootIndicator ? '*' : ' ',
+ PartEntry->LogicalPartition ? " " : "",
PartType,
+ PartEntry->LogicalPartition ? "" : " ",
PartSize.u.LowPart,
Unit);
}
}
Attribute = (List->CurrentDisk == DiskEntry &&
- List->CurrentPartition == PartEntry &&
- List->CurrentPartitionNumber == PartNumber) ?
+ List->CurrentPartition == PartEntry) ?
FOREGROUND_BLUE | BACKGROUND_WHITE :
FOREGROUND_WHITE | BACKGROUND_BLUE;
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
FillConsoleOutputCharacterA(StdOutput,
' ',
}
coPos.X += 4;
Width -= 8;
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
FillConsoleOutputAttribute(StdOutput,
Attribute,
}
coPos.X++;
Width -= 2;
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
WriteConsoleOutputCharacterA(StdOutput,
LineBuffer,
&Written);
}
- List->Line++;
+ ListUi->Line++;
}
static
VOID
PrintDiskData(
- PPARTLIST List,
- PDISKENTRY DiskEntry)
+ IN PPARTLIST_UI ListUi,
+ IN PDISKENTRY DiskEntry)
{
- PPARTENTRY PartEntry;
- PLIST_ENTRY Entry;
+ // PPARTLIST List = ListUi->List;
+ PPARTENTRY PrimaryPartEntry, LogicalPartEntry;
+ PLIST_ENTRY PrimaryEntry, LogicalEntry;
CHAR LineBuffer[128];
COORD coPos;
- DWORD Written;
+ ULONG Written;
USHORT Width;
USHORT Height;
ULARGE_INTEGER DiskSize;
PCHAR Unit;
- ULONG i;
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 2;
+ Width = ListUi->Right - ListUi->Left - 1;
+ Height = ListUi->Bottom - ListUi->Top - 2;
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ coPos.X = ListUi->Left + 1;
+ coPos.Y = ListUi->Top + 1 + ListUi->Line;
-#if 0
- if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+ DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
{
- DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+ DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1073741824);
Unit = MUIGetString(STRING_GB);
}
else
-#endif
{
- DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+ DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1048576);
if (DiskSize.QuadPart == 0)
DiskSize.QuadPart = 1;
Unit = MUIGetString(STRING_MB);
DiskEntry->Id);
}
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
FillConsoleOutputAttribute(StdOutput,
FOREGROUND_WHITE | BACKGROUND_BLUE,
}
coPos.X++;
- if (List->Line >= 0 && List->Line <= Height)
+ if (ListUi->Line >= 0 && ListUi->Line <= Height)
{
WriteConsoleOutputCharacterA(StdOutput,
LineBuffer,
&Written);
}
- List->Line++;
+ ListUi->Line++;
/* Print separator line */
- PrintEmptyLine(List);
+ PrintEmptyLine(ListUi);
- /* Print partition lines*/
- Entry = DiskEntry->PartListHead.Flink;
- while (Entry != &DiskEntry->PartListHead)
+ /* Print partition lines */
+ PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (PrimaryEntry != &DiskEntry->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
- /* Print disk entry */
- for (i = 0; i < 4; i++)
+ PrintPartitionData(ListUi,
+ DiskEntry,
+ PrimaryPartEntry);
+
+ if (IsContainerPartition(PrimaryPartEntry->PartitionType))
{
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED ||
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
+ LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
+ while (LogicalEntry != &DiskEntry->LogicalPartListHead)
{
- PrintPartitionData(List,
+ LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
+
+ PrintPartitionData(ListUi,
DiskEntry,
- PartEntry,
- i);
- }
- }
+ LogicalPartEntry);
- /* Print unpartitioned entry */
- if (PartEntry->Unpartitioned)
- {
- PrintPartitionData(List,
- DiskEntry,
- PartEntry,
- 0);
+ LogicalEntry = LogicalEntry->Flink;
+ }
}
- Entry = Entry->Flink;
+ PrimaryEntry = PrimaryEntry->Flink;
}
/* Print separator line */
- PrintEmptyLine(List);
+ PrintEmptyLine(ListUi);
}
VOID
DrawPartitionList(
- PPARTLIST List)
+ IN PPARTLIST_UI ListUi)
{
+ PPARTLIST List = ListUi->List;
PLIST_ENTRY Entry, Entry2;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry = NULL;
COORD coPos;
- DWORD Written;
+ ULONG Written;
SHORT i;
SHORT CurrentDiskLine;
SHORT CurrentPartLine;
SHORT LastLine;
- BOOL CurrentPartLineFound = FALSE;
- BOOL CurrentDiskLineFound = FALSE;
+ BOOLEAN CurrentPartLineFound = FALSE;
+ BOOLEAN CurrentDiskLineFound = FALSE;
/* Calculate the line of the current disk and partition */
CurrentDiskLine = 0;
CurrentPartLine += 2;
}
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry == List->CurrentPartition)
LastLine++;
}
+ if (CurrentPartLineFound == FALSE)
+ {
+ Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry2 != &DiskEntry->LogicalPartListHead)
+ {
+ 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;
}
/* If it possible, make the disk name visible */
- if (CurrentPartLine < List->Offset)
+ if (CurrentPartLine < ListUi->Offset)
{
- List->Offset = CurrentPartLine;
+ ListUi->Offset = CurrentPartLine;
}
- else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
+ else if (CurrentPartLine - ListUi->Offset > ListUi->Bottom - ListUi->Top - 2)
{
- List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
+ ListUi->Offset = CurrentPartLine - (ListUi->Bottom - ListUi->Top - 2);
}
- if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
+ if (CurrentDiskLine < ListUi->Offset && CurrentPartLine - CurrentDiskLine < ListUi->Bottom - ListUi->Top - 2)
{
- List->Offset = CurrentDiskLine;
+ ListUi->Offset = CurrentDiskLine;
}
- /* draw upper left corner */
- coPos.X = List->Left;
- coPos.Y = List->Top;
+ /* Draw upper left corner */
+ coPos.X = ListUi->Left;
+ coPos.Y = ListUi->Top;
FillConsoleOutputCharacterA(StdOutput,
0xDA, // '+',
1,
coPos,
&Written);
- /* draw upper edge */
- coPos.X = List->Left + 1;
- coPos.Y = List->Top;
- if (List->Offset == 0)
+ /* Draw upper edge */
+ coPos.X = ListUi->Left + 1;
+ coPos.Y = ListUi->Top;
+ if (ListUi->Offset == 0)
{
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
- List->Right - List->Left - 1,
+ ListUi->Right - ListUi->Left - 1,
coPos,
&Written);
}
{
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
- List->Right - List->Left - 5,
+ ListUi->Right - ListUi->Left - 5,
coPos,
&Written);
- coPos.X = List->Right - 5;
+ coPos.X = ListUi->Right - 5;
WriteConsoleOutputCharacterA(StdOutput,
"(\x18)", // "(up)"
3,
coPos,
&Written);
- coPos.X = List->Right - 2;
+ coPos.X = ListUi->Right - 2;
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
2,
&Written);
}
- /* draw upper right corner */
- coPos.X = List->Right;
- coPos.Y = List->Top;
+ /* Draw upper right corner */
+ coPos.X = ListUi->Right;
+ coPos.Y = ListUi->Top;
FillConsoleOutputCharacterA(StdOutput,
0xBF, // '+',
1,
coPos,
&Written);
- /* draw left and right edge */
- for (i = List->Top + 1; i < List->Bottom; i++)
+ /* Draw left and right edge */
+ for (i = ListUi->Top + 1; i < ListUi->Bottom; i++)
{
- coPos.X = List->Left;
+ coPos.X = ListUi->Left;
coPos.Y = i;
FillConsoleOutputCharacterA(StdOutput,
0xB3, // '|',
coPos,
&Written);
- coPos.X = List->Right;
+ coPos.X = ListUi->Right;
FillConsoleOutputCharacterA(StdOutput,
0xB3, //'|',
1,
&Written);
}
- /* draw lower left corner */
- coPos.X = List->Left;
- coPos.Y = List->Bottom;
+ /* Draw lower left corner */
+ coPos.X = ListUi->Left;
+ coPos.Y = ListUi->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)
+ /* Draw lower edge */
+ coPos.X = ListUi->Left + 1;
+ coPos.Y = ListUi->Bottom;
+ if (LastLine - ListUi->Offset <= ListUi->Bottom - ListUi->Top - 2)
{
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
- List->Right - List->Left - 1,
+ ListUi->Right - ListUi->Left - 1,
coPos,
&Written);
}
{
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
- List->Right - List->Left - 5,
+ ListUi->Right - ListUi->Left - 5,
coPos,
&Written);
- coPos.X = List->Right - 5;
+ coPos.X = ListUi->Right - 5;
WriteConsoleOutputCharacterA(StdOutput,
"(\x19)", // "(down)"
3,
coPos,
&Written);
- coPos.X = List->Right - 2;
+ coPos.X = ListUi->Right - 2;
FillConsoleOutputCharacterA(StdOutput,
0xC4, // '-',
2,
&Written);
}
- /* draw lower right corner */
- coPos.X = List->Right;
- coPos.Y = List->Bottom;
+ /* Draw lower right corner */
+ coPos.X = ListUi->Right;
+ coPos.Y = ListUi->Bottom;
FillConsoleOutputCharacterA(StdOutput,
0xD9, // '+',
1,
&Written);
/* print list entries */
- List->Line = - List->Offset;
+ ListUi->Line = - ListUi->Offset;
Entry = List->DiskListHead.Flink;
while (Entry != &List->DiskListHead)
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
/* Print disk entry */
- PrintDiskData(List,
- DiskEntry);
+ PrintDiskData(ListUi, DiskEntry);
Entry = Entry->Flink;
}
}
-DWORD
+ULONG
SelectPartition(
- PPARTLIST List,
- ULONG DiskNumber,
- ULONG PartitionNumber)
+ IN PPARTLIST List,
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
+ PLIST_ENTRY Entry1, Entry2;
/* Check for empty disks */
if (IsListEmpty(&List->DiskListHead))
if (DiskEntry->DiskNumber == DiskNumber)
{
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- for (i = 0; i < 4; i++)
+ if (PartEntry->PartitionNumber == PartitionNumber)
{
- if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
- {
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = i;
- DrawPartitionList(List);
- return TRUE;
- }
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ return TRUE;
}
Entry2 = Entry2->Flink;
}
-VOID
-ScrollDownPartitionList(
- PPARTLIST List)
+PPARTENTRY
+GetNextPartition(
+ IN PPARTLIST List)
{
+ PLIST_ENTRY DiskListEntry;
+ PLIST_ENTRY PartListEntry;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
- /* Check for empty disks */
+ /* Fail, if no disks are available */
if (IsListEmpty(&List->DiskListHead))
- return;
+ return NULL;
/* 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;
- }
-
- 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
- {
- /* Just advance to the next partition */
- List->CurrentPartitionNumber = i;
- DrawPartitionList(List);
- return;
- }
-
- while (Entry2 != &List->CurrentDisk->PartListHead)
+ if (List->CurrentPartition->LogicalPartition)
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ /* Logical partition */
-// if (PartEntry->HidePartEntry == FALSE)
+ PartListEntry = List->CurrentPartition->ListEntry.Flink;
+ if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
{
+ /* Next logical partition */
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = 0;
- DrawPartitionList(List);
- return;
+ return List->CurrentPartition;
}
+ else
+ {
+ PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
+ if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- Entry2 = Entry2->Flink;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
+ }
+ }
}
- }
-
- /* 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);
+ /* Primary or extended partition */
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+ if ((List->CurrentPartition->IsPartitioned != FALSE) &&
+ IsContainerPartition(List->CurrentPartition->PartitionType))
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-
-// if (PartEntry->HidePartEntry == FALSE)
+ /* First logical partition */
+ PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
+ if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
{
- List->CurrentDisk = DiskEntry;
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
List->CurrentPartition = PartEntry;
- List->CurrentPartitionNumber = 0;
- DrawPartitionList(List);
- return;
+ return List->CurrentPartition;
}
+ }
+ else
+ {
+ /* Next primary partition */
+ PartListEntry = List->CurrentPartition->ListEntry.Flink;
+ if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- Entry2 = Entry2->Flink;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
+ }
}
+ }
+ }
+
+ /* Search for the first partition entry on the next disk */
+ DiskListEntry = List->CurrentDisk->ListEntry.Flink;
+ while (DiskListEntry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
- Entry1 = Entry1->Flink;
+ PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
}
+
+ DiskListEntry = DiskListEntry->Flink;
}
-}
+ return NULL;
+}
-VOID
-ScrollUpPartitionList(
- PPARTLIST List)
+PPARTENTRY
+GetPrevPartition(
+ IN PPARTLIST List)
{
+ PLIST_ENTRY DiskListEntry;
+ PLIST_ENTRY PartListEntry;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- UCHAR i;
- /* Check for empty disks */
+ /* Fail, if no disks are available */
if (IsListEmpty(&List->DiskListHead))
- return;
+ return NULL;
- /* check for previous usable entry on current disk */
+ /* Check for previous 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 */
- if (List->CurrentPartitionNumber > 0)
+ if (List->CurrentPartition->LogicalPartition)
{
- /* Find a previous partition */
- for (i = List->CurrentPartitionNumber - 1; i > 0; i--)
+ /* Logical partition */
+ PartListEntry = List->CurrentPartition->ListEntry.Blink;
+ if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+ {
+ /* Previous logical partition */
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ }
+ else
{
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
+ /* Extended partition */
+ PartEntry = List->CurrentDisk->ExtendedPartition;
}
- /* Move to it and return */
- List->CurrentPartitionNumber = i;
- DrawPartitionList(List);
- return;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
}
-
- /* Move to the previous entry */
- Entry2 = Entry2->Blink;
-
- while (Entry2 != &List->CurrentDisk->PartListHead)
+ else
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ /* Primary or extended partition */
-// if (PartEntry->HidePartEntry == FALSE)
+ PartListEntry = List->CurrentPartition->ListEntry.Blink;
+ if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
{
- List->CurrentPartition = PartEntry;
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- /* Find last existing partition in the table */
- for (i = 3; i > 0; i--)
+ if ((PartEntry->IsPartitioned != FALSE) &&
+ IsContainerPartition(PartEntry->PartitionType))
{
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
+ PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
}
- /* Move to it */
- List->CurrentPartitionNumber = i;
-
- /* Draw partition list and return */
- DrawPartitionList(List);
- return;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
}
-
- Entry2 = Entry2->Blink;
}
}
-
- /* check for last usable entry on previous disk */
- if (List->CurrentDisk != NULL)
+ /* Search for the last partition entry on the previous disk */
+ DiskListEntry = List->CurrentDisk->ListEntry.Blink;
+ while (DiskListEntry != &List->DiskListHead)
{
- Entry1 = List->CurrentDisk->ListEntry.Blink;
- while (Entry1 != &List->DiskListHead)
+ DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+
+ PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
+ if (PartListEntry != &DiskEntry->PrimaryPartListHead)
{
- DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- Entry2 = DiskEntry->PartListHead.Blink;
- while (Entry2 != &DiskEntry->PartListHead)
+ if ((PartEntry->IsPartitioned != FALSE) &&
+ IsContainerPartition(PartEntry->PartitionType))
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-
-// if (PartEntry->HidePartEntry == FALSE)
+ PartListEntry = DiskEntry->LogicalPartListHead.Blink;
+ if (PartListEntry != &DiskEntry->LogicalPartListHead)
{
+ PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
List->CurrentDisk = DiskEntry;
List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
+ }
+ }
+ else
+ {
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ return List->CurrentPartition;
+ }
+ }
- /* Find last existing partition in the table */
- for (i = 3; i > 0; i--)
- {
- if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
- break;
- }
+ DiskListEntry = DiskListEntry->Blink;
+ }
- /* Move to it */
- List->CurrentPartitionNumber = i;
+ return NULL;
+}
- /* Draw partition list and return */
- DrawPartitionList(List);
- return;
- }
- Entry2 = Entry2->Blink;
- }
- Entry1 = Entry1->Blink;
- }
- }
+VOID
+ScrollDownPartitionList(
+ IN PPARTLIST_UI ListUi)
+{
+ if (GetNextPartition(ListUi->List))
+ DrawPartitionList(ListUi);
+}
+
+VOID
+ScrollUpPartitionList(
+ IN PPARTLIST_UI ListUi)
+{
+ if (GetPrevPartition(ListUi->List))
+ DrawPartitionList(ListUi);
}
static
-PPARTENTRY
-GetPrevPartitionedEntry(
- PDISKENTRY DiskEntry,
- PPARTENTRY CurrentEntry)
+BOOLEAN
+IsEmptyLayoutEntry(
+ IN PPARTITION_INFORMATION PartitionInfo)
{
- PPARTENTRY PrevEntry;
- PLIST_ENTRY Entry;
+ if (PartitionInfo->StartingOffset.QuadPart == 0 &&
+ PartitionInfo->PartitionLength.QuadPart == 0)
+ return TRUE;
- if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
- return NULL;
+ return FALSE;
+}
- Entry = CurrentEntry->ListEntry.Blink;
- while (Entry != &DiskEntry->PartListHead)
- {
- PrevEntry = CONTAINING_RECORD(Entry,
- PARTENTRY,
- ListEntry);
- if (PrevEntry->Unpartitioned == FALSE)
- return PrevEntry;
- Entry = Entry->Blink;
- }
+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 NULL;
+ return FALSE;
}
static
-PPARTENTRY
-GetNextPartitionedEntry(
- PDISKENTRY DiskEntry,
- PPARTENTRY CurrentEntry)
+ULONG
+GetPrimaryPartitionCount(
+ IN PDISKENTRY DiskEntry)
{
- PPARTENTRY NextEntry;
PLIST_ENTRY Entry;
+ PPARTENTRY PartEntry;
+ ULONG Count = 0;
- if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
- return NULL;
-
- Entry = CurrentEntry->ListEntry.Flink;
- while (Entry != &DiskEntry->PartListHead)
+ Entry = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry != &DiskEntry->PrimaryPartListHead)
{
- NextEntry = CONTAINING_RECORD(Entry,
- PARTENTRY,
- ListEntry);
- if (NextEntry->Unpartitioned == FALSE)
- return NextEntry;
+ PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned == TRUE)
+ Count++;
Entry = Entry->Flink;
}
- return NULL;
+ return Count;
}
static
-PPARTENTRY
-GetPrevUnpartitionedEntry(
- PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry)
+ULONG
+GetLogicalPartitionCount(
+ IN PDISKENTRY DiskEntry)
{
- PPARTENTRY PrevPartEntry;
+ PLIST_ENTRY ListEntry;
+ PPARTENTRY PartEntry;
+ ULONG Count = 0;
- if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
+ ListEntry = DiskEntry->LogicalPartListHead.Flink;
+ while (ListEntry != &DiskEntry->LogicalPartListHead)
{
- PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
- PARTENTRY,
- ListEntry);
- if (PrevPartEntry->Unpartitioned == TRUE)
- return PrevPartEntry;
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned)
+ Count++;
+
+ ListEntry = ListEntry->Flink;
}
- return NULL;
+ return Count;
}
static
-PPARTENTRY
-GetNextUnpartitionedEntry(
- PDISKENTRY DiskEntry,
- PPARTENTRY PartEntry)
+BOOLEAN
+ReAllocateLayoutBuffer(
+ IN PDISKENTRY DiskEntry)
{
- PPARTENTRY NextPartEntry;
+ PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
+ ULONG NewPartitionCount;
+ ULONG CurrentPartitionCount = 0;
+ ULONG LayoutBufferSize;
+ ULONG i;
+
+ DPRINT1("ReAllocateLayoutBuffer()\n");
+
+ NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
+
+ if (DiskEntry->LayoutBuffer)
+ CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
+
+ DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
+ CurrentPartitionCount, NewPartitionCount);
+
+ if (CurrentPartitionCount == NewPartitionCount)
+ return TRUE;
+
+ LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+ ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+ NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ DiskEntry->LayoutBuffer,
+ LayoutBufferSize);
+ if (NewLayoutBuffer == NULL)
+ {
+ DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
+ return FALSE;
+ }
- if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
+ /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
+ if (NewPartitionCount > CurrentPartitionCount)
{
- NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
- PARTENTRY,
- ListEntry);
- if (NextPartEntry->Unpartitioned == TRUE)
- return NextPartEntry;
+ for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
+ NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
}
- return NULL;
+ DiskEntry->LayoutBuffer = NewLayoutBuffer;
+ DiskEntry->LayoutBuffer->PartitionCount = NewPartitionCount;
+
+ return TRUE;
}
+static
VOID
-CreateNewPartition(
- PPARTLIST List,
- ULONGLONG PartitionSize,
- BOOLEAN AutoCreate)
+UpdateDiskLayout(
+ IN PDISKENTRY DiskEntry)
{
- PDISKENTRY DiskEntry;
+ PPARTITION_INFORMATION PartitionInfo;
+ PPARTITION_INFORMATION LinkInfo = NULL;
+ PLIST_ENTRY ListEntry;
PPARTENTRY PartEntry;
- PPARTENTRY PrevPartEntry;
- PPARTENTRY NextPartEntry;
- PPARTENTRY NewPartEntry;
+ LARGE_INTEGER HiddenSectors64;
+ ULONG Index;
+ ULONG PartitionNumber = 1;
- if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->Unpartitioned == FALSE)
+ DPRINT1("UpdateDiskLayout()\n");
+
+ /* Resize the layout buffer if necessary */
+ if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
{
+ DPRINT("ReAllocateLayoutBuffer() failed.\n");
return;
}
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- if (AutoCreate == TRUE ||
- PartitionSize == PartEntry->UnpartitionedLength)
+ /* Update the primary partition table */
+ Index = 0;
+ ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (ListEntry != &DiskEntry->PrimaryPartListHead)
{
- /* 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)
- {
- /* 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;
-
- /* Update previous container partition data */
-
- 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;
- }
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
- else if (PrevPartEntry == NULL && NextPartEntry != NULL)
- {
- /* Current entry is the first entry */
- return;
- }
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
+ if (PartEntry->IsPartitioned != FALSE)
{
- /* 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);
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
- 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
+ if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
{
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
+ DPRINT1("Updating primary partition entry %lu\n", Index);
+
+ PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
+ PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+ PartitionInfo->PartitionType = PartEntry->PartitionType;
+ PartitionInfo->BootIndicator = PartEntry->BootIndicator;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
}
- 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;
- }
+ PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+ PartEntry->PartitionIndex = Index;
- PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
+ if (!IsContainerPartition(PartEntry->PartitionType))
+ PartitionNumber++;
+
+ Index++;
}
- PartEntry->AutoCreate = AutoCreate;
- PartEntry->New = TRUE;
- PartEntry->Unpartitioned = FALSE;
- PartEntry->UnpartitionedOffset = 0ULL;
- PartEntry->UnpartitionedLength = 0ULL;
+ ListEntry = ListEntry->Flink;
}
- else
+
+ /* Update the logical partition table */
+ Index = 4;
+ ListEntry = DiskEntry->LogicalPartListHead.Flink;
+ while (ListEntry != &DiskEntry->LogicalPartListHead)
{
- /* Insert an initialize a new partition entry */
- NewPartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(PARTENTRY));
- if (NewPartEntry == NULL)
- return;
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
- RtlZeroMemory(NewPartEntry,
- sizeof(PARTENTRY));
+ if (PartEntry->IsPartitioned)
+ {
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
- /* Insert the new entry into the list */
- InsertTailList(&PartEntry->ListEntry,
- &NewPartEntry->ListEntry);
+ DPRINT1("Updating logical partition entry %lu\n", Index);
- NewPartEntry->New = TRUE;
+ PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
+ PartitionInfo->PartitionNumber = PartitionNumber;
+ PartitionInfo->PartitionType = PartEntry->PartitionType;
+ PartitionInfo->BootIndicator = FALSE;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
- 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);
-
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
- {
- /* Current entry is in the middle of the list */
-
- /* Copy previous container partition data to current entry */
- RtlCopyMemory(&NewPartEntry->PartInfo[1],
- &PrevPartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- NewPartEntry->PartInfo[1].RewritePartition = TRUE;
-
- /* Update previous container partition data */
- 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
+ PartEntry->PartitionNumber = PartitionNumber;
+ PartEntry->PartitionIndex = Index;
+
+ /* Fill the link entry of the previous partition entry */
+ if (LinkInfo != NULL)
{
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
+ LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
+ LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
+ HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
+ LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
+ LinkInfo->PartitionNumber = 0;
+ LinkInfo->PartitionType = PARTITION_EXTENDED;
+ LinkInfo->BootIndicator = FALSE;
+ LinkInfo->RecognizedPartition = FALSE;
+ LinkInfo->RewritePartition = TRUE;
}
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
+ /* Save a pointer to the link entry of the current partition entry */
+ LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
+
+ PartitionNumber++;
+ Index += 4;
}
- else if (PrevPartEntry == NULL && NextPartEntry != NULL)
+
+ ListEntry = ListEntry->Flink;
+ }
+
+ /* Wipe unused primary partition entries */
+ for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
+ {
+ DPRINT1("Primary partition entry %lu\n", Index);
+
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+
+ if (!IsEmptyLayoutEntry(PartitionInfo))
{
- /* Current entry is the first entry */
- return;
+ DPRINT1("Wiping primary partition entry %lu\n", Index);
+
+ PartitionInfo->StartingOffset.QuadPart = 0;
+ PartitionInfo->PartitionLength.QuadPart = 0;
+ PartitionInfo->HiddenSectors = 0;
+ PartitionInfo->PartitionNumber = 0;
+ PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartitionInfo->BootIndicator = FALSE;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
}
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
+ }
+
+ /* Wipe unused logical partition entries */
+ for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
+ {
+ if (Index % 4 >= 2)
{
- /* Current entry is the last entry */
+ DPRINT1("Logical partition entry %lu\n", Index);
- PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
- NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PrevPartEntry->PartInfo[1].HiddenSectors =
- (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
- 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
+ if (!IsEmptyLayoutEntry(PartitionInfo))
{
- PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
- NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
+ DPRINT1("Wiping partition entry %lu\n", Index);
+
+ PartitionInfo->StartingOffset.QuadPart = 0;
+ PartitionInfo->PartitionLength.QuadPart = 0;
+ PartitionInfo->HiddenSectors = 0;
+ PartitionInfo->PartitionNumber = 0;
+ PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartitionInfo->BootIndicator = FALSE;
+ PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RewritePartition = TRUE;
}
+ }
+ }
- 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;
- }
+#ifdef DUMP_PARTITION_TABLE
+ DumpPartitionTable(DiskEntry);
+#endif
+}
- 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;
+static
+PPARTENTRY
+GetPrevUnpartitionedEntry(
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry)
+{
+ PPARTENTRY PrevPartEntry;
+ PLIST_ENTRY ListHead;
+
+ if (PartEntry->LogicalPartition)
+ ListHead = &DiskEntry->LogicalPartListHead;
+ else
+ ListHead = &DiskEntry->PrimaryPartListHead;
+
+ if (PartEntry->ListEntry.Blink != ListHead)
+ {
+ PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
+ PARTENTRY,
+ ListEntry);
+ if (PrevPartEntry->IsPartitioned == FALSE)
+ return PrevPartEntry;
}
- DiskEntry->Modified = TRUE;
+ return NULL;
+}
+
+
+static
+PPARTENTRY
+GetNextUnpartitionedEntry(
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry)
+{
+ PPARTENTRY NextPartEntry;
+ PLIST_ENTRY ListHead;
+
+ if (PartEntry->LogicalPartition)
+ ListHead = &DiskEntry->LogicalPartListHead;
+ else
+ ListHead = &DiskEntry->PrimaryPartListHead;
- UpdatePartitionNumbers(DiskEntry);
+ if (PartEntry->ListEntry.Flink != ListHead)
+ {
+ NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
+ PARTENTRY,
+ ListEntry);
+ if (NextPartEntry->IsPartitioned == FALSE)
+ return NextPartEntry;
+ }
- AssignDriverLetters(List);
+ return NULL;
}
VOID
-DeleteCurrentPartition(
- PPARTLIST List)
+CreatePrimaryPartition(
+ IN PPARTLIST List,
+ IN ULONGLONG SectorCount,
+ IN BOOLEAN AutoCreate)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PPARTENTRY PrevPartEntry;
- PPARTENTRY NextPartEntry;
+ PPARTENTRY NewPartEntry;
+
+ DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
if (List == NULL ||
List->CurrentDisk == NULL ||
List->CurrentPartition == NULL ||
- List->CurrentPartition->Unpartitioned == TRUE)
+ List->CurrentPartition->IsPartitioned != FALSE)
{
return;
}
DiskEntry = List->CurrentDisk;
PartEntry = List->CurrentPartition;
- /* Adjust container partition entries */
+ DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
- /* Get previous and next partition entries */
- PrevPartEntry = GetPrevPartitionedEntry(DiskEntry,
- PartEntry);
- NextPartEntry = GetNextPartitionedEntry(DiskEntry,
- PartEntry);
-
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
+ if ((AutoCreate != FALSE) ||
+ (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
{
- /* Current entry is in the middle of the list */
+ DPRINT1("Convert existing partition entry\n");
- /*
- * The first extended partition can not be deleted
- * as long as other extended partitions are present.
- */
- if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
- return;
+ /* Convert current entry to 'new (unformatted)' */
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartEntry->FormatState = Unformatted;
+ PartEntry->FileSystem = NULL;
+ PartEntry->AutoCreate = AutoCreate;
+ PartEntry->New = TRUE;
+ PartEntry->BootIndicator = FALSE;
- /* 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;
+ 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);
}
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
+ else
{
- /* Current entry is the last entry */
- RtlZeroMemory(&PrevPartEntry->PartInfo[1],
- sizeof(PARTITION_INFORMATION));
- PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
- }
+ DPRINT1("Add new partition entry\n");
+ /* Insert and initialize a new partition entry */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
- /* Adjust unpartitioned disk space entries */
+ /* Insert the new entry into the list */
+ InsertTailList(&PartEntry->ListEntry,
+ &NewPartEntry->ListEntry);
- /* Get pointer to previous and next unpartitioned entries */
- PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry,
- PartEntry);
+ NewPartEntry->DiskEntry = DiskEntry;
- NextPartEntry = GetNextUnpartitionedEntry(DiskEntry,
- PartEntry);
+ NewPartEntry->IsPartitioned = TRUE;
+ NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+ NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+ NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
- if (PrevPartEntry != NULL && NextPartEntry != NULL)
- {
- /* Merge previous, current and next unpartitioned entry */
+ 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);
- /* Adjust the previous entries length */
- PrevPartEntry->UnpartitionedLength +=
- (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
- NextPartEntry->UnpartitionedLength);
+ NewPartEntry->New = TRUE;
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
+ NewPartEntry->BootIndicator = FALSE;
- /* Remove the current entry */
- RemoveEntryList(&PartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap,
- 0,
- PartEntry);
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+ }
- /* Remove the next entry */
- RemoveEntryList (&NextPartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap,
- 0,
- NextPartEntry);
+ UpdateDiskLayout(DiskEntry);
- /* Update current partition */
- List->CurrentPartition = PrevPartEntry;
- }
- else if (PrevPartEntry != NULL && NextPartEntry == NULL)
- {
- /* Merge current and previous unpartitioned entry */
+ DiskEntry->Dirty = TRUE;
- /* Adjust the previous entries length */
- PrevPartEntry->UnpartitionedLength +=
- (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
+ AssignDriveLetters(List);
+}
- /* 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 */
+static
+VOID
+AddLogicalDiskSpace(
+ IN PDISKENTRY DiskEntry)
+{
+ PPARTENTRY NewPartEntry;
- /* 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);
+ DPRINT1("AddLogicalDiskSpace()\n");
- /* Remove the current entry */
- RemoveEntryList(&PartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap,
- 0,
- PartEntry);
+ /* Create a partition entry that represents the empty space in the container partition */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return;
- /* 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;
+ NewPartEntry->DiskEntry = DiskEntry;
+ NewPartEntry->LogicalPartition = TRUE;
- /* Wipe the partition table */
- RtlZeroMemory(&PartEntry->PartInfo,
- sizeof(PartEntry->PartInfo));
- }
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+ NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
- DiskEntry->Modified = TRUE;
+ 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);
- UpdatePartitionNumbers(DiskEntry);
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
- AssignDriverLetters(List);
+ InsertTailList(&DiskEntry->LogicalPartListHead,
+ &NewPartEntry->ListEntry);
}
VOID
-CheckActiveBootPartition(
- PPARTLIST List)
+CreateExtendedPartition(
+ IN PPARTLIST List,
+ IN ULONGLONG SectorCount)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY ListEntry;
- UCHAR i;
+ PPARTENTRY NewPartEntry;
- /* Check for empty disk list */
- if (IsListEmpty (&List->DiskListHead))
- {
- List->ActiveBootDisk = NULL;
- List->ActiveBootPartition = NULL;
- List->ActiveBootPartitionNumber = 0;
- return;
- }
+ DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
-#if 0
- if (List->ActiveBootDisk != NULL &&
- List->ActiveBootPartition != NULL)
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->IsPartitioned != FALSE)
{
- /* We already have an active boot partition */
return;
}
-#endif
- /* Choose the currently selected disk */
DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
- /* 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);
+ DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
- /* 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))
+ if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
{
- PartEntry->PartInfo[0].BootIndicator = TRUE;
- PartEntry->PartInfo[0].RewritePartition = TRUE;
- DiskEntry->Modified = TRUE;
+ DPRINT1("Convert existing partition entry\n");
- /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
- List->ActiveBootDisk = DiskEntry;
- List->ActiveBootPartition = PartEntry;
- List->ActiveBootPartitionNumber = 0;
+ /* Convert current entry to 'new (unformatted)' */
+ PartEntry->IsPartitioned = TRUE;
+ PartEntry->FormatState = Formatted; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
+ PartEntry->FileSystem = NULL;
+ PartEntry->AutoCreate = FALSE;
+ PartEntry->New = FALSE;
+ PartEntry->BootIndicator = FALSE;
- return;
- }
+ if (PartEntry->StartSector.QuadPart < 1450560)
+ {
+ /* 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;
+ }
- /* Disk is not new, scan all partitions to find a bootable one */
- List->ActiveBootDisk = NULL;
- List->ActiveBootPartition = NULL;
- List->ActiveBootPartitionNumber = 0;
+ DiskEntry->ExtendedPartition = PartEntry;
- ListEntry = DiskEntry->PartListHead.Flink;
- while (ListEntry != &DiskEntry->PartListHead)
+ 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);
+ }
+ else
{
- PartEntry = CONTAINING_RECORD(ListEntry,
- PARTENTRY,
- ListEntry);
+ DPRINT1("Add new partition entry\n");
- /* Check if it's partitioned */
- if (!PartEntry->Unpartitioned)
+ /* Insert and initialize a new partition entry */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ 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 = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+
+ NewPartEntry->New = FALSE;
+ NewPartEntry->FormatState = Formatted; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
+ NewPartEntry->FileSystem = NULL;
+ NewPartEntry->BootIndicator = FALSE;
+
+ if (NewPartEntry->StartSector.QuadPart < 1450560)
{
- /* 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;
+ /* 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;
+ }
- DPRINT("Found bootable partition disk %d, drive letter %c\n",
- DiskEntry->DiskNumber, PartEntry->DriveLetter[i]);
+ DiskEntry->ExtendedPartition = NewPartEntry;
- break;
- }
- }
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - 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);
+ }
+
+ AddLogicalDiskSpace(DiskEntry);
+
+ UpdateDiskLayout(DiskEntry);
+
+ DiskEntry->Dirty = TRUE;
+
+ AssignDriveLetters(List);
+}
+
+
+VOID
+CreateLogicalPartition(
+ IN PPARTLIST List,
+ IN ULONGLONG SectorCount,
+ IN BOOLEAN AutoCreate)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
+
+ DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
+
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->IsPartitioned != FALSE)
+ {
+ return;
+ }
+
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+ if (AutoCreate == TRUE ||
+ AlignDown(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->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartEntry->FormatState = Unformatted;
+ PartEntry->FileSystem = NULL;
+ PartEntry->AutoCreate = FALSE;
+ PartEntry->New = TRUE;
+ PartEntry->BootIndicator = FALSE;
+ PartEntry->LogicalPartition = TRUE;
+
+ 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);
+ }
+ else
+ {
+ DPRINT1("Add new partition entry\n");
+
+ /* Insert and initialize a new partition entry */
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ 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 = AlignDown(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);
+
+ NewPartEntry->New = TRUE;
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem = NULL;
+ NewPartEntry->BootIndicator = FALSE;
+ NewPartEntry->LogicalPartition = TRUE;
+
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+ }
+
+ UpdateDiskLayout(DiskEntry);
+
+ DiskEntry->Dirty = TRUE;
+
+ AssignDriveLetters(List);
+}
+
+
+VOID
+DeleteCurrentPartition(
+ IN PPARTLIST List)
+{
+ 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)
+ {
+ return;
+ }
+
+ /* Clear the system disk and partition pointers if the system partition is being deleted */
+ if (List->SystemPartition == List->CurrentPartition)
+ {
+ List->SystemPartition = NULL;
+ }
+
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ /* Delete all logical partition 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);
+
+ RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
}
- /* Go to the next one */
- ListEntry = ListEntry->Flink;
+ DiskEntry->ExtendedPartition = NULL;
+ }
+
+ /* 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->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
+
+ /* 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->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
+
+ /* 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->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
+ {
+ /* Nothing to merge but change current entry */
+ PartEntry->IsPartitioned = FALSE;
+ PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+ PartEntry->FormatState = Unformatted;
+ PartEntry->FileSystem = NULL;
+ PartEntry->DriveLetter = 0;
+ }
+
+ UpdateDiskLayout(DiskEntry);
+
+ DiskEntry->Dirty = TRUE;
+
+ AssignDriveLetters(List);
}
-BOOLEAN
-CheckForLinuxFdiskPartitions(
- PPARTLIST List)
+VOID
+CheckActiveSystemPartition(
+ IN PPARTLIST List,
+ IN PFILE_SYSTEM_LIST FileSystemList /* Needed for checking the FS of the candidate system partition */
+ )
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY Entry1;
- PLIST_ENTRY Entry2;
- ULONG PartitionCount;
- ULONG i;
+ PLIST_ENTRY ListEntry;
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ PFILE_SYSTEM_ITEM FileSystem;
+
+ /* Check for empty disk list */
+ if (IsListEmpty(&List->DiskListHead))
{
- DiskEntry = CONTAINING_RECORD(Entry1,
- DISKENTRY,
+ List->SystemPartition = NULL;
+ List->OriginalSystemPartition = NULL;
+ return;
+ }
+
+ /* Choose the currently selected disk */
+ DiskEntry = List->CurrentDisk;
+
+ /* Check for empty partition list */
+ if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+ {
+ List->SystemPartition = NULL;
+ List->OriginalSystemPartition = NULL;
+ return;
+ }
+
+ if (List->SystemPartition != NULL)
+ {
+ /* We already have an active system partition */
+ DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
+ List->SystemPartition->PartitionNumber,
+ List->SystemPartition->DiskEntry->DiskNumber,
+ (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+ return;
+ }
+
+ DPRINT1("We are here (1)!\n");
+
+ List->SystemPartition = NULL;
+ List->OriginalSystemPartition = NULL;
+
+ /* Retrieve the first partition of the disk */
+ PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
+ PARTENTRY,
+ ListEntry);
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ List->SystemPartition = PartEntry;
+
+ //
+ // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
+ //
+
+ /* Check if the disk is new and if so, use its first partition as the active system partition */
+ if (DiskEntry->NewDisk)
+ {
+ if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
+ {
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ List->SystemPartition = PartEntry;
+
+ List->OriginalSystemPartition = List->SystemPartition;
+
+ DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
+ List->SystemPartition->PartitionNumber,
+ List->SystemPartition->DiskEntry->DiskNumber,
+ (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+ goto SetSystemPartition;
+ }
+
+ // FIXME: What to do??
+ DPRINT1("NewDisk TRUE but first partition is used?\n");
+ }
+
+ DPRINT1("We are here (2)!\n");
+
+ /*
+ * The disk is not new, check if any partition is initialized;
+ * if not, the first one becomes the system partition.
+ */
+ ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (ListEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ /* Retrieve the partition and go to the next one */
+ PartEntry = CONTAINING_RECORD(ListEntry,
+ PARTENTRY,
ListEntry);
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+ /* Check if the partition is partitioned and is used */
+ if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
{
- PartEntry = CONTAINING_RECORD(Entry2,
- PARTENTRY,
- ListEntry);
+ break;
+ }
- if (PartEntry->Unpartitioned == FALSE)
- {
- PartitionCount = 0;
+ /* Go to the next one */
+ ListEntry = ListEntry->Flink;
+ }
+ if (ListEntry == &DiskEntry->PrimaryPartListHead)
+ {
+ /*
+ * OK we haven't encountered any used and active partition,
+ * so use the first one as the system partition.
+ */
+ ASSERT(DiskEntry == List->SystemPartition->DiskEntry);
+ List->OriginalSystemPartition = List->SystemPartition; // First PartEntry
- for (i = 0; i < 4; i++)
- {
- if (!IsContainerPartition(PartEntry->PartInfo[i].PartitionType) &&
- PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
- {
- PartitionCount++;
- }
- }
+ DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
+ List->SystemPartition->PartitionNumber,
+ List->SystemPartition->DiskEntry->DiskNumber,
+ (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
- if (PartitionCount > 1)
- {
- return TRUE;
- }
- }
+ goto SetSystemPartition;
+ }
- Entry2 = Entry2->Flink;
+ List->SystemPartition = NULL;
+ List->OriginalSystemPartition = NULL;
+
+ DPRINT1("We are here (3)!\n");
+
+ /* The disk is not new, scan all partitions to find the (active) system partition */
+ ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ while (ListEntry != &DiskEntry->PrimaryPartListHead)
+ {
+ /* Retrieve the partition and go to the next one */
+ PartEntry = CONTAINING_RECORD(ListEntry,
+ PARTENTRY,
+ ListEntry);
+ ListEntry = ListEntry->Flink;
+
+ /* Check if the partition is partitioned and used */
+ if (PartEntry->IsPartitioned &&
+ PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
+ {
+ /* Check if the partition is active */
+ if (PartEntry->BootIndicator)
+ {
+ /* Yes, we found it */
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ List->SystemPartition = PartEntry;
+
+ DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
+ PartEntry->PartitionNumber,
+ DiskEntry->DiskNumber,
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter);
+ break;
+ }
}
+ }
- Entry1 = Entry1->Flink;
+ /* Check if we have found the system partition */
+ if (List->SystemPartition == NULL)
+ {
+ /* Nothing, use the alternative system partition */
+ DPRINT1("No system partition found, use the alternative partition!\n");
+ goto UseAlternativeSystemPartition;
}
- return FALSE;
+ /* Save it */
+ List->OriginalSystemPartition = List->SystemPartition;
+
+ /*
+ * ADDITIONAL CHECKS / BIG HACK:
+ *
+ * Retrieve its file system and check whether we have
+ * write support for it. If that is the case we are fine
+ * and we can use it directly. However if we don't have
+ * write support we will need to change the active system
+ * partition.
+ *
+ * NOTE that this is completely useless on architectures
+ * where a real system partition is required, as on these
+ * architectures the partition uses the FAT FS, for which
+ * we do have write support.
+ * NOTE also that for those architectures looking for a
+ * partition boot indicator is insufficient.
+ */
+ FileSystem = GetFileSystem(FileSystemList, List->OriginalSystemPartition);
+ if (FileSystem == NULL)
+ {
+ DPRINT1("System partition %lu in disk %lu with no FS?!\n",
+ List->OriginalSystemPartition->PartitionNumber,
+ List->OriginalSystemPartition->DiskEntry->DiskNumber);
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ // HACK: WARNING: We cannot write on this FS yet!
+ // See fslist.c:GetFileSystem()
+ if (List->OriginalSystemPartition->PartitionType == PARTITION_EXT2 ||
+ List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
+ {
+ DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
+ FileSystem->FileSystemName);
+ goto FindAndUseAlternativeSystemPartition;
+ }
+
+ DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
+ List->SystemPartition->PartitionNumber,
+ List->SystemPartition->DiskEntry->DiskNumber,
+ (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+ return;
+
+FindAndUseAlternativeSystemPartition:
+ /*
+ * We are here because we have not found any (active) candidate
+ * system partition that we know how to support. What we are going
+ * to do is to change the existing system partition and use the
+ * partition on which we install ReactOS as the new system partition,
+ * and then we will need to add in FreeLdr's entry a boot entry to boot
+ * from the original system partition.
+ */
+
+ /* Unset the old system partition */
+ List->SystemPartition->BootIndicator = FALSE;
+ List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = FALSE;
+ List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
+ List->SystemPartition->DiskEntry->Dirty = TRUE;
+
+UseAlternativeSystemPartition:
+ List->SystemPartition = List->CurrentPartition;
+
+ DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
+ List->SystemPartition->PartitionNumber,
+ List->SystemPartition->DiskEntry->DiskNumber,
+ (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+SetSystemPartition:
+ /* Set the new active system partition */
+ List->SystemPartition->BootIndicator = TRUE;
+ List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = TRUE;
+ List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
+ List->SystemPartition->DiskEntry->Dirty = TRUE;
}
-BOOLEAN
-WritePartitionsToDisk(
- PPARTLIST List)
+static
+NTSTATUS
+WritePartitions(
+ IN PPARTLIST List,
+ IN PDISKENTRY DiskEntry)
{
- PDRIVE_LAYOUT_INFORMATION DriveLayout;
+ WCHAR DstPath[MAX_PATH];
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;
+ ULONG BufferSize;
+ HANDLE FileHandle = NULL;
NTSTATUS Status;
- if (List == NULL)
+ 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))
{
- return TRUE;
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ return Status;
}
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+#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);
+ }
+
+ if (FileHandle != NULL)
+ NtClose(FileHandle);
+
+ //
+ // NOTE: Originally (see r40437), we used to install here also a new MBR
+ // for this disk (by calling InstallMbrBootCodeToDisk), only if:
+ // DiskEntry->NewDisk == TRUE and DiskEntry->BiosDiskNumber == 0.
+ // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
+ // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
+ // was called too, the installation test was modified by checking whether
+ // DiskEntry->NoMbr was TRUE (instead of NewDisk).
+ //
+
+ return Status;
+}
+
+
+BOOLEAN
+WritePartitionsToDisk(
+ IN PPARTLIST List)
+{
+ PLIST_ENTRY Entry;
+ PDISKENTRY DiskEntry;
+
+ if (List == NULL)
+ return TRUE;
+
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
{
- DiskEntry1 = CONTAINING_RECORD(Entry1,
- DISKENTRY,
- ListEntry);
+ DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- if (DiskEntry1->Modified == TRUE)
+ if (DiskEntry->Dirty != FALSE)
{
- /* Count partitioned entries */
- PartitionCount = 0;
+ WritePartitions(List, DiskEntry);
+ DiskEntry->Dirty = FALSE;
+ }
- Entry2 = DiskEntry1->PartListHead.Flink;
- while (Entry2 != &DiskEntry1->PartListHead)
- {
- PartEntry = CONTAINING_RECORD(Entry2,
- PARTENTRY,
- ListEntry);
- if (PartEntry->Unpartitioned == FALSE)
- {
- PartitionCount += 4;
- }
+ Entry = Entry->Flink;
+ }
- Entry2 = Entry2->Flink;
- }
+ return TRUE;
+}
- 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");
- return FALSE;
- }
+BOOLEAN
+SetMountedDeviceValues(
+ IN PPARTLIST List)
+{
+ PLIST_ENTRY Entry1, Entry2;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ LARGE_INTEGER StartingOffset;
+
+ if (List == NULL)
+ return FALSE;
- RtlZeroMemory(DriveLayout,
- DriveLayoutSize);
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD(Entry1,
+ DISKENTRY,
+ ListEntry);
- if (PartitionCount == 0)
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned)
{
- /* delete all partitions in the mbr */
- DriveLayout->PartitionCount = 4;
- for (Index = 0; Index < 4; Index++)
+ /* Assign a "\DosDevices\#:" mount point to this partition */
+ if (PartEntry->DriveLetter)
{
- DriveLayout->PartitionEntry[Index].RewritePartition = TRUE;
+ StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ if (!SetMountedDeviceValue(PartEntry->DriveLetter,
+ DiskEntry->LayoutBuffer->Signature,
+ StartingOffset))
+ {
+ return FALSE;
+ }
}
}
- else
- {
- DriveLayout->PartitionCount = PartitionCount;
- Index = 0;
- Entry2 = DiskEntry1->PartListHead.Flink;
- while (Entry2 != &DiskEntry1->PartListHead)
+ Entry2 = Entry2->Flink;
+ }
+
+ Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry2 != &DiskEntry->LogicalPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned)
+ {
+ /* Assign a "\DosDevices\#:" mount point to this partition */
+ if (PartEntry->DriveLetter)
{
- PartEntry = CONTAINING_RECORD(Entry2,
- PARTENTRY,
- ListEntry);
- if (PartEntry->Unpartitioned == FALSE)
+ StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+ if (!SetMountedDeviceValue(PartEntry->DriveLetter,
+ DiskEntry->LayoutBuffer->Signature,
+ StartingOffset))
{
- RtlCopyMemory(&DriveLayout->PartitionEntry[Index],
- &PartEntry->PartInfo[0],
- 4 * sizeof (PARTITION_INFORMATION));
- Index += 4;
+ return FALSE;
}
-
- Entry2 = Entry2->Flink;
}
}
- if (DiskEntry1->Signature == 0)
- {
- LARGE_INTEGER SystemTime;
- TIME_FIELDS TimeFields;
- PUCHAR Buffer;
- Buffer = (PUCHAR)&DiskEntry1->Signature;
+ Entry2 = Entry2->Flink;
+ }
- while (1)
- {
- NtQuerySystemTime(&SystemTime);
- RtlTimeToTimeFields(&SystemTime, &TimeFields);
+ Entry1 = Entry1->Flink;
+ }
- 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);
+ return TRUE;
+}
- if (DiskEntry1->Signature == 0)
- {
- continue;
- }
+VOID
+SetPartitionType(
+ IN PPARTENTRY PartEntry,
+ IN UCHAR PartitionType)
+{
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
- /* 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)
- {
- break;
- }
+ PartEntry->PartitionType = PartitionType;
- Entry2 = Entry2->Flink;
- }
+ DiskEntry->Dirty = TRUE;
+ DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
+ DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
+}
- if (Entry2 == &List->DiskListHead)
- {
- break;
- }
- }
+ULONG
+PrimaryPartitionCreationChecks(
+ IN PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
- /* set one partition entry to dirty, this will update the signature */
- DriveLayout->PartitionEntry[0].RewritePartition = TRUE;
- }
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
- DriveLayout->Signature = DiskEntry1->Signature;
+ /* Fail if partition is already in use */
+ if (PartEntry->IsPartitioned != FALSE)
+ return ERROR_NEW_PARTITION;
- swprintf(DstPath,
- L"\\Device\\Harddisk%d\\Partition0",
- DiskEntry1->DiskNumber);
- RtlInitUnicodeString(&Name,
- DstPath);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
+ /* Fail if there are already 4 primary partitions in the list */
+ if (GetPrimaryPartitionCount(DiskEntry) >= 4)
+ return ERROR_PARTITION_TABLE_FULL;
+
+ 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 != FALSE)
+ return ERROR_NEW_PARTITION;
+
+ /* Fail if there are already 4 primary 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;
+
+ return ERROR_SUCCESS;
+}
+
+
+ULONG
+LogicalPartitionCreationChecks(
+ IN PPARTLIST List)
+{
+// PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+
+// DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ /* Fail if partition is already in use */
+ if (PartEntry->IsPartitioned != FALSE)
+ return ERROR_NEW_PARTITION;
+
+ return ERROR_SUCCESS;
+}
+
+
+BOOLEAN
+GetNextUnformattedPartition(
+ IN PPARTLIST List,
+ OUT PDISKENTRY *pDiskEntry OPTIONAL,
+ OUT PPARTENTRY *pPartEntry)
+{
+ PLIST_ENTRY Entry1, Entry2;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+
+ 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 && PartEntry->New)
{
- DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
- return FALSE;
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ if (pDiskEntry) *pDiskEntry = DiskEntry;
+ *pPartEntry = PartEntry;
+ return TRUE;
}
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_SET_DRIVE_LAYOUT,
- DriveLayout,
- DriveLayoutSize,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
+ Entry2 = Entry2->Flink;
+ }
+
+ Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry2 != &DiskEntry->LogicalPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry->IsPartitioned && PartEntry->New)
{
- DPRINT1("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
- NtClose(FileHandle);
- return FALSE;
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ if (pDiskEntry) *pDiskEntry = DiskEntry;
+ *pPartEntry = PartEntry;
+ return TRUE;
}
- RtlFreeHeap(ProcessHeap,
- 0,
- DriveLayout);
-
- NtClose(FileHandle);
+ Entry2 = Entry2->Flink;
}
Entry1 = Entry1->Flink;
}
- return TRUE;
-}
+ if (pDiskEntry) *pDiskEntry = NULL;
+ *pPartEntry = NULL;
+ return FALSE;
+}
-BOOL
-SetMountedDeviceValues(
- PPARTLIST List)
+BOOLEAN
+GetNextUncheckedPartition(
+ IN PPARTLIST List,
+ OUT PDISKENTRY *pDiskEntry OPTIONAL,
+ OUT PPARTENTRY *pPartEntry)
{
PLIST_ENTRY Entry1, Entry2;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- UCHAR i;
-
- if (List == NULL)
- {
- return FALSE;
- }
Entry1 = List->DiskListHead.Flink;
while (Entry1 != &List->DiskListHead)
DISKENTRY,
ListEntry);
- Entry2 = DiskEntry->PartListHead.Flink;
- while (Entry2 != &DiskEntry->PartListHead)
+ Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ while (Entry2 != &DiskEntry->PrimaryPartListHead)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (!PartEntry->Unpartitioned)
+ if (PartEntry->NeedsCheck == TRUE)
{
- for (i = 0; i < 4; i++)
- {
- if (PartEntry->DriveLetter[i])
- {
- if (!SetMountedDeviceValue(PartEntry->DriveLetter[i],
- DiskEntry->Signature,
- PartEntry->PartInfo[i].StartingOffset))
- {
- return FALSE;
- }
- }
- }
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ if (pDiskEntry) *pDiskEntry = DiskEntry;
+ *pPartEntry = PartEntry;
+ return TRUE;
+ }
+
+ Entry2 = Entry2->Flink;
+ }
+
+ Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ while (Entry2 != &DiskEntry->LogicalPartListHead)
+ {
+ PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+ if (PartEntry->NeedsCheck == TRUE)
+ {
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ if (pDiskEntry) *pDiskEntry = DiskEntry;
+ *pPartEntry = PartEntry;
+ return TRUE;
}
Entry2 = Entry2->Flink;
Entry1 = Entry1->Flink;
}
- return TRUE;
+ if (pDiskEntry) *pDiskEntry = NULL;
+ *pPartEntry = NULL;
+
+ return FALSE;
}
/* EOF */