* PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Partition list functions
- * COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * Copyright 2018-2019 Hermes Belusca-Maito
*/
#include "precomp.h"
Letter = L'C';
/* Assign drive letters to primary partitions */
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ for (Entry1 = List->DiskListHead.Flink;
+ Entry1 != &List->DiskListHead;
+ Entry1 = Entry1->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
- Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ Entry2 != &DiskEntry->PrimaryPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned &&
!IsContainerPartition(PartEntry->PartitionType))
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
if (IsRecognizedPartition(PartEntry->PartitionType) ||
- (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->SectorCount.QuadPart != 0LL))
+ PartEntry->SectorCount.QuadPart != 0LL)
{
if (Letter <= L'Z')
{
}
}
}
-
- Entry2 = Entry2->Flink;
}
-
- Entry1 = Entry1->Flink;
}
/* Assign drive letters to logical drives */
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ for (Entry1 = List->DiskListHead.Flink;
+ Entry1 != &List->DiskListHead;
+ Entry1 = Entry1->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
- Entry2 = DiskEntry->LogicalPartListHead.Flink;
- while (Entry2 != &DiskEntry->LogicalPartListHead)
+ for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ Entry2 != &DiskEntry->LogicalPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned)
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
if (IsRecognizedPartition(PartEntry->PartitionType) ||
- (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
- PartEntry->SectorCount.QuadPart != 0LL))
+ PartEntry->SectorCount.QuadPart != 0LL)
{
if (Letter <= L'Z')
{
}
}
}
-
- Entry2 = Entry2->Flink;
}
-
- Entry1 = Entry1->Flink;
}
}
UNICODE_STRING NameU;
if (ValueType == REG_SZ &&
- ValueLength == 20 * sizeof(WCHAR))
+ ValueLength == 20 * sizeof(WCHAR) &&
+ ((PWCHAR)ValueData)[8] == L'-')
{
NameU.Buffer = (PWCHAR)ValueData;
NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
WCHAR Name[120];
ULONG AdapterCount;
+ ULONG ControllerCount;
ULONG DiskCount;
NTSTATUS Status;
PCM_INT13_DRIVE_PARAMETER Int13Drives;
return;
}
- AdapterCount = 0;
- while (TRUE)
+ for (AdapterCount = 0; ; ++AdapterCount)
{
RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
L"%s\\%lu",
NULL);
if (NT_SUCCESS(Status))
{
- while (TRUE)
+ for (ControllerCount = 0; ; ++ControllerCount)
{
RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
- L"%s\\%lu\\DiskController\\0",
- ROOT_NAME, AdapterCount);
+ L"%s\\%lu\\DiskController\\%lu",
+ ROOT_NAME, AdapterCount, ControllerCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[2],
}
RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
- L"%s\\%lu\\DiskController\\0\\DiskPeripheral",
- ROOT_NAME, AdapterCount);
+ L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral",
+ ROOT_NAME, AdapterCount, ControllerCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
&QueryTable[2],
QueryTable[1].Name = L"Configuration Data";
QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
- DiskCount = 0;
- while (TRUE)
+ for (DiskCount = 0; ; ++DiskCount)
{
BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
if (BiosDiskEntry == NULL)
{
- break;
+ RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+ return;
}
RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
- L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu",
- ROOT_NAME, AdapterCount, DiskCount);
+ L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu",
+ ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
Name,
QueryTable,
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
- break;
+ RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+ return;
}
+ BiosDiskEntry->AdapterNumber = 0; // And NOT "AdapterCount" as it needs to be hardcoded for BIOS!
+ BiosDiskEntry->ControllerNumber = ControllerCount;
BiosDiskEntry->DiskNumber = DiskCount;
- BiosDiskEntry->Recognized = FALSE;
+ BiosDiskEntry->DiskEntry = NULL;
if (DiskCount < Int13Drives[0].NumberDrives)
{
}
else
{
- DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
+ DPRINT1("Didn't find Int13 drive data for disk %u\n", DiskCount);
}
InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
+ DPRINT("--->\n");
+ DPRINT("AdapterNumber: %lu\n", BiosDiskEntry->AdapterNumber);
+ DPRINT("ControllerNumber: %lu\n", BiosDiskEntry->ControllerNumber);
DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
-
- DiskCount++;
+ DPRINT("<---\n");
}
}
-
- RtlFreeHeap(ProcessHeap, 0, Int13Drives);
- return;
}
}
-
- AdapterCount++;
}
RtlFreeHeap(ProcessHeap, 0, Int13Drives);
#undef ROOT_NAME
}
+
+/*
+ * Detects whether a disk reports as a "super-floppy", i.e. an unpartitioned
+ * disk with a valid VBR, following the criteria used by IoReadPartitionTable()
+ * and IoWritePartitionTable():
+ * only one single partition starting at the beginning of the disk; the reported
+ * defaults are: partition number being zero and its type being FAT16 non-bootable.
+ * Note also that accessing \Device\HarddiskN\Partition0 or Partition1 returns
+ * the same data.
+ */
+// static
+BOOLEAN
+IsSuperFloppy(
+ IN PDISKENTRY DiskEntry)
+{
+ PPARTITION_INFORMATION PartitionInfo;
+ ULONGLONG PartitionLengthEstimate;
+
+ /* No layout buffer: we cannot say anything yet */
+ if (DiskEntry->LayoutBuffer == NULL)
+ return FALSE;
+
+ /* We must have only one partition */
+ if (DiskEntry->LayoutBuffer->PartitionCount != 1)
+ return FALSE;
+
+ /* Get the single partition entry */
+ PartitionInfo = DiskEntry->LayoutBuffer->PartitionEntry;
+
+ /* The single partition must start at the beginning of the disk */
+ if (!(PartitionInfo->StartingOffset.QuadPart == 0 &&
+ PartitionInfo->HiddenSectors == 0))
+ {
+ return FALSE;
+ }
+
+ /* The disk signature is usually set to one; warn in case it's not */
+ if (DiskEntry->LayoutBuffer->Signature != 1)
+ {
+ DPRINT1("Super-Floppy disk %lu signature %08x != 1!\n",
+ DiskEntry->DiskNumber, DiskEntry->LayoutBuffer->Signature);
+ }
+
+ /*
+ * The partition number must be zero or one, be recognized,
+ * have FAT16 type and report as non-bootable.
+ */
+ if ((PartitionInfo->PartitionNumber != 0 &&
+ PartitionInfo->PartitionNumber != 1) ||
+ PartitionInfo->RecognizedPartition != TRUE ||
+ PartitionInfo->PartitionType != PARTITION_FAT_16 ||
+ PartitionInfo->BootIndicator != FALSE)
+ {
+ DPRINT1("Super-Floppy disk %lu does not return default settings!\n"
+ " PartitionNumber = %lu, expected 0\n"
+ " RecognizedPartition = %s, expected TRUE\n"
+ " PartitionType = 0x%02x, expected 0x04 (PARTITION_FAT_16)\n"
+ " BootIndicator = %s, expected FALSE\n",
+ DiskEntry->DiskNumber,
+ PartitionInfo->PartitionNumber,
+ PartitionInfo->RecognizedPartition ? "TRUE" : "FALSE",
+ PartitionInfo->PartitionType,
+ PartitionInfo->BootIndicator ? "TRUE" : "FALSE");
+ }
+
+ /* The partition lengths should agree */
+ PartitionLengthEstimate = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+ if (PartitionInfo->PartitionLength.QuadPart != PartitionLengthEstimate)
+ {
+ DPRINT1("PartitionLength = %I64u is different from PartitionLengthEstimate = %I64u\n",
+ PartitionInfo->PartitionLength.QuadPart, PartitionLengthEstimate);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Inserts the disk region represented by PartEntry into either the primary
+ * or the logical partition list of the given disk.
+ * The lists are kept sorted by increasing order of start sectors.
+ * Of course no disk region should overlap at all with one another.
+ */
+static
+VOID
+InsertDiskRegion(
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry,
+ IN BOOLEAN LogicalPartition)
+{
+ PLIST_ENTRY List;
+ PLIST_ENTRY Entry;
+ PPARTENTRY PartEntry2;
+
+ /* Use the correct partition list */
+ if (LogicalPartition)
+ List = &DiskEntry->LogicalPartListHead;
+ else
+ List = &DiskEntry->PrimaryPartListHead;
+
+ /* Find the first disk region before which we need to insert the new one */
+ for (Entry = List->Flink; Entry != List; Entry = Entry->Flink)
+ {
+ PartEntry2 = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+ /* Ignore any unused empty region */
+ if ((PartEntry2->PartitionType == PARTITION_ENTRY_UNUSED &&
+ PartEntry2->StartSector.QuadPart == 0) || PartEntry2->SectorCount.QuadPart == 0)
+ {
+ continue;
+ }
+
+ /* If the current region ends before the one to be inserted, try again */
+ if (PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1 < PartEntry->StartSector.QuadPart)
+ continue;
+
+ /*
+ * One of the disk region boundaries crosses the desired region
+ * (it starts after the desired region, or ends before the end
+ * of the desired region): this is an impossible situation because
+ * disk regions (partitions) cannot overlap!
+ * Throw an error and bail out.
+ */
+ if (max(PartEntry->StartSector.QuadPart, PartEntry2->StartSector.QuadPart)
+ <=
+ min( PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
+ PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1))
+ {
+ DPRINT1("Disk region overlap problem, stopping there!\n"
+ "Partition to be inserted:\n"
+ " StartSector = %I64u ; EndSector = %I64u\n"
+ "Existing disk region:\n"
+ " StartSector = %I64u ; EndSector = %I64u\n",
+ PartEntry->StartSector.QuadPart,
+ PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
+ PartEntry2->StartSector.QuadPart,
+ PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1);
+ return;
+ }
+
+ /* We have found the first region before which the new one has to be inserted */
+ break;
+ }
+
+ /* Insert the disk region */
+ InsertTailList(Entry, &PartEntry->ListEntry);
+}
+
+static
+PPARTENTRY
+CreateInsertBlankRegion(
+ IN PDISKENTRY DiskEntry,
+ IN OUT PLIST_ENTRY ListHead,
+ IN ULONGLONG StartSector,
+ IN ULONGLONG SectorCount,
+ IN BOOLEAN LogicalSpace)
+{
+ PPARTENTRY NewPartEntry;
+
+ NewPartEntry = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(PARTENTRY));
+ if (NewPartEntry == NULL)
+ return NULL;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+
+ NewPartEntry->StartSector.QuadPart = StartSector;
+ NewPartEntry->SectorCount.QuadPart = SectorCount;
+
+ NewPartEntry->IsPartitioned = FALSE;
+ NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem[0] = L'\0';
+
+ 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);
+
+ /* Insert the new entry into the list */
+ InsertTailList(ListHead, &NewPartEntry->ListEntry);
+
+ return NewPartEntry;
+}
+
+static
+// BOOLEAN
+PPARTENTRY
+InitializePartitionEntry(
+ IN PDISKENTRY DiskEntry,
+ IN PPARTENTRY PartEntry,
+ IN ULONGLONG SectorCount,
+ IN BOOLEAN AutoCreate)
+{
+ PPARTENTRY NewPartEntry;
+
+ DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+ if ((AutoCreate != FALSE) ||
+ (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
+ {
+ DPRINT1("Convert existing partition entry\n");
+
+ NewPartEntry = PartEntry;
+ NewPartEntry->AutoCreate = AutoCreate;
+ }
+ 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 NULL;
+
+ NewPartEntry->DiskEntry = DiskEntry;
+
+ NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+ NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+ NewPartEntry->StartSector.QuadPart;
+
+ PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+ PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+
+ /* Insert the new entry into the list */
+ InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry);
+ }
+
+ /* Create entry as 'New (Unformatted)' */
+ NewPartEntry->New = TRUE;
+ NewPartEntry->IsPartitioned = TRUE;
+
+ NewPartEntry->PartitionType = FileSystemToPartitionType(L"RAW", &NewPartEntry->StartSector, &NewPartEntry->SectorCount);
+ ASSERT(NewPartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ NewPartEntry->FormatState = Unformatted;
+ NewPartEntry->FileSystem[0] = L'\0';
+ // NewPartEntry->AutoCreate = AutoCreate;
+ NewPartEntry->BootIndicator = FALSE;
+ NewPartEntry->LogicalPartition = FALSE;
+
+ DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
+ DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+ return NewPartEntry;
+}
+
+
static
VOID
AddPartitionToDisk(
NTSTATUS Status;
PPARTITION_INFORMATION PartitionInfo;
PPARTENTRY PartEntry;
- HANDLE FileHandle;
+ HANDLE PartitionHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- WCHAR Buffer[MAX_PATH];
+ WCHAR PathBuffer[MAX_PATH];
UNICODE_STRING Name;
UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)LabelBuffer;
PartEntry->LogicalPartition = LogicalPartition;
PartEntry->IsPartitioned = TRUE;
+ PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
PartEntry->PartitionIndex = PartitionIndex;
+ /* Specify the partition as initially unformatted */
+ PartEntry->FormatState = Unformatted;
+ PartEntry->FileSystem[0] = L'\0';
+
+ /* Initialize the partition volume label */
+ RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+
if (IsContainerPartition(PartEntry->PartitionType))
{
PartEntry->FormatState = Unformatted;
- PartEntry->FileSystem = NULL;
if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
DiskEntry->ExtendedPartition = PartEntry;
}
else if (IsRecognizedPartition(PartEntry->PartitionType))
{
- PartEntry->FileSystem = GetFileSystem(PartEntry);
- if (PartEntry->FileSystem)
- PartEntry->FormatState = Preformatted;
- else
- PartEntry->FormatState = Unformatted;
- // PartEntry->FormatState = UnknownFormat;
- }
- else
- {
- /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
- PartEntry->FormatState = UnknownFormat;
- }
+ ASSERT(PartitionInfo->RecognizedPartition);
+ ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
- /* Initialize the partition volume label */
- RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+ /* Open the volume, ignore any errors */
+ RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ DiskEntry->DiskNumber,
+ PartEntry->PartitionNumber);
+ RtlInitUnicodeString(&Name, PathBuffer);
- /* Open the volume, ignore any errors */
- RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- DiskEntry->DiskNumber, PartEntry->PartitionNumber);
- RtlInitUnicodeString(&Name, Buffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
+ PartitionHandle = NULL;
+ Status = NtOpenFile(&PartitionHandle,
+ FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
+ }
- Status = NtOpenFile(&FileHandle,
- FILE_READ_DATA | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (NT_SUCCESS(Status))
- {
- /* Retrieve the partition volume label */
- Status = NtQueryVolumeInformationFile(FileHandle,
- &IoStatusBlock,
- &LabelBuffer,
- sizeof(LabelBuffer),
- FileFsVolumeInformation);
- /* Close the handle */
- NtClose(FileHandle);
-
- /* Check for success */
- if (NT_SUCCESS(Status))
+ if (/* NT_SUCCESS(Status) && */ PartitionHandle)
+ {
+ /* We don't have a FS, try to guess one */
+ Status = InferFileSystemByHandle(PartitionHandle,
+ PartEntry->PartitionType,
+ PartEntry->FileSystem,
+ sizeof(PartEntry->FileSystem));
+ if (!NT_SUCCESS(Status))
+ DPRINT1("InferFileSystemByHandle() failed, Status 0x%08lx\n", Status);
+ }
+ if (*PartEntry->FileSystem)
{
- /* Copy the (possibly truncated) volume label and NULL-terminate it */
- RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
- LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
+ if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
+ PartEntry->FormatState = Unformatted;
+ else
+ PartEntry->FormatState = Preformatted;
}
else
{
- DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
+ PartEntry->FormatState = UnknownFormat;
+ }
+
+ /* Retrieve the partition volume label */
+ if (PartitionHandle)
+ {
+ Status = NtQueryVolumeInformationFile(PartitionHandle,
+ &IoStatusBlock,
+ &LabelBuffer,
+ sizeof(LabelBuffer),
+ FileFsVolumeInformation);
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy the (possibly truncated) volume label and NULL-terminate it */
+ RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
+ LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
+ }
+ else
+ {
+ DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
+ }
}
+
+ /* Close the partition */
+ if (PartitionHandle)
+ NtClose(PartitionHandle);
}
else
{
- DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
+ /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
+ PartEntry->FormatState = UnknownFormat;
}
- if (LogicalPartition)
- InsertTailList(&DiskEntry->LogicalPartListHead,
- &PartEntry->ListEntry);
- else
- InsertTailList(&DiskEntry->PrimaryPartListHead,
- &PartEntry->ListEntry);
+ InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
}
static
ScanForUnpartitionedDiskSpace(
IN PDISKENTRY DiskEntry)
{
+ ULONGLONG StartSector;
+ ULONGLONG SectorCount;
ULONGLONG LastStartSector;
ULONGLONG LastSectorCount;
ULONGLONG LastUnusedSectorCount;
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;
if (DiskEntry->SectorAlignment < 2048)
- NewPartEntry->StartSector.QuadPart = 2048ULL;
+ StartSector = 2048ULL;
else
- 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);
+ StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
+ SectorCount = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - StartSector;
+
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &DiskEntry->PrimaryPartListHead,
+ StartSector,
+ SectorCount,
+ FALSE);
+ if (NewPartEntry == NULL)
+ DPRINT1("Failed to create a new empty region for full disk space!\n");
return;
}
if (DiskEntry->SectorAlignment < 2048)
LastStartSector = 2048ULL;
else
- LastStartSector = DiskEntry->SectorAlignment;
+ LastStartSector = (ULONGLONG)DiskEntry->SectorAlignment;
LastSectorCount = 0ULL;
LastUnusedSectorCount = 0ULL;
- Entry = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry != &DiskEntry->PrimaryPartListHead)
+ for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+ Entry != &DiskEntry->PrimaryPartListHead;
+ Entry = Entry->Flink)
{
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
{
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;
+ StartSector = LastStartSector + LastSectorCount;
+ SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
/* Insert the table into the list */
- InsertTailList(&PartEntry->ListEntry,
- &NewPartEntry->ListEntry);
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &PartEntry->ListEntry,
+ StartSector,
+ SectorCount,
+ FALSE);
+ if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for disk space!\n");
+ return;
+ }
}
LastStartSector = PartEntry->StartSector.QuadPart;
LastSectorCount = PartEntry->SectorCount.QuadPart;
}
-
- Entry = Entry->Flink;
}
/* Check for trailing unpartitioned disk space */
{
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;
+ StartSector = LastStartSector + LastSectorCount;
+ SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
/* Append the table to the list */
- InsertTailList(&DiskEntry->PrimaryPartListHead,
- &NewPartEntry->ListEntry);
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &DiskEntry->PrimaryPartListHead,
+ StartSector,
+ SectorCount,
+ FALSE);
+ if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for trailing disk space!\n");
+ return;
+ }
}
}
DPRINT1("No logical partition!\n");
/* Create a partition entry that represents the empty extended partition */
- NewPartEntry = RtlAllocateHeap(ProcessHeap,
- HEAP_ZERO_MEMORY,
- sizeof(PARTENTRY));
+
+ StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+ SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
+
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &DiskEntry->LogicalPartListHead,
+ StartSector,
+ SectorCount,
+ TRUE);
if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for full extended partition space!\n");
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;
}
LastSectorCount = 0ULL;
LastUnusedSectorCount = 0ULL;
- Entry = DiskEntry->LogicalPartListHead.Flink;
- while (Entry != &DiskEntry->LogicalPartListHead)
+ for (Entry = DiskEntry->LogicalPartListHead.Flink;
+ Entry != &DiskEntry->LogicalPartListHead;
+ Entry = Entry->Flink)
{
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
{
DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
- NewPartEntry = RtlAllocateHeap(ProcessHeap,
- HEAP_ZERO_MEMORY,
- sizeof(PARTENTRY));
+ StartSector = LastStartSector + LastSectorCount;
+ SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
+
+ /* Insert the table into the list */
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &PartEntry->ListEntry,
+ StartSector,
+ SectorCount,
+ TRUE);
if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for extended partition space!\n");
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);
+ 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));
+ StartSector = LastStartSector + LastSectorCount;
+ SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
+
+ /* Append the table to the list */
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &DiskEntry->LogicalPartListHead,
+ StartSector,
+ SectorCount,
+ TRUE);
if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for extended partition space!\n");
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);
}
}
}
PDISKENTRY DiskEntry2;
PUCHAR Buffer;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return;
+ }
+
Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
while (TRUE)
* Check also signatures from disks, which are
* not visible (bootable) by the bios.
*/
- Entry2 = List->DiskListHead.Flink;
- while (Entry2 != &List->DiskListHead)
+ for (Entry2 = List->DiskListHead.Flink;
+ Entry2 != &List->DiskListHead;
+ Entry2 = Entry2->Flink)
{
DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
+ if (DiskEntry2->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
+
if (DiskEntry != DiskEntry2 &&
DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
break;
-
- Entry2 = Entry2->Flink;
}
if (Entry2 == &List->DiskListHead)
PLIST_ENTRY Entry;
PDISKENTRY DiskEntry;
- /* Print partition lines */
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ /* Update each disk */
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
+
if (DiskEntry->LayoutBuffer &&
DiskEntry->LayoutBuffer->Signature == 0)
{
SetDiskSignature(List, DiskEntry);
DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
}
+ }
+}
- Entry = Entry->Flink;
+static
+VOID
+UpdateHwDiskNumbers(
+ IN PPARTLIST List)
+{
+ PLIST_ENTRY ListEntry;
+ PBIOSDISKENTRY BiosDiskEntry;
+ PDISKENTRY DiskEntry;
+ ULONG HwAdapterNumber = 0;
+ ULONG HwControllerNumber = 0;
+ ULONG RemovableDiskCount = 0;
+
+ /*
+ * Enumerate the disks recognized by the BIOS and recompute the disk
+ * numbers on the system when *ALL* removable disks are not connected.
+ * The entries are inserted in increasing order of AdapterNumber,
+ * ControllerNumber and DiskNumber.
+ */
+ for (ListEntry = List->BiosDiskListHead.Flink;
+ ListEntry != &List->BiosDiskListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+ DiskEntry = BiosDiskEntry->DiskEntry;
+
+ /*
+ * If the adapter or controller numbers change, update them and reset
+ * the number of removable disks on this adapter/controller.
+ */
+ if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
+ HwControllerNumber != BiosDiskEntry->ControllerNumber)
+ {
+ HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+ HwControllerNumber = BiosDiskEntry->ControllerNumber;
+ RemovableDiskCount = 0;
+ }
+
+ /* Adjust the actual hardware disk number */
+ if (DiskEntry)
+ {
+ ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
+
+ if (DiskEntry->MediaType == RemovableMedia)
+ {
+ /* Increase the number of removable disks and set the disk number to zero */
+ ++RemovableDiskCount;
+ DiskEntry->HwFixedDiskNumber = 0;
+ }
+ else // if (DiskEntry->MediaType == FixedMedia)
+ {
+ /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
+ DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
+ }
+ }
+ else
+ {
+ DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
+ }
}
}
Checksum = ~Checksum + 1;
RtlStringCchPrintfW(Identifier, ARRAYSIZE(Identifier),
- L"%08x-%08x-A", Checksum, Signature);
+ L"%08x-%08x-%c",
+ Checksum, Signature,
+ (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
DPRINT("Identifier: %S\n", Identifier);
DiskEntry = RtlAllocateHeap(ProcessHeap,
return;
}
+ DiskEntry->PartList = List;
+
+#if 0
+ {
+ FILE_FS_DEVICE_INFORMATION FileFsDevice;
+
+ /* Query the device for its type */
+ Status = NtQueryVolumeInformationFile(FileHandle,
+ &Iosb,
+ &FileFsDevice,
+ sizeof(FileFsDevice),
+ FileFsDeviceInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
+ }
+ else
+ {
+ DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
+ }
+ }
+ // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
+#endif
+ DiskEntry->MediaType = DiskGeometry.MediaType;
+ if (DiskEntry->MediaType == RemovableMedia)
+ {
+ DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
+ }
+ else // if (DiskEntry->MediaType == FixedMedia)
+ {
+ DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
+ }
+
// DiskEntry->Checksum = Checksum;
// DiskEntry->Signature = Signature;
DiskEntry->BiosFound = FALSE;
* Check if this disk has a valid MBR: verify its signature,
* and whether its two first bytes are a valid instruction
* (related to this, see IsThereAValidBootSector() in partlist.c).
+ *
+ * See also ntoskrnl/fstub/fstubex.c!FstubDetectPartitionStyle().
*/
- if (Mbr->Magic != 0xaa55 || (*(PUSHORT)Mbr->BootCode) == 0x0000)
- DiskEntry->NoMbr = TRUE;
+
+ // DiskEntry->NoMbr = (Mbr->Magic != PARTITION_MAGIC || (*(PUSHORT)Mbr->BootCode) == 0x0000);
+
+ /* If we have not the 0xAA55 then it's raw partition */
+ if (Mbr->Magic != PARTITION_MAGIC)
+ {
+ DiskEntry->DiskStyle = PARTITION_STYLE_RAW;
+ }
+ /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
+ else if (Mbr->Partition[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
+ Mbr->Partition[1].PartitionType == 0 &&
+ Mbr->Partition[2].PartitionType == 0 &&
+ Mbr->Partition[3].PartitionType == 0)
+ {
+ DiskEntry->DiskStyle = PARTITION_STYLE_GPT;
+ }
+ /* Otherwise, partition table is in MBR */
else
- DiskEntry->NoMbr = FALSE;
+ {
+ DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
+ }
/* Free the MBR sector buffer */
RtlFreeHeap(ProcessHeap, 0, Mbr);
- ListEntry = List->BiosDiskListHead.Flink;
- while (ListEntry != &List->BiosDiskListHead)
+ for (ListEntry = List->BiosDiskListHead.Flink;
+ ListEntry != &List->BiosDiskListHead;
+ ListEntry = ListEntry->Flink)
{
BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
/* FIXME:
*/
if (BiosDiskEntry->Signature == Signature &&
BiosDiskEntry->Checksum == Checksum &&
- !BiosDiskEntry->Recognized)
+ BiosDiskEntry->DiskEntry == NULL)
{
if (!DiskEntry->BiosFound)
{
- DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+ DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+ DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
+ DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
+
+ if (DiskEntry->MediaType == RemovableMedia)
+ {
+ /* Set the removable disk number to zero */
+ DiskEntry->HwFixedDiskNumber = 0;
+ }
+ else // if (DiskEntry->MediaType == FixedMedia)
+ {
+ /* The fixed disk number will later be adjusted using the number of removable disks */
+ DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
+ }
+
DiskEntry->BiosFound = TRUE;
- BiosDiskEntry->Recognized = TRUE;
+ BiosDiskEntry->DiskEntry = DiskEntry;
+ break;
}
else
{
// FIXME: What to do?
+ DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
}
}
- ListEntry = ListEntry->Flink;
}
if (!DiskEntry->BiosFound)
{
-#if 0
- RtlFreeHeap(ProcessHeap, 0, DiskEntry);
- return;
-#else
- DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
-#endif
+ DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
}
- InitializeListHead(&DiskEntry->PrimaryPartListHead);
- InitializeListHead(&DiskEntry->LogicalPartListHead);
-
DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
* See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
*/
+ InitializeListHead(&DiskEntry->PrimaryPartListHead);
+ InitializeListHead(&DiskEntry->LogicalPartListHead);
+
InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
* We now retrieve the disk partition layout
*/
+ /*
+ * Stop there now if the disk is GPT-partitioned,
+ * since we currently do not support such disks.
+ */
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return;
+ }
+
/* Allocate a layout buffer with 4 partition entries first */
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
DumpPartitionTable(DiskEntry);
#endif
+ if (IsSuperFloppy(DiskEntry))
+ DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
+
if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != PARTITION_ENTRY_UNUSED)
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
{
+ /* Enumerate and add the first four primary partitions */
for (i = 0; i < 4; i++)
{
AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
}
+ /* Enumerate and add the remaining partitions as logical ones */
for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
{
AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
if (List == NULL)
return NULL;
- List->CurrentDisk = NULL;
- List->CurrentPartition = NULL;
-
List->SystemPartition = NULL;
List->OriginalSystemPartition = NULL;
}
UpdateDiskSignatures(List);
-
+ UpdateHwDiskNumbers(List);
AssignDriveLetters(List);
- /* Search for first usable disk and partition */
- if (IsListEmpty(&List->DiskListHead))
- {
- List->CurrentDisk = NULL;
- List->CurrentPartition = NULL;
- }
- else
- {
- List->CurrentDisk = CONTAINING_RECORD(List->DiskListHead.Flink,
- DISKENTRY,
- ListEntry);
-
- if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
- {
- List->CurrentPartition = NULL;
- }
- else
- {
- List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
- PARTENTRY,
- ListEntry);
- }
- }
-
return List;
}
PDISKENTRY
GetDiskByBiosNumber(
IN PPARTLIST List,
- IN ULONG BiosDiskNumber)
+ IN ULONG HwDiskNumber)
{
PDISKENTRY DiskEntry;
PLIST_ENTRY Entry;
/* Loop over the disks and find the correct one */
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = Entry->Flink;
- if (DiskEntry->BiosDiskNumber == BiosDiskNumber)
+ if (DiskEntry->HwDiskNumber == HwDiskNumber)
{
/* Disk found */
return DiskEntry;
PLIST_ENTRY Entry;
/* Loop over the disks and find the correct one */
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = Entry->Flink;
if (DiskEntry->DiskNumber == DiskNumber)
{
PLIST_ENTRY Entry;
/* Loop over the disks and find the correct one */
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = Entry->Flink;
if (DiskEntry->Port == Port &&
DiskEntry->Bus == Bus &&
PLIST_ENTRY Entry;
/* Loop over the disks and find the correct one */
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = Entry->Flink;
if (DiskEntry->LayoutBuffer->Signature == Signature)
{
PPARTENTRY PartEntry;
PLIST_ENTRY Entry;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return NULL;
+ }
+
/* Disk found, loop over the primary partitions first... */
- Entry = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry != &DiskEntry->PrimaryPartListHead)
+ for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+ Entry != &DiskEntry->PrimaryPartListHead;
+ Entry = Entry->Flink)
{
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- Entry = Entry->Flink;
if (PartEntry->PartitionNumber == PartitionNumber)
{
}
/* ... then over the logical partitions if needed */
- Entry = DiskEntry->LogicalPartListHead.Flink;
- while (Entry != &DiskEntry->LogicalPartListHead)
+ for (Entry = DiskEntry->LogicalPartListHead.Flink;
+ Entry != &DiskEntry->LogicalPartListHead;
+ Entry = Entry->Flink)
{
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- Entry = Entry->Flink;
if (PartEntry->PartitionNumber == PartitionNumber)
{
/* If we have a partition (PartitionNumber != 0), find it */
if (PartitionNumber != 0)
{
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return FALSE;
+ }
+
PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
if (!PartEntry)
return FALSE;
//
// NOTE: Was introduced broken in r6258 by Casper
//
-BOOLEAN
+PPARTENTRY
SelectPartition(
IN PPARTLIST List,
IN ULONG DiskNumber,
DiskEntry = GetDiskByNumber(List, DiskNumber);
if (!DiskEntry)
- return FALSE;
+ return NULL;
PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
if (!PartEntry)
- return FALSE;
+ return NULL;
ASSERT(PartEntry->DiskEntry == DiskEntry);
ASSERT(DiskEntry->DiskNumber == DiskNumber);
ASSERT(PartEntry->PartitionNumber == PartitionNumber);
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- return TRUE;
+ return PartEntry;
}
PPARTENTRY
GetNextPartition(
- IN PPARTLIST List)
+ IN PPARTLIST List,
+ IN PPARTENTRY CurrentPart OPTIONAL)
{
PLIST_ENTRY DiskListEntry;
PLIST_ENTRY PartListEntry;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PDISKENTRY CurrentDisk;
/* Fail if no disks are available */
if (IsListEmpty(&List->DiskListHead))
return NULL;
- /* Check for next usable entry on current disk */
- if (List->CurrentPartition != NULL)
+ /* Check for the next usable entry on the current partition's disk */
+ if (CurrentPart != NULL)
{
- if (List->CurrentPartition->LogicalPartition)
+ CurrentDisk = CurrentPart->DiskEntry;
+
+ if (CurrentPart->LogicalPartition)
{
/* Logical partition */
- PartListEntry = List->CurrentPartition->ListEntry.Flink;
- if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+ PartListEntry = CurrentPart->ListEntry.Flink;
+ if (PartListEntry != &CurrentDisk->LogicalPartListHead)
{
/* Next logical partition */
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
else
{
- PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
- if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+ PartListEntry = CurrentDisk->ExtendedPartition->ListEntry.Flink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
}
}
{
/* Primary or extended partition */
- if ((List->CurrentPartition->IsPartitioned != FALSE) &&
- IsContainerPartition(List->CurrentPartition->PartitionType))
+ if (CurrentPart->IsPartitioned &&
+ IsContainerPartition(CurrentPart->PartitionType))
{
/* First logical partition */
- PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
- if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+ PartListEntry = CurrentDisk->LogicalPartListHead.Flink;
+ if (PartListEntry != &CurrentDisk->LogicalPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
}
else
{
/* Next primary partition */
- PartListEntry = List->CurrentPartition->ListEntry.Flink;
- if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+ PartListEntry = CurrentPart->ListEntry.Flink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
}
}
}
/* Search for the first partition entry on the next disk */
- DiskListEntry = List->CurrentDisk->ListEntry.Flink;
- while (DiskListEntry != &List->DiskListHead)
+ for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Flink
+ : List->DiskListHead.Flink);
+ DiskListEntry != &List->DiskListHead;
+ DiskListEntry = DiskListEntry->Flink)
{
- DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+ CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
- PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
- if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+ if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
}
- DiskListEntry = DiskListEntry->Flink;
+ PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
+ {
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
+ }
}
return NULL;
PPARTENTRY
GetPrevPartition(
- IN PPARTLIST List)
+ IN PPARTLIST List,
+ IN PPARTENTRY CurrentPart OPTIONAL)
{
PLIST_ENTRY DiskListEntry;
PLIST_ENTRY PartListEntry;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PDISKENTRY CurrentDisk;
/* Fail if no disks are available */
if (IsListEmpty(&List->DiskListHead))
return NULL;
- /* Check for previous usable entry on current disk */
- if (List->CurrentPartition != NULL)
+ /* Check for the previous usable entry on the current partition's disk */
+ if (CurrentPart != NULL)
{
- if (List->CurrentPartition->LogicalPartition)
+ CurrentDisk = CurrentPart->DiskEntry;
+
+ if (CurrentPart->LogicalPartition)
{
/* Logical partition */
- PartListEntry = List->CurrentPartition->ListEntry.Blink;
- if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+
+ PartListEntry = CurrentPart->ListEntry.Blink;
+ if (PartListEntry != &CurrentDisk->LogicalPartListHead)
{
/* Previous logical partition */
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
}
else
{
/* Extended partition */
- PartEntry = List->CurrentDisk->ExtendedPartition;
+ CurrentPart = CurrentDisk->ExtendedPartition;
}
-
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ return CurrentPart;
}
else
{
/* Primary or extended partition */
- PartListEntry = List->CurrentPartition->ListEntry.Blink;
- if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+ PartListEntry = CurrentPart->ListEntry.Blink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- if ((PartEntry->IsPartitioned != FALSE) &&
- IsContainerPartition(PartEntry->PartitionType))
+ if (CurrentPart->IsPartitioned &&
+ IsContainerPartition(CurrentPart->PartitionType))
{
- PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
}
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ return CurrentPart;
}
}
}
/* Search for the last partition entry on the previous disk */
- DiskListEntry = List->CurrentDisk->ListEntry.Blink;
- while (DiskListEntry != &List->DiskListHead)
+ for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Blink
+ : List->DiskListHead.Blink);
+ DiskListEntry != &List->DiskListHead;
+ DiskListEntry = DiskListEntry->Blink)
{
- DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+ CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
- PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
- if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+ if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
- if ((PartEntry->IsPartitioned != FALSE) &&
- IsContainerPartition(PartEntry->PartitionType))
+ PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
+ {
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+ if (CurrentPart->IsPartitioned &&
+ IsContainerPartition(CurrentPart->PartitionType))
{
- PartListEntry = DiskEntry->LogicalPartListHead.Blink;
- if (PartListEntry != &DiskEntry->LogicalPartListHead)
+ PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
+ if (PartListEntry != &CurrentDisk->LogicalPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
}
else
{
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ return CurrentPart;
}
}
-
- DiskListEntry = DiskListEntry->Blink;
}
return NULL;
{
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;
PPARTENTRY PartEntry;
ULONG Count = 0;
- Entry = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry != &DiskEntry->PrimaryPartListHead)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return 0;
+ }
+
+ for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+ Entry != &DiskEntry->PrimaryPartListHead;
+ Entry = Entry->Flink)
{
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned)
Count++;
-
- Entry = Entry->Flink;
}
return Count;
PPARTENTRY PartEntry;
ULONG Count = 0;
- ListEntry = DiskEntry->LogicalPartListHead.Flink;
- while (ListEntry != &DiskEntry->LogicalPartListHead)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return 0;
+ }
+
+ for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+ ListEntry != &DiskEntry->LogicalPartListHead;
+ ListEntry = ListEntry->Flink)
{
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned)
Count++;
-
- ListEntry = ListEntry->Flink;
}
return Count;
if (DiskEntry->LayoutBuffer)
CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
- DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
+ DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
CurrentPartitionCount, NewPartitionCount);
if (CurrentPartitionCount == NewPartitionCount)
return FALSE;
}
+ NewLayoutBuffer->PartitionCount = NewPartitionCount;
+
/* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
if (NewPartitionCount > CurrentPartitionCount)
{
for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
+ {
NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+ }
}
DiskEntry->LayoutBuffer = NewLayoutBuffer;
- DiskEntry->LayoutBuffer->PartitionCount = NewPartitionCount;
return TRUE;
}
DPRINT1("UpdateDiskLayout()\n");
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return;
+ }
+
/* Resize the layout buffer if necessary */
if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
{
/* Update the primary partition table */
Index = 0;
- ListEntry = DiskEntry->PrimaryPartListHead.Flink;
- while (ListEntry != &DiskEntry->PrimaryPartListHead)
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
{
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned != FALSE)
+ if (PartEntry->IsPartitioned)
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+ PartEntry->PartitionIndex = Index;
+
+ /* Reset the current partition number only for newly-created (unmounted) partitions */
+ if (PartEntry->New)
+ PartEntry->PartitionNumber = 0;
+
+ PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0);
if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
{
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->PartitionNumber = PartEntry->PartitionNumber;
PartitionInfo->PartitionType = PartEntry->PartitionType;
PartitionInfo->BootIndicator = PartEntry->BootIndicator;
- PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
PartitionInfo->RewritePartition = TRUE;
}
- PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
- PartEntry->PartitionIndex = Index;
-
if (!IsContainerPartition(PartEntry->PartitionType))
PartitionNumber++;
Index++;
}
-
- ListEntry = ListEntry->Flink;
}
ASSERT(Index <= 4);
/* Update the logical partition table */
Index = 4;
- ListEntry = DiskEntry->LogicalPartListHead.Flink;
- while (ListEntry != &DiskEntry->LogicalPartListHead)
+ for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+ ListEntry != &DiskEntry->LogicalPartListHead;
+ ListEntry = ListEntry->Flink)
{
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned)
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+ PartEntry->PartitionIndex = Index;
+
+ /* Reset the current partition number only for newly-created (unmounted) partitions */
+ if (PartEntry->New)
+ PartEntry->PartitionNumber = 0;
+
+ PartEntry->OnDiskPartitionNumber = PartitionNumber;
DPRINT1("Updating logical partition entry %lu\n", Index);
PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
- PartitionInfo->PartitionNumber = PartitionNumber;
+ PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
PartitionInfo->PartitionType = PartEntry->PartitionType;
PartitionInfo->BootIndicator = FALSE;
- PartitionInfo->RecognizedPartition = FALSE;
+ PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
PartitionInfo->RewritePartition = TRUE;
- PartEntry->PartitionNumber = PartitionNumber;
- PartEntry->PartitionIndex = Index;
-
/* Fill the link entry of the previous partition entry */
if (LinkInfo != NULL)
{
PartitionNumber++;
Index += 4;
}
-
- ListEntry = ListEntry->Flink;
}
/* Wipe unused primary partition entries */
}
}
+ DiskEntry->Dirty = TRUE;
+
#ifdef DUMP_PARTITION_TABLE
DumpPartitionTable(DiskEntry);
#endif
static
PPARTENTRY
GetPrevUnpartitionedEntry(
- IN PDISKENTRY DiskEntry,
IN PPARTENTRY PartEntry)
{
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
PPARTENTRY PrevPartEntry;
PLIST_ENTRY ListHead;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return NULL;
+ }
+
if (PartEntry->LogicalPartition)
ListHead = &DiskEntry->LogicalPartListHead;
else
PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
PARTENTRY,
ListEntry);
- if (PrevPartEntry->IsPartitioned == FALSE)
+ if (!PrevPartEntry->IsPartitioned)
+ {
+ ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
return PrevPartEntry;
+ }
}
return NULL;
static
PPARTENTRY
GetNextUnpartitionedEntry(
- IN PDISKENTRY DiskEntry,
IN PPARTENTRY PartEntry)
{
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
PPARTENTRY NextPartEntry;
PLIST_ENTRY ListHead;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return NULL;
+ }
+
if (PartEntry->LogicalPartition)
ListHead = &DiskEntry->LogicalPartListHead;
else
NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
PARTENTRY,
ListEntry);
- if (NextPartEntry->IsPartitioned == FALSE)
+ if (!NextPartEntry->IsPartitioned)
+ {
+ ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
return NextPartEntry;
+ }
}
return NULL;
BOOLEAN
CreatePrimaryPartition(
IN PPARTLIST List,
+ IN PPARTENTRY SelectedEntry,
IN ULONGLONG SectorCount,
IN BOOLEAN AutoCreate)
{
ERROR_NUMBER Error;
- PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PPARTENTRY NewPartEntry;
DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->IsPartitioned)
+ SelectedEntry == NULL ||
+ SelectedEntry->DiskEntry == NULL ||
+ SelectedEntry->IsPartitioned)
{
return FALSE;
}
- Error = PrimaryPartitionCreationChecks(List);
+ Error = PrimaryPartitionCreationChecks(SelectedEntry);
if (Error != NOT_AN_ERROR)
{
DPRINT1("PrimaryPartitionCreationChecks() failed with error %lu\n", Error);
return FALSE;
}
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
-
- if ((AutoCreate != FALSE) ||
- (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 = AutoCreate;
- PartEntry->New = TRUE;
- PartEntry->BootIndicator = FALSE;
-
- 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 FALSE;
-
- /* 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;
-
- PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
- PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
- }
-
- UpdateDiskLayout(DiskEntry);
+ /* Convert the current entry, or insert and initialize a new partition entry */
+ PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
+ if (PartEntry == NULL)
+ return FALSE;
- DiskEntry->Dirty = TRUE;
+ UpdateDiskLayout(PartEntry->DiskEntry);
AssignDriveLetters(List);
AddLogicalDiskSpace(
IN PDISKENTRY DiskEntry)
{
+ ULONGLONG StartSector;
+ ULONGLONG SectorCount;
PPARTENTRY NewPartEntry;
DPRINT1("AddLogicalDiskSpace()\n");
/* Create a partition entry that represents the empty space in the container partition */
- NewPartEntry = RtlAllocateHeap(ProcessHeap,
- HEAP_ZERO_MEMORY,
- sizeof(PARTENTRY));
+
+ StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+ SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
+
+ NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+ &DiskEntry->LogicalPartListHead,
+ StartSector,
+ SectorCount,
+ TRUE);
if (NewPartEntry == NULL)
+ {
+ DPRINT1("Failed to create a new empty region for extended partition space!\n");
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);
}
BOOLEAN
CreateExtendedPartition(
IN PPARTLIST List,
+ IN PPARTENTRY SelectedEntry,
IN ULONGLONG SectorCount)
{
ERROR_NUMBER Error;
- PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PPARTENTRY NewPartEntry;
DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->IsPartitioned)
+ SelectedEntry == NULL ||
+ SelectedEntry->DiskEntry == NULL ||
+ SelectedEntry->IsPartitioned)
{
return FALSE;
}
- Error = ExtendedPartitionCreationChecks(List);
+ Error = ExtendedPartitionCreationChecks(SelectedEntry);
if (Error != NOT_AN_ERROR)
{
DPRINT1("ExtendedPartitionCreationChecks() failed with error %lu\n", Error);
return FALSE;
}
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+ /* Convert the current entry, or insert and initialize a new partition entry */
+ PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, FALSE);
+ if (PartEntry == NULL)
+ return FALSE;
- if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
+ if (PartEntry->StartSector.QuadPart < 1450560)
{
- DPRINT1("Convert existing partition entry\n");
-
- /* 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;
-
- 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;
- }
-
- DiskEntry->ExtendedPartition = PartEntry;
-
- 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);
+ /* Partition starts below the 8.4GB boundary ==> CHS partition */
+ PartEntry->PartitionType = PARTITION_EXTENDED;
}
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 FALSE;
-
- /* 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)
- {
- /* 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;
- }
-
- DiskEntry->ExtendedPartition = NewPartEntry;
-
- 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);
+ /* Partition starts above the 8.4GB boundary ==> LBA partition */
+ PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
}
- AddLogicalDiskSpace(DiskEntry);
+ // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
+ PartEntry->New = FALSE;
+ PartEntry->FormatState = Formatted;
- UpdateDiskLayout(DiskEntry);
+ PartEntry->DiskEntry->ExtendedPartition = PartEntry;
- DiskEntry->Dirty = TRUE;
+ AddLogicalDiskSpace(PartEntry->DiskEntry);
+
+ UpdateDiskLayout(PartEntry->DiskEntry);
AssignDriveLetters(List);
BOOLEAN
CreateLogicalPartition(
IN PPARTLIST List,
+ IN PPARTENTRY SelectedEntry,
IN ULONGLONG SectorCount,
IN BOOLEAN AutoCreate)
{
ERROR_NUMBER Error;
- PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PPARTENTRY NewPartEntry;
DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
if (List == NULL ||
- List->CurrentDisk == NULL ||
- List->CurrentPartition == NULL ||
- List->CurrentPartition->IsPartitioned)
+ SelectedEntry == NULL ||
+ SelectedEntry->DiskEntry == NULL ||
+ SelectedEntry->IsPartitioned)
{
return FALSE;
}
- Error = LogicalPartitionCreationChecks(List);
+ Error = LogicalPartitionCreationChecks(SelectedEntry);
if (Error != NOT_AN_ERROR)
{
DPRINT1("LogicalPartitionCreationChecks() failed with error %lu\n", Error);
return FALSE;
}
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
-
- DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
-
- if ((AutoCreate != FALSE) ||
- (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 FALSE;
-
- /* 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;
+ /* Convert the current entry, or insert and initialize a new partition entry */
+ PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
+ if (PartEntry == NULL)
+ return FALSE;
- PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
- PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
- }
+ PartEntry->LogicalPartition = TRUE;
- UpdateDiskLayout(DiskEntry);
-
- DiskEntry->Dirty = TRUE;
+ UpdateDiskLayout(PartEntry->DiskEntry);
AssignDriveLetters(List);
HANDLE PartitionHandle;
WCHAR Buffer[MAX_PATH];
- /* Check whether the partition is valid and may have been mounted in the system */
+ /* Check whether the partition is valid and was mounted by the system */
if (!PartEntry->IsPartitioned ||
- PartEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
- IsContainerPartition(PartEntry->PartitionType) ||
- !IsRecognizedPartition(PartEntry->PartitionType) ||
+ IsContainerPartition(PartEntry->PartitionType) ||
+ !IsRecognizedPartition(PartEntry->PartitionType) ||
PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ ||
- PartEntry->FileSystem == NULL ||
+ !*PartEntry->FileSystem ||
PartEntry->PartitionNumber == 0)
{
/* The partition is not mounted, so just return success */
return STATUS_SUCCESS;
}
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
/* Open the volume */
RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
L"\\Device\\Harddisk%lu\\Partition%lu",
return Status;
}
-VOID
-DeleteCurrentPartition(
- IN PPARTLIST List)
+BOOLEAN
+DeletePartition(
+ IN PPARTLIST List,
+ IN PPARTENTRY PartEntry,
+ OUT PPARTENTRY* FreeRegion OPTIONAL)
{
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)
+ PartEntry == NULL ||
+ PartEntry->DiskEntry == NULL ||
+ PartEntry->IsPartitioned == FALSE)
{
- return;
+ return FALSE;
}
- /* Clear the system disk and partition pointers if the system partition is being deleted */
- if (List->SystemPartition == List->CurrentPartition)
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ /* Clear the system partition pointers if it is being deleted */
+ if (List->SystemPartition == PartEntry)
{
+ ASSERT(List->SystemPartition);
+ ASSERT(List->SystemPartition->DiskEntry->MediaType != RemovableMedia);
+
+ if (List->SystemPartition == List->OriginalSystemPartition)
+ List->OriginalSystemPartition = NULL;
List->SystemPartition = NULL;
}
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
+ DiskEntry = PartEntry->DiskEntry;
/* Check which type of partition (primary/logical or extended) is being deleted */
if (DiskEntry->ExtendedPartition == PartEntry)
DismountVolume(PartEntry);
}
- /* Adjust unpartitioned disk space entries */
+ /* Adjust the unpartitioned disk space entries */
/* Get pointer to previous and next unpartitioned entries */
- PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry, PartEntry);
- NextPartEntry = GetNextUnpartitionedEntry(DiskEntry, PartEntry);
+ PrevPartEntry = GetPrevUnpartitionedEntry(PartEntry);
+ NextPartEntry = GetNextUnpartitionedEntry(PartEntry);
if (PrevPartEntry != NULL && NextPartEntry != NULL)
{
- /* Merge previous, current and next unpartitioned entry */
+ /* Merge the previous, current and next unpartitioned entries */
- /* Adjust the previous entries length */
+ /* Adjust the previous entry length */
PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
- /* Remove the current entry */
+ /* Remove the current and next entries */
RemoveEntryList(&PartEntry->ListEntry);
RtlFreeHeap(ProcessHeap, 0, PartEntry);
-
- /* Remove the next entry */
RemoveEntryList(&NextPartEntry->ListEntry);
RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
- /* Update current partition */
- List->CurrentPartition = PrevPartEntry;
+ /* Optionally return the freed region */
+ if (FreeRegion)
+ *FreeRegion = PrevPartEntry;
}
else if (PrevPartEntry != NULL && NextPartEntry == NULL)
{
- /* Merge current and previous unpartitioned entry */
+ /* Merge the current and the previous unpartitioned entries */
- /* Adjust the previous entries length */
+ /* Adjust the previous entry length */
PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
/* Remove the current entry */
RemoveEntryList(&PartEntry->ListEntry);
RtlFreeHeap(ProcessHeap, 0, PartEntry);
- /* Update current partition */
- List->CurrentPartition = PrevPartEntry;
+ /* Optionally return the freed region */
+ if (FreeRegion)
+ *FreeRegion = PrevPartEntry;
}
else if (PrevPartEntry == NULL && NextPartEntry != NULL)
{
- /* Merge current and next unpartitioned entry */
+ /* Merge the current and the next unpartitioned entries */
- /* Adjust the next entries offset and length */
+ /* Adjust the next entry offset and length */
NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
RemoveEntryList(&PartEntry->ListEntry);
RtlFreeHeap(ProcessHeap, 0, PartEntry);
- /* Update current partition */
- List->CurrentPartition = NextPartEntry;
+ /* Optionally return the freed region */
+ if (FreeRegion)
+ *FreeRegion = NextPartEntry;
}
else
{
- /* Nothing to merge but change current entry */
+ /* Nothing to merge but change the current entry */
PartEntry->IsPartitioned = FALSE;
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
PartEntry->FormatState = Unformatted;
- PartEntry->FileSystem = NULL;
+ PartEntry->FileSystem[0] = L'\0';
PartEntry->DriveLetter = 0;
+ PartEntry->OnDiskPartitionNumber = 0;
+ PartEntry->PartitionNumber = 0;
+ // PartEntry->PartitionIndex = 0;
+
+ /* Optionally return the freed region */
+ if (FreeRegion)
+ *FreeRegion = PartEntry;
+ }
+
+ UpdateDiskLayout(DiskEntry);
+
+ AssignDriveLetters(List);
+
+ return TRUE;
+}
+
+/*
+ * Retrieve the actual "active" partition of the given disk.
+ * On MBR disks, partition with the Active/Boot flag set;
+ * on GPT disks, partition with the correct GUID.
+ */
+static
+PPARTENTRY
+GetActiveDiskPartition(
+ IN PDISKENTRY DiskEntry)
+{
+ PLIST_ENTRY ListEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY ActivePartition = NULL;
+
+ /* Check for empty disk list */
+ // ASSERT(DiskEntry);
+ if (!DiskEntry)
+ return NULL;
+
+ /* Check for empty partition list */
+ if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+ return NULL;
+
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return NULL;
}
- UpdateDiskLayout(DiskEntry);
+ /* Scan all (primary) partitions to find the active disk partition */
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ // TODO: Support for GPT disks!
+
+ /* Check if the partition is partitioned, used and active */
+ if (PartEntry->IsPartitioned &&
+ // !IsContainerPartition(PartEntry->PartitionType) &&
+ PartEntry->BootIndicator)
+ {
+ /* Yes, we found it */
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ ActivePartition = PartEntry;
+
+ DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
+ PartEntry->PartitionNumber, DiskEntry->DiskNumber,
+ (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
+ break;
+ }
+ }
+
+ /* Check if the disk is new and if so, use its first partition as the active system partition */
+ if (DiskEntry->NewDisk && ActivePartition != NULL)
+ {
+ // FIXME: What to do??
+ DPRINT1("NewDisk TRUE but already existing active partition?\n");
+ }
+
+ /* Return the active partition found (or none) */
+ return ActivePartition;
+}
+
+static
+BOOLEAN
+IsSupportedActivePartition(
+ IN PPARTENTRY PartEntry)
+{
+ /* Check the type and the filesystem of this partition */
+
+ /*
+ * We do not support extended partition containers (on MBR disks) marked
+ * as active, and containing code inside their extended boot records.
+ */
+ if (IsContainerPartition(PartEntry->PartitionType))
+ {
+ DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
+ PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
+ return FALSE;
+ }
+
+ /*
+ * 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.
+ */
+ if ((PartEntry->FormatState == Unformatted ) ||
+ (PartEntry->FormatState == Preformatted) ||
+ (PartEntry->FormatState == Formatted ))
+ {
+ ASSERT(*PartEntry->FileSystem);
+
+ /* NOTE: Please keep in sync with the RegisteredFileSystems list! */
+ if (wcsicmp(PartEntry->FileSystem, L"FAT") == 0 ||
+ wcsicmp(PartEntry->FileSystem, L"FAT32") == 0 ||
+ // wcsicmp(PartEntry->FileSystem, L"NTFS") == 0 ||
+ wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0 ||
+ wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
+ {
+ return TRUE;
+ }
+ else
+ {
+ // WARNING: We cannot write on this FS yet!
+ DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
+ PartEntry->FileSystem);
+ return FALSE;
+ }
+ }
+ else // if (PartEntry->FormatState == UnknownFormat)
+ {
+ ASSERT(!*PartEntry->FileSystem);
+
+ DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
+ PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
+ return FALSE;
+ }
- DiskEntry->Dirty = TRUE;
+ // HACK: WARNING: We cannot write on this FS yet!
+ // See fsutil.c:InferFileSystem()
+ if (PartEntry->PartitionType == PARTITION_IFS)
+ {
+ DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
+ PartEntry->FileSystem);
+ return FALSE;
+ }
- AssignDriveLetters(List);
+ return TRUE;
}
VOID
CheckActiveSystemPartition(
- IN PPARTLIST List)
+ IN PPARTLIST List,
+ IN BOOLEAN ForceSelect,
+ IN PDISKENTRY AlternateDisk OPTIONAL,
+ IN PPARTENTRY AlternatePart OPTIONAL)
{
+ PLIST_ENTRY ListEntry;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY ListEntry;
-
- PFILE_SYSTEM FileSystem;
+ PPARTENTRY ActivePartition;
+ PPARTENTRY CandidatePartition = NULL;
/* Check for empty disk list */
if (IsListEmpty(&List->DiskListHead))
{
+ /* No system partition! */
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;
+ goto NoSystemPartition;
}
if (List->SystemPartition != NULL)
return;
}
- DPRINT1("We are here (1)!\n");
-
+ /* Start fresh */
List->SystemPartition = NULL;
List->OriginalSystemPartition = NULL;
+ /* Adjust the optional alternate disk if needed */
+ if (!AlternateDisk && AlternatePart)
+ AlternateDisk = AlternatePart->DiskEntry;
+
+ /* Ensure that the alternate partition is on the alternate disk */
+ if (AlternatePart)
+ ASSERT(AlternateDisk && (AlternatePart->DiskEntry == AlternateDisk));
+
+ /* Ensure that the alternate disk is in the list */
+ if (AlternateDisk)
+ ASSERT(AlternateDisk->PartList == List);
+
+//
+// Pass == 1 : Check the first (system) disk.
+//
+
+ /*
+ * First, check whether the first disk (the one that will be booted
+ * by default by the hardware) contains an active partition. If so
+ * this should be our system partition.
+ */
+ DiskEntry = CONTAINING_RECORD(List->DiskListHead.Flink,
+ DISKENTRY, ListEntry);
+
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("First (system) disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ goto UseAlternateDisk;
+ }
+
+ ActivePartition = GetActiveDiskPartition(DiskEntry);
+ if (ActivePartition)
+ {
+ /* Save the actual system partition */
+ List->OriginalSystemPartition = ActivePartition;
+
+ /* If we get a candidate active partition in the first disk, validate it */
+ if (IsSupportedActivePartition(ActivePartition))
+ {
+ CandidatePartition = ActivePartition;
+ goto SystemPartitionFound;
+ }
+ }
+
+ /* If this first disk is not the optional alternate disk, perform the minimal checks */
+ if (DiskEntry != AlternateDisk)
+ {
+ /*
+ * No active partition has been recognized. Enumerate all the (primary)
+ * partitions in the first disk, excluding the possible current active
+ * partition, to find a new candidate.
+ */
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ /* Skip the current active partition */
+ if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+ continue;
+
+ /* Check if the partition is partitioned and used */
+ if (PartEntry->IsPartitioned &&
+ !IsContainerPartition(PartEntry->PartitionType))
+ {
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ /* If we get a candidate active partition in the first disk, validate it */
+ if (IsSupportedActivePartition(PartEntry))
+ {
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+
+#if 0
+ /* Check if the partition is partitioned and used */
+ if (!PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+ // TODO: Check for minimal size!!
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+#endif
+ }
+
+ /*
+ * Still nothing, look whether there is some free space that we can use
+ * for the new system partition. We must be sure that the total number
+ * of partition is less than the maximum allowed, and that the minimal
+ * size is fine.
+ */
+//
+// TODO: Fix the handling of system partition being created in unpartitioned space!!
+// --> When to partition it? etc...
+//
+ if (GetPrimaryPartitionCount(DiskEntry) < 4)
+ {
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ /* Skip the current active partition */
+ if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+ continue;
+
+ /* Check for unpartitioned space */
+ if (!PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+ // TODO: Check for minimal size!!
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+ }
+ }
+
+
+//
+// Pass == 2 : No active partition found: Check the alternate disk if specified.
+//
+
+UseAlternateDisk:
+ if (!AlternateDisk || (!ForceSelect && (DiskEntry != AlternateDisk)))
+ goto NoSystemPartition;
+
+ if (AlternateDisk->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("Alternate disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ goto NoSystemPartition;
+ }
+
+ if (DiskEntry != AlternateDisk)
+ {
+ /* Choose the alternate disk */
+ DiskEntry = AlternateDisk;
+
+ ActivePartition = GetActiveDiskPartition(DiskEntry);
+ if (ActivePartition)
+ {
+ /* If we get a candidate active partition, validate it */
+ if (IsSupportedActivePartition(ActivePartition))
+ {
+ CandidatePartition = ActivePartition;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+ }
+
+ /* We now may have an unsupported active partition, or none */
+
+/***
+ *** TODO: Improve the selection:
+ *** - If we want a really separate system partition from the partition where
+ *** we install, do something similar to what's done below in the code.
+ *** - Otherwise if we allow for the system partition to be also the partition
+ *** where we install, just directly fall down to using AlternatePart.
+ ***/
+
/* Retrieve the first partition of the disk */
PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
- PARTENTRY,
- ListEntry);
+ PARTENTRY, ListEntry);
ASSERT(DiskEntry == PartEntry->DiskEntry);
- List->SystemPartition = PartEntry;
+
+ CandidatePartition = 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)
+ // !IsContainerPartition(PartEntry->PartitionType);
+ if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
{
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- List->SystemPartition = PartEntry;
+ ASSERT(DiskEntry == CandidatePartition->DiskEntry);
+ List->SystemPartition = CandidatePartition;
List->OriginalSystemPartition = List->SystemPartition;
DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
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)
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
{
- /* Retrieve the partition and go to the next one */
- PartEntry = CONTAINING_RECORD(ListEntry,
- PARTENTRY,
- ListEntry);
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
/* Check if the partition is partitioned and is used */
- if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
+ // !IsContainerPartition(PartEntry->PartitionType);
+ if (/* PartEntry->IsPartitioned && */
+ PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
{
break;
}
-
- /* 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
+ ASSERT(DiskEntry == CandidatePartition->DiskEntry);
+ List->SystemPartition = CandidatePartition; // The first PartEntry
+ List->OriginalSystemPartition = List->SystemPartition;
DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
goto SetSystemPartition;
}
- 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) ? L'-' : PartEntry->DriveLetter);
- break;
- }
- }
- }
-
- /* 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;
- }
-
- /* 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.
+ * The disk is not new, we did not find any actual active partition,
+ * or the one we found was not supported, or any possible other canditate
+ * is not supported. We then use the alternate partition if specified.
*/
- FileSystem = GetFileSystem(List->OriginalSystemPartition);
- if (FileSystem == NULL)
+ if (AlternatePart)
{
- DPRINT1("System partition %lu in disk %lu with no FS?!\n",
- List->OriginalSystemPartition->PartitionNumber,
- List->OriginalSystemPartition->DiskEntry->DiskNumber);
- goto FindAndUseAlternativeSystemPartition;
+ DPRINT1("No system partition found, use the alternative partition!\n");
+ CandidatePartition = AlternatePart;
+ goto UseAlternativeSystemPartition;
}
- // HACK: WARNING: We cannot write on this FS yet!
- // See fsutil.c:GetFileSystem()
- if (List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
+ else
{
- DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
- FileSystem->FileSystemName);
- goto FindAndUseAlternativeSystemPartition;
+NoSystemPartition:
+ DPRINT1("No valid or supported system partition has been found on this system!\n");
+ return;
}
+
+SystemPartitionFound:
+ ASSERT(CandidatePartition);
+ List->SystemPartition = CandidatePartition;
+
DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
List->SystemPartition->DiskEntry->DiskNumber,
*/
/* 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;
+ if (List->OriginalSystemPartition)
+ {
+ List->OriginalSystemPartition->BootIndicator = FALSE;
+ List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].BootIndicator = FALSE;
+ List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].RewritePartition = TRUE;
+ List->OriginalSystemPartition->DiskEntry->Dirty = TRUE;
+ }
UseAlternativeSystemPartition:
- List->SystemPartition = List->CurrentPartition;
+ ASSERT(CandidatePartition);
+ List->SystemPartition = CandidatePartition;
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
List->SystemPartition->DiskEntry->Dirty = TRUE;
}
-static
NTSTATUS
WritePartitions(
- IN PPARTLIST List,
IN PDISKENTRY DiskEntry)
{
- WCHAR DstPath[MAX_PATH];
+ NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK Iosb;
UNICODE_STRING Name;
+ HANDLE FileHandle;
+ IO_STATUS_BLOCK Iosb;
ULONG BufferSize;
- HANDLE FileHandle = NULL;
- NTSTATUS Status;
+ PPARTITION_INFORMATION PartitionInfo;
+ ULONG PartitionCount;
+ PLIST_ENTRY ListEntry;
+ PPARTENTRY PartEntry;
+ WCHAR DstPath[MAX_PATH];
DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
+ /* If the disk is not dirty, there is nothing to do */
+ if (!DiskEntry->Dirty)
+ return STATUS_SUCCESS;
+
RtlStringCchPrintfW(DstPath, ARRAYSIZE(DstPath),
L"\\Device\\Harddisk%lu\\Partition0",
DiskEntry->DiskNumber);
// For this we must ask the user which format to use.
//
+ /* Save the original partition count to be restored later (see comment below) */
+ PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
+
+ /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
- ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
+ ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
Status = NtDeviceIoControlFile(FileHandle,
NULL,
NULL,
IOCTL_DISK_SET_DRIVE_LAYOUT,
DiskEntry->LayoutBuffer,
BufferSize,
- NULL,
- 0);
+ DiskEntry->LayoutBuffer,
+ BufferSize);
+ NtClose(FileHandle);
+
+ /*
+ * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
+ * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
+ * where such a table is expected to enumerate up to 4 partitions:
+ * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
+ * Due to this we need to restore the original PartitionCount number.
+ */
+ DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
+
+ /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
if (!NT_SUCCESS(Status))
{
DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+#ifdef DUMP_PARTITION_TABLE
+ DumpPartitionTable(DiskEntry);
+#endif
+
+ /* Update the partition numbers */
+
+ /* Update the primary partition table */
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ if (PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
+ PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ }
}
- if (FileHandle != NULL)
- NtClose(FileHandle);
+ /* Update the logical partition table */
+ for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+ ListEntry != &DiskEntry->LogicalPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ if (PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+ PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
+ PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ }
+ }
//
// 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.
+ // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 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).
//
+ /* The layout has been successfully updated, the disk is not dirty anymore */
+ DiskEntry->Dirty = FALSE;
+
return Status;
}
WritePartitionsToDisk(
IN PPARTLIST List)
{
+ NTSTATUS Status;
PLIST_ENTRY Entry;
PDISKENTRY DiskEntry;
if (List == NULL)
return TRUE;
- Entry = List->DiskListHead.Flink;
- while (Entry != &List->DiskListHead)
+ for (Entry = List->DiskListHead.Flink;
+ Entry != &List->DiskListHead;
+ Entry = Entry->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- if (DiskEntry->Dirty != FALSE)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
{
- WritePartitions(List, DiskEntry);
- DiskEntry->Dirty = FALSE;
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
}
- Entry = Entry->Flink;
+ if (DiskEntry->Dirty != FALSE)
+ {
+ Status = WritePartitions(DiskEntry);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
+ DiskEntry->DiskNumber, Status);
+ }
+ }
}
return TRUE;
if (List == NULL)
return FALSE;
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ for (Entry1 = List->DiskListHead.Flink;
+ Entry1 != &List->DiskListHead;
+ Entry1 = Entry1->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry1,
DISKENTRY,
ListEntry);
- Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
+
+ for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ Entry2 != &DiskEntry->PrimaryPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned)
+ if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
/* Assign a "\DosDevices\#:" mount point to this partition */
if (PartEntry->DriveLetter)
{
}
}
}
-
- Entry2 = Entry2->Flink;
}
- Entry2 = DiskEntry->LogicalPartListHead.Flink;
- while (Entry2 != &DiskEntry->LogicalPartListHead)
+ for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ Entry2 != &DiskEntry->LogicalPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned)
+ if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
{
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
/* Assign a "\DosDevices\#:" mount point to this partition */
if (PartEntry->DriveLetter)
{
}
}
}
-
- Entry2 = Entry2->Flink;
}
-
- Entry1 = Entry1->Flink;
}
return TRUE;
DiskEntry->Dirty = TRUE;
DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
+ DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RecognizedPartition = IsRecognizedPartition(PartitionType);
DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
}
ERROR_NUMBER
PrimaryPartitionCreationChecks(
- IN PPARTLIST List)
+ IN PPARTENTRY PartEntry)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return ERROR_WARN_PARTITION;
+ }
/* Fail if the partition is already in use */
if (PartEntry->IsPartitioned)
return ERROR_NEW_PARTITION;
+ /* Only one primary partition is allowed on super-floppy */
+ if (IsSuperFloppy(DiskEntry))
+ return ERROR_PARTITION_TABLE_FULL;
+
/* Fail if there are already 4 primary partitions in the list */
if (GetPrimaryPartitionCount(DiskEntry) >= 4)
return ERROR_PARTITION_TABLE_FULL;
ERROR_NUMBER
ExtendedPartitionCreationChecks(
- IN PPARTLIST List)
+ IN PPARTENTRY PartEntry)
{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
- DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return ERROR_WARN_PARTITION;
+ }
/* Fail if the partition is already in use */
if (PartEntry->IsPartitioned)
return ERROR_NEW_PARTITION;
+ /* Only one primary partition is allowed on super-floppy */
+ if (IsSuperFloppy(DiskEntry))
+ return ERROR_PARTITION_TABLE_FULL;
+
/* Fail if there are already 4 primary partitions in the list */
if (GetPrimaryPartitionCount(DiskEntry) >= 4)
return ERROR_PARTITION_TABLE_FULL;
ERROR_NUMBER
LogicalPartitionCreationChecks(
- IN PPARTLIST List)
+ IN PPARTENTRY PartEntry)
{
-// PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
-// DiskEntry = List->CurrentDisk;
- PartEntry = List->CurrentPartition;
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return ERROR_WARN_PARTITION;
+ }
/* Fail if the partition is already in use */
if (PartEntry->IsPartitioned)
return ERROR_NEW_PARTITION;
+ /* Only one primary partition is allowed on super-floppy */
+ if (IsSuperFloppy(DiskEntry))
+ return ERROR_PARTITION_TABLE_FULL;
+
return ERROR_SUCCESS;
}
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ for (Entry1 = List->DiskListHead.Flink;
+ Entry1 != &List->DiskListHead;
+ Entry1 = Entry1->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry1,
DISKENTRY,
ListEntry);
- Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
+
+ for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ Entry2 != &DiskEntry->PrimaryPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned && PartEntry->New)
*pPartEntry = PartEntry;
return TRUE;
}
-
- Entry2 = Entry2->Flink;
}
- Entry2 = DiskEntry->LogicalPartListHead.Flink;
- while (Entry2 != &DiskEntry->LogicalPartListHead)
+ for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ Entry2 != &DiskEntry->LogicalPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned && PartEntry->New)
*pPartEntry = PartEntry;
return TRUE;
}
-
- Entry2 = Entry2->Flink;
}
-
- Entry1 = Entry1->Flink;
}
if (pDiskEntry) *pDiskEntry = NULL;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- Entry1 = List->DiskListHead.Flink;
- while (Entry1 != &List->DiskListHead)
+ for (Entry1 = List->DiskListHead.Flink;
+ Entry1 != &List->DiskListHead;
+ Entry1 = Entry1->Flink)
{
DiskEntry = CONTAINING_RECORD(Entry1,
DISKENTRY,
ListEntry);
- Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry2 != &DiskEntry->PrimaryPartListHead)
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ continue;
+ }
+
+ for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+ Entry2 != &DiskEntry->PrimaryPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->NeedsCheck == TRUE)
+ if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
{
ASSERT(DiskEntry == PartEntry->DiskEntry);
if (pDiskEntry) *pDiskEntry = DiskEntry;
*pPartEntry = PartEntry;
return TRUE;
}
-
- Entry2 = Entry2->Flink;
}
- Entry2 = DiskEntry->LogicalPartListHead.Flink;
- while (Entry2 != &DiskEntry->LogicalPartListHead)
+ for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+ Entry2 != &DiskEntry->LogicalPartListHead;
+ Entry2 = Entry2->Flink)
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->NeedsCheck == TRUE)
+ if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
{
ASSERT(DiskEntry == PartEntry->DiskEntry);
if (pDiskEntry) *pDiskEntry = DiskEntry;
*pPartEntry = PartEntry;
return TRUE;
}
-
- Entry2 = Entry2->Flink;
}
-
- Entry1 = Entry1->Flink;
}
if (pDiskEntry) *pDiskEntry = NULL;