xref: /reactos/base/setup/lib/utils/partlist.c (revision d6d3d0ea)
16f19c83bSHermès Bélusca-Maïto /*
26f19c83bSHermès Bélusca-Maïto  * PROJECT:     ReactOS Setup Library
36f15802aSHermès Bélusca-Maïto  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
46f19c83bSHermès Bélusca-Maïto  * PURPOSE:     Partition list functions
5c1fbc2d6SHermès Bélusca-Maïto  * COPYRIGHT:   Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
66f15802aSHermès Bélusca-Maïto  *              Copyright 2018-2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
76f19c83bSHermès Bélusca-Maïto  */
86f19c83bSHermès Bélusca-Maïto 
96f19c83bSHermès Bélusca-Maïto #include "precomp.h"
106f19c83bSHermès Bélusca-Maïto #include <ntddscsi.h>
116f19c83bSHermès Bélusca-Maïto 
126f19c83bSHermès Bélusca-Maïto #include "partlist.h"
136f15802aSHermès Bélusca-Maïto #include "volutil.h"
146f15802aSHermès Bélusca-Maïto #include "fsrec.h" // For FileSystemToMBRPartitionType()
156f15802aSHermès Bélusca-Maïto 
1651cb3cc6SHermès Bélusca-Maïto #include "registry.h"
176f19c83bSHermès Bélusca-Maïto 
186f19c83bSHermès Bélusca-Maïto #define NDEBUG
196f19c83bSHermès Bélusca-Maïto #include <debug.h>
206f19c83bSHermès Bélusca-Maïto 
216f19c83bSHermès Bélusca-Maïto // #define DUMP_PARTITION_TABLE
226f19c83bSHermès Bélusca-Maïto 
236f19c83bSHermès Bélusca-Maïto #include <pshpack1.h>
246f19c83bSHermès Bélusca-Maïto typedef struct _REG_DISK_MOUNT_INFO
256f19c83bSHermès Bélusca-Maïto {
266f19c83bSHermès Bélusca-Maïto     ULONG Signature;
276f15802aSHermès Bélusca-Maïto     ULONGLONG StartingOffset;
286f19c83bSHermès Bélusca-Maïto } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
296f19c83bSHermès Bélusca-Maïto #include <poppack.h>
306f19c83bSHermès Bélusca-Maïto 
316f19c83bSHermès Bélusca-Maïto 
326f19c83bSHermès Bélusca-Maïto /* FUNCTIONS ****************************************************************/
336f19c83bSHermès Bélusca-Maïto 
346f19c83bSHermès Bélusca-Maïto #ifdef DUMP_PARTITION_TABLE
356f19c83bSHermès Bélusca-Maïto static
366f19c83bSHermès Bélusca-Maïto VOID
DumpPartitionTable(PDISKENTRY DiskEntry)376f19c83bSHermès Bélusca-Maïto DumpPartitionTable(
386f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry)
396f19c83bSHermès Bélusca-Maïto {
406f19c83bSHermès Bélusca-Maïto     PPARTITION_INFORMATION PartitionInfo;
416f19c83bSHermès Bélusca-Maïto     ULONG i;
426f19c83bSHermès Bélusca-Maïto 
436f19c83bSHermès Bélusca-Maïto     DbgPrint("\n");
446f19c83bSHermès Bélusca-Maïto     DbgPrint("Index  Start         Length        Hidden      Nr  Type  Boot  RW\n");
456f19c83bSHermès Bélusca-Maïto     DbgPrint("-----  ------------  ------------  ----------  --  ----  ----  --\n");
466f19c83bSHermès Bélusca-Maïto 
476f19c83bSHermès Bélusca-Maïto     for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
486f19c83bSHermès Bélusca-Maïto     {
496f19c83bSHermès Bélusca-Maïto         PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
506f19c83bSHermès Bélusca-Maïto         DbgPrint("  %3lu  %12I64u  %12I64u  %10lu  %2lu    %2x     %c   %c\n",
516f19c83bSHermès Bélusca-Maïto                  i,
526f19c83bSHermès Bélusca-Maïto                  PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
536f19c83bSHermès Bélusca-Maïto                  PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
546f19c83bSHermès Bélusca-Maïto                  PartitionInfo->HiddenSectors,
556f19c83bSHermès Bélusca-Maïto                  PartitionInfo->PartitionNumber,
566f19c83bSHermès Bélusca-Maïto                  PartitionInfo->PartitionType,
576f19c83bSHermès Bélusca-Maïto                  PartitionInfo->BootIndicator ? '*': ' ',
586f19c83bSHermès Bélusca-Maïto                  PartitionInfo->RewritePartition ? 'Y': 'N');
596f19c83bSHermès Bélusca-Maïto     }
606f19c83bSHermès Bélusca-Maïto 
616f19c83bSHermès Bélusca-Maïto     DbgPrint("\n");
626f19c83bSHermès Bélusca-Maïto }
636f19c83bSHermès Bélusca-Maïto #endif
646f19c83bSHermès Bélusca-Maïto 
656f19c83bSHermès Bélusca-Maïto 
666f19c83bSHermès Bélusca-Maïto ULONGLONG
AlignDown(IN ULONGLONG Value,IN ULONG Alignment)676f19c83bSHermès Bélusca-Maïto AlignDown(
686f19c83bSHermès Bélusca-Maïto     IN ULONGLONG Value,
696f19c83bSHermès Bélusca-Maïto     IN ULONG Alignment)
706f19c83bSHermès Bélusca-Maïto {
716f19c83bSHermès Bélusca-Maïto     ULONGLONG Temp;
726f19c83bSHermès Bélusca-Maïto 
736f19c83bSHermès Bélusca-Maïto     Temp = Value / Alignment;
746f19c83bSHermès Bélusca-Maïto 
756f19c83bSHermès Bélusca-Maïto     return Temp * Alignment;
766f19c83bSHermès Bélusca-Maïto }
776f19c83bSHermès Bélusca-Maïto 
786f19c83bSHermès Bélusca-Maïto ULONGLONG
AlignUp(IN ULONGLONG Value,IN ULONG Alignment)796f19c83bSHermès Bélusca-Maïto AlignUp(
806f19c83bSHermès Bélusca-Maïto     IN ULONGLONG Value,
816f19c83bSHermès Bélusca-Maïto     IN ULONG Alignment)
826f19c83bSHermès Bélusca-Maïto {
836f19c83bSHermès Bélusca-Maïto     ULONGLONG Temp, Result;
846f19c83bSHermès Bélusca-Maïto 
856f19c83bSHermès Bélusca-Maïto     Temp = Value / Alignment;
866f19c83bSHermès Bélusca-Maïto 
876f19c83bSHermès Bélusca-Maïto     Result = Temp * Alignment;
886f19c83bSHermès Bélusca-Maïto     if (Value % Alignment)
896f19c83bSHermès Bélusca-Maïto         Result += Alignment;
906f19c83bSHermès Bélusca-Maïto 
916f19c83bSHermès Bélusca-Maïto     return Result;
926f19c83bSHermès Bélusca-Maïto }
936f19c83bSHermès Bélusca-Maïto 
946f19c83bSHermès Bélusca-Maïto ULONGLONG
RoundingDivide(IN ULONGLONG Dividend,IN ULONGLONG Divisor)956f19c83bSHermès Bélusca-Maïto RoundingDivide(
966f19c83bSHermès Bélusca-Maïto    IN ULONGLONG Dividend,
976f19c83bSHermès Bélusca-Maïto    IN ULONGLONG Divisor)
986f19c83bSHermès Bélusca-Maïto {
996f19c83bSHermès Bélusca-Maïto     return (Dividend + Divisor / 2) / Divisor;
1006f19c83bSHermès Bélusca-Maïto }
1016f19c83bSHermès Bélusca-Maïto 
1026f19c83bSHermès Bélusca-Maïto 
1036f19c83bSHermès Bélusca-Maïto static
1046f19c83bSHermès Bélusca-Maïto VOID
GetDriverName(IN PDISKENTRY DiskEntry)1056f19c83bSHermès Bélusca-Maïto GetDriverName(
1066f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
1076f19c83bSHermès Bélusca-Maïto {
1086f19c83bSHermès Bélusca-Maïto     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1096f19c83bSHermès Bélusca-Maïto     WCHAR KeyName[32];
1106f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
1116f19c83bSHermès Bélusca-Maïto 
1126f19c83bSHermès Bélusca-Maïto     RtlInitUnicodeString(&DiskEntry->DriverName, NULL);
1136f19c83bSHermès Bélusca-Maïto 
1146f19c83bSHermès Bélusca-Maïto     RtlStringCchPrintfW(KeyName, ARRAYSIZE(KeyName),
1156f19c83bSHermès Bélusca-Maïto                         L"\\Scsi\\Scsi Port %hu",
1166f19c83bSHermès Bélusca-Maïto                         DiskEntry->Port);
1176f19c83bSHermès Bélusca-Maïto 
1186f19c83bSHermès Bélusca-Maïto     RtlZeroMemory(&QueryTable, sizeof(QueryTable));
1196f19c83bSHermès Bélusca-Maïto 
1206f19c83bSHermès Bélusca-Maïto     QueryTable[0].Name = L"Driver";
1216f19c83bSHermès Bélusca-Maïto     QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1226f19c83bSHermès Bélusca-Maïto     QueryTable[0].EntryContext = &DiskEntry->DriverName;
1236f19c83bSHermès Bélusca-Maïto 
124f41750abSHermès Bélusca-Maïto     /* This will allocate DiskEntry->DriverName if needed */
1256f19c83bSHermès Bélusca-Maïto     Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
1266f19c83bSHermès Bélusca-Maïto                                     KeyName,
1276f19c83bSHermès Bélusca-Maïto                                     QueryTable,
1286f19c83bSHermès Bélusca-Maïto                                     NULL,
1296f19c83bSHermès Bélusca-Maïto                                     NULL);
1306f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
1316f19c83bSHermès Bélusca-Maïto     {
1326f19c83bSHermès Bélusca-Maïto         DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
1336f19c83bSHermès Bélusca-Maïto     }
1346f19c83bSHermès Bélusca-Maïto }
1356f19c83bSHermès Bélusca-Maïto 
1366f19c83bSHermès Bélusca-Maïto static
1376f19c83bSHermès Bélusca-Maïto VOID
AssignDriveLetters(IN PPARTLIST List)1386f19c83bSHermès Bélusca-Maïto AssignDriveLetters(
1396f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List)
1406f19c83bSHermès Bélusca-Maïto {
1416f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
1426f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
1436f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry1;
1446f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry2;
145f41750abSHermès Bélusca-Maïto     WCHAR Letter;
1466f19c83bSHermès Bélusca-Maïto 
147f41750abSHermès Bélusca-Maïto     Letter = L'C';
1486f19c83bSHermès Bélusca-Maïto 
1496f19c83bSHermès Bélusca-Maïto     /* Assign drive letters to primary partitions */
1508bed4adfSHermès Bélusca-Maïto     for (Entry1 = List->DiskListHead.Flink;
1518bed4adfSHermès Bélusca-Maïto          Entry1 != &List->DiskListHead;
1528bed4adfSHermès Bélusca-Maïto          Entry1 = Entry1->Flink)
1536f19c83bSHermès Bélusca-Maïto     {
1546f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
1556f19c83bSHermès Bélusca-Maïto 
1568bed4adfSHermès Bélusca-Maïto         for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
1578bed4adfSHermès Bélusca-Maïto              Entry2 != &DiskEntry->PrimaryPartListHead;
1588bed4adfSHermès Bélusca-Maïto              Entry2 = Entry2->Flink)
1596f19c83bSHermès Bélusca-Maïto         {
1606f19c83bSHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
1616f19c83bSHermès Bélusca-Maïto 
1626f15802aSHermès Bélusca-Maïto             if (!PartEntry->Volume)
1636f15802aSHermès Bélusca-Maïto                 continue;
1646f15802aSHermès Bélusca-Maïto             PartEntry->Volume->Info.DriveLetter = UNICODE_NULL;
1656f19c83bSHermès Bélusca-Maïto 
1666f19c83bSHermès Bélusca-Maïto             if (PartEntry->IsPartitioned &&
1676f15802aSHermès Bélusca-Maïto                 !IsContainerPartition(PartEntry->PartitionType) &&
1686f15802aSHermès Bélusca-Maïto                 (IsRecognizedPartition(PartEntry->PartitionType) ||
1696f15802aSHermès Bélusca-Maïto                  PartEntry->SectorCount.QuadPart != 0LL))
1706f19c83bSHermès Bélusca-Maïto             {
171f41750abSHermès Bélusca-Maïto                 if (Letter <= L'Z')
1726f15802aSHermès Bélusca-Maïto                     PartEntry->Volume->Info.DriveLetter = Letter++;
1736f19c83bSHermès Bélusca-Maïto             }
1746f19c83bSHermès Bélusca-Maïto         }
1756f19c83bSHermès Bélusca-Maïto     }
1766f19c83bSHermès Bélusca-Maïto 
1776f19c83bSHermès Bélusca-Maïto     /* Assign drive letters to logical drives */
1788bed4adfSHermès Bélusca-Maïto     for (Entry1 = List->DiskListHead.Flink;
1798bed4adfSHermès Bélusca-Maïto          Entry1 != &List->DiskListHead;
1808bed4adfSHermès Bélusca-Maïto          Entry1 = Entry1->Flink)
1816f19c83bSHermès Bélusca-Maïto     {
1826f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
1836f19c83bSHermès Bélusca-Maïto 
1848bed4adfSHermès Bélusca-Maïto         for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
1858bed4adfSHermès Bélusca-Maïto              Entry2 != &DiskEntry->LogicalPartListHead;
1868bed4adfSHermès Bélusca-Maïto              Entry2 = Entry2->Flink)
1876f19c83bSHermès Bélusca-Maïto         {
1886f19c83bSHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
1896f19c83bSHermès Bélusca-Maïto 
1906f15802aSHermès Bélusca-Maïto             if (!PartEntry->Volume)
1916f15802aSHermès Bélusca-Maïto                 continue;
1926f15802aSHermès Bélusca-Maïto             PartEntry->Volume->Info.DriveLetter = UNICODE_NULL;
1936f19c83bSHermès Bélusca-Maïto 
1946f15802aSHermès Bélusca-Maïto             if (PartEntry->IsPartitioned &&
1956f15802aSHermès Bélusca-Maïto                 (IsRecognizedPartition(PartEntry->PartitionType) ||
1966f15802aSHermès Bélusca-Maïto                  PartEntry->SectorCount.QuadPart != 0LL))
1976f19c83bSHermès Bélusca-Maïto             {
198f41750abSHermès Bélusca-Maïto                 if (Letter <= L'Z')
1996f15802aSHermès Bélusca-Maïto                     PartEntry->Volume->Info.DriveLetter = Letter++;
2006f19c83bSHermès Bélusca-Maïto             }
2016f19c83bSHermès Bélusca-Maïto         }
2026f19c83bSHermès Bélusca-Maïto     }
2036f19c83bSHermès Bélusca-Maïto }
2046f19c83bSHermès Bélusca-Maïto 
2056f19c83bSHermès Bélusca-Maïto static NTSTATUS
2066f19c83bSHermès Bélusca-Maïto NTAPI
DiskIdentifierQueryRoutine(PWSTR ValueName,ULONG ValueType,PVOID ValueData,ULONG ValueLength,PVOID Context,PVOID EntryContext)2076f19c83bSHermès Bélusca-Maïto DiskIdentifierQueryRoutine(
2086f19c83bSHermès Bélusca-Maïto     PWSTR ValueName,
2096f19c83bSHermès Bélusca-Maïto     ULONG ValueType,
2106f19c83bSHermès Bélusca-Maïto     PVOID ValueData,
2116f19c83bSHermès Bélusca-Maïto     ULONG ValueLength,
2126f19c83bSHermès Bélusca-Maïto     PVOID Context,
2136f19c83bSHermès Bélusca-Maïto     PVOID EntryContext)
2146f19c83bSHermès Bélusca-Maïto {
2156f19c83bSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
2166f19c83bSHermès Bélusca-Maïto     UNICODE_STRING NameU;
2176f19c83bSHermès Bélusca-Maïto 
2186f19c83bSHermès Bélusca-Maïto     if (ValueType == REG_SZ &&
21947a1acedSHermès Bélusca-Maïto         ValueLength == 20 * sizeof(WCHAR) &&
22047a1acedSHermès Bélusca-Maïto         ((PWCHAR)ValueData)[8] == L'-')
2216f19c83bSHermès Bélusca-Maïto     {
2226f19c83bSHermès Bélusca-Maïto         NameU.Buffer = (PWCHAR)ValueData;
2236f19c83bSHermès Bélusca-Maïto         NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
2246f19c83bSHermès Bélusca-Maïto         RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
2256f19c83bSHermès Bélusca-Maïto 
2266f19c83bSHermès Bélusca-Maïto         NameU.Buffer = (PWCHAR)ValueData + 9;
2276f19c83bSHermès Bélusca-Maïto         RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
2286f19c83bSHermès Bélusca-Maïto 
2296f19c83bSHermès Bélusca-Maïto         return STATUS_SUCCESS;
2306f19c83bSHermès Bélusca-Maïto     }
2316f19c83bSHermès Bélusca-Maïto 
2326f19c83bSHermès Bélusca-Maïto     return STATUS_UNSUCCESSFUL;
2336f19c83bSHermès Bélusca-Maïto }
2346f19c83bSHermès Bélusca-Maïto 
2356f19c83bSHermès Bélusca-Maïto static NTSTATUS
2366f19c83bSHermès Bélusca-Maïto NTAPI
DiskConfigurationDataQueryRoutine(PWSTR ValueName,ULONG ValueType,PVOID ValueData,ULONG ValueLength,PVOID Context,PVOID EntryContext)2376f19c83bSHermès Bélusca-Maïto DiskConfigurationDataQueryRoutine(
2386f19c83bSHermès Bélusca-Maïto     PWSTR ValueName,
2396f19c83bSHermès Bélusca-Maïto     ULONG ValueType,
2406f19c83bSHermès Bélusca-Maïto     PVOID ValueData,
2416f19c83bSHermès Bélusca-Maïto     ULONG ValueLength,
2426f19c83bSHermès Bélusca-Maïto     PVOID Context,
2436f19c83bSHermès Bélusca-Maïto     PVOID EntryContext)
2446f19c83bSHermès Bélusca-Maïto {
2456f19c83bSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
2466f19c83bSHermès Bélusca-Maïto     PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
2476f19c83bSHermès Bélusca-Maïto     PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
2486f19c83bSHermès Bélusca-Maïto     ULONG i;
2496f19c83bSHermès Bélusca-Maïto 
2506f19c83bSHermès Bélusca-Maïto     if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
2516f19c83bSHermès Bélusca-Maïto         ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
2526f19c83bSHermès Bélusca-Maïto         return STATUS_UNSUCCESSFUL;
2536f19c83bSHermès Bélusca-Maïto 
2546f19c83bSHermès Bélusca-Maïto     FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
2556f19c83bSHermès Bélusca-Maïto 
2566f19c83bSHermès Bélusca-Maïto     /* Hm. Version and Revision are not set on Microsoft Windows XP... */
2576f19c83bSHermès Bélusca-Maïto #if 0
2586f19c83bSHermès Bélusca-Maïto     if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
2596f19c83bSHermès Bélusca-Maïto         FullResourceDescriptor->PartialResourceList.Revision != 1)
2606f19c83bSHermès Bélusca-Maïto         return STATUS_UNSUCCESSFUL;
2616f19c83bSHermès Bélusca-Maïto #endif
2626f19c83bSHermès Bélusca-Maïto 
2636f19c83bSHermès Bélusca-Maïto     for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
2646f19c83bSHermès Bélusca-Maïto     {
2656f19c83bSHermès Bélusca-Maïto         if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
2666f19c83bSHermès Bélusca-Maïto             FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
2676f19c83bSHermès Bélusca-Maïto             continue;
2686f19c83bSHermès Bélusca-Maïto 
2696f19c83bSHermès Bélusca-Maïto         DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
2706f19c83bSHermès Bélusca-Maïto         BiosDiskEntry->DiskGeometry = *DiskGeometry;
2716f19c83bSHermès Bélusca-Maïto 
2726f19c83bSHermès Bélusca-Maïto         return STATUS_SUCCESS;
2736f19c83bSHermès Bélusca-Maïto     }
2746f19c83bSHermès Bélusca-Maïto 
2756f19c83bSHermès Bélusca-Maïto     return STATUS_UNSUCCESSFUL;
2766f19c83bSHermès Bélusca-Maïto }
2776f19c83bSHermès Bélusca-Maïto 
2786f19c83bSHermès Bélusca-Maïto static NTSTATUS
2796f19c83bSHermès Bélusca-Maïto NTAPI
SystemConfigurationDataQueryRoutine(PWSTR ValueName,ULONG ValueType,PVOID ValueData,ULONG ValueLength,PVOID Context,PVOID EntryContext)2806f19c83bSHermès Bélusca-Maïto SystemConfigurationDataQueryRoutine(
2816f19c83bSHermès Bélusca-Maïto     PWSTR ValueName,
2826f19c83bSHermès Bélusca-Maïto     ULONG ValueType,
2836f19c83bSHermès Bélusca-Maïto     PVOID ValueData,
2846f19c83bSHermès Bélusca-Maïto     ULONG ValueLength,
2856f19c83bSHermès Bélusca-Maïto     PVOID Context,
2866f19c83bSHermès Bélusca-Maïto     PVOID EntryContext)
2876f19c83bSHermès Bélusca-Maïto {
2886f19c83bSHermès Bélusca-Maïto     PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
2896f19c83bSHermès Bélusca-Maïto     PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
2906f19c83bSHermès Bélusca-Maïto     ULONG i;
2916f19c83bSHermès Bélusca-Maïto 
2926f19c83bSHermès Bélusca-Maïto     if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
2936f19c83bSHermès Bélusca-Maïto         ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
2946f19c83bSHermès Bélusca-Maïto         return STATUS_UNSUCCESSFUL;
2956f19c83bSHermès Bélusca-Maïto 
2966f19c83bSHermès Bélusca-Maïto     FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
2976f19c83bSHermès Bélusca-Maïto 
2986f19c83bSHermès Bélusca-Maïto     /* Hm. Version and Revision are not set on Microsoft Windows XP... */
2996f19c83bSHermès Bélusca-Maïto #if 0
3006f19c83bSHermès Bélusca-Maïto     if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
3016f19c83bSHermès Bélusca-Maïto         FullResourceDescriptor->PartialResourceList.Revision != 1)
3026f19c83bSHermès Bélusca-Maïto         return STATUS_UNSUCCESSFUL;
3036f19c83bSHermès Bélusca-Maïto #endif
3046f19c83bSHermès Bélusca-Maïto 
3056f19c83bSHermès Bélusca-Maïto     for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
3066f19c83bSHermès Bélusca-Maïto     {
3076f19c83bSHermès Bélusca-Maïto         if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
3086f19c83bSHermès Bélusca-Maïto             FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
3096f19c83bSHermès Bélusca-Maïto             continue;
3106f19c83bSHermès Bélusca-Maïto 
3116f19c83bSHermès Bélusca-Maïto         *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(ProcessHeap, 0,
3126f19c83bSHermès Bélusca-Maïto                        FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
3136f19c83bSHermès Bélusca-Maïto         if (*Int13Drives == NULL)
3146f19c83bSHermès Bélusca-Maïto             return STATUS_NO_MEMORY;
3156f19c83bSHermès Bélusca-Maïto 
3166f19c83bSHermès Bélusca-Maïto         memcpy(*Int13Drives,
3176f19c83bSHermès Bélusca-Maïto                &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
3186f19c83bSHermès Bélusca-Maïto                FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
3196f19c83bSHermès Bélusca-Maïto         return STATUS_SUCCESS;
3206f19c83bSHermès Bélusca-Maïto     }
3216f19c83bSHermès Bélusca-Maïto 
3226f19c83bSHermès Bélusca-Maïto     return STATUS_UNSUCCESSFUL;
3236f19c83bSHermès Bélusca-Maïto }
3246f19c83bSHermès Bélusca-Maïto 
3256f19c83bSHermès Bélusca-Maïto 
3266f19c83bSHermès Bélusca-Maïto static VOID
EnumerateBiosDiskEntries(IN PPARTLIST PartList)3276f19c83bSHermès Bélusca-Maïto EnumerateBiosDiskEntries(
3286f19c83bSHermès Bélusca-Maïto     IN PPARTLIST PartList)
3296f19c83bSHermès Bélusca-Maïto {
3306f19c83bSHermès Bélusca-Maïto     RTL_QUERY_REGISTRY_TABLE QueryTable[3];
3316f19c83bSHermès Bélusca-Maïto     WCHAR Name[120];
3326f19c83bSHermès Bélusca-Maïto     ULONG AdapterCount;
33347a1acedSHermès Bélusca-Maïto     ULONG ControllerCount;
3346f19c83bSHermès Bélusca-Maïto     ULONG DiskCount;
3356f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
3366f19c83bSHermès Bélusca-Maïto     PCM_INT13_DRIVE_PARAMETER Int13Drives;
3376f19c83bSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry;
3386f19c83bSHermès Bélusca-Maïto 
339f41750abSHermès Bélusca-Maïto #define ROOT_NAME   L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
340f41750abSHermès Bélusca-Maïto 
3416f19c83bSHermès Bélusca-Maïto     memset(QueryTable, 0, sizeof(QueryTable));
3426f19c83bSHermès Bélusca-Maïto 
3436f19c83bSHermès Bélusca-Maïto     QueryTable[1].Name = L"Configuration Data";
3446f19c83bSHermès Bélusca-Maïto     QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
3456f19c83bSHermès Bélusca-Maïto     Int13Drives = NULL;
3466f19c83bSHermès Bélusca-Maïto     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
3476f19c83bSHermès Bélusca-Maïto                                     L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
3486f19c83bSHermès Bélusca-Maïto                                     &QueryTable[1],
3496f19c83bSHermès Bélusca-Maïto                                     (PVOID)&Int13Drives,
3506f19c83bSHermès Bélusca-Maïto                                     NULL);
3516f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
3526f19c83bSHermès Bélusca-Maïto     {
3536f19c83bSHermès Bélusca-Maïto         DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
3546f19c83bSHermès Bélusca-Maïto         return;
3556f19c83bSHermès Bélusca-Maïto     }
3566f19c83bSHermès Bélusca-Maïto 
35747a1acedSHermès Bélusca-Maïto     for (AdapterCount = 0; ; ++AdapterCount)
3586f19c83bSHermès Bélusca-Maïto     {
3596f19c83bSHermès Bélusca-Maïto         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
3606f19c83bSHermès Bélusca-Maïto                             L"%s\\%lu",
3616f19c83bSHermès Bélusca-Maïto                             ROOT_NAME, AdapterCount);
3626f19c83bSHermès Bélusca-Maïto         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
3636f19c83bSHermès Bélusca-Maïto                                         Name,
3646f19c83bSHermès Bélusca-Maïto                                         &QueryTable[2],
3656f19c83bSHermès Bélusca-Maïto                                         NULL,
3666f19c83bSHermès Bélusca-Maïto                                         NULL);
3676f19c83bSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
3686f19c83bSHermès Bélusca-Maïto         {
3696f19c83bSHermès Bélusca-Maïto             break;
3706f19c83bSHermès Bélusca-Maïto         }
3716f19c83bSHermès Bélusca-Maïto 
3726f19c83bSHermès Bélusca-Maïto         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
3736f19c83bSHermès Bélusca-Maïto                             L"%s\\%lu\\DiskController",
3746f19c83bSHermès Bélusca-Maïto                             ROOT_NAME, AdapterCount);
3756f19c83bSHermès Bélusca-Maïto         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
3766f19c83bSHermès Bélusca-Maïto                                         Name,
3776f19c83bSHermès Bélusca-Maïto                                         &QueryTable[2],
3786f19c83bSHermès Bélusca-Maïto                                         NULL,
3796f19c83bSHermès Bélusca-Maïto                                         NULL);
3806f19c83bSHermès Bélusca-Maïto         if (NT_SUCCESS(Status))
3816f19c83bSHermès Bélusca-Maïto         {
38247a1acedSHermès Bélusca-Maïto             for (ControllerCount = 0; ; ++ControllerCount)
3836f19c83bSHermès Bélusca-Maïto             {
3846f19c83bSHermès Bélusca-Maïto                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
38547a1acedSHermès Bélusca-Maïto                                     L"%s\\%lu\\DiskController\\%lu",
38647a1acedSHermès Bélusca-Maïto                                     ROOT_NAME, AdapterCount, ControllerCount);
3876f19c83bSHermès Bélusca-Maïto                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
3886f19c83bSHermès Bélusca-Maïto                                                 Name,
3896f19c83bSHermès Bélusca-Maïto                                                 &QueryTable[2],
3906f19c83bSHermès Bélusca-Maïto                                                 NULL,
3916f19c83bSHermès Bélusca-Maïto                                                 NULL);
3926f19c83bSHermès Bélusca-Maïto                 if (!NT_SUCCESS(Status))
3936f19c83bSHermès Bélusca-Maïto                 {
3946f19c83bSHermès Bélusca-Maïto                     RtlFreeHeap(ProcessHeap, 0, Int13Drives);
3956f19c83bSHermès Bélusca-Maïto                     return;
3966f19c83bSHermès Bélusca-Maïto                 }
3976f19c83bSHermès Bélusca-Maïto 
3986f19c83bSHermès Bélusca-Maïto                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
39947a1acedSHermès Bélusca-Maïto                                     L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral",
40047a1acedSHermès Bélusca-Maïto                                     ROOT_NAME, AdapterCount, ControllerCount);
4016f19c83bSHermès Bélusca-Maïto                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
4026f19c83bSHermès Bélusca-Maïto                                                 Name,
4036f19c83bSHermès Bélusca-Maïto                                                 &QueryTable[2],
4046f19c83bSHermès Bélusca-Maïto                                                 NULL,
4056f19c83bSHermès Bélusca-Maïto                                                 NULL);
4066f19c83bSHermès Bélusca-Maïto                 if (NT_SUCCESS(Status))
4076f19c83bSHermès Bélusca-Maïto                 {
4086f19c83bSHermès Bélusca-Maïto                     QueryTable[0].Name = L"Identifier";
4096f19c83bSHermès Bélusca-Maïto                     QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
4106f19c83bSHermès Bélusca-Maïto                     QueryTable[1].Name = L"Configuration Data";
4116f19c83bSHermès Bélusca-Maïto                     QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
4126f19c83bSHermès Bélusca-Maïto 
41347a1acedSHermès Bélusca-Maïto                     for (DiskCount = 0; ; ++DiskCount)
4146f19c83bSHermès Bélusca-Maïto                     {
4156f19c83bSHermès Bélusca-Maïto                         BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
4166f19c83bSHermès Bélusca-Maïto                         if (BiosDiskEntry == NULL)
4176f19c83bSHermès Bélusca-Maïto                         {
41847a1acedSHermès Bélusca-Maïto                             RtlFreeHeap(ProcessHeap, 0, Int13Drives);
41947a1acedSHermès Bélusca-Maïto                             return;
4206f19c83bSHermès Bélusca-Maïto                         }
4216f19c83bSHermès Bélusca-Maïto 
4226f19c83bSHermès Bélusca-Maïto                         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
42347a1acedSHermès Bélusca-Maïto                                             L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu",
42447a1acedSHermès Bélusca-Maïto                                             ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
4256f19c83bSHermès Bélusca-Maïto                         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
4266f19c83bSHermès Bélusca-Maïto                                                         Name,
4276f19c83bSHermès Bélusca-Maïto                                                         QueryTable,
4286f19c83bSHermès Bélusca-Maïto                                                         (PVOID)BiosDiskEntry,
4296f19c83bSHermès Bélusca-Maïto                                                         NULL);
4306f19c83bSHermès Bélusca-Maïto                         if (!NT_SUCCESS(Status))
4316f19c83bSHermès Bélusca-Maïto                         {
4326f19c83bSHermès Bélusca-Maïto                             RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
43347a1acedSHermès Bélusca-Maïto                             RtlFreeHeap(ProcessHeap, 0, Int13Drives);
43447a1acedSHermès Bélusca-Maïto                             return;
4356f19c83bSHermès Bélusca-Maïto                         }
4366f19c83bSHermès Bélusca-Maïto 
43747a1acedSHermès Bélusca-Maïto                         BiosDiskEntry->AdapterNumber = 0; // And NOT "AdapterCount" as it needs to be hardcoded for BIOS!
43847a1acedSHermès Bélusca-Maïto                         BiosDiskEntry->ControllerNumber = ControllerCount;
4396f19c83bSHermès Bélusca-Maïto                         BiosDiskEntry->DiskNumber = DiskCount;
44047a1acedSHermès Bélusca-Maïto                         BiosDiskEntry->DiskEntry = NULL;
4416f19c83bSHermès Bélusca-Maïto 
4426f19c83bSHermès Bélusca-Maïto                         if (DiskCount < Int13Drives[0].NumberDrives)
4436f19c83bSHermès Bélusca-Maïto                         {
4446f19c83bSHermès Bélusca-Maïto                             BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
4456f19c83bSHermès Bélusca-Maïto                         }
4466f19c83bSHermès Bélusca-Maïto                         else
4476f19c83bSHermès Bélusca-Maïto                         {
44847a1acedSHermès Bélusca-Maïto                             DPRINT1("Didn't find Int13 drive data for disk %u\n", DiskCount);
4496f19c83bSHermès Bélusca-Maïto                         }
4506f19c83bSHermès Bélusca-Maïto 
4516f19c83bSHermès Bélusca-Maïto                         InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
4526f19c83bSHermès Bélusca-Maïto 
45347a1acedSHermès Bélusca-Maïto                         DPRINT("--->\n");
45447a1acedSHermès Bélusca-Maïto                         DPRINT("AdapterNumber:     %lu\n", BiosDiskEntry->AdapterNumber);
45547a1acedSHermès Bélusca-Maïto                         DPRINT("ControllerNumber:  %lu\n", BiosDiskEntry->ControllerNumber);
4566f19c83bSHermès Bélusca-Maïto                         DPRINT("DiskNumber:        %lu\n", BiosDiskEntry->DiskNumber);
4576f19c83bSHermès Bélusca-Maïto                         DPRINT("Signature:         %08lx\n", BiosDiskEntry->Signature);
4586f19c83bSHermès Bélusca-Maïto                         DPRINT("Checksum:          %08lx\n", BiosDiskEntry->Checksum);
4596f19c83bSHermès Bélusca-Maïto                         DPRINT("BytesPerSector:    %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
4606f19c83bSHermès Bélusca-Maïto                         DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
4616f19c83bSHermès Bélusca-Maïto                         DPRINT("NumberOfHeads:     %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
4626f19c83bSHermès Bélusca-Maïto                         DPRINT("DriveSelect:       %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
4636f19c83bSHermès Bélusca-Maïto                         DPRINT("MaxCylinders:      %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
4646f19c83bSHermès Bélusca-Maïto                         DPRINT("SectorsPerTrack:   %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
4656f19c83bSHermès Bélusca-Maïto                         DPRINT("MaxHeads:          %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
4666f19c83bSHermès Bélusca-Maïto                         DPRINT("NumberDrives:      %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
46747a1acedSHermès Bélusca-Maïto                         DPRINT("<---\n");
4686f19c83bSHermès Bélusca-Maïto                     }
4696f19c83bSHermès Bélusca-Maïto                 }
4706f19c83bSHermès Bélusca-Maïto             }
4716f19c83bSHermès Bélusca-Maïto         }
4726f19c83bSHermès Bélusca-Maïto     }
4736f19c83bSHermès Bélusca-Maïto 
4746f19c83bSHermès Bélusca-Maïto     RtlFreeHeap(ProcessHeap, 0, Int13Drives);
475f41750abSHermès Bélusca-Maïto 
476f41750abSHermès Bélusca-Maïto #undef ROOT_NAME
4776f19c83bSHermès Bélusca-Maïto }
4786f19c83bSHermès Bélusca-Maïto 
4797df92966SHermès Bélusca-Maïto 
48047a1acedSHermès Bélusca-Maïto /*
481*d6d3d0eaSHermès Bélusca-Maïto  * Detects whether a disk is a "super-floppy", i.e. an unpartitioned
482*d6d3d0eaSHermès Bélusca-Maïto  * disk with only a valid VBR, as reported by IoReadPartitionTable()
48347a1acedSHermès Bélusca-Maïto  * and IoWritePartitionTable():
484*d6d3d0eaSHermès Bélusca-Maïto  * only one single partition starting at offset zero and spanning the
485*d6d3d0eaSHermès Bélusca-Maïto  * whole disk, without hidden sectors, whose type is FAT16 non-bootable.
486*d6d3d0eaSHermès Bélusca-Maïto  *
487*d6d3d0eaSHermès Bélusca-Maïto  * Accessing \Device\HarddiskN\Partition0 or Partition1 on such disks
488*d6d3d0eaSHermès Bélusca-Maïto  * returns the same data.
48947a1acedSHermès Bélusca-Maïto  */
49047a1acedSHermès Bélusca-Maïto BOOLEAN
IsDiskSuperFloppy2(_In_ const DISK_PARTITION_INFO * DiskInfo,_In_opt_ const ULONGLONG * DiskSize,_In_ const PARTITION_INFORMATION * PartitionInfo)491*d6d3d0eaSHermès Bélusca-Maïto IsDiskSuperFloppy2(
492*d6d3d0eaSHermès Bélusca-Maïto     _In_ const DISK_PARTITION_INFO* DiskInfo,
493*d6d3d0eaSHermès Bélusca-Maïto     _In_opt_ const ULONGLONG* DiskSize,
494*d6d3d0eaSHermès Bélusca-Maïto     _In_ const PARTITION_INFORMATION* PartitionInfo)
49547a1acedSHermès Bélusca-Maïto {
496*d6d3d0eaSHermès Bélusca-Maïto     /* Structure size must be valid */
497*d6d3d0eaSHermès Bélusca-Maïto     if (DiskInfo->SizeOfPartitionInfo < RTL_SIZEOF_THROUGH_FIELD(DISK_PARTITION_INFO, Mbr))
49847a1acedSHermès Bélusca-Maïto         return FALSE;
49947a1acedSHermès Bélusca-Maïto 
500*d6d3d0eaSHermès Bélusca-Maïto     /* The layout must be MBR */
501*d6d3d0eaSHermès Bélusca-Maïto     if (DiskInfo->PartitionStyle != PARTITION_STYLE_MBR)
50247a1acedSHermès Bélusca-Maïto         return FALSE;
50347a1acedSHermès Bélusca-Maïto 
50447a1acedSHermès Bélusca-Maïto     /* The single partition must start at the beginning of the disk */
50547a1acedSHermès Bélusca-Maïto     if (!(PartitionInfo->StartingOffset.QuadPart == 0 &&
50647a1acedSHermès Bélusca-Maïto           PartitionInfo->HiddenSectors == 0))
50747a1acedSHermès Bélusca-Maïto     {
50847a1acedSHermès Bélusca-Maïto         return FALSE;
50947a1acedSHermès Bélusca-Maïto     }
51047a1acedSHermès Bélusca-Maïto 
511*d6d3d0eaSHermès Bélusca-Maïto     /* The disk signature is usually set to 1; warn in case it's not */
512*d6d3d0eaSHermès Bélusca-Maïto     if (DiskInfo->Mbr.Signature != 1)
51347a1acedSHermès Bélusca-Maïto     {
514*d6d3d0eaSHermès Bélusca-Maïto         DPRINT1("Super-Floppy signature %08x != 1\n", DiskInfo->Mbr.Signature);
51547a1acedSHermès Bélusca-Maïto     }
51647a1acedSHermès Bélusca-Maïto 
517*d6d3d0eaSHermès Bélusca-Maïto     /* The partition must be recognized and report as FAT16 non-bootable */
518*d6d3d0eaSHermès Bélusca-Maïto     if ((PartitionInfo->RecognizedPartition != TRUE) ||
519*d6d3d0eaSHermès Bélusca-Maïto         (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
520*d6d3d0eaSHermès Bélusca-Maïto         (PartitionInfo->BootIndicator != FALSE))
52147a1acedSHermès Bélusca-Maïto     {
522*d6d3d0eaSHermès Bélusca-Maïto         DPRINT1("Super-Floppy does not return default settings:\n"
52347a1acedSHermès Bélusca-Maïto                 "    RecognizedPartition = %s, expected TRUE\n"
52447a1acedSHermès Bélusca-Maïto                 "    PartitionType = 0x%02x, expected 0x04 (PARTITION_FAT_16)\n"
52547a1acedSHermès Bélusca-Maïto                 "    BootIndicator = %s, expected FALSE\n",
52647a1acedSHermès Bélusca-Maïto                 PartitionInfo->RecognizedPartition ? "TRUE" : "FALSE",
52747a1acedSHermès Bélusca-Maïto                 PartitionInfo->PartitionType,
52847a1acedSHermès Bélusca-Maïto                 PartitionInfo->BootIndicator ? "TRUE" : "FALSE");
52947a1acedSHermès Bélusca-Maïto     }
53047a1acedSHermès Bélusca-Maïto 
531*d6d3d0eaSHermès Bélusca-Maïto     /* The partition and disk sizes should agree */
532*d6d3d0eaSHermès Bélusca-Maïto     if (DiskSize && (PartitionInfo->PartitionLength.QuadPart != *DiskSize))
53347a1acedSHermès Bélusca-Maïto     {
534*d6d3d0eaSHermès Bélusca-Maïto         DPRINT1("PartitionLength = %I64u is different from DiskSize = %I64u\n",
535*d6d3d0eaSHermès Bélusca-Maïto                 PartitionInfo->PartitionLength.QuadPart, *DiskSize);
53647a1acedSHermès Bélusca-Maïto     }
53747a1acedSHermès Bélusca-Maïto 
53847a1acedSHermès Bélusca-Maïto     return TRUE;
53947a1acedSHermès Bélusca-Maïto }
54047a1acedSHermès Bélusca-Maïto 
541*d6d3d0eaSHermès Bélusca-Maïto BOOLEAN
IsDiskSuperFloppy(_In_ const DRIVE_LAYOUT_INFORMATION * Layout,_In_opt_ const ULONGLONG * DiskSize)542*d6d3d0eaSHermès Bélusca-Maïto IsDiskSuperFloppy(
543*d6d3d0eaSHermès Bélusca-Maïto     _In_ const DRIVE_LAYOUT_INFORMATION* Layout,
544*d6d3d0eaSHermès Bélusca-Maïto     _In_opt_ const ULONGLONG* DiskSize)
545*d6d3d0eaSHermès Bélusca-Maïto {
546*d6d3d0eaSHermès Bélusca-Maïto     DISK_PARTITION_INFO DiskInfo;
547*d6d3d0eaSHermès Bélusca-Maïto 
548*d6d3d0eaSHermès Bélusca-Maïto     /* The layout must contain only one partition */
549*d6d3d0eaSHermès Bélusca-Maïto     if (Layout->PartitionCount != 1)
550*d6d3d0eaSHermès Bélusca-Maïto         return FALSE;
551*d6d3d0eaSHermès Bélusca-Maïto 
552*d6d3d0eaSHermès Bélusca-Maïto     /* Build the disk partition info */
553*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.SizeOfPartitionInfo = RTL_SIZEOF_THROUGH_FIELD(DISK_PARTITION_INFO, Mbr);
554*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.PartitionStyle = PARTITION_STYLE_MBR;
555*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.Mbr.Signature = Layout->Signature;
556*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.Mbr.CheckSum = 0; // Dummy value
557*d6d3d0eaSHermès Bélusca-Maïto 
558*d6d3d0eaSHermès Bélusca-Maïto     /* Call the helper on the single partition entry */
559*d6d3d0eaSHermès Bélusca-Maïto     return IsDiskSuperFloppy2(&DiskInfo, DiskSize, Layout->PartitionEntry);
560*d6d3d0eaSHermès Bélusca-Maïto }
561*d6d3d0eaSHermès Bélusca-Maïto 
562*d6d3d0eaSHermès Bélusca-Maïto BOOLEAN
IsDiskSuperFloppyEx(_In_ const DRIVE_LAYOUT_INFORMATION_EX * LayoutEx,_In_opt_ const ULONGLONG * DiskSize)563*d6d3d0eaSHermès Bélusca-Maïto IsDiskSuperFloppyEx(
564*d6d3d0eaSHermès Bélusca-Maïto     _In_ const DRIVE_LAYOUT_INFORMATION_EX* LayoutEx,
565*d6d3d0eaSHermès Bélusca-Maïto     _In_opt_ const ULONGLONG* DiskSize)
566*d6d3d0eaSHermès Bélusca-Maïto {
567*d6d3d0eaSHermès Bélusca-Maïto     DISK_PARTITION_INFO DiskInfo;
568*d6d3d0eaSHermès Bélusca-Maïto     const PARTITION_INFORMATION_EX* PartitionInfoEx;
569*d6d3d0eaSHermès Bélusca-Maïto     PARTITION_INFORMATION PartitionInfo;
570*d6d3d0eaSHermès Bélusca-Maïto 
571*d6d3d0eaSHermès Bélusca-Maïto     /* The layout must be MBR and contain only one partition */
572*d6d3d0eaSHermès Bélusca-Maïto     if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR)
573*d6d3d0eaSHermès Bélusca-Maïto         return FALSE;
574*d6d3d0eaSHermès Bélusca-Maïto     if (LayoutEx->PartitionCount != 1)
575*d6d3d0eaSHermès Bélusca-Maïto         return FALSE;
576*d6d3d0eaSHermès Bélusca-Maïto 
577*d6d3d0eaSHermès Bélusca-Maïto     /* Build the disk partition info */
578*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.SizeOfPartitionInfo = RTL_SIZEOF_THROUGH_FIELD(DISK_PARTITION_INFO, Mbr);
579*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.PartitionStyle = PARTITION_STYLE_MBR; // LayoutEx->PartitionStyle;
580*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.Mbr.Signature = LayoutEx->Mbr.Signature;
581*d6d3d0eaSHermès Bélusca-Maïto     DiskInfo.Mbr.CheckSum = 0; // Dummy value
582*d6d3d0eaSHermès Bélusca-Maïto 
583*d6d3d0eaSHermès Bélusca-Maïto     /* Convert the single partition entry */
584*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfoEx = LayoutEx->PartitionEntry;
585*d6d3d0eaSHermès Bélusca-Maïto 
586*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.StartingOffset = PartitionInfoEx->StartingOffset;
587*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.PartitionLength = PartitionInfoEx->PartitionLength;
588*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.HiddenSectors = PartitionInfoEx->Mbr.HiddenSectors;
589*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.PartitionNumber = PartitionInfoEx->PartitionNumber;
590*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.PartitionType = PartitionInfoEx->Mbr.PartitionType;
591*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.BootIndicator = PartitionInfoEx->Mbr.BootIndicator;
592*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.RecognizedPartition = PartitionInfoEx->Mbr.RecognizedPartition;
593*d6d3d0eaSHermès Bélusca-Maïto     PartitionInfo.RewritePartition = PartitionInfoEx->RewritePartition;
594*d6d3d0eaSHermès Bélusca-Maïto 
595*d6d3d0eaSHermès Bélusca-Maïto     /* Call the helper on the single partition entry */
596*d6d3d0eaSHermès Bélusca-Maïto     return IsDiskSuperFloppy2(&DiskInfo, DiskSize, &PartitionInfo);
597*d6d3d0eaSHermès Bélusca-Maïto }
598*d6d3d0eaSHermès Bélusca-Maïto 
599*d6d3d0eaSHermès Bélusca-Maïto BOOLEAN
IsSuperFloppy(_In_ PDISKENTRY DiskEntry)600*d6d3d0eaSHermès Bélusca-Maïto IsSuperFloppy(
601*d6d3d0eaSHermès Bélusca-Maïto     _In_ PDISKENTRY DiskEntry)
602*d6d3d0eaSHermès Bélusca-Maïto {
603*d6d3d0eaSHermès Bélusca-Maïto     ULONGLONG DiskSize;
604*d6d3d0eaSHermès Bélusca-Maïto 
605*d6d3d0eaSHermès Bélusca-Maïto     /* No layout buffer: we cannot say anything yet */
606*d6d3d0eaSHermès Bélusca-Maïto     if (!DiskEntry->LayoutBuffer)
607*d6d3d0eaSHermès Bélusca-Maïto         return FALSE;
608*d6d3d0eaSHermès Bélusca-Maïto 
609*d6d3d0eaSHermès Bélusca-Maïto     /* The disk must be MBR */
610*d6d3d0eaSHermès Bélusca-Maïto     if (DiskEntry->DiskStyle != PARTITION_STYLE_MBR)
611*d6d3d0eaSHermès Bélusca-Maïto         return FALSE;
612*d6d3d0eaSHermès Bélusca-Maïto 
613*d6d3d0eaSHermès Bélusca-Maïto     DiskSize = GetDiskSizeInBytes(DiskEntry);
614*d6d3d0eaSHermès Bélusca-Maïto     return IsDiskSuperFloppy(DiskEntry->LayoutBuffer, &DiskSize);
615*d6d3d0eaSHermès Bélusca-Maïto }
616*d6d3d0eaSHermès Bélusca-Maïto 
6177df92966SHermès Bélusca-Maïto 
6187df92966SHermès Bélusca-Maïto /*
6196f15802aSHermès Bélusca-Maïto  * Inserts the disk region represented by PartEntry into either
6206f15802aSHermès Bélusca-Maïto  * the primary or the logical partition list of the given disk.
6217df92966SHermès Bélusca-Maïto  * The lists are kept sorted by increasing order of start sectors.
6227df92966SHermès Bélusca-Maïto  * Of course no disk region should overlap at all with one another.
6237df92966SHermès Bélusca-Maïto  */
6247df92966SHermès Bélusca-Maïto static
625626c654aSHermès Bélusca-Maïto BOOLEAN
InsertDiskRegion(IN PDISKENTRY DiskEntry,IN PPARTENTRY PartEntry,IN BOOLEAN LogicalPartition)6267df92966SHermès Bélusca-Maïto InsertDiskRegion(
6277df92966SHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry,
6287df92966SHermès Bélusca-Maïto     IN PPARTENTRY PartEntry,
6297df92966SHermès Bélusca-Maïto     IN BOOLEAN LogicalPartition)
6307df92966SHermès Bélusca-Maïto {
6317df92966SHermès Bélusca-Maïto     PLIST_ENTRY List;
6327df92966SHermès Bélusca-Maïto     PLIST_ENTRY Entry;
6337df92966SHermès Bélusca-Maïto     PPARTENTRY PartEntry2;
6347df92966SHermès Bélusca-Maïto 
6357df92966SHermès Bélusca-Maïto     /* Use the correct partition list */
6367df92966SHermès Bélusca-Maïto     if (LogicalPartition)
6377df92966SHermès Bélusca-Maïto         List = &DiskEntry->LogicalPartListHead;
6387df92966SHermès Bélusca-Maïto     else
6397df92966SHermès Bélusca-Maïto         List = &DiskEntry->PrimaryPartListHead;
6407df92966SHermès Bélusca-Maïto 
6417df92966SHermès Bélusca-Maïto     /* Find the first disk region before which we need to insert the new one */
6427df92966SHermès Bélusca-Maïto     for (Entry = List->Flink; Entry != List; Entry = Entry->Flink)
6437df92966SHermès Bélusca-Maïto     {
6447df92966SHermès Bélusca-Maïto         PartEntry2 = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
6457df92966SHermès Bélusca-Maïto 
6467df92966SHermès Bélusca-Maïto         /* Ignore any unused empty region */
6477df92966SHermès Bélusca-Maïto         if ((PartEntry2->PartitionType == PARTITION_ENTRY_UNUSED &&
6487df92966SHermès Bélusca-Maïto              PartEntry2->StartSector.QuadPart == 0) || PartEntry2->SectorCount.QuadPart == 0)
6497df92966SHermès Bélusca-Maïto         {
6507df92966SHermès Bélusca-Maïto             continue;
6517df92966SHermès Bélusca-Maïto         }
6527df92966SHermès Bélusca-Maïto 
6537df92966SHermès Bélusca-Maïto         /* If the current region ends before the one to be inserted, try again */
6547df92966SHermès Bélusca-Maïto         if (PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1 < PartEntry->StartSector.QuadPart)
6557df92966SHermès Bélusca-Maïto             continue;
6567df92966SHermès Bélusca-Maïto 
6577df92966SHermès Bélusca-Maïto         /*
6587df92966SHermès Bélusca-Maïto          * One of the disk region boundaries crosses the desired region
6597df92966SHermès Bélusca-Maïto          * (it starts after the desired region, or ends before the end
6607df92966SHermès Bélusca-Maïto          * of the desired region): this is an impossible situation because
6617df92966SHermès Bélusca-Maïto          * disk regions (partitions) cannot overlap!
6627df92966SHermès Bélusca-Maïto          * Throw an error and bail out.
6637df92966SHermès Bélusca-Maïto          */
6647df92966SHermès Bélusca-Maïto         if (max(PartEntry->StartSector.QuadPart, PartEntry2->StartSector.QuadPart)
6657df92966SHermès Bélusca-Maïto             <=
6667df92966SHermès Bélusca-Maïto             min( PartEntry->StartSector.QuadPart +  PartEntry->SectorCount.QuadPart - 1,
6677df92966SHermès Bélusca-Maïto                 PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1))
6687df92966SHermès Bélusca-Maïto         {
6697df92966SHermès Bélusca-Maïto             DPRINT1("Disk region overlap problem, stopping there!\n"
6707df92966SHermès Bélusca-Maïto                     "Partition to be inserted:\n"
6717df92966SHermès Bélusca-Maïto                     "    StartSector = %I64u ; EndSector = %I64u\n"
6727df92966SHermès Bélusca-Maïto                     "Existing disk region:\n"
6737df92966SHermès Bélusca-Maïto                     "    StartSector = %I64u ; EndSector = %I64u\n",
6747df92966SHermès Bélusca-Maïto                      PartEntry->StartSector.QuadPart,
6757df92966SHermès Bélusca-Maïto                      PartEntry->StartSector.QuadPart +  PartEntry->SectorCount.QuadPart - 1,
6767df92966SHermès Bélusca-Maïto                     PartEntry2->StartSector.QuadPart,
6777df92966SHermès Bélusca-Maïto                     PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1);
678626c654aSHermès Bélusca-Maïto             return FALSE;
6797df92966SHermès Bélusca-Maïto         }
6807df92966SHermès Bélusca-Maïto 
6817df92966SHermès Bélusca-Maïto         /* We have found the first region before which the new one has to be inserted */
6827df92966SHermès Bélusca-Maïto         break;
6837df92966SHermès Bélusca-Maïto     }
6847df92966SHermès Bélusca-Maïto 
6857df92966SHermès Bélusca-Maïto     /* Insert the disk region */
6867df92966SHermès Bélusca-Maïto     InsertTailList(Entry, &PartEntry->ListEntry);
687626c654aSHermès Bélusca-Maïto     return TRUE;
6887df92966SHermès Bélusca-Maïto }
6897df92966SHermès Bélusca-Maïto 
6907df92966SHermès Bélusca-Maïto static
6917df92966SHermès Bélusca-Maïto PPARTENTRY
CreateInsertBlankRegion(IN PDISKENTRY DiskEntry,IN OUT PLIST_ENTRY ListHead,IN ULONGLONG StartSector,IN ULONGLONG SectorCount,IN BOOLEAN LogicalSpace)6927df92966SHermès Bélusca-Maïto CreateInsertBlankRegion(
6937df92966SHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry,
6947df92966SHermès Bélusca-Maïto     IN OUT PLIST_ENTRY ListHead,
6957df92966SHermès Bélusca-Maïto     IN ULONGLONG StartSector,
6967df92966SHermès Bélusca-Maïto     IN ULONGLONG SectorCount,
6977df92966SHermès Bélusca-Maïto     IN BOOLEAN LogicalSpace)
6987df92966SHermès Bélusca-Maïto {
6997df92966SHermès Bélusca-Maïto     PPARTENTRY NewPartEntry;
7007df92966SHermès Bélusca-Maïto 
7017df92966SHermès Bélusca-Maïto     NewPartEntry = RtlAllocateHeap(ProcessHeap,
7027df92966SHermès Bélusca-Maïto                                    HEAP_ZERO_MEMORY,
7037df92966SHermès Bélusca-Maïto                                    sizeof(PARTENTRY));
7046f15802aSHermès Bélusca-Maïto     if (!NewPartEntry)
7057df92966SHermès Bélusca-Maïto         return NULL;
7067df92966SHermès Bélusca-Maïto 
7077df92966SHermès Bélusca-Maïto     NewPartEntry->DiskEntry = DiskEntry;
7087df92966SHermès Bélusca-Maïto 
7097df92966SHermès Bélusca-Maïto     NewPartEntry->StartSector.QuadPart = StartSector;
7107df92966SHermès Bélusca-Maïto     NewPartEntry->SectorCount.QuadPart = SectorCount;
7117df92966SHermès Bélusca-Maïto 
712626c654aSHermès Bélusca-Maïto     NewPartEntry->LogicalPartition = LogicalSpace;
713c1fbc2d6SHermès Bélusca-Maïto     NewPartEntry->IsPartitioned = FALSE;
714c1fbc2d6SHermès Bélusca-Maïto     NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
7156f15802aSHermès Bélusca-Maïto     NewPartEntry->Volume = NULL;
716c1fbc2d6SHermès Bélusca-Maïto 
7177df92966SHermès Bélusca-Maïto     DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
7187df92966SHermès Bélusca-Maïto     DPRINT1("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
7197df92966SHermès Bélusca-Maïto     DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
7207df92966SHermès Bélusca-Maïto 
721c1fbc2d6SHermès Bélusca-Maïto     /* Insert the new entry into the list */
7227df92966SHermès Bélusca-Maïto     InsertTailList(ListHead, &NewPartEntry->ListEntry);
7237df92966SHermès Bélusca-Maïto 
7247df92966SHermès Bélusca-Maïto     return NewPartEntry;
7257df92966SHermès Bélusca-Maïto }
7267df92966SHermès Bélusca-Maïto 
7277df92966SHermès Bélusca-Maïto static
72899f0937fSHermès Bélusca-Maïto VOID
DestroyRegion(_Inout_ PPARTENTRY PartEntry)7296f15802aSHermès Bélusca-Maïto DestroyRegion(
7306f15802aSHermès Bélusca-Maïto     _Inout_ PPARTENTRY PartEntry)
7316f15802aSHermès Bélusca-Maïto {
7326f15802aSHermès Bélusca-Maïto     // RemoveEntryList(&PartEntry->Volume->ListEntry);
7336f15802aSHermès Bélusca-Maïto     if (PartEntry->Volume)
7346f15802aSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, PartEntry->Volume);
7356f15802aSHermès Bélusca-Maïto     RtlFreeHeap(ProcessHeap, 0, PartEntry);
7366f15802aSHermès Bélusca-Maïto }
7376f15802aSHermès Bélusca-Maïto 
7386f15802aSHermès Bélusca-Maïto static
7396f15802aSHermès Bélusca-Maïto VOID
AddLogicalDiskSpace(_In_ PDISKENTRY DiskEntry)74099f0937fSHermès Bélusca-Maïto AddLogicalDiskSpace(
74199f0937fSHermès Bélusca-Maïto     _In_ PDISKENTRY DiskEntry)
74299f0937fSHermès Bélusca-Maïto {
74399f0937fSHermès Bélusca-Maïto     ULONGLONG StartSector;
74499f0937fSHermès Bélusca-Maïto     ULONGLONG SectorCount;
74599f0937fSHermès Bélusca-Maïto     PPARTENTRY NewPartEntry;
74699f0937fSHermès Bélusca-Maïto 
74799f0937fSHermès Bélusca-Maïto     DPRINT("AddLogicalDiskSpace()\n");
74899f0937fSHermès Bélusca-Maïto 
74999f0937fSHermès Bélusca-Maïto     /* Create a partition entry that represents the empty space in the container partition */
75099f0937fSHermès Bélusca-Maïto 
75199f0937fSHermès Bélusca-Maïto     StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
75299f0937fSHermès Bélusca-Maïto     SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
75399f0937fSHermès Bélusca-Maïto 
75499f0937fSHermès Bélusca-Maïto     NewPartEntry = CreateInsertBlankRegion(DiskEntry,
75599f0937fSHermès Bélusca-Maïto                                            &DiskEntry->LogicalPartListHead,
75699f0937fSHermès Bélusca-Maïto                                            StartSector,
75799f0937fSHermès Bélusca-Maïto                                            SectorCount,
75899f0937fSHermès Bélusca-Maïto                                            TRUE);
75999f0937fSHermès Bélusca-Maïto     if (!NewPartEntry)
76099f0937fSHermès Bélusca-Maïto         DPRINT1("Failed to create a new empty region for full extended partition space!\n");
76199f0937fSHermès Bélusca-Maïto }
76299f0937fSHermès Bélusca-Maïto 
76399f0937fSHermès Bélusca-Maïto // TODO: Improve upon the PartitionInfo parameter later
76499f0937fSHermès Bélusca-Maïto // (see VDS::CREATE_PARTITION_PARAMETERS and PPARTITION_INFORMATION_MBR/GPT for example)
76599f0937fSHermès Bélusca-Maïto // So far we only use it as the optional type of the partition to create.
76699f0937fSHermès Bélusca-Maïto //
76799f0937fSHermès Bélusca-Maïto // See also CreatePartition().
76899f0937fSHermès Bélusca-Maïto static
769626c654aSHermès Bélusca-Maïto BOOLEAN
InitializePartitionEntry(_Inout_ PPARTENTRY PartEntry,_In_opt_ ULONGLONG SizeBytes,_In_opt_ ULONG_PTR PartitionInfo)7707df92966SHermès Bélusca-Maïto InitializePartitionEntry(
771b7ad4a22SHermès Bélusca-Maïto     _Inout_ PPARTENTRY PartEntry,
77299f0937fSHermès Bélusca-Maïto     _In_opt_ ULONGLONG SizeBytes,
77399f0937fSHermès Bélusca-Maïto     _In_opt_ ULONG_PTR PartitionInfo)
7747df92966SHermès Bélusca-Maïto {
775626c654aSHermès Bélusca-Maïto     PDISKENTRY DiskEntry = PartEntry->DiskEntry;
776b7ad4a22SHermès Bélusca-Maïto     ULONGLONG SectorCount;
77799f0937fSHermès Bélusca-Maïto     BOOLEAN isContainer = IsContainerPartition((UCHAR)PartitionInfo);
7787df92966SHermès Bélusca-Maïto 
779b7ad4a22SHermès Bélusca-Maïto     DPRINT1("Current entry sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
7807df92966SHermès Bélusca-Maïto 
781b7ad4a22SHermès Bélusca-Maïto     /* The entry must not be already partitioned and not be void */
782b7ad4a22SHermès Bélusca-Maïto     ASSERT(!PartEntry->IsPartitioned);
783b7ad4a22SHermès Bélusca-Maïto     ASSERT(PartEntry->SectorCount.QuadPart);
7846f15802aSHermès Bélusca-Maïto     ASSERT(!PartEntry->Volume);
785b7ad4a22SHermès Bélusca-Maïto 
78699f0937fSHermès Bélusca-Maïto     /* Either we create a primary/logical partition, or we create an
78799f0937fSHermès Bélusca-Maïto      * extended partition but the entry must not be logical space */
78899f0937fSHermès Bélusca-Maïto     ASSERT(!isContainer || !PartEntry->LogicalPartition);
78999f0937fSHermès Bélusca-Maïto 
790b7ad4a22SHermès Bélusca-Maïto     /* Convert the size in bytes to sector count. SizeBytes being
791b7ad4a22SHermès Bélusca-Maïto      * zero means the caller wants to use all the empty space. */
792b7ad4a22SHermès Bélusca-Maïto     if ((SizeBytes == 0) || (SizeBytes == GetPartEntrySizeInBytes(PartEntry)))
793b7ad4a22SHermès Bélusca-Maïto     {
794b7ad4a22SHermès Bélusca-Maïto         /* Use all of the unpartitioned disk space */
795b7ad4a22SHermès Bélusca-Maïto         SectorCount = PartEntry->SectorCount.QuadPart;
796b7ad4a22SHermès Bélusca-Maïto     }
797b7ad4a22SHermès Bélusca-Maïto     else
798b7ad4a22SHermès Bélusca-Maïto     {
799b7ad4a22SHermès Bélusca-Maïto         SectorCount = SizeBytes / DiskEntry->BytesPerSector;
800b7ad4a22SHermès Bélusca-Maïto         if (SectorCount == 0)
801b7ad4a22SHermès Bélusca-Maïto         {
802b7ad4a22SHermès Bélusca-Maïto             /* SizeBytes was certainly less than the minimal size, so fail */
803b7ad4a22SHermès Bélusca-Maïto             DPRINT1("Partition size %I64u too small\n", SizeBytes);
804b7ad4a22SHermès Bélusca-Maïto             return FALSE;
805b7ad4a22SHermès Bélusca-Maïto         }
806b7ad4a22SHermès Bélusca-Maïto     }
807b7ad4a22SHermès Bélusca-Maïto     DPRINT1("    New sector count: %I64u\n", SectorCount);
808b7ad4a22SHermès Bélusca-Maïto 
809b7ad4a22SHermès Bélusca-Maïto     /* Fail if we request more sectors than what the entry actually contains */
810626c654aSHermès Bélusca-Maïto     if (SectorCount > PartEntry->SectorCount.QuadPart)
811626c654aSHermès Bélusca-Maïto         return FALSE;
812626c654aSHermès Bélusca-Maïto 
813b7ad4a22SHermès Bélusca-Maïto     if ((SectorCount == 0) ||
8147df92966SHermès Bélusca-Maïto         (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
8157df92966SHermès Bélusca-Maïto                    PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
8167df92966SHermès Bélusca-Maïto     {
817b7ad4a22SHermès Bélusca-Maïto         /* Reuse the whole current entry */
8187df92966SHermès Bélusca-Maïto     }
8197df92966SHermès Bélusca-Maïto     else
8207df92966SHermès Bélusca-Maïto     {
821626c654aSHermès Bélusca-Maïto         ULONGLONG StartSector;
822626c654aSHermès Bélusca-Maïto         ULONGLONG SectorCount2;
823626c654aSHermès Bélusca-Maïto         PPARTENTRY NewPartEntry;
8247df92966SHermès Bélusca-Maïto 
825b7ad4a22SHermès Bélusca-Maïto         /* Create a partition entry that represents the remaining space
826b7ad4a22SHermès Bélusca-Maïto          * after the partition to be initialized */
827626c654aSHermès Bélusca-Maïto 
828626c654aSHermès Bélusca-Maïto         StartSector = AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment);
829626c654aSHermès Bélusca-Maïto         SectorCount2 = PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - StartSector;
830626c654aSHermès Bélusca-Maïto 
831626c654aSHermès Bélusca-Maïto         NewPartEntry = CreateInsertBlankRegion(DiskEntry,
832626c654aSHermès Bélusca-Maïto                                                PartEntry->ListEntry.Flink,
833626c654aSHermès Bélusca-Maïto                                                StartSector,
834626c654aSHermès Bélusca-Maïto                                                SectorCount2,
835626c654aSHermès Bélusca-Maïto                                                PartEntry->LogicalPartition);
83699f0937fSHermès Bélusca-Maïto         if (!NewPartEntry)
837626c654aSHermès Bélusca-Maïto         {
838626c654aSHermès Bélusca-Maïto             DPRINT1("Failed to create a new empty region for disk space!\n");
839626c654aSHermès Bélusca-Maïto             return FALSE;
8407df92966SHermès Bélusca-Maïto         }
8417df92966SHermès Bélusca-Maïto 
842626c654aSHermès Bélusca-Maïto         /* Resize down the partition entry; its StartSector remains the same */
843626c654aSHermès Bélusca-Maïto         PartEntry->SectorCount.QuadPart = StartSector - PartEntry->StartSector.QuadPart;
844626c654aSHermès Bélusca-Maïto     }
845c1fbc2d6SHermès Bélusca-Maïto 
8466f15802aSHermès Bélusca-Maïto     /* Convert to a new partition entry */
847626c654aSHermès Bélusca-Maïto     PartEntry->New = TRUE;
848626c654aSHermès Bélusca-Maïto     PartEntry->IsPartitioned = TRUE;
849c1fbc2d6SHermès Bélusca-Maïto 
85099f0937fSHermès Bélusca-Maïto     PartEntry->BootIndicator = FALSE;
85199f0937fSHermès Bélusca-Maïto     if (PartitionInfo)
85299f0937fSHermès Bélusca-Maïto     {
85399f0937fSHermès Bélusca-Maïto         if (!isContainer)
85499f0937fSHermès Bélusca-Maïto         {
85599f0937fSHermès Bélusca-Maïto             PartEntry->PartitionType = (UCHAR)PartitionInfo;
85699f0937fSHermès Bélusca-Maïto         }
85799f0937fSHermès Bélusca-Maïto         else
85899f0937fSHermès Bélusca-Maïto         {
85999f0937fSHermès Bélusca-Maïto             /* Set the correct extended container partition type,
86099f0937fSHermès Bélusca-Maïto              * depending on whether it is contained below or above
86199f0937fSHermès Bélusca-Maïto              * the 1024-cylinder (usually 8.4GB/7.8GiB) boundary:
86299f0937fSHermès Bélusca-Maïto              * - below: INT13h CHS partition;
86399f0937fSHermès Bélusca-Maïto              * - above: Extended INT13h LBA partition. */
86499f0937fSHermès Bélusca-Maïto             if ((PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1)
86599f0937fSHermès Bélusca-Maïto                   / (DiskEntry->TracksPerCylinder * DiskEntry->SectorsPerTrack) < 1024)
86699f0937fSHermès Bélusca-Maïto             {
86799f0937fSHermès Bélusca-Maïto                 PartEntry->PartitionType = PARTITION_EXTENDED;
86899f0937fSHermès Bélusca-Maïto             }
86999f0937fSHermès Bélusca-Maïto             else
87099f0937fSHermès Bélusca-Maïto             {
87199f0937fSHermès Bélusca-Maïto                 PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
87299f0937fSHermès Bélusca-Maïto             }
87399f0937fSHermès Bélusca-Maïto         }
87499f0937fSHermès Bélusca-Maïto     }
87599f0937fSHermès Bélusca-Maïto     else
87699f0937fSHermès Bélusca-Maïto     {
8779735a837SHermès Bélusca-Maïto // FIXME: Use FileSystemToMBRPartitionType() only for MBR, otherwise use PARTITION_BASIC_DATA_GUID.
87899f0937fSHermès Bélusca-Maïto         ASSERT(!isContainer);
8799735a837SHermès Bélusca-Maïto         PartEntry->PartitionType = FileSystemToMBRPartitionType(L"RAW",
8809735a837SHermès Bélusca-Maïto                                                                 PartEntry->StartSector.QuadPart,
8819735a837SHermès Bélusca-Maïto                                                                 PartEntry->SectorCount.QuadPart);
88299f0937fSHermès Bélusca-Maïto     }
883626c654aSHermès Bélusca-Maïto     ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
884c1fbc2d6SHermès Bélusca-Maïto 
88599f0937fSHermès Bélusca-Maïto     if (isContainer)
88699f0937fSHermès Bélusca-Maïto     {
88799f0937fSHermès Bélusca-Maïto         DiskEntry->ExtendedPartition = PartEntry;
88899f0937fSHermès Bélusca-Maïto         AddLogicalDiskSpace(DiskEntry);
88999f0937fSHermès Bélusca-Maïto     }
8907df92966SHermès Bélusca-Maïto 
891626c654aSHermès Bélusca-Maïto     DPRINT1("First Sector : %I64u\n", PartEntry->StartSector.QuadPart);
892626c654aSHermès Bélusca-Maïto     DPRINT1("Last Sector  : %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
893626c654aSHermès Bélusca-Maïto     DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
894626c654aSHermès Bélusca-Maïto 
895626c654aSHermès Bélusca-Maïto     return TRUE;
8967df92966SHermès Bélusca-Maïto }
8977df92966SHermès Bélusca-Maïto 
8986f15802aSHermès Bélusca-Maïto static
8996f15802aSHermès Bélusca-Maïto VOID
InitPartitionDeviceName(_Inout_ PPARTENTRY PartEntry)9006f15802aSHermès Bélusca-Maïto InitPartitionDeviceName(
9016f15802aSHermès Bélusca-Maïto     _Inout_ PPARTENTRY PartEntry)
9026f15802aSHermès Bélusca-Maïto {
9036f15802aSHermès Bélusca-Maïto     NTSTATUS Status;
9046f15802aSHermès Bélusca-Maïto 
9056f15802aSHermès Bélusca-Maïto     /* Ignore if this is a container partition */
9066f15802aSHermès Bélusca-Maïto     if (IsContainerPartition(PartEntry->PartitionType))
9076f15802aSHermès Bélusca-Maïto         return;
9086f15802aSHermès Bélusca-Maïto     ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
9096f15802aSHermès Bélusca-Maïto 
9106f15802aSHermès Bélusca-Maïto     /* Make a device name for the partition */
9116f15802aSHermès Bélusca-Maïto     Status = RtlStringCchPrintfW(PartEntry->DeviceName,
9126f15802aSHermès Bélusca-Maïto                                  _countof(PartEntry->DeviceName),
9136f15802aSHermès Bélusca-Maïto                                  L"\\Device\\Harddisk%lu\\Partition%lu",
9146f15802aSHermès Bélusca-Maïto                                  PartEntry->DiskEntry->DiskNumber,
9156f15802aSHermès Bélusca-Maïto                                  PartEntry->PartitionNumber);
9166f15802aSHermès Bélusca-Maïto     ASSERT(NT_SUCCESS(Status));
9176f15802aSHermès Bélusca-Maïto }
9186f15802aSHermès Bélusca-Maïto 
9196f15802aSHermès Bélusca-Maïto static
9206f15802aSHermès Bélusca-Maïto VOID
InitVolumeDeviceName(_Inout_ PVOLENTRY Volume)9216f15802aSHermès Bélusca-Maïto InitVolumeDeviceName(
9226f15802aSHermès Bélusca-Maïto     _Inout_ PVOLENTRY Volume)
9236f15802aSHermès Bélusca-Maïto {
9246f15802aSHermès Bélusca-Maïto     NTSTATUS Status;
9256f15802aSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
9266f15802aSHermès Bélusca-Maïto 
9276f15802aSHermès Bélusca-Maïto     /* If we already have a volume device name, do nothing more */
9286f15802aSHermès Bélusca-Maïto     if (*Volume->Info.DeviceName)
9296f15802aSHermès Bélusca-Maïto         return;
9306f15802aSHermès Bélusca-Maïto 
9316f15802aSHermès Bélusca-Maïto     /* Use the partition device name as a temporary volume device name */
9326f15802aSHermès Bélusca-Maïto     // TODO: Ask instead the MOUNTMGR for the name.
9336f15802aSHermès Bélusca-Maïto     PartEntry = Volume->PartEntry;
9346f15802aSHermès Bélusca-Maïto     ASSERT(PartEntry);
9356f15802aSHermès Bélusca-Maïto     ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
9366f15802aSHermès Bélusca-Maïto 
9376f15802aSHermès Bélusca-Maïto     /* Copy the volume device name */
9386f15802aSHermès Bélusca-Maïto     Status = RtlStringCchCopyW(Volume->Info.DeviceName,
9396f15802aSHermès Bélusca-Maïto                                _countof(Volume->Info.DeviceName),
9406f15802aSHermès Bélusca-Maïto                                PartEntry->DeviceName);
9416f15802aSHermès Bélusca-Maïto     ASSERT(NT_SUCCESS(Status));
9426f15802aSHermès Bélusca-Maïto }
9436f15802aSHermès Bélusca-Maïto 
9446f15802aSHermès Bélusca-Maïto static
9456f15802aSHermès Bélusca-Maïto PVOLENTRY
InitVolume(_In_ PPARTLIST List,_In_opt_ PPARTENTRY PartEntry)9466f15802aSHermès Bélusca-Maïto InitVolume(
9476f15802aSHermès Bélusca-Maïto     _In_ PPARTLIST List,
9486f15802aSHermès Bélusca-Maïto     _In_opt_ PPARTENTRY PartEntry)
9496f15802aSHermès Bélusca-Maïto {
9506f15802aSHermès Bélusca-Maïto     PVOLENTRY Volume;
9516f15802aSHermès Bélusca-Maïto 
9526f15802aSHermès Bélusca-Maïto     Volume = RtlAllocateHeap(ProcessHeap,
9536f15802aSHermès Bélusca-Maïto                              HEAP_ZERO_MEMORY,
9546f15802aSHermès Bélusca-Maïto                              sizeof(VOLENTRY));
9556f15802aSHermès Bélusca-Maïto     if (!Volume)
9566f15802aSHermès Bélusca-Maïto         return NULL;
9576f15802aSHermès Bélusca-Maïto 
9586f15802aSHermès Bélusca-Maïto     /* Reset some volume information */
9596f15802aSHermès Bélusca-Maïto 
9606f15802aSHermès Bélusca-Maïto     /* No device name for now */
9616f15802aSHermès Bélusca-Maïto     Volume->Info.DeviceName[0] = UNICODE_NULL;
9626f15802aSHermès Bélusca-Maïto     // Volume->Info.VolumeName[0] = UNICODE_NULL;
9636f15802aSHermès Bélusca-Maïto 
9646f15802aSHermès Bélusca-Maïto     /* Initialize the volume letter and label */
9656f15802aSHermès Bélusca-Maïto     Volume->Info.DriveLetter = UNICODE_NULL;
9666f15802aSHermès Bélusca-Maïto     Volume->Info.VolumeLabel[0] = UNICODE_NULL;
9676f15802aSHermès Bélusca-Maïto 
9686f15802aSHermès Bélusca-Maïto     /* Specify the volume as initially unformatted */
9696f15802aSHermès Bélusca-Maïto     Volume->Info.FileSystem[0] = UNICODE_NULL;
9706f15802aSHermès Bélusca-Maïto     Volume->FormatState = Unformatted;
9716f15802aSHermès Bélusca-Maïto     Volume->NeedsCheck = FALSE;
9726f15802aSHermès Bélusca-Maïto     Volume->New = TRUE;
9736f15802aSHermès Bélusca-Maïto 
9746f15802aSHermès Bélusca-Maïto     if (PartEntry)
9756f15802aSHermès Bélusca-Maïto     {
9766f15802aSHermès Bélusca-Maïto         ASSERT(PartEntry->DiskEntry->PartList == List);
9776f15802aSHermès Bélusca-Maïto         Volume->PartEntry = PartEntry;
9786f15802aSHermès Bélusca-Maïto     }
9796f15802aSHermès Bélusca-Maïto     InsertTailList(&List->VolumesList, &Volume->ListEntry);
9806f15802aSHermès Bélusca-Maïto     return Volume;
9816f15802aSHermès Bélusca-Maïto }
9827df92966SHermès Bélusca-Maïto 
9836f19c83bSHermès Bélusca-Maïto static
9846f19c83bSHermès Bélusca-Maïto VOID
AddPartitionToDisk(IN ULONG DiskNumber,IN PDISKENTRY DiskEntry,IN ULONG PartitionIndex,IN BOOLEAN LogicalPartition)9856f19c83bSHermès Bélusca-Maïto AddPartitionToDisk(
9866f19c83bSHermès Bélusca-Maïto     IN ULONG DiskNumber,
9876f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry,
9886f19c83bSHermès Bélusca-Maïto     IN ULONG PartitionIndex,
9896f19c83bSHermès Bélusca-Maïto     IN BOOLEAN LogicalPartition)
9906f19c83bSHermès Bélusca-Maïto {
9916f19c83bSHermès Bélusca-Maïto     PPARTITION_INFORMATION PartitionInfo;
9926f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
9936f19c83bSHermès Bélusca-Maïto 
9946f19c83bSHermès Bélusca-Maïto     PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
9956f19c83bSHermès Bélusca-Maïto 
9966f15802aSHermès Bélusca-Maïto     /* Ignore empty partitions */
9976f15802aSHermès Bélusca-Maïto     if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED)
9986f19c83bSHermès Bélusca-Maïto         return;
9996f15802aSHermès Bélusca-Maïto     /* Request must be consistent, though! */
10006f15802aSHermès Bélusca-Maïto     ASSERT(!(LogicalPartition && IsContainerPartition(PartitionInfo->PartitionType)));
10016f19c83bSHermès Bélusca-Maïto 
10026f19c83bSHermès Bélusca-Maïto     PartEntry = RtlAllocateHeap(ProcessHeap,
10036f19c83bSHermès Bélusca-Maïto                                 HEAP_ZERO_MEMORY,
10046f19c83bSHermès Bélusca-Maïto                                 sizeof(PARTENTRY));
10056f15802aSHermès Bélusca-Maïto     if (!PartEntry)
10066f19c83bSHermès Bélusca-Maïto         return;
10076f19c83bSHermès Bélusca-Maïto 
10086f19c83bSHermès Bélusca-Maïto     PartEntry->DiskEntry = DiskEntry;
10096f19c83bSHermès Bélusca-Maïto 
10106f19c83bSHermès Bélusca-Maïto     PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
10116f19c83bSHermès Bélusca-Maïto     PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
10126f19c83bSHermès Bélusca-Maïto 
10136f19c83bSHermès Bélusca-Maïto     PartEntry->BootIndicator = PartitionInfo->BootIndicator;
10146f19c83bSHermès Bélusca-Maïto     PartEntry->PartitionType = PartitionInfo->PartitionType;
10156f19c83bSHermès Bélusca-Maïto 
10166f19c83bSHermès Bélusca-Maïto     PartEntry->LogicalPartition = LogicalPartition;
10176f19c83bSHermès Bélusca-Maïto     PartEntry->IsPartitioned = TRUE;
10187df92966SHermès Bélusca-Maïto     PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
10196f19c83bSHermès Bélusca-Maïto     PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
10206f19c83bSHermès Bélusca-Maïto     PartEntry->PartitionIndex = PartitionIndex;
10216f15802aSHermès Bélusca-Maïto     InitPartitionDeviceName(PartEntry);
10226f19c83bSHermès Bélusca-Maïto 
10236f15802aSHermès Bélusca-Maïto     /* No volume initially */
10246f15802aSHermès Bélusca-Maïto     PartEntry->Volume = NULL;
1025c1fbc2d6SHermès Bélusca-Maïto 
10266f19c83bSHermès Bélusca-Maïto     if (IsContainerPartition(PartEntry->PartitionType))
10276f19c83bSHermès Bélusca-Maïto     {
10286f15802aSHermès Bélusca-Maïto         if (!LogicalPartition && DiskEntry->ExtendedPartition == NULL)
10296f19c83bSHermès Bélusca-Maïto             DiskEntry->ExtendedPartition = PartEntry;
10306f19c83bSHermès Bélusca-Maïto     }
10316f15802aSHermès Bélusca-Maïto     else if (IsRecognizedPartition(PartEntry->PartitionType) || // PartitionInfo->RecognizedPartition
10326f15802aSHermès Bélusca-Maïto              IsOEMPartition(PartEntry->PartitionType))
10336f19c83bSHermès Bélusca-Maïto     {
10346f15802aSHermès Bélusca-Maïto         PVOLENTRY Volume;
10356f15802aSHermès Bélusca-Maïto         NTSTATUS Status;
10367df92966SHermès Bélusca-Maïto 
10376f15802aSHermès Bélusca-Maïto         ASSERT(PartEntry->PartitionNumber != 0);
1038f41750abSHermès Bélusca-Maïto 
10396f15802aSHermès Bélusca-Maïto         /* The PARTMGR should have notified the MOUNTMGR that a volume
10406f15802aSHermès Bélusca-Maïto          * associated with this partition had to be created */
10416f15802aSHermès Bélusca-Maïto         Volume = InitVolume(DiskEntry->PartList, PartEntry);
10426f15802aSHermès Bélusca-Maïto         if (!Volume)
10436f15802aSHermès Bélusca-Maïto         {
10446f15802aSHermès Bélusca-Maïto             DPRINT1("Couldn't allocate a volume for device '%S'\n",
10456f15802aSHermès Bélusca-Maïto                     PartEntry->DeviceName);
10466f15802aSHermès Bélusca-Maïto             goto SkipVolume;
10476f15802aSHermès Bélusca-Maïto         }
10486f15802aSHermès Bélusca-Maïto         PartEntry->Volume = Volume;
10496f15802aSHermès Bélusca-Maïto         InitVolumeDeviceName(Volume);
10506f15802aSHermès Bélusca-Maïto         Volume->New = FALSE;
1051f41750abSHermès Bélusca-Maïto 
10526f15802aSHermès Bélusca-Maïto         /* Attach and mount the volume */
10536f15802aSHermès Bélusca-Maïto         Status = MountVolume(&Volume->Info, PartEntry->PartitionType);
1054c1fbc2d6SHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
1055f41750abSHermès Bélusca-Maïto         {
10566f15802aSHermès Bélusca-Maïto             DPRINT1("Failed to mount volume '%S', Status 0x%08lx\n",
10576f15802aSHermès Bélusca-Maïto                     Volume->Info.DeviceName, Status);
1058c1fbc2d6SHermès Bélusca-Maïto         }
1059c1fbc2d6SHermès Bélusca-Maïto 
10606f15802aSHermès Bélusca-Maïto         //
10616f15802aSHermès Bélusca-Maïto         // FIXME: TEMP Backward-compatibility: Set the FormatState
10626f15802aSHermès Bélusca-Maïto         // flag in accordance with the FileSystem volume value.
10636f15802aSHermès Bélusca-Maïto         //
1064626c654aSHermès Bélusca-Maïto         /*
10656f15802aSHermès Bélusca-Maïto          * MountVolume() determines whether the given volume is actually
10666f15802aSHermès Bélusca-Maïto          * unformatted, if it was mounted with RawFS and the partition
10676f15802aSHermès Bélusca-Maïto          * type has specific values for FAT volumes. If so, the volume
10686f15802aSHermès Bélusca-Maïto          * stays mounted with RawFS (the FileSystem is "RAW"). However,
10696f15802aSHermès Bélusca-Maïto          * if the partition type has different values, the volume is
10706f15802aSHermès Bélusca-Maïto          * considered as having an unknown format (it may or may not be
10716f15802aSHermès Bélusca-Maïto          * formatted) and the FileSystem value has been emptied.
1072626c654aSHermès Bélusca-Maïto          */
10736f15802aSHermès Bélusca-Maïto         if (IsUnknown(&Volume->Info))
10746f15802aSHermès Bélusca-Maïto             Volume->FormatState = UnknownFormat;
10756f15802aSHermès Bélusca-Maïto         else if (IsUnformatted(&Volume->Info)) // FileSystem is "RAW"
10766f15802aSHermès Bélusca-Maïto             Volume->FormatState = Unformatted;
10776f15802aSHermès Bélusca-Maïto         else // !IsUnknown && !IsUnformatted == IsFormatted
10786f15802aSHermès Bélusca-Maïto             Volume->FormatState = Formatted;
10796f15802aSHermès Bélusca-Maïto SkipVolume:;
1080626c654aSHermès Bélusca-Maïto     }
1081c1fbc2d6SHermès Bélusca-Maïto     else
1082626c654aSHermès Bélusca-Maïto     {
10836f15802aSHermès Bélusca-Maïto         /* Unknown partition (may or may not be actually formatted):
10846f15802aSHermès Bélusca-Maïto          * the partition is hidden, hence no volume */
10856f15802aSHermès Bélusca-Maïto         DPRINT1("Disk %lu Partition %lu is not recognized (Type 0x%02x)\n",
10866f15802aSHermès Bélusca-Maïto                 DiskEntry->DiskNumber, PartEntry->PartitionNumber,
10876f15802aSHermès Bélusca-Maïto                 PartEntry->PartitionType);
1088f41750abSHermès Bélusca-Maïto     }
1089f41750abSHermès Bélusca-Maïto 
10907df92966SHermès Bélusca-Maïto     InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
10916f19c83bSHermès Bélusca-Maïto }
10926f19c83bSHermès Bélusca-Maïto 
10936f19c83bSHermès Bélusca-Maïto static
10946f19c83bSHermès Bélusca-Maïto VOID
ScanForUnpartitionedDiskSpace(IN PDISKENTRY DiskEntry)10956f19c83bSHermès Bélusca-Maïto ScanForUnpartitionedDiskSpace(
10966f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
10976f19c83bSHermès Bélusca-Maïto {
10987df92966SHermès Bélusca-Maïto     ULONGLONG StartSector;
10997df92966SHermès Bélusca-Maïto     ULONGLONG SectorCount;
11006f19c83bSHermès Bélusca-Maïto     ULONGLONG LastStartSector;
11016f19c83bSHermès Bélusca-Maïto     ULONGLONG LastSectorCount;
11026f19c83bSHermès Bélusca-Maïto     ULONGLONG LastUnusedSectorCount;
11036f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
11046f19c83bSHermès Bélusca-Maïto     PPARTENTRY NewPartEntry;
11056f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
11066f19c83bSHermès Bélusca-Maïto 
11076f19c83bSHermès Bélusca-Maïto     DPRINT("ScanForUnpartitionedDiskSpace()\n");
11086f19c83bSHermès Bélusca-Maïto 
11096f19c83bSHermès Bélusca-Maïto     if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
11106f19c83bSHermès Bélusca-Maïto     {
11116f19c83bSHermès Bélusca-Maïto         DPRINT1("No primary partition!\n");
11126f19c83bSHermès Bélusca-Maïto 
11136f19c83bSHermès Bélusca-Maïto         /* Create a partition entry that represents the empty disk */
11146f19c83bSHermès Bélusca-Maïto 
111526408b02SPierre Schweitzer         if (DiskEntry->SectorAlignment < 2048)
11167df92966SHermès Bélusca-Maïto             StartSector = 2048ULL;
111726408b02SPierre Schweitzer         else
11187df92966SHermès Bélusca-Maïto             StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
11197df92966SHermès Bélusca-Maïto         SectorCount = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - StartSector;
11206f19c83bSHermès Bélusca-Maïto 
11217df92966SHermès Bélusca-Maïto         NewPartEntry = CreateInsertBlankRegion(DiskEntry,
11227df92966SHermès Bélusca-Maïto                                                &DiskEntry->PrimaryPartListHead,
11237df92966SHermès Bélusca-Maïto                                                StartSector,
11247df92966SHermès Bélusca-Maïto                                                SectorCount,
11257df92966SHermès Bélusca-Maïto                                                FALSE);
112699f0937fSHermès Bélusca-Maïto         if (!NewPartEntry)
11277df92966SHermès Bélusca-Maïto             DPRINT1("Failed to create a new empty region for full disk space!\n");
11286f19c83bSHermès Bélusca-Maïto 
11296f19c83bSHermès Bélusca-Maïto         return;
11306f19c83bSHermès Bélusca-Maïto     }
11316f19c83bSHermès Bélusca-Maïto 
11326f19c83bSHermès Bélusca-Maïto     /* Start partition at head 1, cylinder 0 */
113326408b02SPierre Schweitzer     if (DiskEntry->SectorAlignment < 2048)
113426408b02SPierre Schweitzer         LastStartSector = 2048ULL;
113526408b02SPierre Schweitzer     else
11367df92966SHermès Bélusca-Maïto         LastStartSector = (ULONGLONG)DiskEntry->SectorAlignment;
11376f19c83bSHermès Bélusca-Maïto     LastSectorCount = 0ULL;
11386f19c83bSHermès Bélusca-Maïto     LastUnusedSectorCount = 0ULL;
11396f19c83bSHermès Bélusca-Maïto 
11408bed4adfSHermès Bélusca-Maïto     for (Entry = DiskEntry->PrimaryPartListHead.Flink;
11418bed4adfSHermès Bélusca-Maïto          Entry != &DiskEntry->PrimaryPartListHead;
11428bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
11436f19c83bSHermès Bélusca-Maïto     {
11446f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
11456f19c83bSHermès Bélusca-Maïto 
11466f19c83bSHermès Bélusca-Maïto         if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
11476f19c83bSHermès Bélusca-Maïto             PartEntry->SectorCount.QuadPart != 0ULL)
11486f19c83bSHermès Bélusca-Maïto         {
11496f19c83bSHermès Bélusca-Maïto             LastUnusedSectorCount =
11506f19c83bSHermès Bélusca-Maïto                 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
11516f19c83bSHermès Bélusca-Maïto 
11526f19c83bSHermès Bélusca-Maïto             if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
11536f19c83bSHermès Bélusca-Maïto                 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
11546f19c83bSHermès Bélusca-Maïto             {
11556f19c83bSHermès Bélusca-Maïto                 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
11566f19c83bSHermès Bélusca-Maïto 
11577df92966SHermès Bélusca-Maïto                 StartSector = LastStartSector + LastSectorCount;
11587df92966SHermès Bélusca-Maïto                 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
11596f19c83bSHermès Bélusca-Maïto 
11606f19c83bSHermès Bélusca-Maïto                 /* Insert the table into the list */
11617df92966SHermès Bélusca-Maïto                 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
11627df92966SHermès Bélusca-Maïto                                                        &PartEntry->ListEntry,
11637df92966SHermès Bélusca-Maïto                                                        StartSector,
11647df92966SHermès Bélusca-Maïto                                                        SectorCount,
11657df92966SHermès Bélusca-Maïto                                                        FALSE);
116699f0937fSHermès Bélusca-Maïto                 if (!NewPartEntry)
11677df92966SHermès Bélusca-Maïto                 {
11687df92966SHermès Bélusca-Maïto                     DPRINT1("Failed to create a new empty region for disk space!\n");
11697df92966SHermès Bélusca-Maïto                     return;
11707df92966SHermès Bélusca-Maïto                 }
11716f19c83bSHermès Bélusca-Maïto             }
11726f19c83bSHermès Bélusca-Maïto 
11736f19c83bSHermès Bélusca-Maïto             LastStartSector = PartEntry->StartSector.QuadPart;
11746f19c83bSHermès Bélusca-Maïto             LastSectorCount = PartEntry->SectorCount.QuadPart;
11756f19c83bSHermès Bélusca-Maïto         }
11766f19c83bSHermès Bélusca-Maïto     }
11776f19c83bSHermès Bélusca-Maïto 
11786f19c83bSHermès Bélusca-Maïto     /* Check for trailing unpartitioned disk space */
11796f19c83bSHermès Bélusca-Maïto     if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
11806f19c83bSHermès Bélusca-Maïto     {
11816f19c83bSHermès Bélusca-Maïto         LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
11826f19c83bSHermès Bélusca-Maïto 
11836f19c83bSHermès Bélusca-Maïto         if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
11846f19c83bSHermès Bélusca-Maïto         {
11856f19c83bSHermès Bélusca-Maïto             DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
11866f19c83bSHermès Bélusca-Maïto 
11877df92966SHermès Bélusca-Maïto             StartSector = LastStartSector + LastSectorCount;
11887df92966SHermès Bélusca-Maïto             SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
11896f19c83bSHermès Bélusca-Maïto 
11906f19c83bSHermès Bélusca-Maïto             /* Append the table to the list */
11917df92966SHermès Bélusca-Maïto             NewPartEntry = CreateInsertBlankRegion(DiskEntry,
11927df92966SHermès Bélusca-Maïto                                                    &DiskEntry->PrimaryPartListHead,
11937df92966SHermès Bélusca-Maïto                                                    StartSector,
11947df92966SHermès Bélusca-Maïto                                                    SectorCount,
11957df92966SHermès Bélusca-Maïto                                                    FALSE);
119699f0937fSHermès Bélusca-Maïto             if (!NewPartEntry)
11977df92966SHermès Bélusca-Maïto             {
11987df92966SHermès Bélusca-Maïto                 DPRINT1("Failed to create a new empty region for trailing disk space!\n");
11997df92966SHermès Bélusca-Maïto                 return;
12007df92966SHermès Bélusca-Maïto             }
12016f19c83bSHermès Bélusca-Maïto         }
12026f19c83bSHermès Bélusca-Maïto     }
12036f19c83bSHermès Bélusca-Maïto 
12046f19c83bSHermès Bélusca-Maïto     if (DiskEntry->ExtendedPartition != NULL)
12056f19c83bSHermès Bélusca-Maïto     {
12066f19c83bSHermès Bélusca-Maïto         if (IsListEmpty(&DiskEntry->LogicalPartListHead))
12076f19c83bSHermès Bélusca-Maïto         {
12086f19c83bSHermès Bélusca-Maïto             DPRINT1("No logical partition!\n");
12096f19c83bSHermès Bélusca-Maïto 
12106f19c83bSHermès Bélusca-Maïto             /* Create a partition entry that represents the empty extended partition */
121199f0937fSHermès Bélusca-Maïto             AddLogicalDiskSpace(DiskEntry);
12126f19c83bSHermès Bélusca-Maïto             return;
12136f19c83bSHermès Bélusca-Maïto         }
12146f19c83bSHermès Bélusca-Maïto 
12156f19c83bSHermès Bélusca-Maïto         /* Start partition at head 1, cylinder 0 */
12166f19c83bSHermès Bélusca-Maïto         LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
12176f19c83bSHermès Bélusca-Maïto         LastSectorCount = 0ULL;
12186f19c83bSHermès Bélusca-Maïto         LastUnusedSectorCount = 0ULL;
12196f19c83bSHermès Bélusca-Maïto 
12208bed4adfSHermès Bélusca-Maïto         for (Entry = DiskEntry->LogicalPartListHead.Flink;
12218bed4adfSHermès Bélusca-Maïto              Entry != &DiskEntry->LogicalPartListHead;
12228bed4adfSHermès Bélusca-Maïto              Entry = Entry->Flink)
12236f19c83bSHermès Bélusca-Maïto         {
12246f19c83bSHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
12256f19c83bSHermès Bélusca-Maïto 
12266f19c83bSHermès Bélusca-Maïto             if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
12276f19c83bSHermès Bélusca-Maïto                 PartEntry->SectorCount.QuadPart != 0ULL)
12286f19c83bSHermès Bélusca-Maïto             {
12296f19c83bSHermès Bélusca-Maïto                 LastUnusedSectorCount =
12306f19c83bSHermès Bélusca-Maïto                     PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
12316f19c83bSHermès Bélusca-Maïto 
12326f19c83bSHermès Bélusca-Maïto                 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
12336f19c83bSHermès Bélusca-Maïto                     LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
12346f19c83bSHermès Bélusca-Maïto                 {
12356f19c83bSHermès Bélusca-Maïto                     DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
12366f19c83bSHermès Bélusca-Maïto 
12377df92966SHermès Bélusca-Maïto                     StartSector = LastStartSector + LastSectorCount;
12387df92966SHermès Bélusca-Maïto                     SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
12396f19c83bSHermès Bélusca-Maïto 
12406f19c83bSHermès Bélusca-Maïto                     /* Insert the table into the list */
12417df92966SHermès Bélusca-Maïto                     NewPartEntry = CreateInsertBlankRegion(DiskEntry,
12427df92966SHermès Bélusca-Maïto                                                            &PartEntry->ListEntry,
12437df92966SHermès Bélusca-Maïto                                                            StartSector,
12447df92966SHermès Bélusca-Maïto                                                            SectorCount,
12457df92966SHermès Bélusca-Maïto                                                            TRUE);
124699f0937fSHermès Bélusca-Maïto                     if (!NewPartEntry)
12477df92966SHermès Bélusca-Maïto                     {
12487df92966SHermès Bélusca-Maïto                         DPRINT1("Failed to create a new empty region for extended partition space!\n");
12497df92966SHermès Bélusca-Maïto                         return;
12507df92966SHermès Bélusca-Maïto                     }
12516f19c83bSHermès Bélusca-Maïto                 }
12526f19c83bSHermès Bélusca-Maïto 
12536f19c83bSHermès Bélusca-Maïto                 LastStartSector = PartEntry->StartSector.QuadPart;
12546f19c83bSHermès Bélusca-Maïto                 LastSectorCount = PartEntry->SectorCount.QuadPart;
12556f19c83bSHermès Bélusca-Maïto             }
12566f19c83bSHermès Bélusca-Maïto         }
12576f19c83bSHermès Bélusca-Maïto 
12586f19c83bSHermès Bélusca-Maïto         /* Check for trailing unpartitioned disk space */
12596f19c83bSHermès Bélusca-Maïto         if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
12606f19c83bSHermès Bélusca-Maïto         {
12617df92966SHermès Bélusca-Maïto             LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart +
12627df92966SHermès Bélusca-Maïto                                               DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
12637df92966SHermès Bélusca-Maïto                                               DiskEntry->SectorAlignment);
12646f19c83bSHermès Bélusca-Maïto 
12656f19c83bSHermès Bélusca-Maïto             if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
12666f19c83bSHermès Bélusca-Maïto             {
12676f19c83bSHermès Bélusca-Maïto                 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
12686f19c83bSHermès Bélusca-Maïto 
12697df92966SHermès Bélusca-Maïto                 StartSector = LastStartSector + LastSectorCount;
12707df92966SHermès Bélusca-Maïto                 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
12716f19c83bSHermès Bélusca-Maïto 
12726f19c83bSHermès Bélusca-Maïto                 /* Append the table to the list */
12737df92966SHermès Bélusca-Maïto                 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
12747df92966SHermès Bélusca-Maïto                                                        &DiskEntry->LogicalPartListHead,
12757df92966SHermès Bélusca-Maïto                                                        StartSector,
12767df92966SHermès Bélusca-Maïto                                                        SectorCount,
12777df92966SHermès Bélusca-Maïto                                                        TRUE);
127899f0937fSHermès Bélusca-Maïto                 if (!NewPartEntry)
12797df92966SHermès Bélusca-Maïto                 {
12807df92966SHermès Bélusca-Maïto                     DPRINT1("Failed to create a new empty region for extended partition space!\n");
12817df92966SHermès Bélusca-Maïto                     return;
12827df92966SHermès Bélusca-Maïto                 }
12836f19c83bSHermès Bélusca-Maïto             }
12846f19c83bSHermès Bélusca-Maïto         }
12856f19c83bSHermès Bélusca-Maïto     }
12866f19c83bSHermès Bélusca-Maïto 
12876f19c83bSHermès Bélusca-Maïto     DPRINT("ScanForUnpartitionedDiskSpace() done\n");
12886f19c83bSHermès Bélusca-Maïto }
12896f19c83bSHermès Bélusca-Maïto 
12906f19c83bSHermès Bélusca-Maïto static
12916f19c83bSHermès Bélusca-Maïto VOID
SetDiskSignature(IN PPARTLIST List,IN PDISKENTRY DiskEntry)12926f19c83bSHermès Bélusca-Maïto SetDiskSignature(
12936f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List,
12946f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
12956f19c83bSHermès Bélusca-Maïto {
12966f19c83bSHermès Bélusca-Maïto     LARGE_INTEGER SystemTime;
12976f19c83bSHermès Bélusca-Maïto     TIME_FIELDS TimeFields;
12986f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry2;
12996f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry2;
13006f19c83bSHermès Bélusca-Maïto     PUCHAR Buffer;
13016f19c83bSHermès Bélusca-Maïto 
1302a3168373SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1303a3168373SHermès Bélusca-Maïto     {
1304a3168373SHermès Bélusca-Maïto         DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1305a3168373SHermès Bélusca-Maïto         return;
1306a3168373SHermès Bélusca-Maïto     }
1307a3168373SHermès Bélusca-Maïto 
13086f19c83bSHermès Bélusca-Maïto     Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
13096f19c83bSHermès Bélusca-Maïto 
13106f19c83bSHermès Bélusca-Maïto     while (TRUE)
13116f19c83bSHermès Bélusca-Maïto     {
13126f19c83bSHermès Bélusca-Maïto         NtQuerySystemTime(&SystemTime);
13136f19c83bSHermès Bélusca-Maïto         RtlTimeToTimeFields(&SystemTime, &TimeFields);
13146f19c83bSHermès Bélusca-Maïto 
13156f19c83bSHermès Bélusca-Maïto         Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
13166f19c83bSHermès Bélusca-Maïto         Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
13176f19c83bSHermès Bélusca-Maïto         Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
13186f19c83bSHermès Bélusca-Maïto         Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
13196f19c83bSHermès Bélusca-Maïto 
13206f19c83bSHermès Bélusca-Maïto         if (DiskEntry->LayoutBuffer->Signature == 0)
13216f19c83bSHermès Bélusca-Maïto         {
13226f19c83bSHermès Bélusca-Maïto             continue;
13236f19c83bSHermès Bélusca-Maïto         }
13246f19c83bSHermès Bélusca-Maïto 
13256f19c83bSHermès Bélusca-Maïto         /* Check if the signature already exist */
13266f19c83bSHermès Bélusca-Maïto         /* FIXME:
13276f19c83bSHermès Bélusca-Maïto          *   Check also signatures from disks, which are
13286f15802aSHermès Bélusca-Maïto          *   not visible (bootable) by the BIOS.
13296f19c83bSHermès Bélusca-Maïto          */
13308bed4adfSHermès Bélusca-Maïto         for (Entry2 = List->DiskListHead.Flink;
13318bed4adfSHermès Bélusca-Maïto              Entry2 != &List->DiskListHead;
13328bed4adfSHermès Bélusca-Maïto              Entry2 = Entry2->Flink)
13336f19c83bSHermès Bélusca-Maïto         {
13346f19c83bSHermès Bélusca-Maïto             DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
13356f19c83bSHermès Bélusca-Maïto 
1336a3168373SHermès Bélusca-Maïto             if (DiskEntry2->DiskStyle == PARTITION_STYLE_GPT)
1337a3168373SHermès Bélusca-Maïto             {
1338a3168373SHermès Bélusca-Maïto                 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1339a3168373SHermès Bélusca-Maïto                 continue;
1340a3168373SHermès Bélusca-Maïto             }
1341a3168373SHermès Bélusca-Maïto 
13426f19c83bSHermès Bélusca-Maïto             if (DiskEntry != DiskEntry2 &&
13436f19c83bSHermès Bélusca-Maïto                 DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
13446f19c83bSHermès Bélusca-Maïto                 break;
13456f19c83bSHermès Bélusca-Maïto         }
13466f19c83bSHermès Bélusca-Maïto 
13476f19c83bSHermès Bélusca-Maïto         if (Entry2 == &List->DiskListHead)
13486f19c83bSHermès Bélusca-Maïto             break;
13496f19c83bSHermès Bélusca-Maïto     }
13506f19c83bSHermès Bélusca-Maïto }
13516f19c83bSHermès Bélusca-Maïto 
13526f19c83bSHermès Bélusca-Maïto static
13536f19c83bSHermès Bélusca-Maïto VOID
UpdateDiskSignatures(IN PPARTLIST List)13546f19c83bSHermès Bélusca-Maïto UpdateDiskSignatures(
13556f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List)
13566f19c83bSHermès Bélusca-Maïto {
13576f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
13586f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
13596f19c83bSHermès Bélusca-Maïto 
1360a3168373SHermès Bélusca-Maïto     /* Update each disk */
13618bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
13628bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
13638bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
13646f19c83bSHermès Bélusca-Maïto     {
13656f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
13666f19c83bSHermès Bélusca-Maïto 
1367a3168373SHermès Bélusca-Maïto         if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1368a3168373SHermès Bélusca-Maïto         {
1369a3168373SHermès Bélusca-Maïto             DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1370a3168373SHermès Bélusca-Maïto             continue;
1371a3168373SHermès Bélusca-Maïto         }
1372a3168373SHermès Bélusca-Maïto 
13736f19c83bSHermès Bélusca-Maïto         if (DiskEntry->LayoutBuffer &&
13746f19c83bSHermès Bélusca-Maïto             DiskEntry->LayoutBuffer->Signature == 0)
13756f19c83bSHermès Bélusca-Maïto         {
13766f19c83bSHermès Bélusca-Maïto             SetDiskSignature(List, DiskEntry);
13776f19c83bSHermès Bélusca-Maïto             DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
13786f19c83bSHermès Bélusca-Maïto         }
13796f19c83bSHermès Bélusca-Maïto     }
13806f19c83bSHermès Bélusca-Maïto }
13816f19c83bSHermès Bélusca-Maïto 
13826f19c83bSHermès Bélusca-Maïto static
13836f19c83bSHermès Bélusca-Maïto VOID
UpdateHwDiskNumbers(IN PPARTLIST List)138447a1acedSHermès Bélusca-Maïto UpdateHwDiskNumbers(
138547a1acedSHermès Bélusca-Maïto     IN PPARTLIST List)
138647a1acedSHermès Bélusca-Maïto {
138747a1acedSHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
138847a1acedSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry;
138947a1acedSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
139047a1acedSHermès Bélusca-Maïto     ULONG HwAdapterNumber = 0;
139147a1acedSHermès Bélusca-Maïto     ULONG HwControllerNumber = 0;
139247a1acedSHermès Bélusca-Maïto     ULONG RemovableDiskCount = 0;
139347a1acedSHermès Bélusca-Maïto 
139447a1acedSHermès Bélusca-Maïto     /*
139547a1acedSHermès Bélusca-Maïto      * Enumerate the disks recognized by the BIOS and recompute the disk
139647a1acedSHermès Bélusca-Maïto      * numbers on the system when *ALL* removable disks are not connected.
139747a1acedSHermès Bélusca-Maïto      * The entries are inserted in increasing order of AdapterNumber,
139847a1acedSHermès Bélusca-Maïto      * ControllerNumber and DiskNumber.
139947a1acedSHermès Bélusca-Maïto      */
140047a1acedSHermès Bélusca-Maïto     for (ListEntry = List->BiosDiskListHead.Flink;
140147a1acedSHermès Bélusca-Maïto          ListEntry != &List->BiosDiskListHead;
140247a1acedSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
140347a1acedSHermès Bélusca-Maïto     {
140447a1acedSHermès Bélusca-Maïto         BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
140547a1acedSHermès Bélusca-Maïto         DiskEntry = BiosDiskEntry->DiskEntry;
140647a1acedSHermès Bélusca-Maïto 
140747a1acedSHermès Bélusca-Maïto         /*
140847a1acedSHermès Bélusca-Maïto          * If the adapter or controller numbers change, update them and reset
140947a1acedSHermès Bélusca-Maïto          * the number of removable disks on this adapter/controller.
141047a1acedSHermès Bélusca-Maïto          */
141147a1acedSHermès Bélusca-Maïto         if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
141247a1acedSHermès Bélusca-Maïto             HwControllerNumber != BiosDiskEntry->ControllerNumber)
141347a1acedSHermès Bélusca-Maïto         {
141447a1acedSHermès Bélusca-Maïto             HwAdapterNumber = BiosDiskEntry->AdapterNumber;
141547a1acedSHermès Bélusca-Maïto             HwControllerNumber = BiosDiskEntry->ControllerNumber;
141647a1acedSHermès Bélusca-Maïto             RemovableDiskCount = 0;
141747a1acedSHermès Bélusca-Maïto         }
141847a1acedSHermès Bélusca-Maïto 
141947a1acedSHermès Bélusca-Maïto         /* Adjust the actual hardware disk number */
142047a1acedSHermès Bélusca-Maïto         if (DiskEntry)
142147a1acedSHermès Bélusca-Maïto         {
142247a1acedSHermès Bélusca-Maïto             ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
142347a1acedSHermès Bélusca-Maïto 
142447a1acedSHermès Bélusca-Maïto             if (DiskEntry->MediaType == RemovableMedia)
142547a1acedSHermès Bélusca-Maïto             {
142647a1acedSHermès Bélusca-Maïto                 /* Increase the number of removable disks and set the disk number to zero */
142747a1acedSHermès Bélusca-Maïto                 ++RemovableDiskCount;
142847a1acedSHermès Bélusca-Maïto                 DiskEntry->HwFixedDiskNumber = 0;
142947a1acedSHermès Bélusca-Maïto             }
143047a1acedSHermès Bélusca-Maïto             else // if (DiskEntry->MediaType == FixedMedia)
143147a1acedSHermès Bélusca-Maïto             {
143247a1acedSHermès Bélusca-Maïto                 /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
143347a1acedSHermès Bélusca-Maïto                 DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
143447a1acedSHermès Bélusca-Maïto             }
143547a1acedSHermès Bélusca-Maïto         }
143647a1acedSHermès Bélusca-Maïto         else
143747a1acedSHermès Bélusca-Maïto         {
143847a1acedSHermès Bélusca-Maïto             DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
143947a1acedSHermès Bélusca-Maïto         }
144047a1acedSHermès Bélusca-Maïto     }
144147a1acedSHermès Bélusca-Maïto }
144247a1acedSHermès Bélusca-Maïto 
144347a1acedSHermès Bélusca-Maïto static
144447a1acedSHermès Bélusca-Maïto VOID
AddDiskToList(IN HANDLE FileHandle,IN ULONG DiskNumber,IN PPARTLIST List)14456f19c83bSHermès Bélusca-Maïto AddDiskToList(
14466f19c83bSHermès Bélusca-Maïto     IN HANDLE FileHandle,
14476f19c83bSHermès Bélusca-Maïto     IN ULONG DiskNumber,
14486f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List)
14496f19c83bSHermès Bélusca-Maïto {
14506f19c83bSHermès Bélusca-Maïto     DISK_GEOMETRY DiskGeometry;
14516f19c83bSHermès Bélusca-Maïto     SCSI_ADDRESS ScsiAddress;
14526f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
14536f19c83bSHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb;
14546f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
14556f19c83bSHermès Bélusca-Maïto     PPARTITION_SECTOR Mbr;
14566f19c83bSHermès Bélusca-Maïto     PULONG Buffer;
14576f19c83bSHermès Bélusca-Maïto     LARGE_INTEGER FileOffset;
14586f19c83bSHermès Bélusca-Maïto     WCHAR Identifier[20];
14596f19c83bSHermès Bélusca-Maïto     ULONG Checksum;
14606f19c83bSHermès Bélusca-Maïto     ULONG Signature;
14616f19c83bSHermès Bélusca-Maïto     ULONG i;
14626f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
14636f19c83bSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry;
14646f19c83bSHermès Bélusca-Maïto     ULONG LayoutBufferSize;
14656f19c83bSHermès Bélusca-Maïto     PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
14666f19c83bSHermès Bélusca-Maïto 
1467f41750abSHermès Bélusca-Maïto     /* Retrieve the drive geometry */
14686f19c83bSHermès Bélusca-Maïto     Status = NtDeviceIoControlFile(FileHandle,
14696f19c83bSHermès Bélusca-Maïto                                    NULL,
14706f19c83bSHermès Bélusca-Maïto                                    NULL,
14716f19c83bSHermès Bélusca-Maïto                                    NULL,
14726f19c83bSHermès Bélusca-Maïto                                    &Iosb,
14736f19c83bSHermès Bélusca-Maïto                                    IOCTL_DISK_GET_DRIVE_GEOMETRY,
14746f19c83bSHermès Bélusca-Maïto                                    NULL,
14756f19c83bSHermès Bélusca-Maïto                                    0,
14766f19c83bSHermès Bélusca-Maïto                                    &DiskGeometry,
1477f41750abSHermès Bélusca-Maïto                                    sizeof(DiskGeometry));
14786f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
14796f19c83bSHermès Bélusca-Maïto         return;
14806f19c83bSHermès Bélusca-Maïto 
14816f19c83bSHermès Bélusca-Maïto     if (DiskGeometry.MediaType != FixedMedia &&
14826f19c83bSHermès Bélusca-Maïto         DiskGeometry.MediaType != RemovableMedia)
14836f19c83bSHermès Bélusca-Maïto     {
14846f19c83bSHermès Bélusca-Maïto         return;
14856f19c83bSHermès Bélusca-Maïto     }
14866f19c83bSHermès Bélusca-Maïto 
1487f41750abSHermès Bélusca-Maïto     /*
1488f41750abSHermès Bélusca-Maïto      * FIXME: Here we suppose the disk is always SCSI. What if it is
1489f41750abSHermès Bélusca-Maïto      * of another type? To check this we need to retrieve the name of
1490f41750abSHermès Bélusca-Maïto      * the driver the disk device belongs to.
1491f41750abSHermès Bélusca-Maïto      */
14926f19c83bSHermès Bélusca-Maïto     Status = NtDeviceIoControlFile(FileHandle,
14936f19c83bSHermès Bélusca-Maïto                                    NULL,
14946f19c83bSHermès Bélusca-Maïto                                    NULL,
14956f19c83bSHermès Bélusca-Maïto                                    NULL,
14966f19c83bSHermès Bélusca-Maïto                                    &Iosb,
14976f19c83bSHermès Bélusca-Maïto                                    IOCTL_SCSI_GET_ADDRESS,
14986f19c83bSHermès Bélusca-Maïto                                    NULL,
14996f19c83bSHermès Bélusca-Maïto                                    0,
15006f19c83bSHermès Bélusca-Maïto                                    &ScsiAddress,
1501f41750abSHermès Bélusca-Maïto                                    sizeof(ScsiAddress));
15026f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
15036f19c83bSHermès Bélusca-Maïto         return;
15046f19c83bSHermès Bélusca-Maïto 
15056f19c83bSHermès Bélusca-Maïto     /*
15066f19c83bSHermès Bélusca-Maïto      * Check whether the disk is initialized, by looking at its MBR.
15076f19c83bSHermès Bélusca-Maïto      * NOTE that this must be generalized to GPT disks as well!
15086f19c83bSHermès Bélusca-Maïto      */
15096f19c83bSHermès Bélusca-Maïto 
15106f19c83bSHermès Bélusca-Maïto     Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
15116f19c83bSHermès Bélusca-Maïto                                              0,
15126f19c83bSHermès Bélusca-Maïto                                              DiskGeometry.BytesPerSector);
15136f19c83bSHermès Bélusca-Maïto     if (Mbr == NULL)
15146f19c83bSHermès Bélusca-Maïto         return;
15156f19c83bSHermès Bélusca-Maïto 
15166f19c83bSHermès Bélusca-Maïto     FileOffset.QuadPart = 0;
15176f19c83bSHermès Bélusca-Maïto     Status = NtReadFile(FileHandle,
15186f19c83bSHermès Bélusca-Maïto                         NULL,
15196f19c83bSHermès Bélusca-Maïto                         NULL,
15206f19c83bSHermès Bélusca-Maïto                         NULL,
15216f19c83bSHermès Bélusca-Maïto                         &Iosb,
15226f19c83bSHermès Bélusca-Maïto                         (PVOID)Mbr,
15236f19c83bSHermès Bélusca-Maïto                         DiskGeometry.BytesPerSector,
15246f19c83bSHermès Bélusca-Maïto                         &FileOffset,
15256f19c83bSHermès Bélusca-Maïto                         NULL);
15266f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
15276f19c83bSHermès Bélusca-Maïto     {
15286f19c83bSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, Mbr);
15296f19c83bSHermès Bélusca-Maïto         DPRINT1("NtReadFile failed, status=%x\n", Status);
15306f19c83bSHermès Bélusca-Maïto         return;
15316f19c83bSHermès Bélusca-Maïto     }
15326f19c83bSHermès Bélusca-Maïto     Signature = Mbr->Signature;
15336f19c83bSHermès Bélusca-Maïto 
15346f19c83bSHermès Bélusca-Maïto     /* Calculate the MBR checksum */
15356f19c83bSHermès Bélusca-Maïto     Checksum = 0;
15366f19c83bSHermès Bélusca-Maïto     Buffer = (PULONG)Mbr;
15376f19c83bSHermès Bélusca-Maïto     for (i = 0; i < 128; i++)
15386f19c83bSHermès Bélusca-Maïto     {
15396f19c83bSHermès Bélusca-Maïto         Checksum += Buffer[i];
15406f19c83bSHermès Bélusca-Maïto     }
15416f19c83bSHermès Bélusca-Maïto     Checksum = ~Checksum + 1;
15426f19c83bSHermès Bélusca-Maïto 
15436f19c83bSHermès Bélusca-Maïto     RtlStringCchPrintfW(Identifier, ARRAYSIZE(Identifier),
154447a1acedSHermès Bélusca-Maïto                         L"%08x-%08x-%c",
154547a1acedSHermès Bélusca-Maïto                         Checksum, Signature,
154647a1acedSHermès Bélusca-Maïto                         (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
15476f19c83bSHermès Bélusca-Maïto     DPRINT("Identifier: %S\n", Identifier);
15486f19c83bSHermès Bélusca-Maïto 
15496f19c83bSHermès Bélusca-Maïto     DiskEntry = RtlAllocateHeap(ProcessHeap,
15506f19c83bSHermès Bélusca-Maïto                                 HEAP_ZERO_MEMORY,
15516f19c83bSHermès Bélusca-Maïto                                 sizeof(DISKENTRY));
15526f19c83bSHermès Bélusca-Maïto     if (DiskEntry == NULL)
15536f19c83bSHermès Bélusca-Maïto     {
1554f41750abSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, Mbr);
1555f41750abSHermès Bélusca-Maïto         DPRINT1("Failed to allocate a new disk entry.\n");
15566f19c83bSHermès Bélusca-Maïto         return;
15576f19c83bSHermès Bélusca-Maïto     }
15586f19c83bSHermès Bélusca-Maïto 
155984f3e2dfSHermès Bélusca-Maïto     DiskEntry->PartList = List;
156084f3e2dfSHermès Bélusca-Maïto 
156147a1acedSHermès Bélusca-Maïto #if 0
156247a1acedSHermès Bélusca-Maïto     {
156347a1acedSHermès Bélusca-Maïto         FILE_FS_DEVICE_INFORMATION FileFsDevice;
156447a1acedSHermès Bélusca-Maïto 
156547a1acedSHermès Bélusca-Maïto         /* Query the device for its type */
156647a1acedSHermès Bélusca-Maïto         Status = NtQueryVolumeInformationFile(FileHandle,
156747a1acedSHermès Bélusca-Maïto                                               &Iosb,
156847a1acedSHermès Bélusca-Maïto                                               &FileFsDevice,
156947a1acedSHermès Bélusca-Maïto                                               sizeof(FileFsDevice),
157047a1acedSHermès Bélusca-Maïto                                               FileFsDeviceInformation);
157147a1acedSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
157247a1acedSHermès Bélusca-Maïto         {
157347a1acedSHermès Bélusca-Maïto             DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
157447a1acedSHermès Bélusca-Maïto         }
157547a1acedSHermès Bélusca-Maïto         else
157647a1acedSHermès Bélusca-Maïto         {
157747a1acedSHermès Bélusca-Maïto             DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
157847a1acedSHermès Bélusca-Maïto         }
157947a1acedSHermès Bélusca-Maïto     }
158047a1acedSHermès Bélusca-Maïto     // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
158147a1acedSHermès Bélusca-Maïto #endif
158247a1acedSHermès Bélusca-Maïto     DiskEntry->MediaType = DiskGeometry.MediaType;
158347a1acedSHermès Bélusca-Maïto     if (DiskEntry->MediaType == RemovableMedia)
158447a1acedSHermès Bélusca-Maïto     {
158547a1acedSHermès Bélusca-Maïto         DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
158647a1acedSHermès Bélusca-Maïto     }
158747a1acedSHermès Bélusca-Maïto     else // if (DiskEntry->MediaType == FixedMedia)
158847a1acedSHermès Bélusca-Maïto     {
158947a1acedSHermès Bélusca-Maïto         DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
159047a1acedSHermès Bélusca-Maïto     }
159147a1acedSHermès Bélusca-Maïto 
15926f19c83bSHermès Bélusca-Maïto //    DiskEntry->Checksum = Checksum;
15936f19c83bSHermès Bélusca-Maïto //    DiskEntry->Signature = Signature;
15946f19c83bSHermès Bélusca-Maïto     DiskEntry->BiosFound = FALSE;
15956f19c83bSHermès Bélusca-Maïto 
15966f19c83bSHermès Bélusca-Maïto     /*
15976f19c83bSHermès Bélusca-Maïto      * Check if this disk has a valid MBR: verify its signature,
15986f19c83bSHermès Bélusca-Maïto      * and whether its two first bytes are a valid instruction
15996f19c83bSHermès Bélusca-Maïto      * (related to this, see IsThereAValidBootSector() in partlist.c).
1600a3168373SHermès Bélusca-Maïto      *
1601a3168373SHermès Bélusca-Maïto      * See also ntoskrnl/fstub/fstubex.c!FstubDetectPartitionStyle().
16026f19c83bSHermès Bélusca-Maïto      */
1603a3168373SHermès Bélusca-Maïto 
1604a3168373SHermès Bélusca-Maïto     // DiskEntry->NoMbr = (Mbr->Magic != PARTITION_MAGIC || (*(PUSHORT)Mbr->BootCode) == 0x0000);
1605a3168373SHermès Bélusca-Maïto 
1606a3168373SHermès Bélusca-Maïto     /* If we have not the 0xAA55 then it's raw partition */
1607a3168373SHermès Bélusca-Maïto     if (Mbr->Magic != PARTITION_MAGIC)
1608a3168373SHermès Bélusca-Maïto     {
1609a3168373SHermès Bélusca-Maïto         DiskEntry->DiskStyle = PARTITION_STYLE_RAW;
1610a3168373SHermès Bélusca-Maïto     }
1611a3168373SHermès Bélusca-Maïto     /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
1612a3168373SHermès Bélusca-Maïto     else if (Mbr->Partition[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
1613a3168373SHermès Bélusca-Maïto              Mbr->Partition[1].PartitionType == 0 &&
1614a3168373SHermès Bélusca-Maïto              Mbr->Partition[2].PartitionType == 0 &&
1615a3168373SHermès Bélusca-Maïto              Mbr->Partition[3].PartitionType == 0)
1616a3168373SHermès Bélusca-Maïto     {
1617a3168373SHermès Bélusca-Maïto         DiskEntry->DiskStyle = PARTITION_STYLE_GPT;
1618a3168373SHermès Bélusca-Maïto     }
1619a3168373SHermès Bélusca-Maïto     /* Otherwise, partition table is in MBR */
16206f19c83bSHermès Bélusca-Maïto     else
1621a3168373SHermès Bélusca-Maïto     {
1622a3168373SHermès Bélusca-Maïto         DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
1623a3168373SHermès Bélusca-Maïto     }
16246f19c83bSHermès Bélusca-Maïto 
16256f19c83bSHermès Bélusca-Maïto     /* Free the MBR sector buffer */
16266f19c83bSHermès Bélusca-Maïto     RtlFreeHeap(ProcessHeap, 0, Mbr);
16276f19c83bSHermès Bélusca-Maïto 
16286f19c83bSHermès Bélusca-Maïto 
16298bed4adfSHermès Bélusca-Maïto     for (ListEntry = List->BiosDiskListHead.Flink;
16308bed4adfSHermès Bélusca-Maïto          ListEntry != &List->BiosDiskListHead;
16318bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
16326f19c83bSHermès Bélusca-Maïto     {
16336f19c83bSHermès Bélusca-Maïto         BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
16346f19c83bSHermès Bélusca-Maïto         /* FIXME:
16356f15802aSHermès Bélusca-Maïto          *   Compare the size from BIOS and the reported size from driver.
16366f19c83bSHermès Bélusca-Maïto          *   If we have more than one disk with a zero or with the same signature
16376f19c83bSHermès Bélusca-Maïto          *   we must create new signatures and reboot. After the reboot,
16386f19c83bSHermès Bélusca-Maïto          *   it is possible to identify the disks.
16396f19c83bSHermès Bélusca-Maïto          */
16406f19c83bSHermès Bélusca-Maïto         if (BiosDiskEntry->Signature == Signature &&
16416f19c83bSHermès Bélusca-Maïto             BiosDiskEntry->Checksum == Checksum &&
164247a1acedSHermès Bélusca-Maïto             BiosDiskEntry->DiskEntry == NULL)
16436f19c83bSHermès Bélusca-Maïto         {
16446f19c83bSHermès Bélusca-Maïto             if (!DiskEntry->BiosFound)
16456f19c83bSHermès Bélusca-Maïto             {
164647a1acedSHermès Bélusca-Maïto                 DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
164747a1acedSHermès Bélusca-Maïto                 DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
164847a1acedSHermès Bélusca-Maïto                 DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
164947a1acedSHermès Bélusca-Maïto 
165047a1acedSHermès Bélusca-Maïto                 if (DiskEntry->MediaType == RemovableMedia)
165147a1acedSHermès Bélusca-Maïto                 {
165247a1acedSHermès Bélusca-Maïto                     /* Set the removable disk number to zero */
165347a1acedSHermès Bélusca-Maïto                     DiskEntry->HwFixedDiskNumber = 0;
165447a1acedSHermès Bélusca-Maïto                 }
165547a1acedSHermès Bélusca-Maïto                 else // if (DiskEntry->MediaType == FixedMedia)
165647a1acedSHermès Bélusca-Maïto                 {
165747a1acedSHermès Bélusca-Maïto                     /* The fixed disk number will later be adjusted using the number of removable disks */
165847a1acedSHermès Bélusca-Maïto                     DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
165947a1acedSHermès Bélusca-Maïto                 }
166047a1acedSHermès Bélusca-Maïto 
16616f19c83bSHermès Bélusca-Maïto                 DiskEntry->BiosFound = TRUE;
166247a1acedSHermès Bélusca-Maïto                 BiosDiskEntry->DiskEntry = DiskEntry;
166347a1acedSHermès Bélusca-Maïto                 break;
16646f19c83bSHermès Bélusca-Maïto             }
16656f19c83bSHermès Bélusca-Maïto             else
16666f19c83bSHermès Bélusca-Maïto             {
1667f41750abSHermès Bélusca-Maïto                 // FIXME: What to do?
166847a1acedSHermès Bélusca-Maïto                 DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
16696f19c83bSHermès Bélusca-Maïto             }
16706f19c83bSHermès Bélusca-Maïto         }
16716f19c83bSHermès Bélusca-Maïto     }
16726f19c83bSHermès Bélusca-Maïto 
16736f19c83bSHermès Bélusca-Maïto     if (!DiskEntry->BiosFound)
16746f19c83bSHermès Bélusca-Maïto     {
167547a1acedSHermès Bélusca-Maïto         DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
16766f19c83bSHermès Bélusca-Maïto     }
16776f19c83bSHermès Bélusca-Maïto 
16786f19c83bSHermès Bélusca-Maïto     DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
16796f19c83bSHermès Bélusca-Maïto     DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
16806f19c83bSHermès Bélusca-Maïto     DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
16816f19c83bSHermès Bélusca-Maïto     DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
16826f19c83bSHermès Bélusca-Maïto 
16836f19c83bSHermès Bélusca-Maïto     DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
16846f19c83bSHermès Bélusca-Maïto     DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
16856f19c83bSHermès Bélusca-Maïto     DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
16866f19c83bSHermès Bélusca-Maïto     DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
16876f19c83bSHermès Bélusca-Maïto 
16886f19c83bSHermès Bélusca-Maïto     DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
16896f19c83bSHermès Bélusca-Maïto                                       (ULONGLONG)DiskGeometry.TracksPerCylinder *
16906f19c83bSHermès Bélusca-Maïto                                       (ULONGLONG)DiskGeometry.SectorsPerTrack;
16916f19c83bSHermès Bélusca-Maïto 
16926f19c83bSHermès Bélusca-Maïto     DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
16936f19c83bSHermès Bélusca-Maïto     DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
16946f19c83bSHermès Bélusca-Maïto                                    DiskGeometry.SectorsPerTrack;
16956f19c83bSHermès Bélusca-Maïto 
16966f19c83bSHermès Bélusca-Maïto     DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
16976f19c83bSHermès Bélusca-Maïto     DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
16986f19c83bSHermès Bélusca-Maïto 
16996f19c83bSHermès Bélusca-Maïto     DiskEntry->DiskNumber = DiskNumber;
17006f19c83bSHermès Bélusca-Maïto     DiskEntry->Port = ScsiAddress.PortNumber;
17016f19c83bSHermès Bélusca-Maïto     DiskEntry->Bus = ScsiAddress.PathId;
17026f19c83bSHermès Bélusca-Maïto     DiskEntry->Id = ScsiAddress.TargetId;
17036f19c83bSHermès Bélusca-Maïto 
17046f19c83bSHermès Bélusca-Maïto     GetDriverName(DiskEntry);
17056f19c83bSHermès Bélusca-Maïto     /*
17066f19c83bSHermès Bélusca-Maïto      * Actually it would be more correct somehow to use:
17076f19c83bSHermès Bélusca-Maïto      *
17086f19c83bSHermès Bélusca-Maïto      * OBJECT_NAME_INFORMATION NameInfo; // ObjectNameInfo;
17096f19c83bSHermès Bélusca-Maïto      * ULONG ReturnedLength;
17106f19c83bSHermès Bélusca-Maïto      *
17116f19c83bSHermès Bélusca-Maïto      * Status = NtQueryObject(SomeHandleToTheDisk,
17126f19c83bSHermès Bélusca-Maïto      *                        ObjectNameInformation,
17136f19c83bSHermès Bélusca-Maïto      *                        &NameInfo,
17146f19c83bSHermès Bélusca-Maïto      *                        sizeof(NameInfo),
17156f19c83bSHermès Bélusca-Maïto      *                        &ReturnedLength);
17166f19c83bSHermès Bélusca-Maïto      * etc...
17176f19c83bSHermès Bélusca-Maïto      *
17186f19c83bSHermès Bélusca-Maïto      * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
17196f19c83bSHermès Bélusca-Maïto      */
17206f19c83bSHermès Bélusca-Maïto 
172147a1acedSHermès Bélusca-Maïto     InitializeListHead(&DiskEntry->PrimaryPartListHead);
172247a1acedSHermès Bélusca-Maïto     InitializeListHead(&DiskEntry->LogicalPartListHead);
172347a1acedSHermès Bélusca-Maïto 
17246f19c83bSHermès Bélusca-Maïto     InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
17256f19c83bSHermès Bélusca-Maïto 
1726f41750abSHermès Bélusca-Maïto 
1727f41750abSHermès Bélusca-Maïto     /*
1728f41750abSHermès Bélusca-Maïto      * We now retrieve the disk partition layout
1729f41750abSHermès Bélusca-Maïto      */
1730f41750abSHermès Bélusca-Maïto 
1731a3168373SHermès Bélusca-Maïto     /*
1732a3168373SHermès Bélusca-Maïto      * Stop there now if the disk is GPT-partitioned,
1733a3168373SHermès Bélusca-Maïto      * since we currently do not support such disks.
1734a3168373SHermès Bélusca-Maïto      */
1735a3168373SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1736a3168373SHermès Bélusca-Maïto     {
1737a3168373SHermès Bélusca-Maïto         DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1738a3168373SHermès Bélusca-Maïto         return;
1739a3168373SHermès Bélusca-Maïto     }
1740a3168373SHermès Bélusca-Maïto 
17416f19c83bSHermès Bélusca-Maïto     /* Allocate a layout buffer with 4 partition entries first */
17426f19c83bSHermès Bélusca-Maïto     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
17436f19c83bSHermès Bélusca-Maïto                        ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
17446f19c83bSHermès Bélusca-Maïto     DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
17456f19c83bSHermès Bélusca-Maïto                                               HEAP_ZERO_MEMORY,
17466f19c83bSHermès Bélusca-Maïto                                               LayoutBufferSize);
17476f19c83bSHermès Bélusca-Maïto     if (DiskEntry->LayoutBuffer == NULL)
17486f19c83bSHermès Bélusca-Maïto     {
17496f19c83bSHermès Bélusca-Maïto         DPRINT1("Failed to allocate the disk layout buffer!\n");
17506f19c83bSHermès Bélusca-Maïto         return;
17516f19c83bSHermès Bélusca-Maïto     }
17526f19c83bSHermès Bélusca-Maïto 
1753f41750abSHermès Bélusca-Maïto     /* Keep looping while the drive layout buffer is too small */
17546f19c83bSHermès Bélusca-Maïto     for (;;)
17556f19c83bSHermès Bélusca-Maïto     {
17566f19c83bSHermès Bélusca-Maïto         DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
17576f19c83bSHermès Bélusca-Maïto         Status = NtDeviceIoControlFile(FileHandle,
17586f19c83bSHermès Bélusca-Maïto                                        NULL,
17596f19c83bSHermès Bélusca-Maïto                                        NULL,
17606f19c83bSHermès Bélusca-Maïto                                        NULL,
17616f19c83bSHermès Bélusca-Maïto                                        &Iosb,
17626f19c83bSHermès Bélusca-Maïto                                        IOCTL_DISK_GET_DRIVE_LAYOUT,
17636f19c83bSHermès Bélusca-Maïto                                        NULL,
17646f19c83bSHermès Bélusca-Maïto                                        0,
17656f19c83bSHermès Bélusca-Maïto                                        DiskEntry->LayoutBuffer,
17666f19c83bSHermès Bélusca-Maïto                                        LayoutBufferSize);
17676f19c83bSHermès Bélusca-Maïto         if (NT_SUCCESS(Status))
17686f19c83bSHermès Bélusca-Maïto             break;
17696f19c83bSHermès Bélusca-Maïto 
17706f19c83bSHermès Bélusca-Maïto         if (Status != STATUS_BUFFER_TOO_SMALL)
17716f19c83bSHermès Bélusca-Maïto         {
17726f19c83bSHermès Bélusca-Maïto             DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
17736f19c83bSHermès Bélusca-Maïto             return;
17746f19c83bSHermès Bélusca-Maïto         }
17756f19c83bSHermès Bélusca-Maïto 
17766f19c83bSHermès Bélusca-Maïto         LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
17776f19c83bSHermès Bélusca-Maïto         NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
17786f19c83bSHermès Bélusca-Maïto                                             HEAP_ZERO_MEMORY,
17796f19c83bSHermès Bélusca-Maïto                                             DiskEntry->LayoutBuffer,
17806f19c83bSHermès Bélusca-Maïto                                             LayoutBufferSize);
17816f19c83bSHermès Bélusca-Maïto         if (NewLayoutBuffer == NULL)
17826f19c83bSHermès Bélusca-Maïto         {
17836f19c83bSHermès Bélusca-Maïto             DPRINT1("Failed to reallocate the disk layout buffer!\n");
17846f19c83bSHermès Bélusca-Maïto             return;
17856f19c83bSHermès Bélusca-Maïto         }
17866f19c83bSHermès Bélusca-Maïto 
17876f19c83bSHermès Bélusca-Maïto         DiskEntry->LayoutBuffer = NewLayoutBuffer;
17886f19c83bSHermès Bélusca-Maïto     }
17896f19c83bSHermès Bélusca-Maïto 
17906f19c83bSHermès Bélusca-Maïto     DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
17916f19c83bSHermès Bélusca-Maïto 
17926f19c83bSHermès Bélusca-Maïto #ifdef DUMP_PARTITION_TABLE
17936f19c83bSHermès Bélusca-Maïto     DumpPartitionTable(DiskEntry);
17946f19c83bSHermès Bélusca-Maïto #endif
17956f19c83bSHermès Bélusca-Maïto 
179647a1acedSHermès Bélusca-Maïto     if (IsSuperFloppy(DiskEntry))
179747a1acedSHermès Bélusca-Maïto         DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
179847a1acedSHermès Bélusca-Maïto 
17996f19c83bSHermès Bélusca-Maïto     if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
18006f19c83bSHermès Bélusca-Maïto         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
18016f19c83bSHermès Bélusca-Maïto         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != PARTITION_ENTRY_UNUSED)
18026f19c83bSHermès Bélusca-Maïto     {
18036f19c83bSHermès Bélusca-Maïto         if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
18046f19c83bSHermès Bélusca-Maïto         {
18056f19c83bSHermès Bélusca-Maïto             DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
18066f19c83bSHermès Bélusca-Maïto         }
18076f19c83bSHermès Bélusca-Maïto         else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
18086f19c83bSHermès Bélusca-Maïto         {
18096f19c83bSHermès Bélusca-Maïto             DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
18106f19c83bSHermès Bélusca-Maïto         }
18116f19c83bSHermès Bélusca-Maïto         else
18126f19c83bSHermès Bélusca-Maïto         {
18136f19c83bSHermès Bélusca-Maïto             DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
18146f19c83bSHermès Bélusca-Maïto         }
18156f19c83bSHermès Bélusca-Maïto     }
18166f19c83bSHermès Bélusca-Maïto     else
18176f19c83bSHermès Bélusca-Maïto     {
18186f19c83bSHermès Bélusca-Maïto         DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
18196f19c83bSHermès Bélusca-Maïto     }
18206f19c83bSHermès Bélusca-Maïto 
18216f19c83bSHermès Bélusca-Maïto     if (DiskEntry->LayoutBuffer->PartitionCount == 0)
18226f19c83bSHermès Bélusca-Maïto     {
18236f19c83bSHermès Bélusca-Maïto         DiskEntry->NewDisk = TRUE;
18246f19c83bSHermès Bélusca-Maïto         DiskEntry->LayoutBuffer->PartitionCount = 4;
18256f19c83bSHermès Bélusca-Maïto 
18266f19c83bSHermès Bélusca-Maïto         for (i = 0; i < 4; i++)
18277df92966SHermès Bélusca-Maïto         {
18286f19c83bSHermès Bélusca-Maïto             DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
18296f19c83bSHermès Bélusca-Maïto         }
18307df92966SHermès Bélusca-Maïto     }
18316f19c83bSHermès Bélusca-Maïto     else
18326f19c83bSHermès Bélusca-Maïto     {
18337df92966SHermès Bélusca-Maïto         /* Enumerate and add the first four primary partitions */
18346f19c83bSHermès Bélusca-Maïto         for (i = 0; i < 4; i++)
18356f19c83bSHermès Bélusca-Maïto         {
18366f19c83bSHermès Bélusca-Maïto             AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
18376f19c83bSHermès Bélusca-Maïto         }
18386f19c83bSHermès Bélusca-Maïto 
18397df92966SHermès Bélusca-Maïto         /* Enumerate and add the remaining partitions as logical ones */
18406f19c83bSHermès Bélusca-Maïto         for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
18416f19c83bSHermès Bélusca-Maïto         {
18426f19c83bSHermès Bélusca-Maïto             AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
18436f19c83bSHermès Bélusca-Maïto         }
18446f19c83bSHermès Bélusca-Maïto     }
18456f19c83bSHermès Bélusca-Maïto 
18466f19c83bSHermès Bélusca-Maïto     ScanForUnpartitionedDiskSpace(DiskEntry);
18476f19c83bSHermès Bélusca-Maïto }
18486f19c83bSHermès Bélusca-Maïto 
184959acff79SHermès Bélusca-Maïto /*
185059acff79SHermès Bélusca-Maïto  * Retrieve the system disk, i.e. the fixed disk that is accessible by the
185159acff79SHermès Bélusca-Maïto  * firmware during boot time and where the system partition resides.
185259acff79SHermès Bélusca-Maïto  * If no system partition has been determined, we retrieve the first disk
185359acff79SHermès Bélusca-Maïto  * that verifies the mentioned criteria above.
185459acff79SHermès Bélusca-Maïto  */
185559acff79SHermès Bélusca-Maïto static
185659acff79SHermès Bélusca-Maïto PDISKENTRY
GetSystemDisk(IN PPARTLIST List)185759acff79SHermès Bélusca-Maïto GetSystemDisk(
185859acff79SHermès Bélusca-Maïto     IN PPARTLIST List)
185959acff79SHermès Bélusca-Maïto {
186059acff79SHermès Bélusca-Maïto     PLIST_ENTRY Entry;
186159acff79SHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
186259acff79SHermès Bélusca-Maïto 
186359acff79SHermès Bélusca-Maïto     /* Check for empty disk list */
186459acff79SHermès Bélusca-Maïto     if (IsListEmpty(&List->DiskListHead))
186559acff79SHermès Bélusca-Maïto         return NULL;
186659acff79SHermès Bélusca-Maïto 
186759acff79SHermès Bélusca-Maïto     /*
186859acff79SHermès Bélusca-Maïto      * If we already have a system partition, the system disk
186959acff79SHermès Bélusca-Maïto      * is the one on which the system partition resides.
187059acff79SHermès Bélusca-Maïto      */
187159acff79SHermès Bélusca-Maïto     if (List->SystemPartition)
187259acff79SHermès Bélusca-Maïto         return List->SystemPartition->DiskEntry;
187359acff79SHermès Bélusca-Maïto 
187459acff79SHermès Bélusca-Maïto     /* Loop over the disks and find the correct one */
187559acff79SHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
187659acff79SHermès Bélusca-Maïto          Entry != &List->DiskListHead;
187759acff79SHermès Bélusca-Maïto          Entry = Entry->Flink)
187859acff79SHermès Bélusca-Maïto     {
187959acff79SHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
188059acff79SHermès Bélusca-Maïto 
188159acff79SHermès Bélusca-Maïto         /* The disk must be a fixed disk and be found by the firmware */
188259acff79SHermès Bélusca-Maïto         if (DiskEntry->MediaType == FixedMedia && DiskEntry->BiosFound)
188359acff79SHermès Bélusca-Maïto         {
188459acff79SHermès Bélusca-Maïto             break;
188559acff79SHermès Bélusca-Maïto         }
188659acff79SHermès Bélusca-Maïto     }
188759acff79SHermès Bélusca-Maïto     if (Entry == &List->DiskListHead)
188859acff79SHermès Bélusca-Maïto     {
188959acff79SHermès Bélusca-Maïto         /* We haven't encountered any suitable disk */
189059acff79SHermès Bélusca-Maïto         return NULL;
189159acff79SHermès Bélusca-Maïto     }
189259acff79SHermès Bélusca-Maïto 
189359acff79SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
189459acff79SHermès Bélusca-Maïto     {
189559acff79SHermès Bélusca-Maïto         DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
189659acff79SHermès Bélusca-Maïto     }
189759acff79SHermès Bélusca-Maïto 
189859acff79SHermès Bélusca-Maïto     return DiskEntry;
189959acff79SHermès Bélusca-Maïto }
190059acff79SHermès Bélusca-Maïto 
190159acff79SHermès Bélusca-Maïto /*
190259acff79SHermès Bélusca-Maïto  * Retrieve the actual "active" partition of the given disk.
190359acff79SHermès Bélusca-Maïto  * On MBR disks, partition with the Active/Boot flag set;
190459acff79SHermès Bélusca-Maïto  * on GPT disks, partition with the correct GUID.
190559acff79SHermès Bélusca-Maïto  */
190659acff79SHermès Bélusca-Maïto BOOLEAN
IsPartitionActive(IN PPARTENTRY PartEntry)190759acff79SHermès Bélusca-Maïto IsPartitionActive(
190859acff79SHermès Bélusca-Maïto     IN PPARTENTRY PartEntry)
190959acff79SHermès Bélusca-Maïto {
191059acff79SHermès Bélusca-Maïto     // TODO: Support for GPT disks!
191159acff79SHermès Bélusca-Maïto 
191259acff79SHermès Bélusca-Maïto     if (IsContainerPartition(PartEntry->PartitionType))
191359acff79SHermès Bélusca-Maïto         return FALSE;
191459acff79SHermès Bélusca-Maïto 
191559acff79SHermès Bélusca-Maïto     /* Check if the partition is partitioned, used and active */
191659acff79SHermès Bélusca-Maïto     if (PartEntry->IsPartitioned &&
191759acff79SHermès Bélusca-Maïto         // !IsContainerPartition(PartEntry->PartitionType) &&
191859acff79SHermès Bélusca-Maïto         PartEntry->BootIndicator)
191959acff79SHermès Bélusca-Maïto     {
192059acff79SHermès Bélusca-Maïto         /* Yes it is */
192159acff79SHermès Bélusca-Maïto         ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
192259acff79SHermès Bélusca-Maïto         return TRUE;
192359acff79SHermès Bélusca-Maïto     }
192459acff79SHermès Bélusca-Maïto 
192559acff79SHermès Bélusca-Maïto     return FALSE;
192659acff79SHermès Bélusca-Maïto }
192759acff79SHermès Bélusca-Maïto 
192859acff79SHermès Bélusca-Maïto static
192959acff79SHermès Bélusca-Maïto PPARTENTRY
GetActiveDiskPartition(IN PDISKENTRY DiskEntry)193059acff79SHermès Bélusca-Maïto GetActiveDiskPartition(
193159acff79SHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
193259acff79SHermès Bélusca-Maïto {
193359acff79SHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
193459acff79SHermès Bélusca-Maïto     PPARTENTRY PartEntry;
193559acff79SHermès Bélusca-Maïto     PPARTENTRY ActivePartition = NULL;
193659acff79SHermès Bélusca-Maïto 
193759acff79SHermès Bélusca-Maïto     /* Check for empty disk list */
193859acff79SHermès Bélusca-Maïto     // ASSERT(DiskEntry);
193959acff79SHermès Bélusca-Maïto     if (!DiskEntry)
194059acff79SHermès Bélusca-Maïto         return NULL;
194159acff79SHermès Bélusca-Maïto 
194259acff79SHermès Bélusca-Maïto     /* Check for empty partition list */
194359acff79SHermès Bélusca-Maïto     if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
194459acff79SHermès Bélusca-Maïto         return NULL;
194559acff79SHermès Bélusca-Maïto 
194659acff79SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
194759acff79SHermès Bélusca-Maïto     {
194859acff79SHermès Bélusca-Maïto         DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
194959acff79SHermès Bélusca-Maïto         return NULL;
195059acff79SHermès Bélusca-Maïto     }
195159acff79SHermès Bélusca-Maïto 
195259acff79SHermès Bélusca-Maïto     /* Scan all (primary) partitions to find the active disk partition */
195359acff79SHermès Bélusca-Maïto     for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
195459acff79SHermès Bélusca-Maïto          ListEntry != &DiskEntry->PrimaryPartListHead;
195559acff79SHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
195659acff79SHermès Bélusca-Maïto     {
195759acff79SHermès Bélusca-Maïto         /* Retrieve the partition */
195859acff79SHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
195959acff79SHermès Bélusca-Maïto         if (IsPartitionActive(PartEntry))
196059acff79SHermès Bélusca-Maïto         {
196159acff79SHermès Bélusca-Maïto             /* Yes, we've found it */
196259acff79SHermès Bélusca-Maïto             ASSERT(DiskEntry == PartEntry->DiskEntry);
196359acff79SHermès Bélusca-Maïto             ASSERT(PartEntry->IsPartitioned);
19646f15802aSHermès Bélusca-Maïto             ASSERT(PartEntry->Volume);
196559acff79SHermès Bélusca-Maïto 
196659acff79SHermès Bélusca-Maïto             ActivePartition = PartEntry;
196759acff79SHermès Bélusca-Maïto 
196859acff79SHermès Bélusca-Maïto             DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
196959acff79SHermès Bélusca-Maïto                     PartEntry->PartitionNumber, DiskEntry->DiskNumber,
19706f15802aSHermès Bélusca-Maïto                     !PartEntry->Volume->Info.DriveLetter ? L'-' : PartEntry->Volume->Info.DriveLetter);
197159acff79SHermès Bélusca-Maïto             break;
197259acff79SHermès Bélusca-Maïto         }
197359acff79SHermès Bélusca-Maïto     }
197459acff79SHermès Bélusca-Maïto 
197559acff79SHermès Bélusca-Maïto     /* Check if the disk is new and if so, use its first partition as the active system partition */
197659acff79SHermès Bélusca-Maïto     if (DiskEntry->NewDisk && ActivePartition != NULL)
197759acff79SHermès Bélusca-Maïto     {
197859acff79SHermès Bélusca-Maïto         // FIXME: What to do??
197959acff79SHermès Bélusca-Maïto         DPRINT1("NewDisk TRUE but already existing active partition?\n");
198059acff79SHermès Bélusca-Maïto     }
198159acff79SHermès Bélusca-Maïto 
198259acff79SHermès Bélusca-Maïto     /* Return the active partition found (or none) */
198359acff79SHermès Bélusca-Maïto     return ActivePartition;
198459acff79SHermès Bélusca-Maïto }
198559acff79SHermès Bélusca-Maïto 
19866f19c83bSHermès Bélusca-Maïto PPARTLIST
CreatePartitionList(VOID)19876f19c83bSHermès Bélusca-Maïto CreatePartitionList(VOID)
19886f19c83bSHermès Bélusca-Maïto {
19896f19c83bSHermès Bélusca-Maïto     PPARTLIST List;
199059acff79SHermès Bélusca-Maïto     PDISKENTRY SystemDisk;
19916f19c83bSHermès Bélusca-Maïto     OBJECT_ATTRIBUTES ObjectAttributes;
19926f19c83bSHermès Bélusca-Maïto     SYSTEM_DEVICE_INFORMATION Sdi;
19936f19c83bSHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb;
19946f19c83bSHermès Bélusca-Maïto     ULONG ReturnSize;
19956f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
19966f19c83bSHermès Bélusca-Maïto     ULONG DiskNumber;
19976f19c83bSHermès Bélusca-Maïto     HANDLE FileHandle;
1998626c654aSHermès Bélusca-Maïto     UNICODE_STRING Name;
1999626c654aSHermès Bélusca-Maïto     WCHAR Buffer[MAX_PATH];
20006f19c83bSHermès Bélusca-Maïto 
20016f19c83bSHermès Bélusca-Maïto     List = (PPARTLIST)RtlAllocateHeap(ProcessHeap,
20026f19c83bSHermès Bélusca-Maïto                                       0,
20036f19c83bSHermès Bélusca-Maïto                                       sizeof(PARTLIST));
20046f15802aSHermès Bélusca-Maïto     if (!List)
20056f19c83bSHermès Bélusca-Maïto         return NULL;
20066f19c83bSHermès Bélusca-Maïto 
20076f19c83bSHermès Bélusca-Maïto     List->SystemPartition = NULL;
20086f19c83bSHermès Bélusca-Maïto 
20096f19c83bSHermès Bélusca-Maïto     InitializeListHead(&List->DiskListHead);
20106f19c83bSHermès Bélusca-Maïto     InitializeListHead(&List->BiosDiskListHead);
20116f15802aSHermès Bélusca-Maïto     InitializeListHead(&List->VolumesList);
20126f19c83bSHermès Bélusca-Maïto 
2013f41750abSHermès Bélusca-Maïto     /*
2014f41750abSHermès Bélusca-Maïto      * Enumerate the disks seen by the BIOS; this will be used later
2015f41750abSHermès Bélusca-Maïto      * to map drives seen by NTOS with their corresponding BIOS names.
2016f41750abSHermès Bélusca-Maïto      */
20176f19c83bSHermès Bélusca-Maïto     EnumerateBiosDiskEntries(List);
20186f19c83bSHermès Bélusca-Maïto 
2019f41750abSHermès Bélusca-Maïto     /* Enumerate disks seen by NTOS */
20206f19c83bSHermès Bélusca-Maïto     Status = NtQuerySystemInformation(SystemDeviceInformation,
20216f19c83bSHermès Bélusca-Maïto                                       &Sdi,
20226f19c83bSHermès Bélusca-Maïto                                       sizeof(Sdi),
20236f19c83bSHermès Bélusca-Maïto                                       &ReturnSize);
20246f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
20256f19c83bSHermès Bélusca-Maïto     {
2026780c2a03SSerge Gautherie         DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx\n", Status);
20276f19c83bSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, List);
20286f19c83bSHermès Bélusca-Maïto         return NULL;
20296f19c83bSHermès Bélusca-Maïto     }
20306f19c83bSHermès Bélusca-Maïto 
20316f19c83bSHermès Bélusca-Maïto     for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
20326f19c83bSHermès Bélusca-Maïto     {
20336f19c83bSHermès Bélusca-Maïto         RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
20346f19c83bSHermès Bélusca-Maïto                             L"\\Device\\Harddisk%lu\\Partition0",
20356f19c83bSHermès Bélusca-Maïto                             DiskNumber);
20366f19c83bSHermès Bélusca-Maïto         RtlInitUnicodeString(&Name, Buffer);
20376f19c83bSHermès Bélusca-Maïto 
20386f19c83bSHermès Bélusca-Maïto         InitializeObjectAttributes(&ObjectAttributes,
20396f19c83bSHermès Bélusca-Maïto                                    &Name,
2040765994c9SHermès Bélusca-Maïto                                    OBJ_CASE_INSENSITIVE,
20416f19c83bSHermès Bélusca-Maïto                                    NULL,
20426f19c83bSHermès Bélusca-Maïto                                    NULL);
20436f19c83bSHermès Bélusca-Maïto 
20446f19c83bSHermès Bélusca-Maïto         Status = NtOpenFile(&FileHandle,
20456f19c83bSHermès Bélusca-Maïto                             FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
20466f19c83bSHermès Bélusca-Maïto                             &ObjectAttributes,
20476f19c83bSHermès Bélusca-Maïto                             &Iosb,
2048f41750abSHermès Bélusca-Maïto                             FILE_SHARE_READ | FILE_SHARE_WRITE,
20496f19c83bSHermès Bélusca-Maïto                             FILE_SYNCHRONOUS_IO_NONALERT);
20506f19c83bSHermès Bélusca-Maïto         if (NT_SUCCESS(Status))
20516f19c83bSHermès Bélusca-Maïto         {
20526f19c83bSHermès Bélusca-Maïto             AddDiskToList(FileHandle, DiskNumber, List);
20536f19c83bSHermès Bélusca-Maïto             NtClose(FileHandle);
20546f19c83bSHermès Bélusca-Maïto         }
20556f19c83bSHermès Bélusca-Maïto     }
20566f19c83bSHermès Bélusca-Maïto 
20576f19c83bSHermès Bélusca-Maïto     UpdateDiskSignatures(List);
205847a1acedSHermès Bélusca-Maïto     UpdateHwDiskNumbers(List);
20596f19c83bSHermès Bélusca-Maïto     AssignDriveLetters(List);
20606f19c83bSHermès Bélusca-Maïto 
206159acff79SHermès Bélusca-Maïto     /*
206259acff79SHermès Bélusca-Maïto      * Retrieve the system partition: the active partition on the system
206359acff79SHermès Bélusca-Maïto      * disk (the one that will be booted by default by the hardware).
206459acff79SHermès Bélusca-Maïto      */
206559acff79SHermès Bélusca-Maïto     SystemDisk = GetSystemDisk(List);
206659acff79SHermès Bélusca-Maïto     List->SystemPartition = (SystemDisk ? GetActiveDiskPartition(SystemDisk) : NULL);
206759acff79SHermès Bélusca-Maïto 
20686f19c83bSHermès Bélusca-Maïto     return List;
20696f19c83bSHermès Bélusca-Maïto }
20706f19c83bSHermès Bélusca-Maïto 
20716f19c83bSHermès Bélusca-Maïto VOID
DestroyPartitionList(IN PPARTLIST List)20726f19c83bSHermès Bélusca-Maïto DestroyPartitionList(
20736f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List)
20746f19c83bSHermès Bélusca-Maïto {
20756f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
20766f19c83bSHermès Bélusca-Maïto     PBIOSDISKENTRY BiosDiskEntry;
20776f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
20786f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
20796f19c83bSHermès Bélusca-Maïto 
20806f19c83bSHermès Bélusca-Maïto     /* Release disk and partition info */
20816f19c83bSHermès Bélusca-Maïto     while (!IsListEmpty(&List->DiskListHead))
20826f19c83bSHermès Bélusca-Maïto     {
20836f19c83bSHermès Bélusca-Maïto         Entry = RemoveHeadList(&List->DiskListHead);
20846f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
20856f19c83bSHermès Bélusca-Maïto 
20866f19c83bSHermès Bélusca-Maïto         /* Release driver name */
20876f19c83bSHermès Bélusca-Maïto         RtlFreeUnicodeString(&DiskEntry->DriverName);
20886f19c83bSHermès Bélusca-Maïto 
20896f19c83bSHermès Bélusca-Maïto         /* Release primary partition list */
20906f19c83bSHermès Bélusca-Maïto         while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
20916f19c83bSHermès Bélusca-Maïto         {
20926f19c83bSHermès Bélusca-Maïto             Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
20936f19c83bSHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
20946f15802aSHermès Bélusca-Maïto             DestroyRegion(PartEntry);
20956f19c83bSHermès Bélusca-Maïto         }
20966f19c83bSHermès Bélusca-Maïto 
20976f19c83bSHermès Bélusca-Maïto         /* Release logical partition list */
20986f19c83bSHermès Bélusca-Maïto         while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
20996f19c83bSHermès Bélusca-Maïto         {
21006f19c83bSHermès Bélusca-Maïto             Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
21016f19c83bSHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
21026f15802aSHermès Bélusca-Maïto             DestroyRegion(PartEntry);
21036f19c83bSHermès Bélusca-Maïto         }
21046f19c83bSHermès Bélusca-Maïto 
21056f19c83bSHermès Bélusca-Maïto         /* Release layout buffer */
21066f19c83bSHermès Bélusca-Maïto         if (DiskEntry->LayoutBuffer != NULL)
21076f19c83bSHermès Bélusca-Maïto             RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
21086f19c83bSHermès Bélusca-Maïto 
21096f19c83bSHermès Bélusca-Maïto         /* Release disk entry */
21106f19c83bSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, DiskEntry);
21116f19c83bSHermès Bélusca-Maïto     }
21126f19c83bSHermès Bélusca-Maïto 
21136f15802aSHermès Bélusca-Maïto     /* Release the BIOS disk info */
21146f19c83bSHermès Bélusca-Maïto     while (!IsListEmpty(&List->BiosDiskListHead))
21156f19c83bSHermès Bélusca-Maïto     {
21166f19c83bSHermès Bélusca-Maïto         Entry = RemoveHeadList(&List->BiosDiskListHead);
21176f19c83bSHermès Bélusca-Maïto         BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
21186f19c83bSHermès Bélusca-Maïto         RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
21196f19c83bSHermès Bélusca-Maïto     }
21206f19c83bSHermès Bélusca-Maïto 
21216f19c83bSHermès Bélusca-Maïto     /* Release list head */
21226f19c83bSHermès Bélusca-Maïto     RtlFreeHeap(ProcessHeap, 0, List);
21236f19c83bSHermès Bélusca-Maïto }
21246f19c83bSHermès Bélusca-Maïto 
21256f19c83bSHermès Bélusca-Maïto PDISKENTRY
GetDiskByBiosNumber(_In_ PPARTLIST List,_In_ ULONG HwDiskNumber)21266f19c83bSHermès Bélusca-Maïto GetDiskByBiosNumber(
2127a2777cd8SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2128a2777cd8SHermès Bélusca-Maïto     _In_ ULONG HwDiskNumber)
21296f19c83bSHermès Bélusca-Maïto {
21306f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
21316f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
21326f19c83bSHermès Bélusca-Maïto 
21336f19c83bSHermès Bélusca-Maïto     /* Loop over the disks and find the correct one */
21348bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
21358bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
21368bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
21376f19c83bSHermès Bélusca-Maïto     {
21386f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
21396f19c83bSHermès Bélusca-Maïto 
214047a1acedSHermès Bélusca-Maïto         if (DiskEntry->HwDiskNumber == HwDiskNumber)
2141a2777cd8SHermès Bélusca-Maïto             return DiskEntry; /* Disk found, return it */
21426f19c83bSHermès Bélusca-Maïto     }
21436f19c83bSHermès Bélusca-Maïto 
21446f19c83bSHermès Bélusca-Maïto     /* Disk not found, stop there */
21456f19c83bSHermès Bélusca-Maïto     return NULL;
21466f19c83bSHermès Bélusca-Maïto }
21476f19c83bSHermès Bélusca-Maïto 
21486f19c83bSHermès Bélusca-Maïto PDISKENTRY
GetDiskByNumber(_In_ PPARTLIST List,_In_ ULONG DiskNumber)21496f19c83bSHermès Bélusca-Maïto GetDiskByNumber(
2150a2777cd8SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2151a2777cd8SHermès Bélusca-Maïto     _In_ ULONG DiskNumber)
21526f19c83bSHermès Bélusca-Maïto {
21536f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
21546f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
21556f19c83bSHermès Bélusca-Maïto 
21566f19c83bSHermès Bélusca-Maïto     /* Loop over the disks and find the correct one */
21578bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
21588bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
21598bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
21606f19c83bSHermès Bélusca-Maïto     {
21616f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
21626f19c83bSHermès Bélusca-Maïto 
21636f19c83bSHermès Bélusca-Maïto         if (DiskEntry->DiskNumber == DiskNumber)
2164a2777cd8SHermès Bélusca-Maïto             return DiskEntry; /* Disk found, return it */
21656f19c83bSHermès Bélusca-Maïto     }
21666f19c83bSHermès Bélusca-Maïto 
21676f19c83bSHermès Bélusca-Maïto     /* Disk not found, stop there */
21686f19c83bSHermès Bélusca-Maïto     return NULL;
21696f19c83bSHermès Bélusca-Maïto }
21706f19c83bSHermès Bélusca-Maïto 
21716f19c83bSHermès Bélusca-Maïto PDISKENTRY
GetDiskBySCSI(_In_ PPARTLIST List,_In_ USHORT Port,_In_ USHORT Bus,_In_ USHORT Id)21726f19c83bSHermès Bélusca-Maïto GetDiskBySCSI(
2173a2777cd8SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2174a2777cd8SHermès Bélusca-Maïto     _In_ USHORT Port,
2175a2777cd8SHermès Bélusca-Maïto     _In_ USHORT Bus,
2176a2777cd8SHermès Bélusca-Maïto     _In_ USHORT Id)
21776f19c83bSHermès Bélusca-Maïto {
21786f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
21796f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
21806f19c83bSHermès Bélusca-Maïto 
21816f19c83bSHermès Bélusca-Maïto     /* Loop over the disks and find the correct one */
21828bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
21838bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
21848bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
21856f19c83bSHermès Bélusca-Maïto     {
21866f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
21876f19c83bSHermès Bélusca-Maïto 
21886f19c83bSHermès Bélusca-Maïto         if (DiskEntry->Port == Port &&
21896f19c83bSHermès Bélusca-Maïto             DiskEntry->Bus  == Bus  &&
21906f19c83bSHermès Bélusca-Maïto             DiskEntry->Id   == Id)
21916f19c83bSHermès Bélusca-Maïto         {
2192a2777cd8SHermès Bélusca-Maïto             /* Disk found, return it */
21936f19c83bSHermès Bélusca-Maïto             return DiskEntry;
21946f19c83bSHermès Bélusca-Maïto         }
21956f19c83bSHermès Bélusca-Maïto     }
21966f19c83bSHermès Bélusca-Maïto 
21976f19c83bSHermès Bélusca-Maïto     /* Disk not found, stop there */
21986f19c83bSHermès Bélusca-Maïto     return NULL;
21996f19c83bSHermès Bélusca-Maïto }
22006f19c83bSHermès Bélusca-Maïto 
22016f19c83bSHermès Bélusca-Maïto PDISKENTRY
GetDiskBySignature(_In_ PPARTLIST List,_In_ ULONG Signature)22026f19c83bSHermès Bélusca-Maïto GetDiskBySignature(
2203a2777cd8SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2204a2777cd8SHermès Bélusca-Maïto     _In_ ULONG Signature)
22056f19c83bSHermès Bélusca-Maïto {
22066f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
22076f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
22086f19c83bSHermès Bélusca-Maïto 
22096f19c83bSHermès Bélusca-Maïto     /* Loop over the disks and find the correct one */
22108bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
22118bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
22128bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
22136f19c83bSHermès Bélusca-Maïto     {
22146f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
22156f19c83bSHermès Bélusca-Maïto 
22166f19c83bSHermès Bélusca-Maïto         if (DiskEntry->LayoutBuffer->Signature == Signature)
2217a2777cd8SHermès Bélusca-Maïto             return DiskEntry; /* Disk found, return it */
22186f19c83bSHermès Bélusca-Maïto     }
22196f19c83bSHermès Bélusca-Maïto 
22206f19c83bSHermès Bélusca-Maïto     /* Disk not found, stop there */
22216f19c83bSHermès Bélusca-Maïto     return NULL;
22226f19c83bSHermès Bélusca-Maïto }
22236f19c83bSHermès Bélusca-Maïto 
22246f19c83bSHermès Bélusca-Maïto PPARTENTRY
GetPartition(_In_ PDISKENTRY DiskEntry,_In_ ULONG PartitionNumber)22256f19c83bSHermès Bélusca-Maïto GetPartition(
2226a2777cd8SHermès Bélusca-Maïto     _In_ PDISKENTRY DiskEntry,
2227a2777cd8SHermès Bélusca-Maïto     _In_ ULONG PartitionNumber)
22286f19c83bSHermès Bélusca-Maïto {
22296f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
22306f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
22316f19c83bSHermès Bélusca-Maïto 
223297821f00SHermès Bélusca-Maïto     /* Forbid whole-disk or extended container partition access */
223397821f00SHermès Bélusca-Maïto     if (PartitionNumber == 0)
223497821f00SHermès Bélusca-Maïto         return NULL;
223597821f00SHermès Bélusca-Maïto 
2236a2777cd8SHermès Bélusca-Maïto     /* Loop over the primary partitions first... */
22378bed4adfSHermès Bélusca-Maïto     for (Entry = DiskEntry->PrimaryPartListHead.Flink;
22388bed4adfSHermès Bélusca-Maïto          Entry != &DiskEntry->PrimaryPartListHead;
22398bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
22406f19c83bSHermès Bélusca-Maïto     {
22416f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
22426f19c83bSHermès Bélusca-Maïto 
22436f19c83bSHermès Bélusca-Maïto         if (PartEntry->PartitionNumber == PartitionNumber)
2244a2777cd8SHermès Bélusca-Maïto             return PartEntry; /* Partition found, return it */
22456f19c83bSHermès Bélusca-Maïto     }
2246a2777cd8SHermès Bélusca-Maïto 
2247a2777cd8SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2248a2777cd8SHermès Bélusca-Maïto         return NULL;
22496f19c83bSHermès Bélusca-Maïto 
22506f19c83bSHermès Bélusca-Maïto     /* ... then over the logical partitions if needed */
22518bed4adfSHermès Bélusca-Maïto     for (Entry = DiskEntry->LogicalPartListHead.Flink;
22528bed4adfSHermès Bélusca-Maïto          Entry != &DiskEntry->LogicalPartListHead;
22538bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
22546f19c83bSHermès Bélusca-Maïto     {
22556f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
22566f19c83bSHermès Bélusca-Maïto 
22576f19c83bSHermès Bélusca-Maïto         if (PartEntry->PartitionNumber == PartitionNumber)
2258a2777cd8SHermès Bélusca-Maïto             return PartEntry; /* Partition found, return it */
22596f19c83bSHermès Bélusca-Maïto     }
22606f19c83bSHermès Bélusca-Maïto 
22616f19c83bSHermès Bélusca-Maïto     /* The partition was not found on the disk, stop there */
22626f19c83bSHermès Bélusca-Maïto     return NULL;
22636f19c83bSHermès Bélusca-Maïto }
22646f19c83bSHermès Bélusca-Maïto 
226584f3e2dfSHermès Bélusca-Maïto PPARTENTRY
SelectPartition(_In_ PPARTLIST List,_In_ ULONG DiskNumber,_In_ ULONG PartitionNumber)22666f19c83bSHermès Bélusca-Maïto SelectPartition(
2267a2777cd8SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2268a2777cd8SHermès Bélusca-Maïto     _In_ ULONG DiskNumber,
2269a2777cd8SHermès Bélusca-Maïto     _In_ ULONG PartitionNumber)
22706f19c83bSHermès Bélusca-Maïto {
22716f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
22726f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
22736f19c83bSHermès Bélusca-Maïto 
2274a2777cd8SHermès Bélusca-Maïto     /* Find the disk */
22756f19c83bSHermès Bélusca-Maïto     DiskEntry = GetDiskByNumber(List, DiskNumber);
22766f19c83bSHermès Bélusca-Maïto     if (!DiskEntry)
227784f3e2dfSHermès Bélusca-Maïto         return NULL;
2278a2777cd8SHermès Bélusca-Maïto     ASSERT(DiskEntry->DiskNumber == DiskNumber);
22796f19c83bSHermès Bélusca-Maïto 
2280a2777cd8SHermès Bélusca-Maïto     /* Find the partition */
2281a2777cd8SHermès Bélusca-Maïto     PartEntry = GetPartition(DiskEntry, PartitionNumber);
22826f19c83bSHermès Bélusca-Maïto     if (!PartEntry)
228384f3e2dfSHermès Bélusca-Maïto         return NULL;
22846f19c83bSHermès Bélusca-Maïto     ASSERT(PartEntry->DiskEntry == DiskEntry);
22856f19c83bSHermès Bélusca-Maïto     ASSERT(PartEntry->PartitionNumber == PartitionNumber);
22866f19c83bSHermès Bélusca-Maïto 
228784f3e2dfSHermès Bélusca-Maïto     return PartEntry;
22886f19c83bSHermès Bélusca-Maïto }
22896f19c83bSHermès Bélusca-Maïto 
22906f19c83bSHermès Bélusca-Maïto PPARTENTRY
GetNextPartition(IN PPARTLIST List,IN PPARTENTRY CurrentPart OPTIONAL)22916f19c83bSHermès Bélusca-Maïto GetNextPartition(
229284f3e2dfSHermès Bélusca-Maïto     IN PPARTLIST List,
229384f3e2dfSHermès Bélusca-Maïto     IN PPARTENTRY CurrentPart OPTIONAL)
22946f19c83bSHermès Bélusca-Maïto {
22956f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY DiskListEntry;
22966f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY PartListEntry;
229784f3e2dfSHermès Bélusca-Maïto     PDISKENTRY CurrentDisk;
22986f19c83bSHermès Bélusca-Maïto 
22996f19c83bSHermès Bélusca-Maïto     /* Fail if no disks are available */
23006f19c83bSHermès Bélusca-Maïto     if (IsListEmpty(&List->DiskListHead))
23016f19c83bSHermès Bélusca-Maïto         return NULL;
23026f19c83bSHermès Bélusca-Maïto 
230384f3e2dfSHermès Bélusca-Maïto     /* Check for the next usable entry on the current partition's disk */
230484f3e2dfSHermès Bélusca-Maïto     if (CurrentPart != NULL)
23056f19c83bSHermès Bélusca-Maïto     {
230684f3e2dfSHermès Bélusca-Maïto         CurrentDisk = CurrentPart->DiskEntry;
230784f3e2dfSHermès Bélusca-Maïto 
230884f3e2dfSHermès Bélusca-Maïto         if (CurrentPart->LogicalPartition)
23096f19c83bSHermès Bélusca-Maïto         {
23106f19c83bSHermès Bélusca-Maïto             /* Logical partition */
23116f19c83bSHermès Bélusca-Maïto 
231284f3e2dfSHermès Bélusca-Maïto             PartListEntry = CurrentPart->ListEntry.Flink;
231384f3e2dfSHermès Bélusca-Maïto             if (PartListEntry != &CurrentDisk->LogicalPartListHead)
23146f19c83bSHermès Bélusca-Maïto             {
23156f19c83bSHermès Bélusca-Maïto                 /* Next logical partition */
231684f3e2dfSHermès Bélusca-Maïto                 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
231784f3e2dfSHermès Bélusca-Maïto                 return CurrentPart;
23186f19c83bSHermès Bélusca-Maïto             }
23196f19c83bSHermès Bélusca-Maïto             else
23206f19c83bSHermès Bélusca-Maïto             {
232184f3e2dfSHermès Bélusca-Maïto                 PartListEntry = CurrentDisk->ExtendedPartition->ListEntry.Flink;
232284f3e2dfSHermès Bélusca-Maïto                 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
23236f19c83bSHermès Bélusca-Maïto                 {
232484f3e2dfSHermès Bélusca-Maïto                     CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
232584f3e2dfSHermès Bélusca-Maïto                     return CurrentPart;
23266f19c83bSHermès Bélusca-Maïto                 }
23276f19c83bSHermès Bélusca-Maïto             }
23286f19c83bSHermès Bélusca-Maïto         }
23296f19c83bSHermès Bélusca-Maïto         else
23306f19c83bSHermès Bélusca-Maïto         {
23316f19c83bSHermès Bélusca-Maïto             /* Primary or extended partition */
23326f19c83bSHermès Bélusca-Maïto 
233384f3e2dfSHermès Bélusca-Maïto             if (CurrentPart->IsPartitioned &&
233484f3e2dfSHermès Bélusca-Maïto                 IsContainerPartition(CurrentPart->PartitionType))
23356f19c83bSHermès Bélusca-Maïto             {
23366f19c83bSHermès Bélusca-Maïto                 /* First logical partition */
233784f3e2dfSHermès Bélusca-Maïto                 PartListEntry = CurrentDisk->LogicalPartListHead.Flink;
233884f3e2dfSHermès Bélusca-Maïto                 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
23396f19c83bSHermès Bélusca-Maïto                 {
234084f3e2dfSHermès Bélusca-Maïto                     CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
234184f3e2dfSHermès Bélusca-Maïto                     return CurrentPart;
23426f19c83bSHermès Bélusca-Maïto                 }
23436f19c83bSHermès Bélusca-Maïto             }
23446f19c83bSHermès Bélusca-Maïto             else
23456f19c83bSHermès Bélusca-Maïto             {
23466f19c83bSHermès Bélusca-Maïto                 /* Next primary partition */
234784f3e2dfSHermès Bélusca-Maïto                 PartListEntry = CurrentPart->ListEntry.Flink;
234884f3e2dfSHermès Bélusca-Maïto                 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
23496f19c83bSHermès Bélusca-Maïto                 {
235084f3e2dfSHermès Bélusca-Maïto                     CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
235184f3e2dfSHermès Bélusca-Maïto                     return CurrentPart;
23526f19c83bSHermès Bélusca-Maïto                 }
23536f19c83bSHermès Bélusca-Maïto             }
23546f19c83bSHermès Bélusca-Maïto         }
23556f19c83bSHermès Bélusca-Maïto     }
23566f19c83bSHermès Bélusca-Maïto 
23576f19c83bSHermès Bélusca-Maïto     /* Search for the first partition entry on the next disk */
235884f3e2dfSHermès Bélusca-Maïto     for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Flink
235984f3e2dfSHermès Bélusca-Maïto                                       : List->DiskListHead.Flink);
23608bed4adfSHermès Bélusca-Maïto          DiskListEntry != &List->DiskListHead;
23618bed4adfSHermès Bélusca-Maïto          DiskListEntry = DiskListEntry->Flink)
23626f19c83bSHermès Bélusca-Maïto     {
236384f3e2dfSHermès Bélusca-Maïto         CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
23646f19c83bSHermès Bélusca-Maïto 
236584f3e2dfSHermès Bélusca-Maïto         if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
2366a3168373SHermès Bélusca-Maïto         {
2367a3168373SHermès Bélusca-Maïto             DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2368a3168373SHermès Bélusca-Maïto             continue;
2369a3168373SHermès Bélusca-Maïto         }
2370a3168373SHermès Bélusca-Maïto 
237184f3e2dfSHermès Bélusca-Maïto         PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
237284f3e2dfSHermès Bélusca-Maïto         if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
23736f19c83bSHermès Bélusca-Maïto         {
237484f3e2dfSHermès Bélusca-Maïto             CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
237584f3e2dfSHermès Bélusca-Maïto             return CurrentPart;
23766f19c83bSHermès Bélusca-Maïto         }
23776f19c83bSHermès Bélusca-Maïto     }
23786f19c83bSHermès Bélusca-Maïto 
23796f19c83bSHermès Bélusca-Maïto     return NULL;
23806f19c83bSHermès Bélusca-Maïto }
23816f19c83bSHermès Bélusca-Maïto 
23826f19c83bSHermès Bélusca-Maïto PPARTENTRY
GetPrevPartition(IN PPARTLIST List,IN PPARTENTRY CurrentPart OPTIONAL)23836f19c83bSHermès Bélusca-Maïto GetPrevPartition(
238484f3e2dfSHermès Bélusca-Maïto     IN PPARTLIST List,
238584f3e2dfSHermès Bélusca-Maïto     IN PPARTENTRY CurrentPart OPTIONAL)
23866f19c83bSHermès Bélusca-Maïto {
23876f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY DiskListEntry;
23886f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY PartListEntry;
238984f3e2dfSHermès Bélusca-Maïto     PDISKENTRY CurrentDisk;
23906f19c83bSHermès Bélusca-Maïto 
23916f19c83bSHermès Bélusca-Maïto     /* Fail if no disks are available */
23926f19c83bSHermès Bélusca-Maïto     if (IsListEmpty(&List->DiskListHead))
23936f19c83bSHermès Bélusca-Maïto         return NULL;
23946f19c83bSHermès Bélusca-Maïto 
239584f3e2dfSHermès Bélusca-Maïto     /* Check for the previous usable entry on the current partition's disk */
239684f3e2dfSHermès Bélusca-Maïto     if (CurrentPart != NULL)
23976f19c83bSHermès Bélusca-Maïto     {
239884f3e2dfSHermès Bélusca-Maïto         CurrentDisk = CurrentPart->DiskEntry;
239984f3e2dfSHermès Bélusca-Maïto 
240084f3e2dfSHermès Bélusca-Maïto         if (CurrentPart->LogicalPartition)
24016f19c83bSHermès Bélusca-Maïto         {
24026f19c83bSHermès Bélusca-Maïto             /* Logical partition */
240384f3e2dfSHermès Bélusca-Maïto 
240484f3e2dfSHermès Bélusca-Maïto             PartListEntry = CurrentPart->ListEntry.Blink;
240584f3e2dfSHermès Bélusca-Maïto             if (PartListEntry != &CurrentDisk->LogicalPartListHead)
24066f19c83bSHermès Bélusca-Maïto             {
24076f19c83bSHermès Bélusca-Maïto                 /* Previous logical partition */
240884f3e2dfSHermès Bélusca-Maïto                 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
24096f19c83bSHermès Bélusca-Maïto             }
24106f19c83bSHermès Bélusca-Maïto             else
24116f19c83bSHermès Bélusca-Maïto             {
24126f19c83bSHermès Bélusca-Maïto                 /* Extended partition */
241384f3e2dfSHermès Bélusca-Maïto                 CurrentPart = CurrentDisk->ExtendedPartition;
24146f19c83bSHermès Bélusca-Maïto             }
241584f3e2dfSHermès Bélusca-Maïto             return CurrentPart;
24166f19c83bSHermès Bélusca-Maïto         }
24176f19c83bSHermès Bélusca-Maïto         else
24186f19c83bSHermès Bélusca-Maïto         {
24196f19c83bSHermès Bélusca-Maïto             /* Primary or extended partition */
24206f19c83bSHermès Bélusca-Maïto 
242184f3e2dfSHermès Bélusca-Maïto             PartListEntry = CurrentPart->ListEntry.Blink;
242284f3e2dfSHermès Bélusca-Maïto             if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
24236f19c83bSHermès Bélusca-Maïto             {
242484f3e2dfSHermès Bélusca-Maïto                 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
24256f19c83bSHermès Bélusca-Maïto 
242684f3e2dfSHermès Bélusca-Maïto                 if (CurrentPart->IsPartitioned &&
242784f3e2dfSHermès Bélusca-Maïto                     IsContainerPartition(CurrentPart->PartitionType))
24286f19c83bSHermès Bélusca-Maïto                 {
242984f3e2dfSHermès Bélusca-Maïto                     PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
243084f3e2dfSHermès Bélusca-Maïto                     CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
24316f19c83bSHermès Bélusca-Maïto                 }
24326f19c83bSHermès Bélusca-Maïto 
243384f3e2dfSHermès Bélusca-Maïto                 return CurrentPart;
24346f19c83bSHermès Bélusca-Maïto             }
24356f19c83bSHermès Bélusca-Maïto         }
24366f19c83bSHermès Bélusca-Maïto     }
24376f19c83bSHermès Bélusca-Maïto 
24386f19c83bSHermès Bélusca-Maïto     /* Search for the last partition entry on the previous disk */
243984f3e2dfSHermès Bélusca-Maïto     for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Blink
244084f3e2dfSHermès Bélusca-Maïto                                       : List->DiskListHead.Blink);
24418bed4adfSHermès Bélusca-Maïto          DiskListEntry != &List->DiskListHead;
24428bed4adfSHermès Bélusca-Maïto          DiskListEntry = DiskListEntry->Blink)
24436f19c83bSHermès Bélusca-Maïto     {
244484f3e2dfSHermès Bélusca-Maïto         CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
24456f19c83bSHermès Bélusca-Maïto 
244684f3e2dfSHermès Bélusca-Maïto         if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
2447a3168373SHermès Bélusca-Maïto         {
2448a3168373SHermès Bélusca-Maïto             DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2449a3168373SHermès Bélusca-Maïto             continue;
2450a3168373SHermès Bélusca-Maïto         }
2451a3168373SHermès Bélusca-Maïto 
245284f3e2dfSHermès Bélusca-Maïto         PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
245384f3e2dfSHermès Bélusca-Maïto         if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
24546f19c83bSHermès Bélusca-Maïto         {
245584f3e2dfSHermès Bélusca-Maïto             CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
24566f19c83bSHermès Bélusca-Maïto 
245784f3e2dfSHermès Bélusca-Maïto             if (CurrentPart->IsPartitioned &&
245884f3e2dfSHermès Bélusca-Maïto                 IsContainerPartition(CurrentPart->PartitionType))
24596f19c83bSHermès Bélusca-Maïto             {
246084f3e2dfSHermès Bélusca-Maïto                 PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
246184f3e2dfSHermès Bélusca-Maïto                 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
24626f19c83bSHermès Bélusca-Maïto                 {
246384f3e2dfSHermès Bélusca-Maïto                     CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
246484f3e2dfSHermès Bélusca-Maïto                     return CurrentPart;
24656f19c83bSHermès Bélusca-Maïto                 }
24666f19c83bSHermès Bélusca-Maïto             }
24676f19c83bSHermès Bélusca-Maïto             else
24686f19c83bSHermès Bélusca-Maïto             {
246984f3e2dfSHermès Bélusca-Maïto                 return CurrentPart;
24706f19c83bSHermès Bélusca-Maïto             }
24716f19c83bSHermès Bélusca-Maïto         }
24726f19c83bSHermès Bélusca-Maïto     }
24736f19c83bSHermès Bélusca-Maïto 
24746f19c83bSHermès Bélusca-Maïto     return NULL;
24756f19c83bSHermès Bélusca-Maïto }
24766f19c83bSHermès Bélusca-Maïto 
2477b7ad4a22SHermès Bélusca-Maïto static inline
24786f19c83bSHermès Bélusca-Maïto BOOLEAN
IsEmptyLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo)24796f19c83bSHermès Bélusca-Maïto IsEmptyLayoutEntry(
2480b7ad4a22SHermès Bélusca-Maïto     _In_ PPARTITION_INFORMATION PartitionInfo)
24816f19c83bSHermès Bélusca-Maïto {
2482b7ad4a22SHermès Bélusca-Maïto     return (PartitionInfo->StartingOffset.QuadPart == 0 &&
2483b7ad4a22SHermès Bélusca-Maïto             PartitionInfo->PartitionLength.QuadPart == 0);
24846f19c83bSHermès Bélusca-Maïto }
24856f19c83bSHermès Bélusca-Maïto 
2486b7ad4a22SHermès Bélusca-Maïto static inline
24876f19c83bSHermès Bélusca-Maïto BOOLEAN
IsSamePrimaryLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo,_In_ PPARTENTRY PartEntry)24886f19c83bSHermès Bélusca-Maïto IsSamePrimaryLayoutEntry(
2489b7ad4a22SHermès Bélusca-Maïto     _In_ PPARTITION_INFORMATION PartitionInfo,
2490b7ad4a22SHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry)
24916f19c83bSHermès Bélusca-Maïto {
2492b7ad4a22SHermès Bélusca-Maïto     return ((PartitionInfo->StartingOffset.QuadPart == GetPartEntryOffsetInBytes(PartEntry)) &&
2493b7ad4a22SHermès Bélusca-Maïto             (PartitionInfo->PartitionLength.QuadPart == GetPartEntrySizeInBytes(PartEntry)));
24946f19c83bSHermès Bélusca-Maïto //        PartitionInfo->PartitionType == PartEntry->PartitionType
24956f19c83bSHermès Bélusca-Maïto }
24966f19c83bSHermès Bélusca-Maïto 
24977639cb75SHermès Bélusca-Maïto 
24987639cb75SHermès Bélusca-Maïto /**
24997639cb75SHermès Bélusca-Maïto  * @brief
25007639cb75SHermès Bélusca-Maïto  * Counts the number of partitioned disk regions in a given partition list.
25017639cb75SHermès Bélusca-Maïto  **/
25026f19c83bSHermès Bélusca-Maïto static
25036f19c83bSHermès Bélusca-Maïto ULONG
GetPartitionCount(_In_ PLIST_ENTRY PartListHead)25047639cb75SHermès Bélusca-Maïto GetPartitionCount(
25057639cb75SHermès Bélusca-Maïto     _In_ PLIST_ENTRY PartListHead)
25066f19c83bSHermès Bélusca-Maïto {
25076f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
25086f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
25096f19c83bSHermès Bélusca-Maïto     ULONG Count = 0;
25106f19c83bSHermès Bélusca-Maïto 
25117639cb75SHermès Bélusca-Maïto     for (Entry = PartListHead->Flink;
25127639cb75SHermès Bélusca-Maïto          Entry != PartListHead;
25138bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
25146f19c83bSHermès Bélusca-Maïto     {
25156f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
25166f19c83bSHermès Bélusca-Maïto         if (PartEntry->IsPartitioned)
25177639cb75SHermès Bélusca-Maïto             ++Count;
25186f19c83bSHermès Bélusca-Maïto     }
25196f19c83bSHermès Bélusca-Maïto 
25206f19c83bSHermès Bélusca-Maïto     return Count;
25216f19c83bSHermès Bélusca-Maïto }
25226f19c83bSHermès Bélusca-Maïto 
25237639cb75SHermès Bélusca-Maïto #define GetPrimaryPartitionCount(DiskEntry) \
25247639cb75SHermès Bélusca-Maïto     GetPartitionCount(&(DiskEntry)->PrimaryPartListHead)
25256f19c83bSHermès Bélusca-Maïto 
25267639cb75SHermès Bélusca-Maïto #define GetLogicalPartitionCount(DiskEntry) \
25277639cb75SHermès Bélusca-Maïto     (((DiskEntry)->DiskStyle == PARTITION_STYLE_MBR) \
25287639cb75SHermès Bélusca-Maïto         ? GetPartitionCount(&(DiskEntry)->LogicalPartListHead) : 0)
2529a3168373SHermès Bélusca-Maïto 
25306f19c83bSHermès Bélusca-Maïto 
25316f19c83bSHermès Bélusca-Maïto static
25326f19c83bSHermès Bélusca-Maïto BOOLEAN
ReAllocateLayoutBuffer(IN PDISKENTRY DiskEntry)25336f19c83bSHermès Bélusca-Maïto ReAllocateLayoutBuffer(
25346f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
25356f19c83bSHermès Bélusca-Maïto {
25366f19c83bSHermès Bélusca-Maïto     PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
25376f19c83bSHermès Bélusca-Maïto     ULONG NewPartitionCount;
25386f19c83bSHermès Bélusca-Maïto     ULONG CurrentPartitionCount = 0;
25396f19c83bSHermès Bélusca-Maïto     ULONG LayoutBufferSize;
25406f19c83bSHermès Bélusca-Maïto     ULONG i;
25416f19c83bSHermès Bélusca-Maïto 
25426f19c83bSHermès Bélusca-Maïto     DPRINT1("ReAllocateLayoutBuffer()\n");
25436f19c83bSHermès Bélusca-Maïto 
25446f19c83bSHermès Bélusca-Maïto     NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
25456f19c83bSHermès Bélusca-Maïto 
25466f19c83bSHermès Bélusca-Maïto     if (DiskEntry->LayoutBuffer)
25476f19c83bSHermès Bélusca-Maïto         CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
25486f19c83bSHermès Bélusca-Maïto 
25497df92966SHermès Bélusca-Maïto     DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
25506f19c83bSHermès Bélusca-Maïto             CurrentPartitionCount, NewPartitionCount);
25516f19c83bSHermès Bélusca-Maïto 
25526f19c83bSHermès Bélusca-Maïto     if (CurrentPartitionCount == NewPartitionCount)
25536f19c83bSHermès Bélusca-Maïto         return TRUE;
25546f19c83bSHermès Bélusca-Maïto 
25556f19c83bSHermès Bélusca-Maïto     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
25566f19c83bSHermès Bélusca-Maïto                        ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
25576f19c83bSHermès Bélusca-Maïto     NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
25586f19c83bSHermès Bélusca-Maïto                                         HEAP_ZERO_MEMORY,
25596f19c83bSHermès Bélusca-Maïto                                         DiskEntry->LayoutBuffer,
25606f19c83bSHermès Bélusca-Maïto                                         LayoutBufferSize);
25616f19c83bSHermès Bélusca-Maïto     if (NewLayoutBuffer == NULL)
25626f19c83bSHermès Bélusca-Maïto     {
25636f19c83bSHermès Bélusca-Maïto         DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
25646f19c83bSHermès Bélusca-Maïto         return FALSE;
25656f19c83bSHermès Bélusca-Maïto     }
25666f19c83bSHermès Bélusca-Maïto 
25677df92966SHermès Bélusca-Maïto     NewLayoutBuffer->PartitionCount = NewPartitionCount;
25687df92966SHermès Bélusca-Maïto 
25696f19c83bSHermès Bélusca-Maïto     /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
25706f19c83bSHermès Bélusca-Maïto     if (NewPartitionCount > CurrentPartitionCount)
25716f19c83bSHermès Bélusca-Maïto     {
25726f19c83bSHermès Bélusca-Maïto         for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
25737df92966SHermès Bélusca-Maïto         {
25746f19c83bSHermès Bélusca-Maïto             NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
25756f19c83bSHermès Bélusca-Maïto         }
25767df92966SHermès Bélusca-Maïto     }
25776f19c83bSHermès Bélusca-Maïto 
25786f19c83bSHermès Bélusca-Maïto     DiskEntry->LayoutBuffer = NewLayoutBuffer;
25796f19c83bSHermès Bélusca-Maïto 
25806f19c83bSHermès Bélusca-Maïto     return TRUE;
25816f19c83bSHermès Bélusca-Maïto }
25826f19c83bSHermès Bélusca-Maïto 
25836f19c83bSHermès Bélusca-Maïto static
25846f19c83bSHermès Bélusca-Maïto VOID
UpdateDiskLayout(IN PDISKENTRY DiskEntry)25856f19c83bSHermès Bélusca-Maïto UpdateDiskLayout(
25866f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
25876f19c83bSHermès Bélusca-Maïto {
25886f19c83bSHermès Bélusca-Maïto     PPARTITION_INFORMATION PartitionInfo;
258999f0937fSHermès Bélusca-Maïto     PPARTITION_INFORMATION LinkInfo;
25906f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
25916f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
25926f19c83bSHermès Bélusca-Maïto     LARGE_INTEGER HiddenSectors64;
25936f19c83bSHermès Bélusca-Maïto     ULONG Index;
25946f19c83bSHermès Bélusca-Maïto     ULONG PartitionNumber = 1;
25956f19c83bSHermès Bélusca-Maïto 
25966f19c83bSHermès Bélusca-Maïto     DPRINT1("UpdateDiskLayout()\n");
25976f19c83bSHermès Bélusca-Maïto 
2598a3168373SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2599a3168373SHermès Bélusca-Maïto     {
260029cc1843SHermès Bélusca-Maïto         DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2601a3168373SHermès Bélusca-Maïto         return;
2602a3168373SHermès Bélusca-Maïto     }
2603a3168373SHermès Bélusca-Maïto 
26046f19c83bSHermès Bélusca-Maïto     /* Resize the layout buffer if necessary */
26056f15802aSHermès Bélusca-Maïto     if (!ReAllocateLayoutBuffer(DiskEntry))
26066f19c83bSHermès Bélusca-Maïto     {
26076f19c83bSHermès Bélusca-Maïto         DPRINT("ReAllocateLayoutBuffer() failed.\n");
26086f19c83bSHermès Bélusca-Maïto         return;
26096f19c83bSHermès Bélusca-Maïto     }
26106f19c83bSHermès Bélusca-Maïto 
26116f19c83bSHermès Bélusca-Maïto     /* Update the primary partition table */
26126f19c83bSHermès Bélusca-Maïto     Index = 0;
26138bed4adfSHermès Bélusca-Maïto     for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
26148bed4adfSHermès Bélusca-Maïto          ListEntry != &DiskEntry->PrimaryPartListHead;
26158bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
26166f19c83bSHermès Bélusca-Maïto     {
26176f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
26186f19c83bSHermès Bélusca-Maïto 
26197df92966SHermès Bélusca-Maïto         if (PartEntry->IsPartitioned)
26206f19c83bSHermès Bélusca-Maïto         {
262129cc1843SHermès Bélusca-Maïto             ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
262229cc1843SHermès Bélusca-Maïto 
26236f19c83bSHermès Bélusca-Maïto             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
26247df92966SHermès Bélusca-Maïto             PartEntry->PartitionIndex = Index;
26257df92966SHermès Bélusca-Maïto 
26266f15802aSHermès Bélusca-Maïto             /* Reset the current partition number only for not-yet written partitions */
26277df92966SHermès Bélusca-Maïto             if (PartEntry->New)
26287df92966SHermès Bélusca-Maïto                 PartEntry->PartitionNumber = 0;
26297df92966SHermès Bélusca-Maïto 
263029cc1843SHermès Bélusca-Maïto             PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0);
26316f19c83bSHermès Bélusca-Maïto 
2632b7ad4a22SHermès Bélusca-Maïto             if (!IsSamePrimaryLayoutEntry(PartitionInfo, PartEntry))
26336f19c83bSHermès Bélusca-Maïto             {
26346f19c83bSHermès Bélusca-Maïto                 DPRINT1("Updating primary partition entry %lu\n", Index);
26356f19c83bSHermès Bélusca-Maïto 
2636b7ad4a22SHermès Bélusca-Maïto                 PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
2637b7ad4a22SHermès Bélusca-Maïto                 PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry);
26386f19c83bSHermès Bélusca-Maïto                 PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
26397df92966SHermès Bélusca-Maïto                 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
26406f19c83bSHermès Bélusca-Maïto                 PartitionInfo->PartitionType = PartEntry->PartitionType;
26416f19c83bSHermès Bélusca-Maïto                 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
26427df92966SHermès Bélusca-Maïto                 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
26436f19c83bSHermès Bélusca-Maïto                 PartitionInfo->RewritePartition = TRUE;
26446f19c83bSHermès Bélusca-Maïto             }
26456f19c83bSHermès Bélusca-Maïto 
26466f19c83bSHermès Bélusca-Maïto             if (!IsContainerPartition(PartEntry->PartitionType))
26476f19c83bSHermès Bélusca-Maïto                 PartitionNumber++;
26486f19c83bSHermès Bélusca-Maïto 
26496f19c83bSHermès Bélusca-Maïto             Index++;
26506f19c83bSHermès Bélusca-Maïto         }
26516f19c83bSHermès Bélusca-Maïto     }
26526f19c83bSHermès Bélusca-Maïto 
265370fa2e2eSHermès Bélusca-Maïto     ASSERT(Index <= 4);
265470fa2e2eSHermès Bélusca-Maïto 
26556f19c83bSHermès Bélusca-Maïto     /* Update the logical partition table */
265699f0937fSHermès Bélusca-Maïto     LinkInfo = NULL;
26576f19c83bSHermès Bélusca-Maïto     Index = 4;
26588bed4adfSHermès Bélusca-Maïto     for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
26598bed4adfSHermès Bélusca-Maïto          ListEntry != &DiskEntry->LogicalPartListHead;
26608bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
26616f19c83bSHermès Bélusca-Maïto     {
26626f19c83bSHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
26636f19c83bSHermès Bélusca-Maïto 
26646f19c83bSHermès Bélusca-Maïto         if (PartEntry->IsPartitioned)
26656f19c83bSHermès Bélusca-Maïto         {
266629cc1843SHermès Bélusca-Maïto             ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
266729cc1843SHermès Bélusca-Maïto 
26686f19c83bSHermès Bélusca-Maïto             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
26697df92966SHermès Bélusca-Maïto             PartEntry->PartitionIndex = Index;
26706f19c83bSHermès Bélusca-Maïto 
26716f15802aSHermès Bélusca-Maïto             /* Reset the current partition number only for not-yet written partitions */
26727df92966SHermès Bélusca-Maïto             if (PartEntry->New)
26737df92966SHermès Bélusca-Maïto                 PartEntry->PartitionNumber = 0;
26747df92966SHermès Bélusca-Maïto 
26757df92966SHermès Bélusca-Maïto             PartEntry->OnDiskPartitionNumber = PartitionNumber;
26767df92966SHermès Bélusca-Maïto 
267729cc1843SHermès Bélusca-Maïto             DPRINT1("Updating logical partition entry %lu\n", Index);
267829cc1843SHermès Bélusca-Maïto 
2679b7ad4a22SHermès Bélusca-Maïto             PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
2680b7ad4a22SHermès Bélusca-Maïto             PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry);
26816f19c83bSHermès Bélusca-Maïto             PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
26827df92966SHermès Bélusca-Maïto             PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
26836f19c83bSHermès Bélusca-Maïto             PartitionInfo->PartitionType = PartEntry->PartitionType;
26846f19c83bSHermès Bélusca-Maïto             PartitionInfo->BootIndicator = FALSE;
26857df92966SHermès Bélusca-Maïto             PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
26866f19c83bSHermès Bélusca-Maïto             PartitionInfo->RewritePartition = TRUE;
26876f19c83bSHermès Bélusca-Maïto 
26886f19c83bSHermès Bélusca-Maïto             /* Fill the link entry of the previous partition entry */
268999f0937fSHermès Bélusca-Maïto             if (LinkInfo)
26906f19c83bSHermès Bélusca-Maïto             {
26916f19c83bSHermès Bélusca-Maïto                 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
26926f19c83bSHermès Bélusca-Maïto                 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
26936f19c83bSHermès Bélusca-Maïto                 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
26946f19c83bSHermès Bélusca-Maïto                 LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
26956f19c83bSHermès Bélusca-Maïto                 LinkInfo->PartitionNumber = 0;
269699f0937fSHermès Bélusca-Maïto 
269799f0937fSHermès Bélusca-Maïto                 /* Extended partition links only use type 0x05, as observed
269899f0937fSHermès Bélusca-Maïto                  * on Windows NT. Alternatively they could inherit the type
269999f0937fSHermès Bélusca-Maïto                  * of the main extended container. */
270099f0937fSHermès Bélusca-Maïto                 LinkInfo->PartitionType = PARTITION_EXTENDED; // DiskEntry->ExtendedPartition->PartitionType;
270199f0937fSHermès Bélusca-Maïto 
27026f19c83bSHermès Bélusca-Maïto                 LinkInfo->BootIndicator = FALSE;
27036f19c83bSHermès Bélusca-Maïto                 LinkInfo->RecognizedPartition = FALSE;
27046f19c83bSHermès Bélusca-Maïto                 LinkInfo->RewritePartition = TRUE;
27056f19c83bSHermès Bélusca-Maïto             }
27066f19c83bSHermès Bélusca-Maïto 
27076f19c83bSHermès Bélusca-Maïto             /* Save a pointer to the link entry of the current partition entry */
27086f19c83bSHermès Bélusca-Maïto             LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
27096f19c83bSHermès Bélusca-Maïto 
27106f19c83bSHermès Bélusca-Maïto             PartitionNumber++;
27116f19c83bSHermès Bélusca-Maïto             Index += 4;
27126f19c83bSHermès Bélusca-Maïto         }
27136f19c83bSHermès Bélusca-Maïto     }
27146f19c83bSHermès Bélusca-Maïto 
27156f19c83bSHermès Bélusca-Maïto     /* Wipe unused primary partition entries */
27166f19c83bSHermès Bélusca-Maïto     for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
27176f19c83bSHermès Bélusca-Maïto     {
27186f19c83bSHermès Bélusca-Maïto         DPRINT1("Primary partition entry %lu\n", Index);
27196f19c83bSHermès Bélusca-Maïto 
27206f19c83bSHermès Bélusca-Maïto         PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
27216f19c83bSHermès Bélusca-Maïto 
27226f19c83bSHermès Bélusca-Maïto         if (!IsEmptyLayoutEntry(PartitionInfo))
27236f19c83bSHermès Bélusca-Maïto         {
27246f19c83bSHermès Bélusca-Maïto             DPRINT1("Wiping primary partition entry %lu\n", Index);
27256f19c83bSHermès Bélusca-Maïto 
27266f19c83bSHermès Bélusca-Maïto             PartitionInfo->StartingOffset.QuadPart = 0;
27276f19c83bSHermès Bélusca-Maïto             PartitionInfo->PartitionLength.QuadPart = 0;
27286f19c83bSHermès Bélusca-Maïto             PartitionInfo->HiddenSectors = 0;
27296f19c83bSHermès Bélusca-Maïto             PartitionInfo->PartitionNumber = 0;
27306f19c83bSHermès Bélusca-Maïto             PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
27316f19c83bSHermès Bélusca-Maïto             PartitionInfo->BootIndicator = FALSE;
27326f19c83bSHermès Bélusca-Maïto             PartitionInfo->RecognizedPartition = FALSE;
27336f19c83bSHermès Bélusca-Maïto             PartitionInfo->RewritePartition = TRUE;
27346f19c83bSHermès Bélusca-Maïto         }
27356f19c83bSHermès Bélusca-Maïto     }
27366f19c83bSHermès Bélusca-Maïto 
27376f19c83bSHermès Bélusca-Maïto     /* Wipe unused logical partition entries */
27386f19c83bSHermès Bélusca-Maïto     for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
27396f19c83bSHermès Bélusca-Maïto     {
27406f19c83bSHermès Bélusca-Maïto         if (Index % 4 >= 2)
27416f19c83bSHermès Bélusca-Maïto         {
27426f19c83bSHermès Bélusca-Maïto             DPRINT1("Logical partition entry %lu\n", Index);
27436f19c83bSHermès Bélusca-Maïto 
27446f19c83bSHermès Bélusca-Maïto             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
27456f19c83bSHermès Bélusca-Maïto 
27466f19c83bSHermès Bélusca-Maïto             if (!IsEmptyLayoutEntry(PartitionInfo))
27476f19c83bSHermès Bélusca-Maïto             {
27486f19c83bSHermès Bélusca-Maïto                 DPRINT1("Wiping partition entry %lu\n", Index);
27496f19c83bSHermès Bélusca-Maïto 
27506f19c83bSHermès Bélusca-Maïto                 PartitionInfo->StartingOffset.QuadPart = 0;
27516f19c83bSHermès Bélusca-Maïto                 PartitionInfo->PartitionLength.QuadPart = 0;
27526f19c83bSHermès Bélusca-Maïto                 PartitionInfo->HiddenSectors = 0;
27536f19c83bSHermès Bélusca-Maïto                 PartitionInfo->PartitionNumber = 0;
27546f19c83bSHermès Bélusca-Maïto                 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
27556f19c83bSHermès Bélusca-Maïto                 PartitionInfo->BootIndicator = FALSE;
27566f19c83bSHermès Bélusca-Maïto                 PartitionInfo->RecognizedPartition = FALSE;
27576f19c83bSHermès Bélusca-Maïto                 PartitionInfo->RewritePartition = TRUE;
27586f19c83bSHermès Bélusca-Maïto             }
27596f19c83bSHermès Bélusca-Maïto         }
27606f19c83bSHermès Bélusca-Maïto     }
27616f19c83bSHermès Bélusca-Maïto 
2762a59cecd8SHermès Bélusca-Maïto     // HACK: See the FIXMEs in WritePartitions(): (Re)set the PartitionStyle to MBR.
2763a59cecd8SHermès Bélusca-Maïto     DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
2764a59cecd8SHermès Bélusca-Maïto 
27657df92966SHermès Bélusca-Maïto     DiskEntry->Dirty = TRUE;
27667df92966SHermès Bélusca-Maïto 
27676f19c83bSHermès Bélusca-Maïto #ifdef DUMP_PARTITION_TABLE
27686f19c83bSHermès Bélusca-Maïto     DumpPartitionTable(DiskEntry);
27696f19c83bSHermès Bélusca-Maïto #endif
27706f19c83bSHermès Bélusca-Maïto }
27716f19c83bSHermès Bélusca-Maïto 
27727639cb75SHermès Bélusca-Maïto /**
27737639cb75SHermès Bélusca-Maïto  * @brief
27747639cb75SHermès Bélusca-Maïto  * Retrieves, if any, the unpartitioned disk region that is adjacent
27757639cb75SHermès Bélusca-Maïto  * (next or previous) to the specified partition.
27767639cb75SHermès Bélusca-Maïto  *
27777639cb75SHermès Bélusca-Maïto  * @param[in]   PartEntry
27787639cb75SHermès Bélusca-Maïto  * Partition from where to find the adjacent unpartitioned region.
27797639cb75SHermès Bélusca-Maïto  *
27807639cb75SHermès Bélusca-Maïto  * @param[in]   Direction
27817639cb75SHermès Bélusca-Maïto  * TRUE or FALSE to search the next or previous region, respectively.
27827639cb75SHermès Bélusca-Maïto  *
27837639cb75SHermès Bélusca-Maïto  * @return  The adjacent unpartitioned region, if it exists, or NULL.
27847639cb75SHermès Bélusca-Maïto  **/
27856f19c83bSHermès Bélusca-Maïto PPARTENTRY
GetAdjUnpartitionedEntry(_In_ PPARTENTRY PartEntry,_In_ BOOLEAN Direction)27867639cb75SHermès Bélusca-Maïto GetAdjUnpartitionedEntry(
27877639cb75SHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry,
27887639cb75SHermès Bélusca-Maïto     _In_ BOOLEAN Direction)
27896f19c83bSHermès Bélusca-Maïto {
279084f3e2dfSHermès Bélusca-Maïto     PDISKENTRY DiskEntry = PartEntry->DiskEntry;
27917639cb75SHermès Bélusca-Maïto     PLIST_ENTRY ListHead, AdjEntry;
27926f19c83bSHermès Bélusca-Maïto 
27937639cb75SHermès Bélusca-Maïto     /* In case of MBR disks only, check the logical partitions if necessary */
27947639cb75SHermès Bélusca-Maïto     if ((DiskEntry->DiskStyle == PARTITION_STYLE_MBR) &&
27957639cb75SHermès Bélusca-Maïto         PartEntry->LogicalPartition)
2796a3168373SHermès Bélusca-Maïto     {
27976f19c83bSHermès Bélusca-Maïto         ListHead = &DiskEntry->LogicalPartListHead;
27987639cb75SHermès Bélusca-Maïto     }
27996f19c83bSHermès Bélusca-Maïto     else
28007639cb75SHermès Bélusca-Maïto     {
28016f19c83bSHermès Bélusca-Maïto         ListHead = &DiskEntry->PrimaryPartListHead;
280229cc1843SHermès Bélusca-Maïto     }
28036f19c83bSHermès Bélusca-Maïto 
28047639cb75SHermès Bélusca-Maïto     if (Direction)
28057639cb75SHermès Bélusca-Maïto         AdjEntry = PartEntry->ListEntry.Flink; // Next region.
28066f19c83bSHermès Bélusca-Maïto     else
28077639cb75SHermès Bélusca-Maïto         AdjEntry = PartEntry->ListEntry.Blink; // Previous region.
28086f19c83bSHermès Bélusca-Maïto 
28097639cb75SHermès Bélusca-Maïto     if (AdjEntry != ListHead)
28106f19c83bSHermès Bélusca-Maïto     {
28117639cb75SHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(AdjEntry, PARTENTRY, ListEntry);
28127639cb75SHermès Bélusca-Maïto         if (!PartEntry->IsPartitioned)
281329cc1843SHermès Bélusca-Maïto         {
28147639cb75SHermès Bélusca-Maïto             ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
28157639cb75SHermès Bélusca-Maïto             return PartEntry;
28166f19c83bSHermès Bélusca-Maïto         }
281729cc1843SHermès Bélusca-Maïto     }
28186f19c83bSHermès Bélusca-Maïto     return NULL;
28196f19c83bSHermès Bélusca-Maïto }
28206f19c83bSHermès Bélusca-Maïto 
2821ebcf3cf3SHermès Bélusca-Maïto ERROR_NUMBER
PartitionCreationChecks(_In_ PPARTENTRY PartEntry)2822ebcf3cf3SHermès Bélusca-Maïto PartitionCreationChecks(
2823ebcf3cf3SHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry)
2824ebcf3cf3SHermès Bélusca-Maïto {
2825ebcf3cf3SHermès Bélusca-Maïto     PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2826ebcf3cf3SHermès Bélusca-Maïto 
2827ebcf3cf3SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2828ebcf3cf3SHermès Bélusca-Maïto     {
2829ebcf3cf3SHermès Bélusca-Maïto         DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2830ebcf3cf3SHermès Bélusca-Maïto         return ERROR_WARN_PARTITION;
2831ebcf3cf3SHermès Bélusca-Maïto     }
2832ebcf3cf3SHermès Bélusca-Maïto 
2833ebcf3cf3SHermès Bélusca-Maïto     /* Fail if the partition is already in use */
2834ebcf3cf3SHermès Bélusca-Maïto     if (PartEntry->IsPartitioned)
2835ebcf3cf3SHermès Bélusca-Maïto         return ERROR_NEW_PARTITION;
2836ebcf3cf3SHermès Bélusca-Maïto 
2837ebcf3cf3SHermès Bélusca-Maïto     /*
2838ebcf3cf3SHermès Bélusca-Maïto      * For primary partitions
2839ebcf3cf3SHermès Bélusca-Maïto      */
2840ebcf3cf3SHermès Bélusca-Maïto     if (!PartEntry->LogicalPartition)
2841ebcf3cf3SHermès Bélusca-Maïto     {
2842ebcf3cf3SHermès Bélusca-Maïto         /* Only one primary partition is allowed on super-floppy */
2843ebcf3cf3SHermès Bélusca-Maïto         if (IsSuperFloppy(DiskEntry))
2844ebcf3cf3SHermès Bélusca-Maïto             return ERROR_PARTITION_TABLE_FULL;
2845ebcf3cf3SHermès Bélusca-Maïto 
2846ebcf3cf3SHermès Bélusca-Maïto         /* Fail if there are already 4 primary partitions in the list */
2847ebcf3cf3SHermès Bélusca-Maïto         if (GetPrimaryPartitionCount(DiskEntry) >= 4)
2848ebcf3cf3SHermès Bélusca-Maïto             return ERROR_PARTITION_TABLE_FULL;
2849ebcf3cf3SHermès Bélusca-Maïto     }
2850ebcf3cf3SHermès Bélusca-Maïto     /*
2851ebcf3cf3SHermès Bélusca-Maïto      * For logical partitions
2852ebcf3cf3SHermès Bélusca-Maïto      */
2853ebcf3cf3SHermès Bélusca-Maïto     else
2854ebcf3cf3SHermès Bélusca-Maïto     {
2855ebcf3cf3SHermès Bélusca-Maïto         // TODO: Check that we are inside an extended partition!!
2856ebcf3cf3SHermès Bélusca-Maïto         // Then the following check will be useless.
2857ebcf3cf3SHermès Bélusca-Maïto 
2858ebcf3cf3SHermès Bélusca-Maïto         /* Only one (primary) partition is allowed on super-floppy */
2859ebcf3cf3SHermès Bélusca-Maïto         if (IsSuperFloppy(DiskEntry))
2860ebcf3cf3SHermès Bélusca-Maïto             return ERROR_PARTITION_TABLE_FULL;
2861ebcf3cf3SHermès Bélusca-Maïto     }
2862ebcf3cf3SHermès Bélusca-Maïto 
2863ebcf3cf3SHermès Bélusca-Maïto     return ERROR_SUCCESS;
2864ebcf3cf3SHermès Bélusca-Maïto }
2865ebcf3cf3SHermès Bélusca-Maïto 
2866ebcf3cf3SHermès Bélusca-Maïto ERROR_NUMBER
ExtendedPartitionCreationChecks(_In_ PPARTENTRY PartEntry)2867ebcf3cf3SHermès Bélusca-Maïto ExtendedPartitionCreationChecks(
2868ebcf3cf3SHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry)
2869ebcf3cf3SHermès Bélusca-Maïto {
2870ebcf3cf3SHermès Bélusca-Maïto     PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2871ebcf3cf3SHermès Bélusca-Maïto 
2872ebcf3cf3SHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2873ebcf3cf3SHermès Bélusca-Maïto     {
2874ebcf3cf3SHermès Bélusca-Maïto         DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2875ebcf3cf3SHermès Bélusca-Maïto         return ERROR_WARN_PARTITION;
2876ebcf3cf3SHermès Bélusca-Maïto     }
2877ebcf3cf3SHermès Bélusca-Maïto 
2878ebcf3cf3SHermès Bélusca-Maïto     /* Fail if the partition is already in use */
2879ebcf3cf3SHermès Bélusca-Maïto     if (PartEntry->IsPartitioned)
2880ebcf3cf3SHermès Bélusca-Maïto         return ERROR_NEW_PARTITION;
2881ebcf3cf3SHermès Bélusca-Maïto 
288299f0937fSHermès Bélusca-Maïto     /* Cannot create an extended partition within logical partition space */
288399f0937fSHermès Bélusca-Maïto     if (PartEntry->LogicalPartition)
288499f0937fSHermès Bélusca-Maïto         return ERROR_ONLY_ONE_EXTENDED;
288599f0937fSHermès Bélusca-Maïto 
2886ebcf3cf3SHermès Bélusca-Maïto     /* Only one primary partition is allowed on super-floppy */
2887ebcf3cf3SHermès Bélusca-Maïto     if (IsSuperFloppy(DiskEntry))
2888ebcf3cf3SHermès Bélusca-Maïto         return ERROR_PARTITION_TABLE_FULL;
2889ebcf3cf3SHermès Bélusca-Maïto 
2890ebcf3cf3SHermès Bélusca-Maïto     /* Fail if there are already 4 primary partitions in the list */
2891ebcf3cf3SHermès Bélusca-Maïto     if (GetPrimaryPartitionCount(DiskEntry) >= 4)
2892ebcf3cf3SHermès Bélusca-Maïto         return ERROR_PARTITION_TABLE_FULL;
2893ebcf3cf3SHermès Bélusca-Maïto 
2894ebcf3cf3SHermès Bélusca-Maïto     /* Fail if there is another extended partition in the list */
289599f0937fSHermès Bélusca-Maïto     if (DiskEntry->ExtendedPartition)
2896ebcf3cf3SHermès Bélusca-Maïto         return ERROR_ONLY_ONE_EXTENDED;
2897ebcf3cf3SHermès Bélusca-Maïto 
2898ebcf3cf3SHermès Bélusca-Maïto     return ERROR_SUCCESS;
2899ebcf3cf3SHermès Bélusca-Maïto }
2900ebcf3cf3SHermès Bélusca-Maïto 
290199f0937fSHermès Bélusca-Maïto // TODO: Improve upon the PartitionInfo parameter later
290299f0937fSHermès Bélusca-Maïto // (see VDS::CREATE_PARTITION_PARAMETERS and PPARTITION_INFORMATION_MBR/GPT for example)
290399f0937fSHermès Bélusca-Maïto // So far we only use it as the optional type of the partition to create.
290470fa2e2eSHermès Bélusca-Maïto BOOLEAN
CreatePartition(_In_ PPARTLIST List,_Inout_ PPARTENTRY PartEntry,_In_opt_ ULONGLONG SizeBytes,_In_opt_ ULONG_PTR PartitionInfo)2905ebcf3cf3SHermès Bélusca-Maïto CreatePartition(
2906ebcf3cf3SHermès Bélusca-Maïto     _In_ PPARTLIST List,
2907ebcf3cf3SHermès Bélusca-Maïto     _Inout_ PPARTENTRY PartEntry,
290899f0937fSHermès Bélusca-Maïto     _In_opt_ ULONGLONG SizeBytes,
290999f0937fSHermès Bélusca-Maïto     _In_opt_ ULONG_PTR PartitionInfo)
29106f19c83bSHermès Bélusca-Maïto {
291170fa2e2eSHermès Bélusca-Maïto     ERROR_NUMBER Error;
291299f0937fSHermès Bélusca-Maïto     BOOLEAN isContainer = IsContainerPartition((UCHAR)PartitionInfo);
29136f15802aSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
291499f0937fSHermès Bélusca-Maïto     PCSTR mainType = "Primary";
29156f19c83bSHermès Bélusca-Maïto 
291699f0937fSHermès Bélusca-Maïto     if (isContainer)
291799f0937fSHermès Bélusca-Maïto         mainType = "Extended";
291899f0937fSHermès Bélusca-Maïto     else if (PartEntry && PartEntry->LogicalPartition)
291999f0937fSHermès Bélusca-Maïto         mainType = "Logical";
29206f19c83bSHermès Bélusca-Maïto 
292199f0937fSHermès Bélusca-Maïto     DPRINT1("CreatePartition(%s, %I64u bytes)\n", mainType, SizeBytes);
292299f0937fSHermès Bélusca-Maïto 
292399f0937fSHermès Bélusca-Maïto     if (!List || !PartEntry ||
292499f0937fSHermès Bélusca-Maïto         !PartEntry->DiskEntry || PartEntry->IsPartitioned)
29256f19c83bSHermès Bélusca-Maïto     {
292670fa2e2eSHermès Bélusca-Maïto         return FALSE;
292770fa2e2eSHermès Bélusca-Maïto     }
292870fa2e2eSHermès Bélusca-Maïto 
292999f0937fSHermès Bélusca-Maïto     if (isContainer)
293099f0937fSHermès Bélusca-Maïto         Error = ExtendedPartitionCreationChecks(PartEntry);
293199f0937fSHermès Bélusca-Maïto     else
2932ebcf3cf3SHermès Bélusca-Maïto         Error = PartitionCreationChecks(PartEntry);
293370fa2e2eSHermès Bélusca-Maïto     if (Error != NOT_AN_ERROR)
293470fa2e2eSHermès Bélusca-Maïto     {
293599f0937fSHermès Bélusca-Maïto         DPRINT1("PartitionCreationChecks(%s) failed with error %lu\n", mainType, Error);
293670fa2e2eSHermès Bélusca-Maïto         return FALSE;
29376f19c83bSHermès Bélusca-Maïto     }
29386f19c83bSHermès Bélusca-Maïto 
2939626c654aSHermès Bélusca-Maïto     /* Initialize the partition entry, inserting a new blank region if needed */
294099f0937fSHermès Bélusca-Maïto     if (!InitializePartitionEntry(PartEntry, SizeBytes, PartitionInfo))
294170fa2e2eSHermès Bélusca-Maïto         return FALSE;
29426f19c83bSHermès Bélusca-Maïto 
29436f15802aSHermès Bélusca-Maïto     DiskEntry = PartEntry->DiskEntry;
29446f15802aSHermès Bélusca-Maïto     UpdateDiskLayout(DiskEntry);
29456f15802aSHermès Bélusca-Maïto 
29466f15802aSHermès Bélusca-Maïto     ASSERT(!PartEntry->Volume);
29476f15802aSHermès Bélusca-Maïto     if (!isContainer)
29486f19c83bSHermès Bélusca-Maïto     {
29496f15802aSHermès Bélusca-Maïto         /* We create a primary/logical partition: initialize a new basic
29506f15802aSHermès Bélusca-Maïto          * volume entry. When the partition will actually be written onto
29516f15802aSHermès Bélusca-Maïto          * the disk, the PARTMGR will notify the MOUNTMGR that a volume
29526f15802aSHermès Bélusca-Maïto          * associated with this partition has to be created. */
29536f15802aSHermès Bélusca-Maïto         PartEntry->Volume = InitVolume(DiskEntry->PartList, PartEntry);
29546f15802aSHermès Bélusca-Maïto         ASSERT(PartEntry->Volume);
295599f0937fSHermès Bélusca-Maïto     }
29566f19c83bSHermès Bélusca-Maïto 
29576f19c83bSHermès Bélusca-Maïto     AssignDriveLetters(List);
295870fa2e2eSHermès Bélusca-Maïto 
295970fa2e2eSHermès Bélusca-Maïto     return TRUE;
29606f19c83bSHermès Bélusca-Maïto }
29616f19c83bSHermès Bélusca-Maïto 
29626f15802aSHermès Bélusca-Maïto static NTSTATUS
DismountPartition(_In_ PPARTLIST List,_In_ PPARTENTRY PartEntry)29636f15802aSHermès Bélusca-Maïto DismountPartition(
29646f15802aSHermès Bélusca-Maïto     _In_ PPARTLIST List,
29656f15802aSHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry)
29669504a38fSHermès Bélusca-Maïto {
29679504a38fSHermès Bélusca-Maïto     NTSTATUS Status;
29686f15802aSHermès Bélusca-Maïto     PVOLENTRY Volume = PartEntry->Volume;
29696f15802aSHermès Bélusca-Maïto 
29706f15802aSHermès Bélusca-Maïto     ASSERT(PartEntry->DiskEntry->PartList == List);
29719504a38fSHermès Bélusca-Maïto 
297229cc1843SHermès Bélusca-Maïto     /* Check whether the partition is valid and was mounted by the system */
29739504a38fSHermès Bélusca-Maïto     if (!PartEntry->IsPartitioned ||
29749504a38fSHermès Bélusca-Maïto         IsContainerPartition(PartEntry->PartitionType)   ||
29759504a38fSHermès Bélusca-Maïto         !IsRecognizedPartition(PartEntry->PartitionType) ||
29766f15802aSHermès Bélusca-Maïto         !Volume || Volume->FormatState == UnknownFormat  ||
2977626c654aSHermès Bélusca-Maïto         // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
2978626c654aSHermès Bélusca-Maïto         // it has been usually mounted with RawFS and thus needs to be dismounted.
29799504a38fSHermès Bélusca-Maïto         PartEntry->PartitionNumber == 0)
29809504a38fSHermès Bélusca-Maïto     {
29819504a38fSHermès Bélusca-Maïto         /* The partition is not mounted, so just return success */
29829504a38fSHermès Bélusca-Maïto         return STATUS_SUCCESS;
29839504a38fSHermès Bélusca-Maïto     }
29849504a38fSHermès Bélusca-Maïto 
298529cc1843SHermès Bélusca-Maïto     ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
29866f15802aSHermès Bélusca-Maïto     ASSERT(Volume->PartEntry == PartEntry);
298729cc1843SHermès Bélusca-Maïto 
29886f15802aSHermès Bélusca-Maïto     /* Unlink the basic volume from the volumes list and dismount it */
29896f15802aSHermès Bélusca-Maïto     PartEntry->Volume = NULL;
29906f15802aSHermès Bélusca-Maïto     Volume->PartEntry = NULL;
29916f15802aSHermès Bélusca-Maïto     RemoveEntryList(&Volume->ListEntry);
29926f15802aSHermès Bélusca-Maïto     Status = DismountVolume(&Volume->Info, TRUE);
29936f15802aSHermès Bélusca-Maïto     RtlFreeHeap(ProcessHeap, 0, Volume);
29949504a38fSHermès Bélusca-Maïto     return Status;
29959504a38fSHermès Bélusca-Maïto }
29969504a38fSHermès Bélusca-Maïto 
299784f3e2dfSHermès Bélusca-Maïto BOOLEAN
DeletePartition(_In_ PPARTLIST List,_In_ PPARTENTRY PartEntry,_Out_opt_ PPARTENTRY * FreeRegion)299829cc1843SHermès Bélusca-Maïto DeletePartition(
299999f0937fSHermès Bélusca-Maïto     _In_ PPARTLIST List,
300099f0937fSHermès Bélusca-Maïto     _In_ PPARTENTRY PartEntry,
300199f0937fSHermès Bélusca-Maïto     _Out_opt_ PPARTENTRY* FreeRegion)
30026f19c83bSHermès Bélusca-Maïto {
30036f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
30046f19c83bSHermès Bélusca-Maïto     PPARTENTRY PrevPartEntry;
30056f19c83bSHermès Bélusca-Maïto     PPARTENTRY NextPartEntry;
30066f19c83bSHermès Bélusca-Maïto     PPARTENTRY LogicalPartEntry;
30076f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
30086f19c83bSHermès Bélusca-Maïto 
300999f0937fSHermès Bélusca-Maïto     if (!List || !PartEntry ||
301099f0937fSHermès Bélusca-Maïto         !PartEntry->DiskEntry || !PartEntry->IsPartitioned)
30116f19c83bSHermès Bélusca-Maïto     {
301284f3e2dfSHermès Bélusca-Maïto         return FALSE;
30136f19c83bSHermès Bélusca-Maïto     }
30146f19c83bSHermès Bélusca-Maïto 
30156f15802aSHermès Bélusca-Maïto     ASSERT(PartEntry->DiskEntry->PartList == List);
301629cc1843SHermès Bélusca-Maïto     ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
301729cc1843SHermès Bélusca-Maïto 
301859acff79SHermès Bélusca-Maïto     /* Clear the system partition if it is being deleted */
301929cc1843SHermès Bélusca-Maïto     if (List->SystemPartition == PartEntry)
30206f19c83bSHermès Bélusca-Maïto     {
302129cc1843SHermès Bélusca-Maïto         ASSERT(List->SystemPartition);
30226f19c83bSHermès Bélusca-Maïto         List->SystemPartition = NULL;
30236f19c83bSHermès Bélusca-Maïto     }
30246f19c83bSHermès Bélusca-Maïto 
302529cc1843SHermès Bélusca-Maïto     DiskEntry = PartEntry->DiskEntry;
30266f19c83bSHermès Bélusca-Maïto 
30279504a38fSHermès Bélusca-Maïto     /* Check which type of partition (primary/logical or extended) is being deleted */
30286f19c83bSHermès Bélusca-Maïto     if (DiskEntry->ExtendedPartition == PartEntry)
30296f19c83bSHermès Bélusca-Maïto     {
30309504a38fSHermès Bélusca-Maïto         /* An extended partition is being deleted: delete all logical partition entries */
30316f19c83bSHermès Bélusca-Maïto         while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
30326f19c83bSHermès Bélusca-Maïto         {
30336f19c83bSHermès Bélusca-Maïto             Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
30346f19c83bSHermès Bélusca-Maïto             LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
30356f19c83bSHermès Bélusca-Maïto 
30366f15802aSHermès Bélusca-Maïto             /* Dismount the logical partition and delete it */
30376f15802aSHermès Bélusca-Maïto             DismountPartition(List, LogicalPartEntry);
30386f15802aSHermès Bélusca-Maïto             DestroyRegion(LogicalPartEntry);
30396f19c83bSHermès Bélusca-Maïto         }
30406f19c83bSHermès Bélusca-Maïto 
30416f19c83bSHermès Bélusca-Maïto         DiskEntry->ExtendedPartition = NULL;
30426f19c83bSHermès Bélusca-Maïto     }
30439504a38fSHermès Bélusca-Maïto     else
30449504a38fSHermès Bélusca-Maïto     {
30456f15802aSHermès Bélusca-Maïto         /* A primary/logical partition is being deleted: dismount it */
30466f15802aSHermès Bélusca-Maïto         DismountPartition(List, PartEntry);
30479504a38fSHermès Bélusca-Maïto     }
30486f19c83bSHermès Bélusca-Maïto 
304984f3e2dfSHermès Bélusca-Maïto     /* Adjust the unpartitioned disk space entries */
30506f19c83bSHermès Bélusca-Maïto 
30516f19c83bSHermès Bélusca-Maïto     /* Get pointer to previous and next unpartitioned entries */
30527639cb75SHermès Bélusca-Maïto     PrevPartEntry = GetAdjUnpartitionedEntry(PartEntry, FALSE);
30537639cb75SHermès Bélusca-Maïto     NextPartEntry = GetAdjUnpartitionedEntry(PartEntry, TRUE);
30546f19c83bSHermès Bélusca-Maïto 
30556f19c83bSHermès Bélusca-Maïto     if (PrevPartEntry != NULL && NextPartEntry != NULL)
30566f19c83bSHermès Bélusca-Maïto     {
305784f3e2dfSHermès Bélusca-Maïto         /* Merge the previous, current and next unpartitioned entries */
30586f19c83bSHermès Bélusca-Maïto 
305984f3e2dfSHermès Bélusca-Maïto         /* Adjust the previous entry length */
30606f19c83bSHermès Bélusca-Maïto         PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
30616f19c83bSHermès Bélusca-Maïto 
306284f3e2dfSHermès Bélusca-Maïto         /* Remove the current and next entries */
30636f19c83bSHermès Bélusca-Maïto         RemoveEntryList(&PartEntry->ListEntry);
30646f15802aSHermès Bélusca-Maïto         DestroyRegion(PartEntry);
30656f19c83bSHermès Bélusca-Maïto         RemoveEntryList(&NextPartEntry->ListEntry);
30666f15802aSHermès Bélusca-Maïto         DestroyRegion(NextPartEntry);
30676f19c83bSHermès Bélusca-Maïto 
306884f3e2dfSHermès Bélusca-Maïto         /* Optionally return the freed region */
306984f3e2dfSHermès Bélusca-Maïto         if (FreeRegion)
307084f3e2dfSHermès Bélusca-Maïto             *FreeRegion = PrevPartEntry;
307129cc1843SHermès Bélusca-Maïto     }
30726f19c83bSHermès Bélusca-Maïto     else if (PrevPartEntry != NULL && NextPartEntry == NULL)
30736f19c83bSHermès Bélusca-Maïto     {
307484f3e2dfSHermès Bélusca-Maïto         /* Merge the current and the previous unpartitioned entries */
30756f19c83bSHermès Bélusca-Maïto 
307684f3e2dfSHermès Bélusca-Maïto         /* Adjust the previous entry length */
30776f19c83bSHermès Bélusca-Maïto         PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
30786f19c83bSHermès Bélusca-Maïto 
30796f19c83bSHermès Bélusca-Maïto         /* Remove the current entry */
30806f19c83bSHermès Bélusca-Maïto         RemoveEntryList(&PartEntry->ListEntry);
30816f15802aSHermès Bélusca-Maïto         DestroyRegion(PartEntry);
30826f19c83bSHermès Bélusca-Maïto 
308384f3e2dfSHermès Bélusca-Maïto         /* Optionally return the freed region */
308484f3e2dfSHermès Bélusca-Maïto         if (FreeRegion)
308584f3e2dfSHermès Bélusca-Maïto             *FreeRegion = PrevPartEntry;
308629cc1843SHermès Bélusca-Maïto     }
30876f19c83bSHermès Bélusca-Maïto     else if (PrevPartEntry == NULL && NextPartEntry != NULL)
30886f19c83bSHermès Bélusca-Maïto     {
308984f3e2dfSHermès Bélusca-Maïto         /* Merge the current and the next unpartitioned entries */
30906f19c83bSHermès Bélusca-Maïto 
309184f3e2dfSHermès Bélusca-Maïto         /* Adjust the next entry offset and length */
30926f19c83bSHermès Bélusca-Maïto         NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
30936f19c83bSHermès Bélusca-Maïto         NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
30946f19c83bSHermès Bélusca-Maïto 
30956f19c83bSHermès Bélusca-Maïto         /* Remove the current entry */
30966f19c83bSHermès Bélusca-Maïto         RemoveEntryList(&PartEntry->ListEntry);
30976f15802aSHermès Bélusca-Maïto         DestroyRegion(PartEntry);
30986f19c83bSHermès Bélusca-Maïto 
309984f3e2dfSHermès Bélusca-Maïto         /* Optionally return the freed region */
310084f3e2dfSHermès Bélusca-Maïto         if (FreeRegion)
310184f3e2dfSHermès Bélusca-Maïto             *FreeRegion = NextPartEntry;
310229cc1843SHermès Bélusca-Maïto     }
31036f19c83bSHermès Bélusca-Maïto     else
31046f19c83bSHermès Bélusca-Maïto     {
310584f3e2dfSHermès Bélusca-Maïto         /* Nothing to merge but change the current entry */
31066f15802aSHermès Bélusca-Maïto         PartEntry->New = FALSE;
31076f19c83bSHermès Bélusca-Maïto         PartEntry->IsPartitioned = FALSE;
31086f15802aSHermès Bélusca-Maïto         PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
3109626c654aSHermès Bélusca-Maïto         PartEntry->OnDiskPartitionNumber = 0;
3110626c654aSHermès Bélusca-Maïto         PartEntry->PartitionNumber = 0;
3111626c654aSHermès Bélusca-Maïto         // PartEntry->PartitionIndex = 0;
3112626c654aSHermès Bélusca-Maïto         PartEntry->BootIndicator = FALSE;
31136f15802aSHermès Bélusca-Maïto         PartEntry->DeviceName[0] = UNICODE_NULL;
31146f15802aSHermès Bélusca-Maïto 
31156f15802aSHermès Bélusca-Maïto         if (PartEntry->Volume)
31166f15802aSHermès Bélusca-Maïto         {
31176f15802aSHermès Bélusca-Maïto             RemoveEntryList(&PartEntry->Volume->ListEntry);
31186f15802aSHermès Bélusca-Maïto             RtlFreeHeap(ProcessHeap, 0, PartEntry->Volume);
31196f15802aSHermès Bélusca-Maïto         }
31206f15802aSHermès Bélusca-Maïto         PartEntry->Volume = NULL;
312184f3e2dfSHermès Bélusca-Maïto 
312284f3e2dfSHermès Bélusca-Maïto         /* Optionally return the freed region */
312384f3e2dfSHermès Bélusca-Maïto         if (FreeRegion)
312484f3e2dfSHermès Bélusca-Maïto             *FreeRegion = PartEntry;
31256f19c83bSHermès Bélusca-Maïto     }
31266f19c83bSHermès Bélusca-Maïto 
31276f19c83bSHermès Bélusca-Maïto     UpdateDiskLayout(DiskEntry);
31286f19c83bSHermès Bélusca-Maïto     AssignDriveLetters(List);
31296f19c83bSHermès Bélusca-Maïto 
313084f3e2dfSHermès Bélusca-Maïto     return TRUE;
313129cc1843SHermès Bélusca-Maïto }
313229cc1843SHermès Bélusca-Maïto 
3133c1fbc2d6SHermès Bélusca-Maïto static
3134c1fbc2d6SHermès Bélusca-Maïto BOOLEAN
IsSupportedActivePartition(IN PPARTENTRY PartEntry)3135c1fbc2d6SHermès Bélusca-Maïto IsSupportedActivePartition(
3136c1fbc2d6SHermès Bélusca-Maïto     IN PPARTENTRY PartEntry)
3137c1fbc2d6SHermès Bélusca-Maïto {
31386f15802aSHermès Bélusca-Maïto     PVOLENTRY Volume;
31396f15802aSHermès Bélusca-Maïto 
3140c1fbc2d6SHermès Bélusca-Maïto     /* Check the type and the file system of this partition */
3141c1fbc2d6SHermès Bélusca-Maïto 
3142c1fbc2d6SHermès Bélusca-Maïto     /*
3143c1fbc2d6SHermès Bélusca-Maïto      * We do not support extended partition containers (on MBR disks) marked
3144c1fbc2d6SHermès Bélusca-Maïto      * as active, and containing code inside their extended boot records.
3145c1fbc2d6SHermès Bélusca-Maïto      */
3146c1fbc2d6SHermès Bélusca-Maïto     if (IsContainerPartition(PartEntry->PartitionType))
3147c1fbc2d6SHermès Bélusca-Maïto     {
3148c1fbc2d6SHermès Bélusca-Maïto         DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
3149c1fbc2d6SHermès Bélusca-Maïto                 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3150c1fbc2d6SHermès Bélusca-Maïto         return FALSE;
3151c1fbc2d6SHermès Bélusca-Maïto     }
3152c1fbc2d6SHermès Bélusca-Maïto 
31536f15802aSHermès Bélusca-Maïto     Volume = PartEntry->Volume;
31546f15802aSHermès Bélusca-Maïto     if (!Volume)
31556f15802aSHermès Bélusca-Maïto     {
31566f15802aSHermès Bélusca-Maïto         /* Still no recognizable volume mounted: partition not supported */
31576f15802aSHermès Bélusca-Maïto         return FALSE;
31586f15802aSHermès Bélusca-Maïto     }
31596f15802aSHermès Bélusca-Maïto 
3160c1fbc2d6SHermès Bélusca-Maïto     /*
3161c1fbc2d6SHermès Bélusca-Maïto      * ADDITIONAL CHECKS / BIG HACK:
3162c1fbc2d6SHermès Bélusca-Maïto      *
3163c1fbc2d6SHermès Bélusca-Maïto      * Retrieve its file system and check whether we have
3164c1fbc2d6SHermès Bélusca-Maïto      * write support for it. If that is the case we are fine
3165c1fbc2d6SHermès Bélusca-Maïto      * and we can use it directly. However if we don't have
3166c1fbc2d6SHermès Bélusca-Maïto      * write support we will need to change the active system
3167c1fbc2d6SHermès Bélusca-Maïto      * partition.
3168c1fbc2d6SHermès Bélusca-Maïto      *
3169c1fbc2d6SHermès Bélusca-Maïto      * NOTE that this is completely useless on architectures
3170c1fbc2d6SHermès Bélusca-Maïto      * where a real system partition is required, as on these
3171c1fbc2d6SHermès Bélusca-Maïto      * architectures the partition uses the FAT FS, for which
3172c1fbc2d6SHermès Bélusca-Maïto      * we do have write support.
3173c1fbc2d6SHermès Bélusca-Maïto      * NOTE also that for those architectures looking for a
3174c1fbc2d6SHermès Bélusca-Maïto      * partition boot indicator is insufficient.
3175c1fbc2d6SHermès Bélusca-Maïto      */
31766f15802aSHermès Bélusca-Maïto     if (Volume->FormatState == Unformatted)
3177626c654aSHermès Bélusca-Maïto     {
3178626c654aSHermès Bélusca-Maïto         /* If this partition is mounted, it would use RawFS ("RAW") */
3179626c654aSHermès Bélusca-Maïto         return TRUE;
3180626c654aSHermès Bélusca-Maïto     }
31816f15802aSHermès Bélusca-Maïto     else if (Volume->FormatState == Formatted)
3182c1fbc2d6SHermès Bélusca-Maïto     {
31836f15802aSHermès Bélusca-Maïto         ASSERT(*Volume->Info.FileSystem);
3184c1fbc2d6SHermès Bélusca-Maïto 
3185c1fbc2d6SHermès Bélusca-Maïto         /* NOTE: Please keep in sync with the RegisteredFileSystems list! */
3186e4930be4STimo Kreuzer         if (_wcsicmp(Volume->Info.FileSystem, L"FAT")   == 0 ||
3187e4930be4STimo Kreuzer             _wcsicmp(Volume->Info.FileSystem, L"FAT32") == 0 ||
3188e4930be4STimo Kreuzer          // _wcsicmp(Volume->Info.FileSystem, L"NTFS")  == 0 ||
3189e4930be4STimo Kreuzer             _wcsicmp(Volume->Info.FileSystem, L"BTRFS") == 0)
3190c1fbc2d6SHermès Bélusca-Maïto         {
3191c1fbc2d6SHermès Bélusca-Maïto             return TRUE;
3192c1fbc2d6SHermès Bélusca-Maïto         }
3193c1fbc2d6SHermès Bélusca-Maïto         else
3194c1fbc2d6SHermès Bélusca-Maïto         {
3195c1fbc2d6SHermès Bélusca-Maïto             // WARNING: We cannot write on this FS yet!
3196c1fbc2d6SHermès Bélusca-Maïto             DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
31976f15802aSHermès Bélusca-Maïto                     Volume->Info.FileSystem);
3198c1fbc2d6SHermès Bélusca-Maïto             return FALSE;
3199c1fbc2d6SHermès Bélusca-Maïto         }
3200c1fbc2d6SHermès Bélusca-Maïto     }
32016f15802aSHermès Bélusca-Maïto     else // if (Volume->FormatState == UnknownFormat)
3202c1fbc2d6SHermès Bélusca-Maïto     {
32036f15802aSHermès Bélusca-Maïto         ASSERT(!*Volume->Info.FileSystem);
3204c1fbc2d6SHermès Bélusca-Maïto 
3205c1fbc2d6SHermès Bélusca-Maïto         DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
3206c1fbc2d6SHermès Bélusca-Maïto                 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3207c1fbc2d6SHermès Bélusca-Maïto         return FALSE;
3208c1fbc2d6SHermès Bélusca-Maïto     }
3209c1fbc2d6SHermès Bélusca-Maïto 
3210c1fbc2d6SHermès Bélusca-Maïto     // HACK: WARNING: We cannot write on this FS yet!
3211c1fbc2d6SHermès Bélusca-Maïto     // See fsutil.c:InferFileSystem()
3212c1fbc2d6SHermès Bélusca-Maïto     if (PartEntry->PartitionType == PARTITION_IFS)
3213c1fbc2d6SHermès Bélusca-Maïto     {
3214c1fbc2d6SHermès Bélusca-Maïto         DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
32156f15802aSHermès Bélusca-Maïto                 Volume->Info.FileSystem);
3216c1fbc2d6SHermès Bélusca-Maïto         return FALSE;
3217c1fbc2d6SHermès Bélusca-Maïto     }
3218c1fbc2d6SHermès Bélusca-Maïto 
3219c1fbc2d6SHermès Bélusca-Maïto     return TRUE;
3220c1fbc2d6SHermès Bélusca-Maïto }
3221c1fbc2d6SHermès Bélusca-Maïto 
322259acff79SHermès Bélusca-Maïto PPARTENTRY
FindSupportedSystemPartition(IN PPARTLIST List,IN BOOLEAN ForceSelect,IN PDISKENTRY AlternativeDisk OPTIONAL,IN PPARTENTRY AlternativePart OPTIONAL)322359acff79SHermès Bélusca-Maïto FindSupportedSystemPartition(
322484f3e2dfSHermès Bélusca-Maïto     IN PPARTLIST List,
322584f3e2dfSHermès Bélusca-Maïto     IN BOOLEAN ForceSelect,
322659acff79SHermès Bélusca-Maïto     IN PDISKENTRY AlternativeDisk OPTIONAL,
322759acff79SHermès Bélusca-Maïto     IN PPARTENTRY AlternativePart OPTIONAL)
32286f19c83bSHermès Bélusca-Maïto {
32290d9ebb67SHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
32306f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
32316f19c83bSHermès Bélusca-Maïto     PPARTENTRY PartEntry;
32320d9ebb67SHermès Bélusca-Maïto     PPARTENTRY ActivePartition;
32330d9ebb67SHermès Bélusca-Maïto     PPARTENTRY CandidatePartition = NULL;
32346f19c83bSHermès Bélusca-Maïto 
32356f19c83bSHermès Bélusca-Maïto     /* Check for empty disk list */
32366f19c83bSHermès Bélusca-Maïto     if (IsListEmpty(&List->DiskListHead))
32376f19c83bSHermès Bélusca-Maïto     {
32380d9ebb67SHermès Bélusca-Maïto         /* No system partition! */
323959acff79SHermès Bélusca-Maïto         ASSERT(List->SystemPartition == NULL);
324084f3e2dfSHermès Bélusca-Maïto         goto NoSystemPartition;
32416f19c83bSHermès Bélusca-Maïto     }
32426f19c83bSHermès Bélusca-Maïto 
324359acff79SHermès Bélusca-Maïto     /* Adjust the optional alternative disk if needed */
324459acff79SHermès Bélusca-Maïto     if (!AlternativeDisk && AlternativePart)
324559acff79SHermès Bélusca-Maïto         AlternativeDisk = AlternativePart->DiskEntry;
324659acff79SHermès Bélusca-Maïto 
324759acff79SHermès Bélusca-Maïto     /* Ensure that the alternative partition is on the alternative disk */
324859acff79SHermès Bélusca-Maïto     if (AlternativePart)
324959acff79SHermès Bélusca-Maïto         ASSERT(AlternativeDisk && (AlternativePart->DiskEntry == AlternativeDisk));
325059acff79SHermès Bélusca-Maïto 
325159acff79SHermès Bélusca-Maïto     /* Ensure that the alternative disk is in the list */
325259acff79SHermès Bélusca-Maïto     if (AlternativeDisk)
325359acff79SHermès Bélusca-Maïto         ASSERT(AlternativeDisk->PartList == List);
32546f19c83bSHermès Bélusca-Maïto 
32550d9ebb67SHermès Bélusca-Maïto     /* Start fresh */
325659acff79SHermès Bélusca-Maïto     CandidatePartition = NULL;
32570d9ebb67SHermès Bélusca-Maïto 
32580d9ebb67SHermès Bélusca-Maïto //
325959acff79SHermès Bélusca-Maïto // Step 1 : Check the system disk.
32600d9ebb67SHermès Bélusca-Maïto //
32610d9ebb67SHermès Bélusca-Maïto 
32620d9ebb67SHermès Bélusca-Maïto     /*
326359acff79SHermès Bélusca-Maïto      * First, check whether the system disk, i.e. the one that will be booted
326459acff79SHermès Bélusca-Maïto      * by default by the hardware, contains an active partition. If so this
326559acff79SHermès Bélusca-Maïto      * should be our system partition.
32660d9ebb67SHermès Bélusca-Maïto      */
326759acff79SHermès Bélusca-Maïto     DiskEntry = GetSystemDisk(List);
3268c752e8c0SHermès Bélusca-Maïto     if (!DiskEntry)
3269c752e8c0SHermès Bélusca-Maïto     {
3270c752e8c0SHermès Bélusca-Maïto         /* No system disk found, directly go check the alternative disk */
3271c752e8c0SHermès Bélusca-Maïto         goto UseAlternativeDisk;
3272c752e8c0SHermès Bélusca-Maïto     }
32730d9ebb67SHermès Bélusca-Maïto 
327484f3e2dfSHermès Bélusca-Maïto     if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
327584f3e2dfSHermès Bélusca-Maïto     {
327659acff79SHermès Bélusca-Maïto         DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
327759acff79SHermès Bélusca-Maïto         goto UseAlternativeDisk;
327884f3e2dfSHermès Bélusca-Maïto     }
32790d9ebb67SHermès Bélusca-Maïto 
328059acff79SHermès Bélusca-Maïto     /* If we have a system partition (in the system disk), validate it */
328159acff79SHermès Bélusca-Maïto     ActivePartition = List->SystemPartition;
328259acff79SHermès Bélusca-Maïto     if (ActivePartition && IsSupportedActivePartition(ActivePartition))
32830d9ebb67SHermès Bélusca-Maïto     {
32840d9ebb67SHermès Bélusca-Maïto         CandidatePartition = ActivePartition;
328559acff79SHermès Bélusca-Maïto 
328659acff79SHermès Bélusca-Maïto         DPRINT1("Use the current system partition %lu in disk %lu, drive letter %C\n",
328759acff79SHermès Bélusca-Maïto                 CandidatePartition->PartitionNumber,
328859acff79SHermès Bélusca-Maïto                 CandidatePartition->DiskEntry->DiskNumber,
32896f15802aSHermès Bélusca-Maïto                 !CandidatePartition->Volume->Info.DriveLetter ? L'-' : CandidatePartition->Volume->Info.DriveLetter);
329059acff79SHermès Bélusca-Maïto 
329159acff79SHermès Bélusca-Maïto         /* Return the candidate system partition */
329259acff79SHermès Bélusca-Maïto         return CandidatePartition;
32930d9ebb67SHermès Bélusca-Maïto     }
32940d9ebb67SHermès Bélusca-Maïto 
329559acff79SHermès Bélusca-Maïto     /* If the system disk is not the optional alternative disk, perform the minimal checks */
329659acff79SHermès Bélusca-Maïto     if (DiskEntry != AlternativeDisk)
32970d9ebb67SHermès Bélusca-Maïto     {
32980d9ebb67SHermès Bélusca-Maïto         /*
329984f3e2dfSHermès Bélusca-Maïto          * No active partition has been recognized. Enumerate all the (primary)
330059acff79SHermès Bélusca-Maïto          * partitions in the system disk, excluding the possible current active
330184f3e2dfSHermès Bélusca-Maïto          * partition, to find a new candidate.
33020d9ebb67SHermès Bélusca-Maïto          */
33030d9ebb67SHermès Bélusca-Maïto         for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
33040d9ebb67SHermès Bélusca-Maïto              ListEntry != &DiskEntry->PrimaryPartListHead;
33050d9ebb67SHermès Bélusca-Maïto              ListEntry = ListEntry->Flink)
33060d9ebb67SHermès Bélusca-Maïto         {
33070d9ebb67SHermès Bélusca-Maïto             /* Retrieve the partition */
33080d9ebb67SHermès Bélusca-Maïto             PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
33090d9ebb67SHermès Bélusca-Maïto 
33100d9ebb67SHermès Bélusca-Maïto             /* Skip the current active partition */
331159acff79SHermès Bélusca-Maïto             if (PartEntry == ActivePartition)
33120d9ebb67SHermès Bélusca-Maïto                 continue;
33130d9ebb67SHermès Bélusca-Maïto 
33140d9ebb67SHermès Bélusca-Maïto             /* Check if the partition is partitioned and used */
33150d9ebb67SHermès Bélusca-Maïto             if (PartEntry->IsPartitioned &&
33160d9ebb67SHermès Bélusca-Maïto                 !IsContainerPartition(PartEntry->PartitionType))
33170d9ebb67SHermès Bélusca-Maïto             {
33180d9ebb67SHermès Bélusca-Maïto                 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
33190d9ebb67SHermès Bélusca-Maïto 
332059acff79SHermès Bélusca-Maïto                 /* If we get a candidate active partition in the disk, validate it */
33210d9ebb67SHermès Bélusca-Maïto                 if (IsSupportedActivePartition(PartEntry))
33220d9ebb67SHermès Bélusca-Maïto                 {
33230d9ebb67SHermès Bélusca-Maïto                     CandidatePartition = PartEntry;
332459acff79SHermès Bélusca-Maïto                     goto UseAlternativePartition;
33250d9ebb67SHermès Bélusca-Maïto                 }
33260d9ebb67SHermès Bélusca-Maïto             }
33270d9ebb67SHermès Bélusca-Maïto 
33280d9ebb67SHermès Bélusca-Maïto #if 0
33290d9ebb67SHermès Bélusca-Maïto             /* Check if the partition is partitioned and used */
33300d9ebb67SHermès Bélusca-Maïto             if (!PartEntry->IsPartitioned)
33310d9ebb67SHermès Bélusca-Maïto             {
33320d9ebb67SHermès Bélusca-Maïto                 ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
33330d9ebb67SHermès Bélusca-Maïto 
33340d9ebb67SHermès Bélusca-Maïto                 // TODO: Check for minimal size!!
33350d9ebb67SHermès Bélusca-Maïto                 CandidatePartition = PartEntry;
333659acff79SHermès Bélusca-Maïto                 goto UseAlternativePartition;
33370d9ebb67SHermès Bélusca-Maïto             }
33380d9ebb67SHermès Bélusca-Maïto #endif
33390d9ebb67SHermès Bélusca-Maïto         }
33400d9ebb67SHermès Bélusca-Maïto 
33410d9ebb67SHermès Bélusca-Maïto         /*
33420d9ebb67SHermès Bélusca-Maïto          * Still nothing, look whether there is some free space that we can use
33430d9ebb67SHermès Bélusca-Maïto          * for the new system partition. We must be sure that the total number
33440d9ebb67SHermès Bélusca-Maïto          * of partition is less than the maximum allowed, and that the minimal
33450d9ebb67SHermès Bélusca-Maïto          * size is fine.
33460d9ebb67SHermès Bélusca-Maïto          */
33470d9ebb67SHermès Bélusca-Maïto //
33480d9ebb67SHermès Bélusca-Maïto // TODO: Fix the handling of system partition being created in unpartitioned space!!
33490d9ebb67SHermès Bélusca-Maïto // --> When to partition it? etc...
33500d9ebb67SHermès Bélusca-Maïto //
33510d9ebb67SHermès Bélusca-Maïto         if (GetPrimaryPartitionCount(DiskEntry) < 4)
33520d9ebb67SHermès Bélusca-Maïto         {
33530d9ebb67SHermès Bélusca-Maïto             for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
33540d9ebb67SHermès Bélusca-Maïto                  ListEntry != &DiskEntry->PrimaryPartListHead;
33550d9ebb67SHermès Bélusca-Maïto                  ListEntry = ListEntry->Flink)
33560d9ebb67SHermès Bélusca-Maïto             {
33570d9ebb67SHermès Bélusca-Maïto                 /* Retrieve the partition */
33580d9ebb67SHermès Bélusca-Maïto                 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
33590d9ebb67SHermès Bélusca-Maïto 
33600d9ebb67SHermès Bélusca-Maïto                 /* Skip the current active partition */
336159acff79SHermès Bélusca-Maïto                 if (PartEntry == ActivePartition)
33620d9ebb67SHermès Bélusca-Maïto                     continue;
33630d9ebb67SHermès Bélusca-Maïto 
33640d9ebb67SHermès Bélusca-Maïto                 /* Check for unpartitioned space */
33650d9ebb67SHermès Bélusca-Maïto                 if (!PartEntry->IsPartitioned)
33660d9ebb67SHermès Bélusca-Maïto                 {
33670d9ebb67SHermès Bélusca-Maïto                     ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
33680d9ebb67SHermès Bélusca-Maïto 
33690d9ebb67SHermès Bélusca-Maïto                     // TODO: Check for minimal size!!
33700d9ebb67SHermès Bélusca-Maïto                     CandidatePartition = PartEntry;
337159acff79SHermès Bélusca-Maïto                     goto UseAlternativePartition;
33720d9ebb67SHermès Bélusca-Maïto                 }
33730d9ebb67SHermès Bélusca-Maïto             }
33740d9ebb67SHermès Bélusca-Maïto         }
33750d9ebb67SHermès Bélusca-Maïto     }
33760d9ebb67SHermès Bélusca-Maïto 
33770d9ebb67SHermès Bélusca-Maïto 
33780d9ebb67SHermès Bélusca-Maïto //
337959acff79SHermès Bélusca-Maïto // Step 2 : No active partition found: Check the alternative disk if specified.
33800d9ebb67SHermès Bélusca-Maïto //
33810d9ebb67SHermès Bélusca-Maïto 
338259acff79SHermès Bélusca-Maïto UseAlternativeDisk:
338359acff79SHermès Bélusca-Maïto     if (!AlternativeDisk || (!ForceSelect && (DiskEntry != AlternativeDisk)))
338484f3e2dfSHermès Bélusca-Maïto         goto NoSystemPartition;
33850d9ebb67SHermès Bélusca-Maïto 
338659acff79SHermès Bélusca-Maïto     if (AlternativeDisk->DiskStyle == PARTITION_STYLE_GPT)
33870d9ebb67SHermès Bélusca-Maïto     {
338859acff79SHermès Bélusca-Maïto         DPRINT1("Alternative disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
338984f3e2dfSHermès Bélusca-Maïto         goto NoSystemPartition;
33900d9ebb67SHermès Bélusca-Maïto     }
33910d9ebb67SHermès Bélusca-Maïto 
339259acff79SHermès Bélusca-Maïto     if (DiskEntry != AlternativeDisk)
339384f3e2dfSHermès Bélusca-Maïto     {
339459acff79SHermès Bélusca-Maïto         /* Choose the alternative disk */
339559acff79SHermès Bélusca-Maïto         DiskEntry = AlternativeDisk;
33960d9ebb67SHermès Bélusca-Maïto 
33970d9ebb67SHermès Bélusca-Maïto         /* If we get a candidate active partition, validate it */
339859acff79SHermès Bélusca-Maïto         ActivePartition = GetActiveDiskPartition(DiskEntry);
339959acff79SHermès Bélusca-Maïto         if (ActivePartition && IsSupportedActivePartition(ActivePartition))
34000d9ebb67SHermès Bélusca-Maïto         {
34010d9ebb67SHermès Bélusca-Maïto             CandidatePartition = ActivePartition;
340259acff79SHermès Bélusca-Maïto             goto UseAlternativePartition;
34030d9ebb67SHermès Bélusca-Maïto         }
34040d9ebb67SHermès Bélusca-Maïto     }
34050d9ebb67SHermès Bélusca-Maïto 
340684f3e2dfSHermès Bélusca-Maïto     /* We now may have an unsupported active partition, or none */
34070d9ebb67SHermès Bélusca-Maïto 
34080d9ebb67SHermès Bélusca-Maïto /***
34090d9ebb67SHermès Bélusca-Maïto  *** TODO: Improve the selection:
34100d9ebb67SHermès Bélusca-Maïto  *** - If we want a really separate system partition from the partition where
34110d9ebb67SHermès Bélusca-Maïto  ***   we install, do something similar to what's done below in the code.
34120d9ebb67SHermès Bélusca-Maïto  *** - Otherwise if we allow for the system partition to be also the partition
341359acff79SHermès Bélusca-Maïto  ***   where we install, just directly fall down to using AlternativePart.
34140d9ebb67SHermès Bélusca-Maïto  ***/
34150d9ebb67SHermès Bélusca-Maïto 
34166f19c83bSHermès Bélusca-Maïto     /* Retrieve the first partition of the disk */
34176f19c83bSHermès Bélusca-Maïto     PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
34180d9ebb67SHermès Bélusca-Maïto                                   PARTENTRY, ListEntry);
34196f19c83bSHermès Bélusca-Maïto     ASSERT(DiskEntry == PartEntry->DiskEntry);
34200d9ebb67SHermès Bélusca-Maïto 
34210d9ebb67SHermès Bélusca-Maïto     CandidatePartition = PartEntry;
34226f19c83bSHermès Bélusca-Maïto 
34236f19c83bSHermès Bélusca-Maïto     //
34246f19c83bSHermès Bélusca-Maïto     // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
34256f19c83bSHermès Bélusca-Maïto     //
34266f19c83bSHermès Bélusca-Maïto 
34276f19c83bSHermès Bélusca-Maïto     /* Check if the disk is new and if so, use its first partition as the active system partition */
34286f19c83bSHermès Bélusca-Maïto     if (DiskEntry->NewDisk)
34296f19c83bSHermès Bélusca-Maïto     {
34300d9ebb67SHermès Bélusca-Maïto         // !IsContainerPartition(PartEntry->PartitionType);
34310d9ebb67SHermès Bélusca-Maïto         if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
34326f19c83bSHermès Bélusca-Maïto         {
34330d9ebb67SHermès Bélusca-Maïto             ASSERT(DiskEntry == CandidatePartition->DiskEntry);
34346f19c83bSHermès Bélusca-Maïto 
3435f41750abSHermès Bélusca-Maïto             DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
343659acff79SHermès Bélusca-Maïto                     CandidatePartition->PartitionNumber,
343759acff79SHermès Bélusca-Maïto                     CandidatePartition->DiskEntry->DiskNumber,
34386f15802aSHermès Bélusca-Maïto                     !CandidatePartition->Volume->Info.DriveLetter ? L'-' : CandidatePartition->Volume->Info.DriveLetter);
34396f19c83bSHermès Bélusca-Maïto 
344059acff79SHermès Bélusca-Maïto             /* Return the candidate system partition */
344159acff79SHermès Bélusca-Maïto             return CandidatePartition;
34426f19c83bSHermès Bélusca-Maïto         }
34436f19c83bSHermès Bélusca-Maïto 
34446f19c83bSHermès Bélusca-Maïto         // FIXME: What to do??
34456f19c83bSHermès Bélusca-Maïto         DPRINT1("NewDisk TRUE but first partition is used?\n");
34466f19c83bSHermès Bélusca-Maïto     }
34476f19c83bSHermès Bélusca-Maïto 
34486f19c83bSHermès Bélusca-Maïto     /*
34496f19c83bSHermès Bélusca-Maïto      * The disk is not new, check if any partition is initialized;
34506f19c83bSHermès Bélusca-Maïto      * if not, the first one becomes the system partition.
34516f19c83bSHermès Bélusca-Maïto      */
34528bed4adfSHermès Bélusca-Maïto     for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
34538bed4adfSHermès Bélusca-Maïto          ListEntry != &DiskEntry->PrimaryPartListHead;
34548bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
34556f19c83bSHermès Bélusca-Maïto     {
34568bed4adfSHermès Bélusca-Maïto         /* Retrieve the partition */
34570d9ebb67SHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
34586f19c83bSHermès Bélusca-Maïto 
34596f19c83bSHermès Bélusca-Maïto         /* Check if the partition is partitioned and is used */
34600d9ebb67SHermès Bélusca-Maïto         // !IsContainerPartition(PartEntry->PartitionType);
34610d9ebb67SHermès Bélusca-Maïto         if (/* PartEntry->IsPartitioned && */
34620d9ebb67SHermès Bélusca-Maïto             PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
34636f19c83bSHermès Bélusca-Maïto         {
34646f19c83bSHermès Bélusca-Maïto             break;
34656f19c83bSHermès Bélusca-Maïto         }
34666f19c83bSHermès Bélusca-Maïto     }
34676f19c83bSHermès Bélusca-Maïto     if (ListEntry == &DiskEntry->PrimaryPartListHead)
34686f19c83bSHermès Bélusca-Maïto     {
34696f19c83bSHermès Bélusca-Maïto         /*
34706f19c83bSHermès Bélusca-Maïto          * OK we haven't encountered any used and active partition,
34716f19c83bSHermès Bélusca-Maïto          * so use the first one as the system partition.
34726f19c83bSHermès Bélusca-Maïto          */
34730d9ebb67SHermès Bélusca-Maïto         ASSERT(DiskEntry == CandidatePartition->DiskEntry);
34746f19c83bSHermès Bélusca-Maïto 
3475f41750abSHermès Bélusca-Maïto         DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
347659acff79SHermès Bélusca-Maïto                 CandidatePartition->PartitionNumber,
347759acff79SHermès Bélusca-Maïto                 CandidatePartition->DiskEntry->DiskNumber,
34786f15802aSHermès Bélusca-Maïto                 !CandidatePartition->Volume->Info.DriveLetter ? L'-' : CandidatePartition->Volume->Info.DriveLetter);
34796f19c83bSHermès Bélusca-Maïto 
348059acff79SHermès Bélusca-Maïto         /* Return the candidate system partition */
348159acff79SHermès Bélusca-Maïto         return CandidatePartition;
34826f19c83bSHermès Bélusca-Maïto     }
34836f19c83bSHermès Bélusca-Maïto 
34840d9ebb67SHermès Bélusca-Maïto     /*
34850d9ebb67SHermès Bélusca-Maïto      * The disk is not new, we did not find any actual active partition,
348659acff79SHermès Bélusca-Maïto      * or the one we found was not supported, or any possible other candidate
348759acff79SHermès Bélusca-Maïto      * is not supported. We then use the alternative partition if specified.
34880d9ebb67SHermès Bélusca-Maïto      */
348959acff79SHermès Bélusca-Maïto     if (AlternativePart)
349084f3e2dfSHermès Bélusca-Maïto     {
349159acff79SHermès Bélusca-Maïto         DPRINT1("No valid or supported system partition has been found, use the alternative partition!\n");
349259acff79SHermès Bélusca-Maïto         CandidatePartition = AlternativePart;
349359acff79SHermès Bélusca-Maïto         goto UseAlternativePartition;
349484f3e2dfSHermès Bélusca-Maïto     }
349584f3e2dfSHermès Bélusca-Maïto     else
349684f3e2dfSHermès Bélusca-Maïto     {
349784f3e2dfSHermès Bélusca-Maïto NoSystemPartition:
349884f3e2dfSHermès Bélusca-Maïto         DPRINT1("No valid or supported system partition has been found on this system!\n");
349959acff79SHermès Bélusca-Maïto         return NULL;
350084f3e2dfSHermès Bélusca-Maïto     }
35016f19c83bSHermès Bélusca-Maïto 
350259acff79SHermès Bélusca-Maïto UseAlternativePartition:
35036f19c83bSHermès Bélusca-Maïto     /*
350459acff79SHermès Bélusca-Maïto      * We are here because we did not find any (active) candidate system
350559acff79SHermès Bélusca-Maïto      * partition that we know how to support. What we are going to do is
350659acff79SHermès Bélusca-Maïto      * to change the existing system partition and use the alternative partition
350759acff79SHermès Bélusca-Maïto      * (e.g. on which we install ReactOS) as the new system partition.
350859acff79SHermès Bélusca-Maïto      * Then we will need to add in FreeLdr's boot menu an entry for booting
35096f19c83bSHermès Bélusca-Maïto      * from the original system partition.
35106f19c83bSHermès Bélusca-Maïto      */
351184f3e2dfSHermès Bélusca-Maïto     ASSERT(CandidatePartition);
35126f19c83bSHermès Bélusca-Maïto 
3513f41750abSHermès Bélusca-Maïto     DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
351459acff79SHermès Bélusca-Maïto             CandidatePartition->PartitionNumber,
351559acff79SHermès Bélusca-Maïto             CandidatePartition->DiskEntry->DiskNumber,
35166f15802aSHermès Bélusca-Maïto             !CandidatePartition->Volume->Info.DriveLetter ? L'-' : CandidatePartition->Volume->Info.DriveLetter);
35176f19c83bSHermès Bélusca-Maïto 
351859acff79SHermès Bélusca-Maïto     /* Return the candidate system partition */
351959acff79SHermès Bélusca-Maïto     return CandidatePartition;
352059acff79SHermès Bélusca-Maïto }
352159acff79SHermès Bélusca-Maïto 
352259acff79SHermès Bélusca-Maïto BOOLEAN
SetActivePartition(IN PPARTLIST List,IN PPARTENTRY PartEntry,IN PPARTENTRY OldActivePart OPTIONAL)352359acff79SHermès Bélusca-Maïto SetActivePartition(
352459acff79SHermès Bélusca-Maïto     IN PPARTLIST List,
352559acff79SHermès Bélusca-Maïto     IN PPARTENTRY PartEntry,
352659acff79SHermès Bélusca-Maïto     IN PPARTENTRY OldActivePart OPTIONAL)
352759acff79SHermès Bélusca-Maïto {
352859acff79SHermès Bélusca-Maïto     /* Check for empty disk list */
352959acff79SHermès Bélusca-Maïto     if (IsListEmpty(&List->DiskListHead))
353059acff79SHermès Bélusca-Maïto         return FALSE;
353159acff79SHermès Bélusca-Maïto 
353259acff79SHermès Bélusca-Maïto     /* Validate the partition entry */
353359acff79SHermès Bélusca-Maïto     if (!PartEntry)
353459acff79SHermès Bélusca-Maïto         return FALSE;
353559acff79SHermès Bélusca-Maïto 
353659acff79SHermès Bélusca-Maïto     /*
353759acff79SHermès Bélusca-Maïto      * If the partition entry is already the system partition, or if it is
353859acff79SHermès Bélusca-Maïto      * the same as the old active partition hint the user provided (and if
353959acff79SHermès Bélusca-Maïto      * it is already active), just return success.
354059acff79SHermès Bélusca-Maïto      */
354159acff79SHermès Bélusca-Maïto     if ((PartEntry == List->SystemPartition) ||
354259acff79SHermès Bélusca-Maïto         ((PartEntry == OldActivePart) && IsPartitionActive(OldActivePart)))
354359acff79SHermès Bélusca-Maïto     {
354459acff79SHermès Bélusca-Maïto         return TRUE;
354559acff79SHermès Bélusca-Maïto     }
354659acff79SHermès Bélusca-Maïto 
354759acff79SHermès Bélusca-Maïto     ASSERT(PartEntry->DiskEntry);
354859acff79SHermès Bélusca-Maïto 
354959acff79SHermès Bélusca-Maïto     /* Ensure that the partition's disk is in the list */
355059acff79SHermès Bélusca-Maïto     ASSERT(PartEntry->DiskEntry->PartList == List);
355159acff79SHermès Bélusca-Maïto 
355259acff79SHermès Bélusca-Maïto     /*
355359acff79SHermès Bélusca-Maïto      * If the user provided an old active partition hint, verify that it is
35546f15802aSHermès Bélusca-Maïto      * indeed active and belongs to the same disk where the new partition
355559acff79SHermès Bélusca-Maïto      * belongs. Otherwise determine the current active partition on the disk
355659acff79SHermès Bélusca-Maïto      * where the new partition belongs.
355759acff79SHermès Bélusca-Maïto      */
355859acff79SHermès Bélusca-Maïto     if (!(OldActivePart && IsPartitionActive(OldActivePart) && (OldActivePart->DiskEntry == PartEntry->DiskEntry)))
355959acff79SHermès Bélusca-Maïto     {
356059acff79SHermès Bélusca-Maïto         /* It's not, determine the current active partition for the disk */
356159acff79SHermès Bélusca-Maïto         OldActivePart = GetActiveDiskPartition(PartEntry->DiskEntry);
356259acff79SHermès Bélusca-Maïto     }
356359acff79SHermès Bélusca-Maïto 
356459acff79SHermès Bélusca-Maïto     /* Unset the old active partition if it exists */
356559acff79SHermès Bélusca-Maïto     if (OldActivePart)
356659acff79SHermès Bélusca-Maïto     {
356759acff79SHermès Bélusca-Maïto         OldActivePart->BootIndicator = FALSE;
356859acff79SHermès Bélusca-Maïto         OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].BootIndicator = FALSE;
356959acff79SHermès Bélusca-Maïto         OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].RewritePartition = TRUE;
357059acff79SHermès Bélusca-Maïto         OldActivePart->DiskEntry->Dirty = TRUE;
357159acff79SHermès Bélusca-Maïto     }
357259acff79SHermès Bélusca-Maïto 
357359acff79SHermès Bélusca-Maïto     /* Modify the system partition if the new partition is on the system disk */
357459acff79SHermès Bélusca-Maïto     if (PartEntry->DiskEntry == GetSystemDisk(List))
357559acff79SHermès Bélusca-Maïto         List->SystemPartition = PartEntry;
357659acff79SHermès Bélusca-Maïto 
357759acff79SHermès Bélusca-Maïto     /* Set the new active partition */
357859acff79SHermès Bélusca-Maïto     PartEntry->BootIndicator = TRUE;
357959acff79SHermès Bélusca-Maïto     PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
358059acff79SHermès Bélusca-Maïto     PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
358159acff79SHermès Bélusca-Maïto     PartEntry->DiskEntry->Dirty = TRUE;
358259acff79SHermès Bélusca-Maïto 
358359acff79SHermès Bélusca-Maïto     return TRUE;
35846f19c83bSHermès Bélusca-Maïto }
35856f19c83bSHermès Bélusca-Maïto 
35866f19c83bSHermès Bélusca-Maïto NTSTATUS
WritePartitions(IN PDISKENTRY DiskEntry)35876f19c83bSHermès Bélusca-Maïto WritePartitions(
35886f19c83bSHermès Bélusca-Maïto     IN PDISKENTRY DiskEntry)
35896f19c83bSHermès Bélusca-Maïto {
35906f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
35917df92966SHermès Bélusca-Maïto     OBJECT_ATTRIBUTES ObjectAttributes;
35927df92966SHermès Bélusca-Maïto     UNICODE_STRING Name;
35937df92966SHermès Bélusca-Maïto     HANDLE FileHandle;
35947df92966SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb;
35957df92966SHermès Bélusca-Maïto     ULONG BufferSize;
35967df92966SHermès Bélusca-Maïto     PPARTITION_INFORMATION PartitionInfo;
35977df92966SHermès Bélusca-Maïto     ULONG PartitionCount;
35987df92966SHermès Bélusca-Maïto     PLIST_ENTRY ListEntry;
35997df92966SHermès Bélusca-Maïto     PPARTENTRY PartEntry;
36007df92966SHermès Bélusca-Maïto     WCHAR DstPath[MAX_PATH];
36016f19c83bSHermès Bélusca-Maïto 
36026f19c83bSHermès Bélusca-Maïto     DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
36036f19c83bSHermès Bélusca-Maïto 
360429cc1843SHermès Bélusca-Maïto     /* If the disk is not dirty, there is nothing to do */
360529cc1843SHermès Bélusca-Maïto     if (!DiskEntry->Dirty)
360629cc1843SHermès Bélusca-Maïto         return STATUS_SUCCESS;
360729cc1843SHermès Bélusca-Maïto 
36086f19c83bSHermès Bélusca-Maïto     RtlStringCchPrintfW(DstPath, ARRAYSIZE(DstPath),
36096f19c83bSHermès Bélusca-Maïto                         L"\\Device\\Harddisk%lu\\Partition0",
36106f19c83bSHermès Bélusca-Maïto                         DiskEntry->DiskNumber);
36116f19c83bSHermès Bélusca-Maïto     RtlInitUnicodeString(&Name, DstPath);
3612765994c9SHermès Bélusca-Maïto 
36136f19c83bSHermès Bélusca-Maïto     InitializeObjectAttributes(&ObjectAttributes,
36146f19c83bSHermès Bélusca-Maïto                                &Name,
3615765994c9SHermès Bélusca-Maïto                                OBJ_CASE_INSENSITIVE,
36166f19c83bSHermès Bélusca-Maïto                                NULL,
36176f19c83bSHermès Bélusca-Maïto                                NULL);
36186f19c83bSHermès Bélusca-Maïto 
36196f19c83bSHermès Bélusca-Maïto     Status = NtOpenFile(&FileHandle,
36206f19c83bSHermès Bélusca-Maïto                         GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
36216f19c83bSHermès Bélusca-Maïto                         &ObjectAttributes,
36226f19c83bSHermès Bélusca-Maïto                         &Iosb,
36236f19c83bSHermès Bélusca-Maïto                         0,
36246f19c83bSHermès Bélusca-Maïto                         FILE_SYNCHRONOUS_IO_NONALERT);
36256f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
36266f19c83bSHermès Bélusca-Maïto     {
36276f19c83bSHermès Bélusca-Maïto         DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
36286f19c83bSHermès Bélusca-Maïto         return Status;
36296f19c83bSHermès Bélusca-Maïto     }
36306f19c83bSHermès Bélusca-Maïto 
36316f19c83bSHermès Bélusca-Maïto #ifdef DUMP_PARTITION_TABLE
36326f19c83bSHermès Bélusca-Maïto     DumpPartitionTable(DiskEntry);
36336f19c83bSHermès Bélusca-Maïto #endif
36346f19c83bSHermès Bélusca-Maïto 
3635f41750abSHermès Bélusca-Maïto     //
3636f41750abSHermès Bélusca-Maïto     // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
3637f41750abSHermès Bélusca-Maïto     // the disk in MBR or GPT format in case the disk was not initialized!!
3638f41750abSHermès Bélusca-Maïto     // For this we must ask the user which format to use.
3639f41750abSHermès Bélusca-Maïto     //
3640f41750abSHermès Bélusca-Maïto 
36417df92966SHermès Bélusca-Maïto     /* Save the original partition count to be restored later (see comment below) */
36427df92966SHermès Bélusca-Maïto     PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
36437df92966SHermès Bélusca-Maïto 
36446f15802aSHermès Bélusca-Maïto     /* Set the new disk layout and retrieve its updated version with
36456f15802aSHermès Bélusca-Maïto      * new partition numbers for the new partitions. The PARTMGR will
36466f15802aSHermès Bélusca-Maïto      * automatically notify the MOUNTMGR of new or deleted volumes. */
36476f19c83bSHermès Bélusca-Maïto     BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
36487df92966SHermès Bélusca-Maïto                  ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
36496f19c83bSHermès Bélusca-Maïto     Status = NtDeviceIoControlFile(FileHandle,
36506f19c83bSHermès Bélusca-Maïto                                    NULL,
36516f19c83bSHermès Bélusca-Maïto                                    NULL,
36526f19c83bSHermès Bélusca-Maïto                                    NULL,
36536f19c83bSHermès Bélusca-Maïto                                    &Iosb,
36546f19c83bSHermès Bélusca-Maïto                                    IOCTL_DISK_SET_DRIVE_LAYOUT,
36556f19c83bSHermès Bélusca-Maïto                                    DiskEntry->LayoutBuffer,
36566f19c83bSHermès Bélusca-Maïto                                    BufferSize,
36577df92966SHermès Bélusca-Maïto                                    DiskEntry->LayoutBuffer,
36587df92966SHermès Bélusca-Maïto                                    BufferSize);
36597df92966SHermès Bélusca-Maïto     NtClose(FileHandle);
36607df92966SHermès Bélusca-Maïto 
36617df92966SHermès Bélusca-Maïto     /*
36627df92966SHermès Bélusca-Maïto      * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
36637df92966SHermès Bélusca-Maïto      * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
36647df92966SHermès Bélusca-Maïto      * where such a table is expected to enumerate up to 4 partitions:
36657df92966SHermès Bélusca-Maïto      * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
36667df92966SHermès Bélusca-Maïto      * Due to this we need to restore the original PartitionCount number.
36677df92966SHermès Bélusca-Maïto      */
36687df92966SHermès Bélusca-Maïto     DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
36697df92966SHermès Bélusca-Maïto 
36707df92966SHermès Bélusca-Maïto     /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
36716f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
36726f19c83bSHermès Bélusca-Maïto     {
36736f19c83bSHermès Bélusca-Maïto         DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
36747df92966SHermès Bélusca-Maïto         return Status;
36756f19c83bSHermès Bélusca-Maïto     }
36766f19c83bSHermès Bélusca-Maïto 
36777df92966SHermès Bélusca-Maïto #ifdef DUMP_PARTITION_TABLE
36787df92966SHermès Bélusca-Maïto     DumpPartitionTable(DiskEntry);
36797df92966SHermès Bélusca-Maïto #endif
36807df92966SHermès Bélusca-Maïto 
36816f15802aSHermès Bélusca-Maïto     /* Update the partition numbers and device names */
36827df92966SHermès Bélusca-Maïto 
36837df92966SHermès Bélusca-Maïto     /* Update the primary partition table */
36848bed4adfSHermès Bélusca-Maïto     for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
36858bed4adfSHermès Bélusca-Maïto          ListEntry != &DiskEntry->PrimaryPartListHead;
36868bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
36877df92966SHermès Bélusca-Maïto     {
36887df92966SHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
36896f15802aSHermès Bélusca-Maïto         if (!PartEntry->IsPartitioned)
36906f15802aSHermès Bélusca-Maïto             continue;
369129cc1843SHermès Bélusca-Maïto         ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
36926f15802aSHermès Bélusca-Maïto 
36936f15802aSHermès Bélusca-Maïto         /*
36946f15802aSHermès Bélusca-Maïto          * Initialize the partition's number and its device name only
36956f15802aSHermès Bélusca-Maïto          * if the partition was new. Note that the partition number
36966f15802aSHermès Bélusca-Maïto          * should not change if this partition has not been deleted
36976f15802aSHermès Bélusca-Maïto          * during repartitioning.
36986f15802aSHermès Bélusca-Maïto          */
36996f15802aSHermès Bélusca-Maïto         // FIXME: Our PartMgr currently returns modified numbers
37006f15802aSHermès Bélusca-Maïto         // in the layout, this needs to be investigated and fixed.
37016f15802aSHermès Bélusca-Maïto         if (PartEntry->New)
37026f15802aSHermès Bélusca-Maïto         {
37037df92966SHermès Bélusca-Maïto             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
37047df92966SHermès Bélusca-Maïto             PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
37056f15802aSHermès Bélusca-Maïto             InitPartitionDeviceName(PartEntry);
37067df92966SHermès Bélusca-Maïto         }
37076f15802aSHermès Bélusca-Maïto         PartEntry->New = FALSE;
37087df92966SHermès Bélusca-Maïto     }
37097df92966SHermès Bélusca-Maïto 
37107df92966SHermès Bélusca-Maïto     /* Update the logical partition table */
37118bed4adfSHermès Bélusca-Maïto     for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
37128bed4adfSHermès Bélusca-Maïto          ListEntry != &DiskEntry->LogicalPartListHead;
37138bed4adfSHermès Bélusca-Maïto          ListEntry = ListEntry->Flink)
37147df92966SHermès Bélusca-Maïto     {
37157df92966SHermès Bélusca-Maïto         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
37166f15802aSHermès Bélusca-Maïto         if (!PartEntry->IsPartitioned)
37176f15802aSHermès Bélusca-Maïto             continue;
371829cc1843SHermès Bélusca-Maïto         ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
37196f15802aSHermès Bélusca-Maïto 
37206f15802aSHermès Bélusca-Maïto         /* See comment above */
37216f15802aSHermès Bélusca-Maïto         if (PartEntry->New)
37226f15802aSHermès Bélusca-Maïto         {
37237df92966SHermès Bélusca-Maïto             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
37247df92966SHermès Bélusca-Maïto             PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
37256f15802aSHermès Bélusca-Maïto             InitPartitionDeviceName(PartEntry);
37267df92966SHermès Bélusca-Maïto         }
37276f15802aSHermès Bélusca-Maïto         PartEntry->New = FALSE;
37287df92966SHermès Bélusca-Maïto     }
37296f19c83bSHermès Bélusca-Maïto 
37306f19c83bSHermès Bélusca-Maïto     //
37316f19c83bSHermès Bélusca-Maïto     // NOTE: Originally (see r40437), we used to install here also a new MBR
37326f19c83bSHermès Bélusca-Maïto     // for this disk (by calling InstallMbrBootCodeToDisk), only if:
373347a1acedSHermès Bélusca-Maïto     // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 0.
37346f19c83bSHermès Bélusca-Maïto     // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
37356f19c83bSHermès Bélusca-Maïto     // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
37366f19c83bSHermès Bélusca-Maïto     // was called too, the installation test was modified by checking whether
37376f19c83bSHermès Bélusca-Maïto     // DiskEntry->NoMbr was TRUE (instead of NewDisk).
37386f19c83bSHermès Bélusca-Maïto     //
37396f19c83bSHermès Bélusca-Maïto 
3740a59cecd8SHermès Bélusca-Maïto     // HACK: Parts of FIXMEs described above: (Re)set the PartitionStyle to MBR.
3741a59cecd8SHermès Bélusca-Maïto     DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
3742a59cecd8SHermès Bélusca-Maïto 
374329cc1843SHermès Bélusca-Maïto     /* The layout has been successfully updated, the disk is not dirty anymore */
374429cc1843SHermès Bélusca-Maïto     DiskEntry->Dirty = FALSE;
37457df92966SHermès Bélusca-Maïto 
37466f19c83bSHermès Bélusca-Maïto     return Status;
37476f19c83bSHermès Bélusca-Maïto }
37486f19c83bSHermès Bélusca-Maïto 
37496f19c83bSHermès Bélusca-Maïto BOOLEAN
WritePartitionsToDisk(IN PPARTLIST List)37506f19c83bSHermès Bélusca-Maïto WritePartitionsToDisk(
37516f19c83bSHermès Bélusca-Maïto     IN PPARTLIST List)
37526f19c83bSHermès Bélusca-Maïto {
375329cc1843SHermès Bélusca-Maïto     NTSTATUS Status;
37546f19c83bSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
37556f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry;
37566f15802aSHermès Bélusca-Maïto     PVOLENTRY Volume;
37576f19c83bSHermès Bélusca-Maïto 
37586f15802aSHermès Bélusca-Maïto     if (!List)
37596f19c83bSHermès Bélusca-Maïto         return TRUE;
37606f19c83bSHermès Bélusca-Maïto 
37616f15802aSHermès Bélusca-Maïto     /* Write all the partitions to all the disks */
37628bed4adfSHermès Bélusca-Maïto     for (Entry = List->DiskListHead.Flink;
37638bed4adfSHermès Bélusca-Maïto          Entry != &List->DiskListHead;
37648bed4adfSHermès Bélusca-Maïto          Entry = Entry->Flink)
37656f19c83bSHermès Bélusca-Maïto     {
37666f19c83bSHermès Bélusca-Maïto         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
37676f19c83bSHermès Bélusca-Maïto 
3768a3168373SHermès Bélusca-Maïto         if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3769a3168373SHermès Bélusca-Maïto         {
3770a3168373SHermès Bélusca-Maïto             DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3771a3168373SHermès Bélusca-Maïto             continue;
3772a3168373SHermès Bélusca-Maïto         }
3773a3168373SHermès Bélusca-Maïto 
37746f19c83bSHermès Bélusca-Maïto         if (DiskEntry->Dirty != FALSE)
37756f19c83bSHermès Bélusca-Maïto         {
377629cc1843SHermès Bélusca-Maïto             Status = WritePartitions(DiskEntry);
377729cc1843SHermès Bélusca-Maïto             if (!NT_SUCCESS(Status))
377829cc1843SHermès Bélusca-Maïto             {
377929cc1843SHermès Bélusca-Maïto                 DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
378029cc1843SHermès Bélusca-Maïto                         DiskEntry->DiskNumber, Status);
378129cc1843SHermès Bélusca-Maïto             }
37826f19c83bSHermès Bélusca-Maïto         }
37836f19c83bSHermès Bélusca-Maïto     }
37846f19c83bSHermès Bélusca-Maïto 
37856f15802aSHermès Bélusca-Maïto     /* The PARTMGR should have notified the MOUNTMGR that new volumes
37866f15802aSHermès Bélusca-Maïto      * associated with the new partitions had to be created */
37876f15802aSHermès Bélusca-Maïto 
37886f15802aSHermès Bélusca-Maïto     /* Assign valid device names to new volumes */
37896f15802aSHermès Bélusca-Maïto     for (Entry = List->VolumesList.Flink;
37906f15802aSHermès Bélusca-Maïto          Entry != &List->VolumesList;
37916f15802aSHermès Bélusca-Maïto          Entry = Entry->Flink)
37926f15802aSHermès Bélusca-Maïto     {
37936f15802aSHermès Bélusca-Maïto         Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
37946f15802aSHermès Bélusca-Maïto         InitVolumeDeviceName(Volume);
37956f15802aSHermès Bélusca-Maïto     }
37966f15802aSHermès Bélusca-Maïto 
37976f19c83bSHermès Bélusca-Maïto     return TRUE;
37986f19c83bSHermès Bélusca-Maïto }
37996f19c83bSHermès Bélusca-Maïto 
38006f15802aSHermès Bélusca-Maïto 
38016f15802aSHermès Bélusca-Maïto /**
38026f15802aSHermès Bélusca-Maïto  * @brief
38036f15802aSHermès Bélusca-Maïto  * Assign a "\DosDevices\#:" mount point drive letter to a disk partition or
38046f15802aSHermès Bélusca-Maïto  * volume, specified by a given disk signature and starting partition offset.
38056f15802aSHermès Bélusca-Maïto  **/
38066f15802aSHermès Bélusca-Maïto static BOOLEAN
SetMountedDeviceValue(_In_ PVOLENTRY Volume)38076f19c83bSHermès Bélusca-Maïto SetMountedDeviceValue(
38086f15802aSHermès Bélusca-Maïto     _In_ PVOLENTRY Volume)
38096f19c83bSHermès Bélusca-Maïto {
38106f15802aSHermès Bélusca-Maïto     PPARTENTRY PartEntry = Volume->PartEntry;
38116f15802aSHermès Bélusca-Maïto     WCHAR Letter = Volume->Info.DriveLetter;
38126f19c83bSHermès Bélusca-Maïto     NTSTATUS Status;
381351cb3cc6SHermès Bélusca-Maïto     OBJECT_ATTRIBUTES ObjectAttributes;
381451cb3cc6SHermès Bélusca-Maïto     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SYSTEM\\MountedDevices");
381551cb3cc6SHermès Bélusca-Maïto     UNICODE_STRING ValueName;
38166f15802aSHermès Bélusca-Maïto     WCHAR Buffer[16];
38176f19c83bSHermès Bélusca-Maïto     HANDLE KeyHandle;
381851cb3cc6SHermès Bélusca-Maïto     REG_DISK_MOUNT_INFO MountInfo;
38196f19c83bSHermès Bélusca-Maïto 
38206f15802aSHermès Bélusca-Maïto     /* Ignore no letter */
38216f15802aSHermès Bélusca-Maïto     if (!Letter)
38226f15802aSHermès Bélusca-Maïto         return TRUE;
38236f15802aSHermès Bélusca-Maïto 
38246f15802aSHermès Bélusca-Maïto     RtlStringCchPrintfW(Buffer, _countof(Buffer),
3825f41750abSHermès Bélusca-Maïto                         L"\\DosDevices\\%c:", Letter);
38266f15802aSHermès Bélusca-Maïto     RtlInitUnicodeString(&ValueName, Buffer);
38276f19c83bSHermès Bélusca-Maïto 
38286f19c83bSHermès Bélusca-Maïto     InitializeObjectAttributes(&ObjectAttributes,
38296f19c83bSHermès Bélusca-Maïto                                &KeyName,
38306f19c83bSHermès Bélusca-Maïto                                OBJ_CASE_INSENSITIVE,
383151cb3cc6SHermès Bélusca-Maïto                                GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
38326f19c83bSHermès Bélusca-Maïto                                NULL);
3833765994c9SHermès Bélusca-Maïto 
38346f19c83bSHermès Bélusca-Maïto     Status = NtOpenKey(&KeyHandle,
38356f19c83bSHermès Bélusca-Maïto                        KEY_ALL_ACCESS,
38366f19c83bSHermès Bélusca-Maïto                        &ObjectAttributes);
38376f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
38386f19c83bSHermès Bélusca-Maïto     {
38396f19c83bSHermès Bélusca-Maïto         Status = NtCreateKey(&KeyHandle,
38406f19c83bSHermès Bélusca-Maïto                              KEY_ALL_ACCESS,
38416f19c83bSHermès Bélusca-Maïto                              &ObjectAttributes,
38426f19c83bSHermès Bélusca-Maïto                              0,
38436f19c83bSHermès Bélusca-Maïto                              NULL,
38446f19c83bSHermès Bélusca-Maïto                              REG_OPTION_NON_VOLATILE,
38456f19c83bSHermès Bélusca-Maïto                              NULL);
38466f19c83bSHermès Bélusca-Maïto     }
38476f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
38486f19c83bSHermès Bélusca-Maïto     {
38496f19c83bSHermès Bélusca-Maïto         DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
38506f19c83bSHermès Bélusca-Maïto         return FALSE;
38516f19c83bSHermès Bélusca-Maïto     }
38526f19c83bSHermès Bélusca-Maïto 
38536f15802aSHermès Bélusca-Maïto     MountInfo.Signature = PartEntry->DiskEntry->LayoutBuffer->Signature;
38546f15802aSHermès Bélusca-Maïto     MountInfo.StartingOffset = GetPartEntryOffsetInBytes(PartEntry);
38556f19c83bSHermès Bélusca-Maïto     Status = NtSetValueKey(KeyHandle,
38566f19c83bSHermès Bélusca-Maïto                            &ValueName,
38576f19c83bSHermès Bélusca-Maïto                            0,
38586f19c83bSHermès Bélusca-Maïto                            REG_BINARY,
38596f19c83bSHermès Bélusca-Maïto                            (PVOID)&MountInfo,
38606f19c83bSHermès Bélusca-Maïto                            sizeof(MountInfo));
38616f19c83bSHermès Bélusca-Maïto     NtClose(KeyHandle);
38626f19c83bSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
38636f19c83bSHermès Bélusca-Maïto     {
38646f19c83bSHermès Bélusca-Maïto         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
38656f19c83bSHermès Bélusca-Maïto         return FALSE;
38666f19c83bSHermès Bélusca-Maïto     }
38676f19c83bSHermès Bélusca-Maïto 
38686f19c83bSHermès Bélusca-Maïto     return TRUE;
38696f19c83bSHermès Bélusca-Maïto }
38706f19c83bSHermès Bélusca-Maïto 
38716f19c83bSHermès Bélusca-Maïto BOOLEAN
SetMountedDeviceValues(_In_ PPARTLIST List)38726f19c83bSHermès Bélusca-Maïto SetMountedDeviceValues(
38736f15802aSHermès Bélusca-Maïto     _In_ PPARTLIST List)
38746f19c83bSHermès Bélusca-Maïto {
38756f15802aSHermès Bélusca-Maïto     PLIST_ENTRY Entry;
38766f15802aSHermès Bélusca-Maïto     PVOLENTRY Volume;
38776f19c83bSHermès Bélusca-Maïto 
38786f15802aSHermès Bélusca-Maïto     if (!List)
38796f19c83bSHermès Bélusca-Maïto         return FALSE;
38806f19c83bSHermès Bélusca-Maïto 
38816f15802aSHermès Bélusca-Maïto     for (Entry = List->VolumesList.Flink;
38826f15802aSHermès Bélusca-Maïto          Entry != &List->VolumesList;
38836f15802aSHermès Bélusca-Maïto          Entry = Entry->Flink)
38846f19c83bSHermès Bélusca-Maïto     {
38856f15802aSHermès Bélusca-Maïto         Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
38866f19c83bSHermès Bélusca-Maïto 
38876f15802aSHermès Bélusca-Maïto         /* Assign a "\DosDevices\#:" mount point to this volume */
38886f15802aSHermès Bélusca-Maïto         if (!SetMountedDeviceValue(Volume))
38896f19c83bSHermès Bélusca-Maïto             return FALSE;
38906f19c83bSHermès Bélusca-Maïto     }
38916f19c83bSHermès Bélusca-Maïto 
38926f19c83bSHermès Bélusca-Maïto     return TRUE;
38936f19c83bSHermès Bélusca-Maïto }
38946f19c83bSHermès Bélusca-Maïto 
38956f19c83bSHermès Bélusca-Maïto VOID
SetMBRPartitionType(IN PPARTENTRY PartEntry,IN UCHAR PartitionType)38969735a837SHermès Bélusca-Maïto SetMBRPartitionType(
38976f19c83bSHermès Bélusca-Maïto     IN PPARTENTRY PartEntry,
38986f19c83bSHermès Bélusca-Maïto     IN UCHAR PartitionType)
38996f19c83bSHermès Bélusca-Maïto {
39006f19c83bSHermès Bélusca-Maïto     PDISKENTRY DiskEntry = PartEntry->DiskEntry;
39016f19c83bSHermès Bélusca-Maïto 
39029735a837SHermès Bélusca-Maïto     ASSERT(DiskEntry->DiskStyle == PARTITION_STYLE_MBR);
39039735a837SHermès Bélusca-Maïto 
39046f15802aSHermès Bélusca-Maïto     /* Nothing to do if we assign the same type */
39056f15802aSHermès Bélusca-Maïto     if (PartitionType == PartEntry->PartitionType)
39066f15802aSHermès Bélusca-Maïto         return;
39076f15802aSHermès Bélusca-Maïto 
39086f15802aSHermès Bélusca-Maïto     // TODO: We might need to remount the associated basic volume...
39096f15802aSHermès Bélusca-Maïto 
39106f19c83bSHermès Bélusca-Maïto     PartEntry->PartitionType = PartitionType;
39116f19c83bSHermès Bélusca-Maïto 
39126f19c83bSHermès Bélusca-Maïto     DiskEntry->Dirty = TRUE;
39136f19c83bSHermès Bélusca-Maïto     DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
39147df92966SHermès Bélusca-Maïto     DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RecognizedPartition = IsRecognizedPartition(PartitionType);
39156f19c83bSHermès Bélusca-Maïto     DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
39166f19c83bSHermès Bélusca-Maïto }
39176f19c83bSHermès Bélusca-Maïto 
39186f19c83bSHermès Bélusca-Maïto /* EOF */
3919