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);
}
+/*
+ * 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
}
}
+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);
+ }
+ }
+}
+
static
VOID
AddDiskToList(
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;
*/
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);
}
}
}
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);
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)
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;
{
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- if (DiskEntry->BiosDiskNumber == BiosDiskNumber)
+ if (DiskEntry->HwDiskNumber == HwDiskNumber)
{
/* Disk found */
return DiskEntry;
//
// 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 &&
- 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 */
- for (DiskListEntry = List->CurrentDisk->ListEntry.Flink;
+ 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);
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
{
DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
continue;
}
- PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
- if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+ PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
- List->CurrentDisk = DiskEntry;
- List->CurrentPartition = PartEntry;
- return List->CurrentPartition;
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ return CurrentPart;
}
}
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 &&
- 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 */
- for (DiskListEntry = List->CurrentDisk->ListEntry.Blink;
+ 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);
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
{
DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
continue;
}
- PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
- if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+ PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
+ if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
{
- PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+ CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned &&
- IsContainerPartition(PartEntry->PartitionType))
+ 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;
}
}
}
static
PPARTENTRY
GetPrevUnpartitionedEntry(
- IN PDISKENTRY DiskEntry,
IN PPARTENTRY PartEntry)
{
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
PPARTENTRY PrevPartEntry;
PLIST_ENTRY ListHead;
PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
PARTENTRY,
ListEntry);
- if (PrevPartEntry->IsPartitioned == FALSE)
+ if (!PrevPartEntry->IsPartitioned)
{
ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
return PrevPartEntry;
static
PPARTENTRY
GetNextUnpartitionedEntry(
- IN PDISKENTRY DiskEntry,
IN PPARTENTRY PartEntry)
{
+ PDISKENTRY DiskEntry = PartEntry->DiskEntry;
PPARTENTRY NextPartEntry;
PLIST_ENTRY ListHead;
NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
PARTENTRY,
ListEntry);
- if (NextPartEntry->IsPartitioned == FALSE)
+ if (!NextPartEntry->IsPartitioned)
{
ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
return NextPartEntry;
return Status;
}
-VOID
+BOOLEAN
DeletePartition(
IN PPARTLIST List,
- IN PPARTENTRY PartEntry)
+ IN PPARTENTRY PartEntry,
+ OUT PPARTENTRY* FreeRegion OPTIONAL)
{
PDISKENTRY DiskEntry;
PPARTENTRY PrevPartEntry;
PartEntry->DiskEntry == NULL ||
PartEntry->IsPartitioned == FALSE)
{
- return;
+ return FALSE;
}
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
if (List->SystemPartition == PartEntry)
{
ASSERT(List->SystemPartition);
+ ASSERT(List->SystemPartition->DiskEntry->MediaType != RemovableMedia);
if (List->SystemPartition == List->OriginalSystemPartition)
List->OriginalSystemPartition = NULL;
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 */
- if (List->CurrentPartition == PartEntry ||
- List->CurrentPartition == NextPartEntry)
- {
- 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 */
- if (List->CurrentPartition == PartEntry)
- {
- 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 */
- if (List->CurrentPartition == PartEntry)
- {
- 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->OnDiskPartitionNumber = 0;
PartEntry->PartitionNumber = 0;
// PartEntry->PartitionIndex = 0;
+
+ /* Optionally return the freed region */
+ if (FreeRegion)
+ *FreeRegion = PartEntry;
}
UpdateDiskLayout(DiskEntry);
AssignDriveLetters(List);
-}
-VOID
-DeleteCurrentPartition(
- IN PPARTLIST List)
-{
- DeletePartition(List, List->CurrentPartition);
+ 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;
/* No system partition! */
List->SystemPartition = NULL;
List->OriginalSystemPartition = NULL;
- return;
+ goto NoSystemPartition;
}
if (List->SystemPartition != NULL)
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 : Checking the first disk.
+// Pass == 1 : Check the first (system) disk.
//
- DPRINT("We are here (1)!\n");
/*
* First, check whether the first disk (the one that will be booted
DiskEntry = CONTAINING_RECORD(List->DiskListHead.Flink,
DISKENTRY, ListEntry);
- // if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
- // {
- // DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
- // continue;
- // }
-
- DPRINT("We are here (1a)!\n");
+ 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)
}
}
- DPRINT("We are here (1b)!\n");
-
- /* If this first disk is not the current installation disk, do the minimal checks */
- if (DiskEntry != List->CurrentDisk)
+ /* If this first disk is not the optional alternate disk, perform the minimal checks */
+ if (DiskEntry != AlternateDisk)
{
/*
- * We don't. Enumerate all the (primary) partitions in the first disk,
- * excluding the current active partition, to find a candidate new one.
+ * 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;
}
- /**** Case where we don't have an active partition on the first disk ****/
-
//
-// Pass == 2 : Checking the CurrentDisk on which we install.
+// Pass == 2 : No active partition found: Check the alternate disk if specified.
//
- DPRINT("We are here (2)!\n");
- if (DiskEntry != List->CurrentDisk)
- {
- /* Choose the currently selected disk */
- DiskEntry = List->CurrentDisk;
+UseAlternateDisk:
+ if (!AlternateDisk || (!ForceSelect && (DiskEntry != AlternateDisk)))
+ goto NoSystemPartition;
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
- {
- DPRINT1("Current disk?! -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
- DPRINT1("No supported active partition found on this system!\n");
- return;
- }
+ if (AlternateDisk->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("Alternate disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ goto NoSystemPartition;
+ }
- DPRINT("We are here (2x)!\n");
+ if (DiskEntry != AlternateDisk)
+ {
+ /* Choose the alternate disk */
+ DiskEntry = AlternateDisk;
ActivePartition = GetActiveDiskPartition(DiskEntry);
if (ActivePartition)
}
}
-
- /**** Here, we either don't have an active partition, or we have one BUT it is not supported ****/
+ /* 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 List->CurrentPartition.
+ *** where we install, just directly fall down to using AlternatePart.
***/
- DPRINT("We are here (2a)!\n");
-
/* Retrieve the first partition of the disk */
PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
PARTENTRY, ListEntry);
DPRINT1("NewDisk TRUE but first partition is used?\n");
}
- DPRINT("We are here (3)!\n");
-
/*
* The disk is not new, check if any partition is initialized;
* if not, the first one becomes the system partition.
goto SetSystemPartition;
}
- DPRINT("We are here (4)!\n");
-
/*
* 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 current (installation) partition.
+ * is not supported. We then use the alternate partition if specified.
*/
- /* Nothing, use the alternative system partition */
- DPRINT1("No system partition found, use the alternative partition!\n");
- CandidatePartition = List->CurrentPartition;
- goto UseAlternativeSystemPartition;
+ if (AlternatePart)
+ {
+ DPRINT1("No system partition found, use the alternative partition!\n");
+ CandidatePartition = AlternatePart;
+ goto UseAlternativeSystemPartition;
+ }
+ else
+ {
+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",
}
UseAlternativeSystemPartition:
+ ASSERT(CandidatePartition);
List->SystemPartition = CandidatePartition;
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
//
// 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
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;
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;
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;
}