2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Partition list functions
5 * COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
17 //#define DUMP_PARTITION_TABLE
21 typedef struct _REG_DISK_MOUNT_INFO
24 LARGE_INTEGER StartingOffset
;
25 } REG_DISK_MOUNT_INFO
, *PREG_DISK_MOUNT_INFO
;
30 /* HELPERS FOR PARTITION TYPES **********************************************/
33 * This partition type list was ripped from the kernelDisk.c module of
34 * the Visopsys Operating System (see license below), and completed with
35 * information from Paragon Hard-Disk Manager, and the following websites:
36 * http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
37 * https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
42 * Visopsys Operating System
43 * Copyright (C) 1998-2015 J. Andrew McLaughlin
45 * This program is free software; you can redistribute it and/or modify it
46 * under the terms of the GNU General Public License as published by the Free
47 * Software Foundation; either version 2 of the License, or (at your option)
50 * This program is distributed in the hope that it will be useful, but
51 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
52 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55 * You should have received a copy of the GNU General Public License along
56 * with this program; if not, write to the Free Software Foundation, Inc.,
57 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
60 /* This is a table for keeping known partition type codes and descriptions */
61 PARTITION_TYPE PartitionTypes
[NUM_PARTITION_TYPE_ENTRIES
] =
65 { 0x02, "XENIX root" },
66 { 0x03, "XENIX usr" },
67 { 0x04, "FAT16 (< 32 MB)" },
70 { 0x07, "NTFS/HPFS/exFAT" },
71 { 0x08, "OS/2 or AIX boot" },
73 { 0x0A, "OS/2 Boot Manager" },
75 { 0x0C, "FAT32 (LBA)" },
76 { 0x0E, "FAT16 (LBA)" },
77 { 0x0F, "Extended (LBA)" },
79 { 0x11, "Hidden FAT12" },
80 { 0x12, "FAT diagnostic (Compaq)" },
82 { 0x14, "Hidden FAT16 (< 32 MB)" },
83 { 0x16, "Hidden FAT16" },
84 { 0x17, "Hidden HPFS or NTFS" },
85 { 0x18, "AST SmartSleep" },
86 { 0x1B, "Hidden FAT32" },
87 { 0x1C, "Hidden FAT32 (LBA)" },
88 { 0x1E, "Hidden FAT16 (LBA)" },
89 { 0x24, "NEC DOS 3.x" },
90 { 0x27, "Hidden WinRE NTFS" },
91 { 0x2A, "AtheOS File System (AFS)" },
92 { 0x2B, "SyllableSecure (SylStor)" },
94 { 0x35, "JFS on OS/2 or eCS" },
95 { 0x38, "THEOS v3.2 2GB partition" },
97 { 0x3A, "THEOS v4 4GB partition" },
98 { 0x3B, "THEOS v4 extended partition" },
99 { 0x3C, "PartitionMagic recovery partition" },
100 { 0x3D, "Hidden NetWare" },
102 { 0x41, "PowerPC PReP boot" },
103 { 0x42, "Win2K Dynamic Volume extended" },
104 { 0x43, "Old Linux" },
106 { 0x45, "Priam or Boot-US Boot Manager" },
108 { 0x4E, "QNX4.x 2nd partition" },
109 { 0x4F, "QNX4.x 3rd partition" },
110 { 0x50, "OnTrack Disk Manager R/O" },
111 { 0x51, "OnTrack Disk Manager R/W or Novell" },
113 { 0x53, "OnTrack DM6 Aux3" },
114 { 0x54, "OnTrack DM6 Dynamic Drive Overlay" },
115 { 0x55, "EZ-Drive" },
116 { 0x56, "Golden Bow VFeature Partitioned Volume" },
117 { 0x5C, "Priam EDisk" },
118 { 0x61, "SpeedStor" },
120 { 0x63, "GNU HURD or Unix System V (SCO, ISC Unix, UnixWare)" },
121 { 0x64, "Novell NetWare 286, 2.xx" },
122 { 0x65, "Novell NetWare 386, 3.xx or 4.xx" },
123 { 0x66, "Novell NetWare SMS Partition" },
126 { 0x69, "Novell NetWare 5+" },
127 { 0x70, "DiskSecure Multi-Boot" },
128 { 0x75, "IBM PC/IX" },
129 { 0x7E, "Veritas VxVM public" },
130 { 0x7F, "Veritas VxVM private" },
131 { 0x80, "Old MINIX" },
132 { 0x81, "Linux or MINIX" },
133 { 0x82, "Linux swap or Solaris" },
134 { 0x83, "Linux Native" },
135 { 0x84, "Hibernate" },
136 { 0x85, "Extended Linux" },
137 { 0x86, "FAT16 mirrored" },
138 { 0x87, "HPFS or NTFS mirrored" },
139 { 0x88, "Linux plaintext partition table" },
140 { 0x8B, "FAT32 mirrored" },
141 { 0x8C, "FAT32 (LBA) mirrored" },
142 { 0x8E, "Linux LVM" },
143 { 0x93, "Hidden Linux" },
144 { 0x94, "Amoeba BBT" },
145 { 0x96, "CDFS/ISO-9660" },
147 { 0xA0, "Laptop Hibernate" },
148 { 0xA1, "Laptop Hibernate (NEC 6000H)" },
149 { 0xA5, "BSD, NetBSD, FreeBSD" },
151 { 0xA7, "NeXTStep" },
152 { 0xA8, "Darwin UFS" }, // Also known as "OS-X"
154 { 0xAB, "Darwin boot" },
155 { 0xAF, "Apple HFS" },
156 { 0xB6, "NT FAT16 corrupt mirror" },
157 { 0xB7, "BSDI BSD/386 FS" }, // Alternatively, "NT NTFS corrupt mirror"
158 { 0xB8, "BSDI BSD/386 swap" },
159 { 0xBB, "Boot Wizard hidden" },
160 { 0xBC, "Paragon Backup capsule" },
161 { 0xBE, "Solaris 8 boot partition" },
162 { 0xBF, "Solaris 10 x86" },
163 { 0xC0, "NTFT" }, // Alternatively, "CTOS" or "REAL/32 or DR-DOS or Novell-DOS secure partition"
164 { 0xC1, "DR-DOS FAT12" },
165 { 0xC2, "Hidden Linux" },
166 { 0xC3, "Hidden Linux swap" },
167 { 0xC4, "DR-DOS FAT16 (< 32 MB)" },
168 { 0xC5, "DR-DOS Extended" },
169 { 0xC6, "DR-DOS FAT16" },
170 { 0xC7, "HPFS mirrored" }, // Alternatively, "Syrinx boot"
171 { 0xCB, "DR-DOS FAT32" },
172 { 0xCC, "DR-DOS FAT32 (LBA)" },
173 { 0xCE, "DR-DOS FAT16 (LBA)" },
175 { 0xD1, "MDOS FAT12" },
176 { 0xD4, "MDOS FAT16 (< 32 MB)" },
177 { 0xD5, "MDOS Extended" },
178 { 0xD6, "MDOS FAT16" },
180 { 0xDB, "Digital Research CP/M" },
181 { 0xDE, "Dell OEM" },
182 { 0xDF, "BootIt EMBRM (FAT16/32)" },
183 { 0xE1, "SpeedStor FAT12" },
184 { 0xE3, "SpeedStor (0xE3)" },
185 { 0xE4, "SpeedStor FAT16" },
186 { 0xE5, "Tandy MSDOS" },
187 { 0xE6, "SpeedStor (0xE6)" },
188 { 0xE8, "Linux Unified Key Setup partition" },
189 { 0xEA, "Rufus private partition" },
190 { 0xEB, "BeOS BFS" },
191 { 0xEC, "SkyOS SkyFS" },
192 { 0xEE, "EFI GPT protective" },
193 { 0xEF, "EFI System partition" },
194 { 0xF0, "Linux/PA-RISC boot loader" },
195 { 0xF1, "SpeedStor (0xF1)" },
196 { 0xF2, "DOS 3.3+ second" },
197 { 0xF4, "SpeedStor (0xF4)" },
198 { 0xF5, "SpeedStor (0xF5)" },
199 { 0xF6, "SpeedStor (0xF6)" },
201 { 0xFB, "VMware FS" },
202 { 0xFC, "VMware swap" },
203 { 0xFD, "Linux RAID auto" },
204 { 0xFE, "NT hidden partition" },
205 { 0xFF, "XENIX Bad Block Table" },
209 /* FUNCTIONS ****************************************************************/
211 #ifdef DUMP_PARTITION_TABLE
215 PDISKENTRY DiskEntry
)
217 PPARTITION_INFORMATION PartitionInfo
;
221 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
222 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
224 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
226 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
227 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
229 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
230 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
231 PartitionInfo
->HiddenSectors
,
232 PartitionInfo
->PartitionNumber
,
233 PartitionInfo
->PartitionType
,
234 PartitionInfo
->BootIndicator
? '*': ' ',
235 PartitionInfo
->RewritePartition
? 'Y': 'N');
250 Temp
= Value
/ Alignment
;
252 return Temp
* Alignment
;
260 ULONGLONG Temp
, Result
;
262 Temp
= Value
/ Alignment
;
264 Result
= Temp
* Alignment
;
265 if (Value
% Alignment
)
273 IN ULONGLONG Dividend
,
274 IN ULONGLONG Divisor
)
276 return (Dividend
+ Divisor
/ 2) / Divisor
;
283 IN PDISKENTRY DiskEntry
)
285 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
289 RtlInitUnicodeString(&DiskEntry
->DriverName
, NULL
);
291 RtlStringCchPrintfW(KeyName
, ARRAYSIZE(KeyName
),
292 L
"\\Scsi\\Scsi Port %hu",
295 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
297 QueryTable
[0].Name
= L
"Driver";
298 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
299 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
301 /* This will allocate DiskEntry->DriverName if needed */
302 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
307 if (!NT_SUCCESS(Status
))
309 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
318 PDISKENTRY DiskEntry
;
319 PPARTENTRY PartEntry
;
326 /* Assign drive letters to primary partitions */
327 Entry1
= List
->DiskListHead
.Flink
;
328 while (Entry1
!= &List
->DiskListHead
)
330 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
332 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
333 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
335 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
337 PartEntry
->DriveLetter
= 0;
339 if (PartEntry
->IsPartitioned
&&
340 !IsContainerPartition(PartEntry
->PartitionType
))
342 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
343 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
344 PartEntry
->SectorCount
.QuadPart
!= 0LL))
348 PartEntry
->DriveLetter
= Letter
;
354 Entry2
= Entry2
->Flink
;
357 Entry1
= Entry1
->Flink
;
360 /* Assign drive letters to logical drives */
361 Entry1
= List
->DiskListHead
.Flink
;
362 while (Entry1
!= &List
->DiskListHead
)
364 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
366 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
367 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
369 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
371 PartEntry
->DriveLetter
= 0;
373 if (PartEntry
->IsPartitioned
)
375 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
376 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
377 PartEntry
->SectorCount
.QuadPart
!= 0LL))
381 PartEntry
->DriveLetter
= Letter
;
387 Entry2
= Entry2
->Flink
;
390 Entry1
= Entry1
->Flink
;
396 DiskIdentifierQueryRoutine(
404 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
405 UNICODE_STRING NameU
;
407 if (ValueType
== REG_SZ
&&
408 ValueLength
== 20 * sizeof(WCHAR
))
410 NameU
.Buffer
= (PWCHAR
)ValueData
;
411 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
412 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
414 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
415 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
417 return STATUS_SUCCESS
;
420 return STATUS_UNSUCCESSFUL
;
425 DiskConfigurationDataQueryRoutine(
433 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
434 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
435 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
438 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
439 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
440 return STATUS_UNSUCCESSFUL
;
442 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
444 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
446 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
447 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
448 return STATUS_UNSUCCESSFUL
;
451 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
453 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
454 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
457 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
458 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
460 return STATUS_SUCCESS
;
463 return STATUS_UNSUCCESSFUL
;
468 SystemConfigurationDataQueryRoutine(
476 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
477 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
480 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
481 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
482 return STATUS_UNSUCCESSFUL
;
484 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
486 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
488 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
489 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
490 return STATUS_UNSUCCESSFUL
;
493 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
495 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
496 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
499 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*)RtlAllocateHeap(ProcessHeap
, 0,
500 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
501 if (*Int13Drives
== NULL
)
502 return STATUS_NO_MEMORY
;
505 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
506 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
507 return STATUS_SUCCESS
;
510 return STATUS_UNSUCCESSFUL
;
515 EnumerateBiosDiskEntries(
516 IN PPARTLIST PartList
)
518 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
523 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
524 PBIOSDISKENTRY BiosDiskEntry
;
526 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
528 memset(QueryTable
, 0, sizeof(QueryTable
));
530 QueryTable
[1].Name
= L
"Configuration Data";
531 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
533 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
534 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
538 if (!NT_SUCCESS(Status
))
540 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
547 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
549 ROOT_NAME
, AdapterCount
);
550 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
555 if (!NT_SUCCESS(Status
))
560 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
561 L
"%s\\%lu\\DiskController",
562 ROOT_NAME
, AdapterCount
);
563 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
568 if (NT_SUCCESS(Status
))
572 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
573 L
"%s\\%lu\\DiskController\\0",
574 ROOT_NAME
, AdapterCount
);
575 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
580 if (!NT_SUCCESS(Status
))
582 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
586 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
587 L
"%s\\%lu\\DiskController\\0\\DiskPeripheral",
588 ROOT_NAME
, AdapterCount
);
589 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
594 if (NT_SUCCESS(Status
))
596 QueryTable
[0].Name
= L
"Identifier";
597 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
598 QueryTable
[1].Name
= L
"Configuration Data";
599 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
604 BiosDiskEntry
= (BIOSDISKENTRY
*)RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
605 if (BiosDiskEntry
== NULL
)
610 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
611 L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu",
612 ROOT_NAME
, AdapterCount
, DiskCount
);
613 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
616 (PVOID
)BiosDiskEntry
,
618 if (!NT_SUCCESS(Status
))
620 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
624 BiosDiskEntry
->DiskNumber
= DiskCount
;
625 BiosDiskEntry
->Recognized
= FALSE
;
627 if (DiskCount
< Int13Drives
[0].NumberDrives
)
629 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
633 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
636 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
638 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
639 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
640 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
641 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
642 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
643 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
644 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
645 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
646 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
647 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
648 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
654 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
662 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
671 IN PDISKENTRY DiskEntry
,
672 IN ULONG PartitionIndex
,
673 IN BOOLEAN LogicalPartition
)
676 PPARTITION_INFORMATION PartitionInfo
;
677 PPARTENTRY PartEntry
;
679 OBJECT_ATTRIBUTES ObjectAttributes
;
680 IO_STATUS_BLOCK IoStatusBlock
;
681 WCHAR Buffer
[MAX_PATH
];
683 UCHAR LabelBuffer
[sizeof(FILE_FS_VOLUME_INFORMATION
) + 256 * sizeof(WCHAR
)];
684 PFILE_FS_VOLUME_INFORMATION LabelInfo
= (PFILE_FS_VOLUME_INFORMATION
)LabelBuffer
;
686 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
688 if (PartitionInfo
->PartitionType
== PARTITION_ENTRY_UNUSED
||
689 ((LogicalPartition
!= FALSE
) && IsContainerPartition(PartitionInfo
->PartitionType
)))
694 PartEntry
= RtlAllocateHeap(ProcessHeap
,
697 if (PartEntry
== NULL
)
700 PartEntry
->DiskEntry
= DiskEntry
;
702 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
703 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
705 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
706 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
707 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
709 PartEntry
->LogicalPartition
= LogicalPartition
;
710 PartEntry
->IsPartitioned
= TRUE
;
711 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
712 PartEntry
->PartitionIndex
= PartitionIndex
;
714 if (IsContainerPartition(PartEntry
->PartitionType
))
716 PartEntry
->FormatState
= Unformatted
;
717 PartEntry
->FileSystem
= NULL
;
719 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
720 DiskEntry
->ExtendedPartition
= PartEntry
;
722 else if (IsRecognizedPartition(PartEntry
->PartitionType
))
724 PartEntry
->FileSystem
= GetFileSystem(PartEntry
);
725 if (PartEntry
->FileSystem
)
726 PartEntry
->FormatState
= Preformatted
;
728 PartEntry
->FormatState
= Unformatted
;
729 // PartEntry->FormatState = UnknownFormat;
733 /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
734 PartEntry
->FormatState
= UnknownFormat
;
737 /* Initialize the partition volume label */
738 RtlZeroMemory(PartEntry
->VolumeLabel
, sizeof(PartEntry
->VolumeLabel
));
740 /* Open the volume, ignore any errors */
741 RtlStringCchPrintfW(Buffer
, ARRAYSIZE(Buffer
),
742 L
"\\Device\\Harddisk%lu\\Partition%lu",
743 DiskEntry
->DiskNumber
, PartEntry
->PartitionNumber
);
744 RtlInitUnicodeString(&Name
, Buffer
);
746 InitializeObjectAttributes(&ObjectAttributes
,
748 OBJ_CASE_INSENSITIVE
,
752 Status
= NtOpenFile(&FileHandle
,
753 FILE_READ_DATA
| SYNCHRONIZE
,
756 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
757 FILE_SYNCHRONOUS_IO_NONALERT
);
758 if (NT_SUCCESS(Status
))
760 /* Retrieve the partition volume label */
761 Status
= NtQueryVolumeInformationFile(FileHandle
,
765 FileFsVolumeInformation
);
766 /* Close the handle */
769 /* Check for success */
770 if (NT_SUCCESS(Status
))
772 /* Copy the (possibly truncated) volume label and NULL-terminate it */
773 RtlStringCbCopyNW(PartEntry
->VolumeLabel
, sizeof(PartEntry
->VolumeLabel
),
774 LabelInfo
->VolumeLabel
, LabelInfo
->VolumeLabelLength
);
778 DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status
);
783 DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status
);
786 if (LogicalPartition
)
787 InsertTailList(&DiskEntry
->LogicalPartListHead
,
788 &PartEntry
->ListEntry
);
790 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
791 &PartEntry
->ListEntry
);
796 ScanForUnpartitionedDiskSpace(
797 IN PDISKENTRY DiskEntry
)
799 ULONGLONG LastStartSector
;
800 ULONGLONG LastSectorCount
;
801 ULONGLONG LastUnusedSectorCount
;
802 PPARTENTRY PartEntry
;
803 PPARTENTRY NewPartEntry
;
806 DPRINT("ScanForUnpartitionedDiskSpace()\n");
808 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
810 DPRINT1("No primary partition!\n");
812 /* Create a partition entry that represents the empty disk */
813 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
816 if (NewPartEntry
== NULL
)
819 NewPartEntry
->DiskEntry
= DiskEntry
;
821 NewPartEntry
->IsPartitioned
= FALSE
;
822 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
823 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
824 NewPartEntry
->StartSector
.QuadPart
;
826 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
827 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
828 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
830 NewPartEntry
->FormatState
= Unformatted
;
831 NewPartEntry
->FileSystem
= NULL
;
833 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
834 &NewPartEntry
->ListEntry
);
839 /* Start partition at head 1, cylinder 0 */
840 LastStartSector
= DiskEntry
->SectorAlignment
;
841 LastSectorCount
= 0ULL;
842 LastUnusedSectorCount
= 0ULL;
844 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
845 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
847 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
849 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
850 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
852 LastUnusedSectorCount
=
853 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
855 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
856 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
858 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
860 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
863 if (NewPartEntry
== NULL
)
866 NewPartEntry
->DiskEntry
= DiskEntry
;
868 NewPartEntry
->IsPartitioned
= FALSE
;
869 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
870 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
871 NewPartEntry
->StartSector
.QuadPart
;
873 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
874 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
875 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
877 NewPartEntry
->FormatState
= Unformatted
;
878 NewPartEntry
->FileSystem
= NULL
;
880 /* Insert the table into the list */
881 InsertTailList(&PartEntry
->ListEntry
,
882 &NewPartEntry
->ListEntry
);
885 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
886 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
889 Entry
= Entry
->Flink
;
892 /* Check for trailing unpartitioned disk space */
893 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
895 LastUnusedSectorCount
= AlignDown(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
897 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
899 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
901 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
904 if (NewPartEntry
== NULL
)
907 NewPartEntry
->DiskEntry
= DiskEntry
;
909 NewPartEntry
->IsPartitioned
= FALSE
;
910 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
911 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
912 NewPartEntry
->StartSector
.QuadPart
;
914 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
915 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
916 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
918 NewPartEntry
->FormatState
= Unformatted
;
919 NewPartEntry
->FileSystem
= NULL
;
921 /* Append the table to the list */
922 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
923 &NewPartEntry
->ListEntry
);
927 if (DiskEntry
->ExtendedPartition
!= NULL
)
929 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
931 DPRINT1("No logical partition!\n");
933 /* Create a partition entry that represents the empty extended partition */
934 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
937 if (NewPartEntry
== NULL
)
940 NewPartEntry
->DiskEntry
= DiskEntry
;
941 NewPartEntry
->LogicalPartition
= TRUE
;
943 NewPartEntry
->IsPartitioned
= FALSE
;
944 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
945 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
947 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
948 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
949 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
951 NewPartEntry
->FormatState
= Unformatted
;
952 NewPartEntry
->FileSystem
= NULL
;
954 InsertTailList(&DiskEntry
->LogicalPartListHead
,
955 &NewPartEntry
->ListEntry
);
960 /* Start partition at head 1, cylinder 0 */
961 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
962 LastSectorCount
= 0ULL;
963 LastUnusedSectorCount
= 0ULL;
965 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
966 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
968 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
970 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
971 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
973 LastUnusedSectorCount
=
974 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
976 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
977 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
979 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
981 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
984 if (NewPartEntry
== NULL
)
987 NewPartEntry
->DiskEntry
= DiskEntry
;
988 NewPartEntry
->LogicalPartition
= TRUE
;
990 NewPartEntry
->IsPartitioned
= FALSE
;
991 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
992 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
993 NewPartEntry
->StartSector
.QuadPart
;
995 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
996 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
997 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
999 NewPartEntry
->FormatState
= Unformatted
;
1000 NewPartEntry
->FileSystem
= NULL
;
1002 /* Insert the table into the list */
1003 InsertTailList(&PartEntry
->ListEntry
,
1004 &NewPartEntry
->ListEntry
);
1007 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
1008 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
1011 Entry
= Entry
->Flink
;
1014 /* Check for trailing unpartitioned disk space */
1015 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
1017 LastUnusedSectorCount
= AlignDown(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
1019 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
1021 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
1023 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
1026 if (NewPartEntry
== NULL
)
1029 NewPartEntry
->DiskEntry
= DiskEntry
;
1030 NewPartEntry
->LogicalPartition
= TRUE
;
1032 NewPartEntry
->IsPartitioned
= FALSE
;
1033 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
1034 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
1035 NewPartEntry
->StartSector
.QuadPart
;
1037 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
1038 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
1039 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
1041 NewPartEntry
->FormatState
= Unformatted
;
1042 NewPartEntry
->FileSystem
= NULL
;
1044 /* Append the table to the list */
1045 InsertTailList(&DiskEntry
->LogicalPartListHead
,
1046 &NewPartEntry
->ListEntry
);
1051 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1058 IN PDISKENTRY DiskEntry
)
1060 LARGE_INTEGER SystemTime
;
1061 TIME_FIELDS TimeFields
;
1063 PDISKENTRY DiskEntry2
;
1066 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
1070 NtQuerySystemTime(&SystemTime
);
1071 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
1073 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
1074 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
1075 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
1076 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
1078 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
1083 /* Check if the signature already exist */
1085 * Check also signatures from disks, which are
1086 * not visible (bootable) by the bios.
1088 Entry2
= List
->DiskListHead
.Flink
;
1089 while (Entry2
!= &List
->DiskListHead
)
1091 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
1093 if (DiskEntry
!= DiskEntry2
&&
1094 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
1097 Entry2
= Entry2
->Flink
;
1100 if (Entry2
== &List
->DiskListHead
)
1107 UpdateDiskSignatures(
1111 PDISKENTRY DiskEntry
;
1113 /* Print partition lines */
1114 Entry
= List
->DiskListHead
.Flink
;
1115 while (Entry
!= &List
->DiskListHead
)
1117 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1119 if (DiskEntry
->LayoutBuffer
&&
1120 DiskEntry
->LayoutBuffer
->Signature
== 0)
1122 SetDiskSignature(List
, DiskEntry
);
1123 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
1126 Entry
= Entry
->Flink
;
1133 IN HANDLE FileHandle
,
1134 IN ULONG DiskNumber
,
1137 DISK_GEOMETRY DiskGeometry
;
1138 SCSI_ADDRESS ScsiAddress
;
1139 PDISKENTRY DiskEntry
;
1140 IO_STATUS_BLOCK Iosb
;
1142 PPARTITION_SECTOR Mbr
;
1144 LARGE_INTEGER FileOffset
;
1145 WCHAR Identifier
[20];
1149 PLIST_ENTRY ListEntry
;
1150 PBIOSDISKENTRY BiosDiskEntry
;
1151 ULONG LayoutBufferSize
;
1152 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
1154 /* Retrieve the drive geometry */
1155 Status
= NtDeviceIoControlFile(FileHandle
,
1160 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1164 sizeof(DiskGeometry
));
1165 if (!NT_SUCCESS(Status
))
1168 if (DiskGeometry
.MediaType
!= FixedMedia
&&
1169 DiskGeometry
.MediaType
!= RemovableMedia
)
1175 * FIXME: Here we suppose the disk is always SCSI. What if it is
1176 * of another type? To check this we need to retrieve the name of
1177 * the driver the disk device belongs to.
1179 Status
= NtDeviceIoControlFile(FileHandle
,
1184 IOCTL_SCSI_GET_ADDRESS
,
1188 sizeof(ScsiAddress
));
1189 if (!NT_SUCCESS(Status
))
1193 * Check whether the disk is initialized, by looking at its MBR.
1194 * NOTE that this must be generalized to GPT disks as well!
1197 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1199 DiskGeometry
.BytesPerSector
);
1203 FileOffset
.QuadPart
= 0;
1204 Status
= NtReadFile(FileHandle
,
1210 DiskGeometry
.BytesPerSector
,
1213 if (!NT_SUCCESS(Status
))
1215 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1216 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1219 Signature
= Mbr
->Signature
;
1221 /* Calculate the MBR checksum */
1223 Buffer
= (PULONG
)Mbr
;
1224 for (i
= 0; i
< 128; i
++)
1226 Checksum
+= Buffer
[i
];
1228 Checksum
= ~Checksum
+ 1;
1230 RtlStringCchPrintfW(Identifier
, ARRAYSIZE(Identifier
),
1231 L
"%08x-%08x-A", Checksum
, Signature
);
1232 DPRINT("Identifier: %S\n", Identifier
);
1234 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1237 if (DiskEntry
== NULL
)
1239 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1240 DPRINT1("Failed to allocate a new disk entry.\n");
1244 // DiskEntry->Checksum = Checksum;
1245 // DiskEntry->Signature = Signature;
1246 DiskEntry
->BiosFound
= FALSE
;
1249 * Check if this disk has a valid MBR: verify its signature,
1250 * and whether its two first bytes are a valid instruction
1251 * (related to this, see IsThereAValidBootSector() in partlist.c).
1253 if (Mbr
->Magic
!= 0xaa55 || (*(PUSHORT
)Mbr
->BootCode
) == 0x0000)
1254 DiskEntry
->NoMbr
= TRUE
;
1256 DiskEntry
->NoMbr
= FALSE
;
1258 /* Free the MBR sector buffer */
1259 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1262 ListEntry
= List
->BiosDiskListHead
.Flink
;
1263 while (ListEntry
!= &List
->BiosDiskListHead
)
1265 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1267 * Compare the size from bios and the reported size from driver.
1268 * If we have more than one disk with a zero or with the same signature
1269 * we must create new signatures and reboot. After the reboot,
1270 * it is possible to identify the disks.
1272 if (BiosDiskEntry
->Signature
== Signature
&&
1273 BiosDiskEntry
->Checksum
== Checksum
&&
1274 !BiosDiskEntry
->Recognized
)
1276 if (!DiskEntry
->BiosFound
)
1278 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1279 DiskEntry
->BiosFound
= TRUE
;
1280 BiosDiskEntry
->Recognized
= TRUE
;
1284 // FIXME: What to do?
1287 ListEntry
= ListEntry
->Flink
;
1290 if (!DiskEntry
->BiosFound
)
1293 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1296 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1300 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1301 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1303 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1304 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1305 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1306 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1308 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1309 DPRINT("TracksPerCylinder %lu\n", DiskEntry
->TracksPerCylinder
);
1310 DPRINT("SectorsPerTrack %lu\n", DiskEntry
->SectorsPerTrack
);
1311 DPRINT("BytesPerSector %lu\n", DiskEntry
->BytesPerSector
);
1313 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1314 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1315 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1317 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1318 DiskEntry
->CylinderAlignment
= DiskGeometry
.TracksPerCylinder
*
1319 DiskGeometry
.SectorsPerTrack
;
1321 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
.QuadPart
);
1322 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1324 DiskEntry
->DiskNumber
= DiskNumber
;
1325 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1326 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1327 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1329 GetDriverName(DiskEntry
);
1331 * Actually it would be more correct somehow to use:
1333 * OBJECT_NAME_INFORMATION NameInfo; // ObjectNameInfo;
1334 * ULONG ReturnedLength;
1336 * Status = NtQueryObject(SomeHandleToTheDisk,
1337 * ObjectNameInformation,
1343 * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
1346 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1350 * We now retrieve the disk partition layout
1353 /* Allocate a layout buffer with 4 partition entries first */
1354 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1355 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1356 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1359 if (DiskEntry
->LayoutBuffer
== NULL
)
1361 DPRINT1("Failed to allocate the disk layout buffer!\n");
1365 /* Keep looping while the drive layout buffer is too small */
1368 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1369 Status
= NtDeviceIoControlFile(FileHandle
,
1374 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1377 DiskEntry
->LayoutBuffer
,
1379 if (NT_SUCCESS(Status
))
1382 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1384 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1388 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1389 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1391 DiskEntry
->LayoutBuffer
,
1393 if (NewLayoutBuffer
== NULL
)
1395 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1399 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1402 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1404 #ifdef DUMP_PARTITION_TABLE
1405 DumpPartitionTable(DiskEntry
);
1408 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1409 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1410 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1412 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1414 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1416 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1418 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1422 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1427 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1431 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1433 DiskEntry
->NewDisk
= TRUE
;
1434 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1436 for (i
= 0; i
< 4; i
++)
1437 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1441 for (i
= 0; i
< 4; i
++)
1443 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, FALSE
);
1446 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1448 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, TRUE
);
1452 ScanForUnpartitionedDiskSpace(DiskEntry
);
1456 CreatePartitionList(VOID
)
1459 OBJECT_ATTRIBUTES ObjectAttributes
;
1460 SYSTEM_DEVICE_INFORMATION Sdi
;
1461 IO_STATUS_BLOCK Iosb
;
1465 WCHAR Buffer
[MAX_PATH
];
1466 UNICODE_STRING Name
;
1469 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1475 List
->CurrentDisk
= NULL
;
1476 List
->CurrentPartition
= NULL
;
1478 List
->SystemPartition
= NULL
;
1479 List
->OriginalSystemPartition
= NULL
;
1481 InitializeListHead(&List
->DiskListHead
);
1482 InitializeListHead(&List
->BiosDiskListHead
);
1485 * Enumerate the disks seen by the BIOS; this will be used later
1486 * to map drives seen by NTOS with their corresponding BIOS names.
1488 EnumerateBiosDiskEntries(List
);
1490 /* Enumerate disks seen by NTOS */
1491 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1495 if (!NT_SUCCESS(Status
))
1497 DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status
);
1498 RtlFreeHeap(ProcessHeap
, 0, List
);
1502 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1504 RtlStringCchPrintfW(Buffer
, ARRAYSIZE(Buffer
),
1505 L
"\\Device\\Harddisk%lu\\Partition0",
1507 RtlInitUnicodeString(&Name
, Buffer
);
1509 InitializeObjectAttributes(&ObjectAttributes
,
1511 OBJ_CASE_INSENSITIVE
,
1515 Status
= NtOpenFile(&FileHandle
,
1516 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1519 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1520 FILE_SYNCHRONOUS_IO_NONALERT
);
1521 if (NT_SUCCESS(Status
))
1523 AddDiskToList(FileHandle
, DiskNumber
, List
);
1524 NtClose(FileHandle
);
1528 UpdateDiskSignatures(List
);
1530 AssignDriveLetters(List
);
1532 /* Search for first usable disk and partition */
1533 if (IsListEmpty(&List
->DiskListHead
))
1535 List
->CurrentDisk
= NULL
;
1536 List
->CurrentPartition
= NULL
;
1540 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1544 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1546 List
->CurrentPartition
= NULL
;
1550 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1560 DestroyPartitionList(
1563 PDISKENTRY DiskEntry
;
1564 PBIOSDISKENTRY BiosDiskEntry
;
1565 PPARTENTRY PartEntry
;
1568 /* Release disk and partition info */
1569 while (!IsListEmpty(&List
->DiskListHead
))
1571 Entry
= RemoveHeadList(&List
->DiskListHead
);
1572 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1574 /* Release driver name */
1575 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1577 /* Release primary partition list */
1578 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1580 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1581 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1583 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1586 /* Release logical partition list */
1587 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1589 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1590 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1592 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1595 /* Release layout buffer */
1596 if (DiskEntry
->LayoutBuffer
!= NULL
)
1597 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1599 /* Release disk entry */
1600 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1603 /* Release the bios disk info */
1604 while (!IsListEmpty(&List
->BiosDiskListHead
))
1606 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1607 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1609 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1612 /* Release list head */
1613 RtlFreeHeap(ProcessHeap
, 0, List
);
1617 GetDiskByBiosNumber(
1619 IN ULONG BiosDiskNumber
)
1621 PDISKENTRY DiskEntry
;
1624 /* Loop over the disks and find the correct one */
1625 Entry
= List
->DiskListHead
.Flink
;
1626 while (Entry
!= &List
->DiskListHead
)
1628 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1629 Entry
= Entry
->Flink
;
1631 if (DiskEntry
->BiosDiskNumber
== BiosDiskNumber
)
1638 /* Disk not found, stop there */
1645 IN ULONG DiskNumber
)
1647 PDISKENTRY DiskEntry
;
1650 /* Loop over the disks and find the correct one */
1651 Entry
= List
->DiskListHead
.Flink
;
1652 while (Entry
!= &List
->DiskListHead
)
1654 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1655 Entry
= Entry
->Flink
;
1657 if (DiskEntry
->DiskNumber
== DiskNumber
)
1664 /* Disk not found, stop there */
1675 PDISKENTRY DiskEntry
;
1678 /* Loop over the disks and find the correct one */
1679 Entry
= List
->DiskListHead
.Flink
;
1680 while (Entry
!= &List
->DiskListHead
)
1682 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1683 Entry
= Entry
->Flink
;
1685 if (DiskEntry
->Port
== Port
&&
1686 DiskEntry
->Bus
== Bus
&&
1687 DiskEntry
->Id
== Id
)
1694 /* Disk not found, stop there */
1703 PDISKENTRY DiskEntry
;
1706 /* Loop over the disks and find the correct one */
1707 Entry
= List
->DiskListHead
.Flink
;
1708 while (Entry
!= &List
->DiskListHead
)
1710 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1711 Entry
= Entry
->Flink
;
1713 if (DiskEntry
->LayoutBuffer
->Signature
== Signature
)
1720 /* Disk not found, stop there */
1726 // IN PPARTLIST List,
1727 IN PDISKENTRY DiskEntry
,
1728 IN ULONG PartitionNumber
)
1730 PPARTENTRY PartEntry
;
1733 /* Disk found, loop over the primary partitions first... */
1734 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1735 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
1737 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1738 Entry
= Entry
->Flink
;
1740 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1742 /* Partition found */
1747 /* ... then over the logical partitions if needed */
1748 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
1749 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
1751 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1752 Entry
= Entry
->Flink
;
1754 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1756 /* Partition found */
1761 /* The partition was not found on the disk, stop there */
1768 IN ULONG DiskNumber
,
1769 IN ULONG PartitionNumber OPTIONAL
,
1770 OUT PDISKENTRY
* pDiskEntry
,
1771 OUT PPARTENTRY
* pPartEntry OPTIONAL
)
1773 PDISKENTRY DiskEntry
;
1774 PPARTENTRY PartEntry
= NULL
;
1777 DiskEntry
= GetDiskByNumber(List
, DiskNumber
);
1781 /* If we have a partition (PartitionNumber != 0), find it */
1782 if (PartitionNumber
!= 0)
1784 PartEntry
= GetPartition(/*List,*/ DiskEntry
, PartitionNumber
);
1787 ASSERT(PartEntry
->DiskEntry
== DiskEntry
);
1790 /* Return the disk (and optionally the partition) */
1791 *pDiskEntry
= DiskEntry
;
1792 if (pPartEntry
) *pPartEntry
= PartEntry
;
1797 // NOTE: Was introduced broken in r6258 by Casper
1802 IN ULONG DiskNumber
,
1803 IN ULONG PartitionNumber
)
1805 PDISKENTRY DiskEntry
;
1806 PPARTENTRY PartEntry
;
1808 DiskEntry
= GetDiskByNumber(List
, DiskNumber
);
1812 PartEntry
= GetPartition(/*List,*/ DiskEntry
, PartitionNumber
);
1816 ASSERT(PartEntry
->DiskEntry
== DiskEntry
);
1817 ASSERT(DiskEntry
->DiskNumber
== DiskNumber
);
1818 ASSERT(PartEntry
->PartitionNumber
== PartitionNumber
);
1820 List
->CurrentDisk
= DiskEntry
;
1821 List
->CurrentPartition
= PartEntry
;
1829 PLIST_ENTRY DiskListEntry
;
1830 PLIST_ENTRY PartListEntry
;
1831 PDISKENTRY DiskEntry
;
1832 PPARTENTRY PartEntry
;
1834 /* Fail if no disks are available */
1835 if (IsListEmpty(&List
->DiskListHead
))
1838 /* Check for next usable entry on current disk */
1839 if (List
->CurrentPartition
!= NULL
)
1841 if (List
->CurrentPartition
->LogicalPartition
)
1843 /* Logical partition */
1845 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
1846 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1848 /* Next logical partition */
1849 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1851 List
->CurrentPartition
= PartEntry
;
1852 return List
->CurrentPartition
;
1856 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
1857 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1859 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1861 List
->CurrentPartition
= PartEntry
;
1862 return List
->CurrentPartition
;
1868 /* Primary or extended partition */
1870 if ((List
->CurrentPartition
->IsPartitioned
!= FALSE
) &&
1871 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
1873 /* First logical partition */
1874 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
1875 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1877 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1879 List
->CurrentPartition
= PartEntry
;
1880 return List
->CurrentPartition
;
1885 /* Next primary partition */
1886 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
1887 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1889 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1891 List
->CurrentPartition
= PartEntry
;
1892 return List
->CurrentPartition
;
1898 /* Search for the first partition entry on the next disk */
1899 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
1900 while (DiskListEntry
!= &List
->DiskListHead
)
1902 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
1904 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1905 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1907 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1909 List
->CurrentDisk
= DiskEntry
;
1910 List
->CurrentPartition
= PartEntry
;
1911 return List
->CurrentPartition
;
1914 DiskListEntry
= DiskListEntry
->Flink
;
1924 PLIST_ENTRY DiskListEntry
;
1925 PLIST_ENTRY PartListEntry
;
1926 PDISKENTRY DiskEntry
;
1927 PPARTENTRY PartEntry
;
1929 /* Fail if no disks are available */
1930 if (IsListEmpty(&List
->DiskListHead
))
1933 /* Check for previous usable entry on current disk */
1934 if (List
->CurrentPartition
!= NULL
)
1936 if (List
->CurrentPartition
->LogicalPartition
)
1938 /* Logical partition */
1939 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
1940 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1942 /* Previous logical partition */
1943 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1947 /* Extended partition */
1948 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
1951 List
->CurrentPartition
= PartEntry
;
1952 return List
->CurrentPartition
;
1956 /* Primary or extended partition */
1958 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
1959 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1961 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1963 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
1964 IsContainerPartition(PartEntry
->PartitionType
))
1966 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
1967 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1970 List
->CurrentPartition
= PartEntry
;
1971 return List
->CurrentPartition
;
1976 /* Search for the last partition entry on the previous disk */
1977 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
1978 while (DiskListEntry
!= &List
->DiskListHead
)
1980 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
1982 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
1983 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1985 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1987 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
1988 IsContainerPartition(PartEntry
->PartitionType
))
1990 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
1991 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
1993 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1995 List
->CurrentDisk
= DiskEntry
;
1996 List
->CurrentPartition
= PartEntry
;
1997 return List
->CurrentPartition
;
2002 List
->CurrentDisk
= DiskEntry
;
2003 List
->CurrentPartition
= PartEntry
;
2004 return List
->CurrentPartition
;
2008 DiskListEntry
= DiskListEntry
->Blink
;
2018 IN PPARTITION_INFORMATION PartitionInfo
)
2020 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2021 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2032 IsSamePrimaryLayoutEntry(
2033 IN PPARTITION_INFORMATION PartitionInfo
,
2034 IN PDISKENTRY DiskEntry
,
2035 IN PPARTENTRY PartEntry
)
2037 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2038 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2039 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2040 // PartitionInfo->PartitionType == PartEntry->PartitionType
2050 GetPrimaryPartitionCount(
2051 IN PDISKENTRY DiskEntry
)
2054 PPARTENTRY PartEntry
;
2057 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2058 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2060 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2061 if (PartEntry
->IsPartitioned
)
2064 Entry
= Entry
->Flink
;
2072 GetLogicalPartitionCount(
2073 IN PDISKENTRY DiskEntry
)
2075 PLIST_ENTRY ListEntry
;
2076 PPARTENTRY PartEntry
;
2079 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2080 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2082 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2083 if (PartEntry
->IsPartitioned
)
2086 ListEntry
= ListEntry
->Flink
;
2094 ReAllocateLayoutBuffer(
2095 IN PDISKENTRY DiskEntry
)
2097 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
2098 ULONG NewPartitionCount
;
2099 ULONG CurrentPartitionCount
= 0;
2100 ULONG LayoutBufferSize
;
2103 DPRINT1("ReAllocateLayoutBuffer()\n");
2105 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
2107 if (DiskEntry
->LayoutBuffer
)
2108 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
2110 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2111 CurrentPartitionCount
, NewPartitionCount
);
2113 if (CurrentPartitionCount
== NewPartitionCount
)
2116 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2117 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
2118 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
2120 DiskEntry
->LayoutBuffer
,
2122 if (NewLayoutBuffer
== NULL
)
2124 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
2128 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2129 if (NewPartitionCount
> CurrentPartitionCount
)
2131 for (i
= CurrentPartitionCount
; i
< NewPartitionCount
; i
++)
2132 NewLayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
2135 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
2136 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
2144 IN PDISKENTRY DiskEntry
)
2146 PPARTITION_INFORMATION PartitionInfo
;
2147 PPARTITION_INFORMATION LinkInfo
= NULL
;
2148 PLIST_ENTRY ListEntry
;
2149 PPARTENTRY PartEntry
;
2150 LARGE_INTEGER HiddenSectors64
;
2152 ULONG PartitionNumber
= 1;
2154 DPRINT1("UpdateDiskLayout()\n");
2156 /* Resize the layout buffer if necessary */
2157 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
2159 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2163 /* Update the primary partition table */
2165 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2166 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2168 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2170 if (PartEntry
->IsPartitioned
!= FALSE
)
2172 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2174 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2176 DPRINT1("Updating primary partition entry %lu\n", Index
);
2178 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2179 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2180 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
2181 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2182 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2183 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2184 PartitionInfo
->RecognizedPartition
= FALSE
;
2185 PartitionInfo
->RewritePartition
= TRUE
;
2188 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2189 PartEntry
->PartitionIndex
= Index
;
2191 if (!IsContainerPartition(PartEntry
->PartitionType
))
2197 ListEntry
= ListEntry
->Flink
;
2200 /* Update the logical partition table */
2202 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2203 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2205 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2207 if (PartEntry
->IsPartitioned
)
2209 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2211 DPRINT1("Updating logical partition entry %lu\n", Index
);
2213 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2214 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2215 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
2216 PartitionInfo
->PartitionNumber
= PartitionNumber
;
2217 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2218 PartitionInfo
->BootIndicator
= FALSE
;
2219 PartitionInfo
->RecognizedPartition
= FALSE
;
2220 PartitionInfo
->RewritePartition
= TRUE
;
2222 PartEntry
->PartitionNumber
= PartitionNumber
;
2223 PartEntry
->PartitionIndex
= Index
;
2225 /* Fill the link entry of the previous partition entry */
2226 if (LinkInfo
!= NULL
)
2228 LinkInfo
->StartingOffset
.QuadPart
= (PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2229 LinkInfo
->PartitionLength
.QuadPart
= (PartEntry
->StartSector
.QuadPart
+ DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2230 HiddenSectors64
.QuadPart
= PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
- DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
;
2231 LinkInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
2232 LinkInfo
->PartitionNumber
= 0;
2233 LinkInfo
->PartitionType
= PARTITION_EXTENDED
;
2234 LinkInfo
->BootIndicator
= FALSE
;
2235 LinkInfo
->RecognizedPartition
= FALSE
;
2236 LinkInfo
->RewritePartition
= TRUE
;
2239 /* Save a pointer to the link entry of the current partition entry */
2240 LinkInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
+ 1];
2246 ListEntry
= ListEntry
->Flink
;
2249 /* Wipe unused primary partition entries */
2250 for (Index
= GetPrimaryPartitionCount(DiskEntry
); Index
< 4; Index
++)
2252 DPRINT1("Primary partition entry %lu\n", Index
);
2254 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2256 if (!IsEmptyLayoutEntry(PartitionInfo
))
2258 DPRINT1("Wiping primary partition entry %lu\n", Index
);
2260 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2261 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2262 PartitionInfo
->HiddenSectors
= 0;
2263 PartitionInfo
->PartitionNumber
= 0;
2264 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2265 PartitionInfo
->BootIndicator
= FALSE
;
2266 PartitionInfo
->RecognizedPartition
= FALSE
;
2267 PartitionInfo
->RewritePartition
= TRUE
;
2271 /* Wipe unused logical partition entries */
2272 for (Index
= 4; Index
< DiskEntry
->LayoutBuffer
->PartitionCount
; Index
++)
2276 DPRINT1("Logical partition entry %lu\n", Index
);
2278 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2280 if (!IsEmptyLayoutEntry(PartitionInfo
))
2282 DPRINT1("Wiping partition entry %lu\n", Index
);
2284 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2285 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2286 PartitionInfo
->HiddenSectors
= 0;
2287 PartitionInfo
->PartitionNumber
= 0;
2288 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2289 PartitionInfo
->BootIndicator
= FALSE
;
2290 PartitionInfo
->RecognizedPartition
= FALSE
;
2291 PartitionInfo
->RewritePartition
= TRUE
;
2296 #ifdef DUMP_PARTITION_TABLE
2297 DumpPartitionTable(DiskEntry
);
2303 GetPrevUnpartitionedEntry(
2304 IN PDISKENTRY DiskEntry
,
2305 IN PPARTENTRY PartEntry
)
2307 PPARTENTRY PrevPartEntry
;
2308 PLIST_ENTRY ListHead
;
2310 if (PartEntry
->LogicalPartition
)
2311 ListHead
= &DiskEntry
->LogicalPartListHead
;
2313 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2315 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2317 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2320 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2321 return PrevPartEntry
;
2329 GetNextUnpartitionedEntry(
2330 IN PDISKENTRY DiskEntry
,
2331 IN PPARTENTRY PartEntry
)
2333 PPARTENTRY NextPartEntry
;
2334 PLIST_ENTRY ListHead
;
2336 if (PartEntry
->LogicalPartition
)
2337 ListHead
= &DiskEntry
->LogicalPartListHead
;
2339 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2341 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2343 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2346 if (NextPartEntry
->IsPartitioned
== FALSE
)
2347 return NextPartEntry
;
2354 CreatePrimaryPartition(
2356 IN ULONGLONG SectorCount
,
2357 IN BOOLEAN AutoCreate
)
2359 PDISKENTRY DiskEntry
;
2360 PPARTENTRY PartEntry
;
2361 PPARTENTRY NewPartEntry
;
2363 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2366 List
->CurrentDisk
== NULL
||
2367 List
->CurrentPartition
== NULL
||
2368 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2373 DiskEntry
= List
->CurrentDisk
;
2374 PartEntry
= List
->CurrentPartition
;
2376 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2378 if ((AutoCreate
!= FALSE
) ||
2379 (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
))
2381 DPRINT1("Convert existing partition entry\n");
2383 /* Convert current entry to 'new (unformatted)' */
2384 PartEntry
->IsPartitioned
= TRUE
;
2385 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2386 PartEntry
->FormatState
= Unformatted
;
2387 PartEntry
->FileSystem
= NULL
;
2388 PartEntry
->AutoCreate
= AutoCreate
;
2389 PartEntry
->New
= TRUE
;
2390 PartEntry
->BootIndicator
= FALSE
;
2392 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2393 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2394 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2398 DPRINT1("Add new partition entry\n");
2400 /* Insert and initialize a new partition entry */
2401 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2404 if (NewPartEntry
== NULL
)
2407 /* Insert the new entry into the list */
2408 InsertTailList(&PartEntry
->ListEntry
,
2409 &NewPartEntry
->ListEntry
);
2411 NewPartEntry
->DiskEntry
= DiskEntry
;
2413 NewPartEntry
->IsPartitioned
= TRUE
;
2414 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2415 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2416 NewPartEntry
->StartSector
.QuadPart
;
2417 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2419 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2420 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2421 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2423 NewPartEntry
->New
= TRUE
;
2424 NewPartEntry
->FormatState
= Unformatted
;
2425 NewPartEntry
->FileSystem
= NULL
;
2426 NewPartEntry
->BootIndicator
= FALSE
;
2428 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2429 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2432 UpdateDiskLayout(DiskEntry
);
2434 DiskEntry
->Dirty
= TRUE
;
2436 AssignDriveLetters(List
);
2441 AddLogicalDiskSpace(
2442 IN PDISKENTRY DiskEntry
)
2444 PPARTENTRY NewPartEntry
;
2446 DPRINT1("AddLogicalDiskSpace()\n");
2448 /* Create a partition entry that represents the empty space in the container partition */
2449 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2452 if (NewPartEntry
== NULL
)
2455 NewPartEntry
->DiskEntry
= DiskEntry
;
2456 NewPartEntry
->LogicalPartition
= TRUE
;
2458 NewPartEntry
->IsPartitioned
= FALSE
;
2459 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2460 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2462 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2463 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2464 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2466 NewPartEntry
->FormatState
= Unformatted
;
2467 NewPartEntry
->FileSystem
= NULL
;
2469 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2470 &NewPartEntry
->ListEntry
);
2474 CreateExtendedPartition(
2476 IN ULONGLONG SectorCount
)
2478 PDISKENTRY DiskEntry
;
2479 PPARTENTRY PartEntry
;
2480 PPARTENTRY NewPartEntry
;
2482 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2485 List
->CurrentDisk
== NULL
||
2486 List
->CurrentPartition
== NULL
||
2487 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2492 DiskEntry
= List
->CurrentDisk
;
2493 PartEntry
= List
->CurrentPartition
;
2495 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2497 if (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2499 DPRINT1("Convert existing partition entry\n");
2501 /* Convert current entry to 'new (unformatted)' */
2502 PartEntry
->IsPartitioned
= TRUE
;
2503 PartEntry
->FormatState
= Formatted
; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2504 PartEntry
->FileSystem
= NULL
;
2505 PartEntry
->AutoCreate
= FALSE
;
2506 PartEntry
->New
= FALSE
;
2507 PartEntry
->BootIndicator
= FALSE
;
2509 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2511 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2512 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2516 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2517 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2520 DiskEntry
->ExtendedPartition
= PartEntry
;
2522 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2523 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2524 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2528 DPRINT1("Add new partition entry\n");
2530 /* Insert and initialize a new partition entry */
2531 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2534 if (NewPartEntry
== NULL
)
2537 /* Insert the new entry into the list */
2538 InsertTailList(&PartEntry
->ListEntry
,
2539 &NewPartEntry
->ListEntry
);
2541 NewPartEntry
->DiskEntry
= DiskEntry
;
2543 NewPartEntry
->IsPartitioned
= TRUE
;
2544 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2545 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2546 NewPartEntry
->StartSector
.QuadPart
;
2548 NewPartEntry
->New
= FALSE
;
2549 NewPartEntry
->FormatState
= Formatted
; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2550 NewPartEntry
->FileSystem
= NULL
;
2551 NewPartEntry
->BootIndicator
= FALSE
;
2553 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2555 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2556 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2560 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2561 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2564 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2566 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2567 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2569 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2570 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2571 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2574 AddLogicalDiskSpace(DiskEntry
);
2576 UpdateDiskLayout(DiskEntry
);
2578 DiskEntry
->Dirty
= TRUE
;
2580 AssignDriveLetters(List
);
2584 CreateLogicalPartition(
2586 IN ULONGLONG SectorCount
,
2587 IN BOOLEAN AutoCreate
)
2589 PDISKENTRY DiskEntry
;
2590 PPARTENTRY PartEntry
;
2591 PPARTENTRY NewPartEntry
;
2593 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2596 List
->CurrentDisk
== NULL
||
2597 List
->CurrentPartition
== NULL
||
2598 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2603 DiskEntry
= List
->CurrentDisk
;
2604 PartEntry
= List
->CurrentPartition
;
2606 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2608 if ((AutoCreate
!= FALSE
) ||
2609 (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
))
2611 DPRINT1("Convert existing partition entry\n");
2613 /* Convert current entry to 'new (unformatted)' */
2614 PartEntry
->IsPartitioned
= TRUE
;
2615 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2616 PartEntry
->FormatState
= Unformatted
;
2617 PartEntry
->FileSystem
= NULL
;
2618 PartEntry
->AutoCreate
= FALSE
;
2619 PartEntry
->New
= TRUE
;
2620 PartEntry
->BootIndicator
= FALSE
;
2621 PartEntry
->LogicalPartition
= TRUE
;
2623 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2624 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2625 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2629 DPRINT1("Add new partition entry\n");
2631 /* Insert and initialize a new partition entry */
2632 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2635 if (NewPartEntry
== NULL
)
2638 /* Insert the new entry into the list */
2639 InsertTailList(&PartEntry
->ListEntry
,
2640 &NewPartEntry
->ListEntry
);
2642 NewPartEntry
->DiskEntry
= DiskEntry
;
2644 NewPartEntry
->IsPartitioned
= TRUE
;
2645 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2646 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2647 NewPartEntry
->StartSector
.QuadPart
;
2648 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2650 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2651 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2652 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2654 NewPartEntry
->New
= TRUE
;
2655 NewPartEntry
->FormatState
= Unformatted
;
2656 NewPartEntry
->FileSystem
= NULL
;
2657 NewPartEntry
->BootIndicator
= FALSE
;
2658 NewPartEntry
->LogicalPartition
= TRUE
;
2660 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2661 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2664 UpdateDiskLayout(DiskEntry
);
2666 DiskEntry
->Dirty
= TRUE
;
2668 AssignDriveLetters(List
);
2672 DeleteCurrentPartition(
2675 PDISKENTRY DiskEntry
;
2676 PPARTENTRY PartEntry
;
2677 PPARTENTRY PrevPartEntry
;
2678 PPARTENTRY NextPartEntry
;
2679 PPARTENTRY LogicalPartEntry
;
2683 List
->CurrentDisk
== NULL
||
2684 List
->CurrentPartition
== NULL
||
2685 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2690 /* Clear the system disk and partition pointers if the system partition is being deleted */
2691 if (List
->SystemPartition
== List
->CurrentPartition
)
2693 List
->SystemPartition
= NULL
;
2696 DiskEntry
= List
->CurrentDisk
;
2697 PartEntry
= List
->CurrentPartition
;
2699 /* Delete all logical partition entries if an extended partition will be deleted */
2700 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2702 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2704 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2705 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2707 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2710 DiskEntry
->ExtendedPartition
= NULL
;
2713 /* Adjust unpartitioned disk space entries */
2715 /* Get pointer to previous and next unpartitioned entries */
2716 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
, PartEntry
);
2717 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
, PartEntry
);
2719 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2721 /* Merge previous, current and next unpartitioned entry */
2723 /* Adjust the previous entries length */
2724 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2726 /* Remove the current entry */
2727 RemoveEntryList(&PartEntry
->ListEntry
);
2728 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2730 /* Remove the next entry */
2731 RemoveEntryList(&NextPartEntry
->ListEntry
);
2732 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2734 /* Update current partition */
2735 List
->CurrentPartition
= PrevPartEntry
;
2737 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2739 /* Merge current and previous unpartitioned entry */
2741 /* Adjust the previous entries length */
2742 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2744 /* Remove the current entry */
2745 RemoveEntryList(&PartEntry
->ListEntry
);
2746 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2748 /* Update current partition */
2749 List
->CurrentPartition
= PrevPartEntry
;
2751 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2753 /* Merge current and next unpartitioned entry */
2755 /* Adjust the next entries offset and length */
2756 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2757 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2759 /* Remove the current entry */
2760 RemoveEntryList(&PartEntry
->ListEntry
);
2761 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2763 /* Update current partition */
2764 List
->CurrentPartition
= NextPartEntry
;
2768 /* Nothing to merge but change current entry */
2769 PartEntry
->IsPartitioned
= FALSE
;
2770 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2771 PartEntry
->FormatState
= Unformatted
;
2772 PartEntry
->FileSystem
= NULL
;
2773 PartEntry
->DriveLetter
= 0;
2776 UpdateDiskLayout(DiskEntry
);
2778 DiskEntry
->Dirty
= TRUE
;
2780 AssignDriveLetters(List
);
2784 CheckActiveSystemPartition(
2787 PDISKENTRY DiskEntry
;
2788 PPARTENTRY PartEntry
;
2789 PLIST_ENTRY ListEntry
;
2791 PFILE_SYSTEM FileSystem
;
2793 /* Check for empty disk list */
2794 if (IsListEmpty(&List
->DiskListHead
))
2796 List
->SystemPartition
= NULL
;
2797 List
->OriginalSystemPartition
= NULL
;
2801 /* Choose the currently selected disk */
2802 DiskEntry
= List
->CurrentDisk
;
2804 /* Check for empty partition list */
2805 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
2807 List
->SystemPartition
= NULL
;
2808 List
->OriginalSystemPartition
= NULL
;
2812 if (List
->SystemPartition
!= NULL
)
2814 /* We already have an active system partition */
2815 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %C\n",
2816 List
->SystemPartition
->PartitionNumber
,
2817 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2818 (List
->SystemPartition
->DriveLetter
== 0) ? L
'-' : List
->SystemPartition
->DriveLetter
);
2822 DPRINT1("We are here (1)!\n");
2824 List
->SystemPartition
= NULL
;
2825 List
->OriginalSystemPartition
= NULL
;
2827 /* Retrieve the first partition of the disk */
2828 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2831 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2832 List
->SystemPartition
= PartEntry
;
2835 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
2838 /* Check if the disk is new and if so, use its first partition as the active system partition */
2839 if (DiskEntry
->NewDisk
)
2841 if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
== FALSE
)
2843 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2844 List
->SystemPartition
= PartEntry
;
2846 List
->OriginalSystemPartition
= List
->SystemPartition
;
2848 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
2849 List
->SystemPartition
->PartitionNumber
,
2850 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2851 (List
->SystemPartition
->DriveLetter
== 0) ? L
'-' : List
->SystemPartition
->DriveLetter
);
2853 goto SetSystemPartition
;
2856 // FIXME: What to do??
2857 DPRINT1("NewDisk TRUE but first partition is used?\n");
2860 DPRINT1("We are here (2)!\n");
2863 * The disk is not new, check if any partition is initialized;
2864 * if not, the first one becomes the system partition.
2866 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2867 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2869 /* Retrieve the partition and go to the next one */
2870 PartEntry
= CONTAINING_RECORD(ListEntry
,
2874 /* Check if the partition is partitioned and is used */
2875 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
!= FALSE
)
2880 /* Go to the next one */
2881 ListEntry
= ListEntry
->Flink
;
2883 if (ListEntry
== &DiskEntry
->PrimaryPartListHead
)
2886 * OK we haven't encountered any used and active partition,
2887 * so use the first one as the system partition.
2889 ASSERT(DiskEntry
== List
->SystemPartition
->DiskEntry
);
2890 List
->OriginalSystemPartition
= List
->SystemPartition
; // First PartEntry
2892 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
2893 List
->SystemPartition
->PartitionNumber
,
2894 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2895 (List
->SystemPartition
->DriveLetter
== 0) ? L
'-' : List
->SystemPartition
->DriveLetter
);
2897 goto SetSystemPartition
;
2900 List
->SystemPartition
= NULL
;
2901 List
->OriginalSystemPartition
= NULL
;
2903 DPRINT1("We are here (3)!\n");
2905 /* The disk is not new, scan all partitions to find the (active) system partition */
2906 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2907 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2909 /* Retrieve the partition and go to the next one */
2910 PartEntry
= CONTAINING_RECORD(ListEntry
,
2913 ListEntry
= ListEntry
->Flink
;
2915 /* Check if the partition is partitioned and used */
2916 if (PartEntry
->IsPartitioned
&&
2917 PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
)
2919 /* Check if the partition is active */
2920 if (PartEntry
->BootIndicator
)
2922 /* Yes, we found it */
2923 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2924 List
->SystemPartition
= PartEntry
;
2926 DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
2927 PartEntry
->PartitionNumber
,
2928 DiskEntry
->DiskNumber
,
2929 (PartEntry
->DriveLetter
== 0) ? L
'-' : PartEntry
->DriveLetter
);
2935 /* Check if we have found the system partition */
2936 if (List
->SystemPartition
== NULL
)
2938 /* Nothing, use the alternative system partition */
2939 DPRINT1("No system partition found, use the alternative partition!\n");
2940 goto UseAlternativeSystemPartition
;
2944 List
->OriginalSystemPartition
= List
->SystemPartition
;
2947 * ADDITIONAL CHECKS / BIG HACK:
2949 * Retrieve its file system and check whether we have
2950 * write support for it. If that is the case we are fine
2951 * and we can use it directly. However if we don't have
2952 * write support we will need to change the active system
2955 * NOTE that this is completely useless on architectures
2956 * where a real system partition is required, as on these
2957 * architectures the partition uses the FAT FS, for which
2958 * we do have write support.
2959 * NOTE also that for those architectures looking for a
2960 * partition boot indicator is insufficient.
2962 FileSystem
= GetFileSystem(List
->OriginalSystemPartition
);
2963 if (FileSystem
== NULL
)
2965 DPRINT1("System partition %lu in disk %lu with no FS?!\n",
2966 List
->OriginalSystemPartition
->PartitionNumber
,
2967 List
->OriginalSystemPartition
->DiskEntry
->DiskNumber
);
2968 goto FindAndUseAlternativeSystemPartition
;
2970 // HACK: WARNING: We cannot write on this FS yet!
2971 // See fsutil.c:GetFileSystem()
2972 if (List
->OriginalSystemPartition
->PartitionType
== PARTITION_IFS
)
2974 DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
2975 FileSystem
->FileSystemName
);
2976 goto FindAndUseAlternativeSystemPartition
;
2979 DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %C\n",
2980 List
->SystemPartition
->PartitionNumber
,
2981 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2982 (List
->SystemPartition
->DriveLetter
== 0) ? L
'-' : List
->SystemPartition
->DriveLetter
);
2986 FindAndUseAlternativeSystemPartition
:
2988 * We are here because we have not found any (active) candidate
2989 * system partition that we know how to support. What we are going
2990 * to do is to change the existing system partition and use the
2991 * partition on which we install ReactOS as the new system partition,
2992 * and then we will need to add in FreeLdr's entry a boot entry to boot
2993 * from the original system partition.
2996 /* Unset the old system partition */
2997 List
->SystemPartition
->BootIndicator
= FALSE
;
2998 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= FALSE
;
2999 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3000 List
->SystemPartition
->DiskEntry
->Dirty
= TRUE
;
3002 UseAlternativeSystemPartition
:
3003 List
->SystemPartition
= List
->CurrentPartition
;
3005 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
3006 List
->SystemPartition
->PartitionNumber
,
3007 List
->SystemPartition
->DiskEntry
->DiskNumber
,
3008 (List
->SystemPartition
->DriveLetter
== 0) ? L
'-' : List
->SystemPartition
->DriveLetter
);
3011 /* Set the new active system partition */
3012 List
->SystemPartition
->BootIndicator
= TRUE
;
3013 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= TRUE
;
3014 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3015 List
->SystemPartition
->DiskEntry
->Dirty
= TRUE
;
3022 IN PDISKENTRY DiskEntry
)
3024 WCHAR DstPath
[MAX_PATH
];
3025 OBJECT_ATTRIBUTES ObjectAttributes
;
3026 IO_STATUS_BLOCK Iosb
;
3027 UNICODE_STRING Name
;
3029 HANDLE FileHandle
= NULL
;
3032 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
3034 RtlStringCchPrintfW(DstPath
, ARRAYSIZE(DstPath
),
3035 L
"\\Device\\Harddisk%lu\\Partition0",
3036 DiskEntry
->DiskNumber
);
3037 RtlInitUnicodeString(&Name
, DstPath
);
3039 InitializeObjectAttributes(&ObjectAttributes
,
3041 OBJ_CASE_INSENSITIVE
,
3045 Status
= NtOpenFile(&FileHandle
,
3046 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
3050 FILE_SYNCHRONOUS_IO_NONALERT
);
3051 if (!NT_SUCCESS(Status
))
3053 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
3057 #ifdef DUMP_PARTITION_TABLE
3058 DumpPartitionTable(DiskEntry
);
3062 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
3063 // the disk in MBR or GPT format in case the disk was not initialized!!
3064 // For this we must ask the user which format to use.
3067 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
3068 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
3069 Status
= NtDeviceIoControlFile(FileHandle
,
3074 IOCTL_DISK_SET_DRIVE_LAYOUT
,
3075 DiskEntry
->LayoutBuffer
,
3079 if (!NT_SUCCESS(Status
))
3081 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
3084 if (FileHandle
!= NULL
)
3085 NtClose(FileHandle
);
3088 // NOTE: Originally (see r40437), we used to install here also a new MBR
3089 // for this disk (by calling InstallMbrBootCodeToDisk), only if:
3090 // DiskEntry->NewDisk == TRUE and DiskEntry->BiosDiskNumber == 0.
3091 // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
3092 // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
3093 // was called too, the installation test was modified by checking whether
3094 // DiskEntry->NoMbr was TRUE (instead of NewDisk).
3101 WritePartitionsToDisk(
3105 PDISKENTRY DiskEntry
;
3110 Entry
= List
->DiskListHead
.Flink
;
3111 while (Entry
!= &List
->DiskListHead
)
3113 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3115 if (DiskEntry
->Dirty
!= FALSE
)
3117 WritePartitions(List
, DiskEntry
);
3118 DiskEntry
->Dirty
= FALSE
;
3121 Entry
= Entry
->Flink
;
3128 SetMountedDeviceValue(
3131 IN LARGE_INTEGER StartingOffset
)
3133 OBJECT_ATTRIBUTES ObjectAttributes
;
3134 WCHAR ValueNameBuffer
[16];
3135 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
3136 UNICODE_STRING ValueName
;
3137 REG_DISK_MOUNT_INFO MountInfo
;
3141 RtlStringCchPrintfW(ValueNameBuffer
, ARRAYSIZE(ValueNameBuffer
),
3142 L
"\\DosDevices\\%c:", Letter
);
3143 RtlInitUnicodeString(&ValueName
, ValueNameBuffer
);
3145 InitializeObjectAttributes(&ObjectAttributes
,
3147 OBJ_CASE_INSENSITIVE
,
3151 Status
= NtOpenKey(&KeyHandle
,
3154 if (!NT_SUCCESS(Status
))
3156 Status
= NtCreateKey(&KeyHandle
,
3161 REG_OPTION_NON_VOLATILE
,
3165 if (!NT_SUCCESS(Status
))
3167 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
3171 MountInfo
.Signature
= Signature
;
3172 MountInfo
.StartingOffset
= StartingOffset
;
3173 Status
= NtSetValueKey(KeyHandle
,
3180 if (!NT_SUCCESS(Status
))
3182 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
3190 SetMountedDeviceValues(
3193 PLIST_ENTRY Entry1
, Entry2
;
3194 PDISKENTRY DiskEntry
;
3195 PPARTENTRY PartEntry
;
3196 LARGE_INTEGER StartingOffset
;
3201 Entry1
= List
->DiskListHead
.Flink
;
3202 while (Entry1
!= &List
->DiskListHead
)
3204 DiskEntry
= CONTAINING_RECORD(Entry1
,
3208 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3209 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3211 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3212 if (PartEntry
->IsPartitioned
)
3214 /* Assign a "\DosDevices\#:" mount point to this partition */
3215 if (PartEntry
->DriveLetter
)
3217 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3218 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3219 DiskEntry
->LayoutBuffer
->Signature
,
3227 Entry2
= Entry2
->Flink
;
3230 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3231 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3233 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3234 if (PartEntry
->IsPartitioned
)
3236 /* Assign a "\DosDevices\#:" mount point to this partition */
3237 if (PartEntry
->DriveLetter
)
3239 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3240 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3241 DiskEntry
->LayoutBuffer
->Signature
,
3249 Entry2
= Entry2
->Flink
;
3252 Entry1
= Entry1
->Flink
;
3260 IN PPARTENTRY PartEntry
,
3261 IN UCHAR PartitionType
)
3263 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
3265 PartEntry
->PartitionType
= PartitionType
;
3267 DiskEntry
->Dirty
= TRUE
;
3268 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].PartitionType
= PartitionType
;
3269 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3273 PrimaryPartitionCreationChecks(
3276 PDISKENTRY DiskEntry
;
3277 PPARTENTRY PartEntry
;
3279 DiskEntry
= List
->CurrentDisk
;
3280 PartEntry
= List
->CurrentPartition
;
3282 /* Fail if the partition is already in use */
3283 if (PartEntry
->IsPartitioned
!= FALSE
)
3284 return ERROR_NEW_PARTITION
;
3286 /* Fail if there are already 4 primary partitions in the list */
3287 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3288 return ERROR_PARTITION_TABLE_FULL
;
3290 return ERROR_SUCCESS
;
3294 ExtendedPartitionCreationChecks(
3297 PDISKENTRY DiskEntry
;
3298 PPARTENTRY PartEntry
;
3300 DiskEntry
= List
->CurrentDisk
;
3301 PartEntry
= List
->CurrentPartition
;
3303 /* Fail if the partition is already in use */
3304 if (PartEntry
->IsPartitioned
!= FALSE
)
3305 return ERROR_NEW_PARTITION
;
3307 /* Fail if there are already 4 primary partitions in the list */
3308 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3309 return ERROR_PARTITION_TABLE_FULL
;
3311 /* Fail if there is another extended partition in the list */
3312 if (DiskEntry
->ExtendedPartition
!= NULL
)
3313 return ERROR_ONLY_ONE_EXTENDED
;
3315 return ERROR_SUCCESS
;
3319 LogicalPartitionCreationChecks(
3322 // PDISKENTRY DiskEntry;
3323 PPARTENTRY PartEntry
;
3325 // DiskEntry = List->CurrentDisk;
3326 PartEntry
= List
->CurrentPartition
;
3328 /* Fail if the partition is already in use */
3329 if (PartEntry
->IsPartitioned
!= FALSE
)
3330 return ERROR_NEW_PARTITION
;
3332 return ERROR_SUCCESS
;
3336 GetNextUnformattedPartition(
3338 OUT PDISKENTRY
*pDiskEntry OPTIONAL
,
3339 OUT PPARTENTRY
*pPartEntry
)
3341 PLIST_ENTRY Entry1
, Entry2
;
3342 PDISKENTRY DiskEntry
;
3343 PPARTENTRY PartEntry
;
3345 Entry1
= List
->DiskListHead
.Flink
;
3346 while (Entry1
!= &List
->DiskListHead
)
3348 DiskEntry
= CONTAINING_RECORD(Entry1
,
3352 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3353 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3355 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3356 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3358 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3359 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3360 *pPartEntry
= PartEntry
;
3364 Entry2
= Entry2
->Flink
;
3367 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3368 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3370 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3371 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3373 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3374 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3375 *pPartEntry
= PartEntry
;
3379 Entry2
= Entry2
->Flink
;
3382 Entry1
= Entry1
->Flink
;
3385 if (pDiskEntry
) *pDiskEntry
= NULL
;
3392 GetNextUncheckedPartition(
3394 OUT PDISKENTRY
*pDiskEntry OPTIONAL
,
3395 OUT PPARTENTRY
*pPartEntry
)
3397 PLIST_ENTRY Entry1
, Entry2
;
3398 PDISKENTRY DiskEntry
;
3399 PPARTENTRY PartEntry
;
3401 Entry1
= List
->DiskListHead
.Flink
;
3402 while (Entry1
!= &List
->DiskListHead
)
3404 DiskEntry
= CONTAINING_RECORD(Entry1
,
3408 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3409 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3411 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3412 if (PartEntry
->NeedsCheck
== TRUE
)
3414 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3415 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3416 *pPartEntry
= PartEntry
;
3420 Entry2
= Entry2
->Flink
;
3423 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3424 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3426 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3427 if (PartEntry
->NeedsCheck
== TRUE
)
3429 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3430 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3431 *pPartEntry
= PartEntry
;
3435 Entry2
= Entry2
->Flink
;
3438 Entry1
= Entry1
->Flink
;
3441 if (pDiskEntry
) *pDiskEntry
= NULL
;