3 * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: base/setup/usetup/partlist.c
22 * PURPOSE: Partition list functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
34 //#define DUMP_PARTITION_TABLE
36 /* HELPERS FOR PARTITION TYPES **********************************************/
38 typedef struct _PARTITION_TYPE
42 } PARTITION_TYPE
, *PPARTITION_TYPE
;
45 * This partition type list was ripped off the kernelDisk.c module from:
47 * Visopsys Operating System
48 * Copyright (C) 1998-2015 J. Andrew McLaughlin
50 * This program is free software; you can redistribute it and/or modify it
51 * under the terms of the GNU General Public License as published by the Free
52 * Software Foundation; either version 2 of the License, or (at your option)
55 * This program is distributed in the hope that it will be useful, but
56 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
57 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
60 * You should have received a copy of the GNU General Public License along
61 * with this program; if not, write to the Free Software Foundation, Inc.,
62 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
65 * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
66 * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
67 * for a complete list.
70 /* This is a table for keeping known partition type codes and descriptions */
71 static PARTITION_TYPE PartitionTypes
[] =
75 { 0x02, "XENIX root" },
76 { 0x03, "XENIX /usr" },
77 { 0x04, "FAT16 (small)" },
80 { 0x07, "NTFS/HPFS/exFAT" },
81 { 0x08, "OS/2 or AIX boot" },
83 { 0x0A, "OS/2 Boot Manager" },
85 { 0x0C, "FAT32 (LBA)" },
86 { 0x0E, "FAT16 (LBA)" },
87 { 0x0F, "Extended (LBA)" },
88 { 0x11, "Hidden FAT12" },
89 { 0x12, "FAT diagnostic" },
90 { 0x14, "Hidden FAT16 (small)" },
91 { 0x16, "Hidden FAT16" },
92 { 0x17, "Hidden HPFS or NTFS" },
93 { 0x1B, "Hidden FAT32" },
94 { 0x1C, "Hidden FAT32 (LBA)" },
95 { 0x1E, "Hidden FAT16 (LBA)" },
98 { 0x3C, "PartitionMagic" },
99 { 0x3D, "Hidden Netware" },
100 { 0x41, "PowerPC PReP" },
101 { 0x42, "Win2K dynamic extended" },
102 { 0x43, "Old Linux" },
105 { 0x4D, "QNX4.x 2nd" },
106 { 0x4D, "QNX4.x 3rd" },
107 { 0x50, "Ontrack R/O" },
108 { 0x51, "Ontrack R/W or Novell" },
110 { 0x63, "GNU HURD or UNIX SysV" },
111 { 0x64, "Netware 2" },
112 { 0x65, "Netware 3/4" },
113 { 0x66, "Netware SMS" },
116 { 0x69, "Netware 5+" },
117 { 0x7E, "Veritas VxVM public" },
118 { 0x7F, "Veritas VxVM private" },
120 { 0x81, "Linux or Minix" },
121 { 0x82, "Linux swap or Solaris" },
123 { 0x84, "Hibernation" },
124 { 0x85, "Linux extended" },
125 { 0x86, "HPFS or NTFS mirrored" },
126 { 0x87, "HPFS or NTFS mirrored" },
127 { 0x8E, "Linux LVM" },
128 { 0x93, "Hidden Linux" },
130 { 0xA0, "Laptop hibernation" },
131 { 0xA1, "Laptop hibernation" },
132 { 0xA5, "BSD, NetBSD, FreeBSD" },
134 { 0xA7, "NeXTSTEP" },
135 { 0xA8, "OS-X UFS" },
137 { 0xAB, "OS-X boot" },
138 { 0xAF, "OS-X HFS" },
139 { 0xB6, "NT corrupt mirror" },
141 { 0xB8, "BSDI swap" },
142 { 0xBE, "Solaris 8 boot" },
143 { 0xBF, "Solaris x86" },
145 { 0xC1, "DR-DOS FAT12" },
146 { 0xC2, "Hidden Linux" },
147 { 0xC3, "Hidden Linux swap" },
148 { 0xC4, "DR-DOS FAT16 (small)" },
149 { 0xC5, "DR-DOS Extended" },
150 { 0xC6, "DR-DOS FAT16" },
151 { 0xC7, "HPFS mirrored" },
152 { 0xCB, "DR-DOS FAT32" },
153 { 0xCC, "DR-DOS FAT32 (LBA)" },
154 { 0xCE, "DR-DOS FAT16 (LBA)" },
156 { 0xD1, "MDOS FAT12" },
157 { 0xD4, "MDOS FAT16 (small)" },
158 { 0xD5, "MDOS Extended" },
159 { 0xD6, "MDOS FAT16" },
161 { 0xDF, "BootIt EMBRM(FAT16/32)" },
162 { 0xEB, "BeOS BFS" },
163 { 0xEE, "EFI GPT protective" },
164 { 0xEF, "EFI filesystem" },
165 { 0xF0, "Linux/PA-RISC boot" },
166 { 0xF2, "DOS 3.3+ second" },
169 { 0xFC, "VmWare swap" },
170 { 0xFD, "Linux RAID" },
171 { 0xFE, "NT hidden" },
175 GetPartTypeStringFromPartitionType(
180 /* Determine partition type */
182 if (IsContainerPartition(partitionType
))
184 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
186 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
188 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
194 /* Do the table lookup */
195 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
197 if (partitionType
== PartitionTypes
[i
].Type
)
199 StringCchCopy(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
204 /* We are here because the partition type is unknown */
205 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
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
;
261 ULONGLONG Temp
, Result
;
263 Temp
= Value
/ Alignment
;
265 Result
= Temp
* Alignment
;
266 if (Value
% Alignment
)
274 IN ULONGLONG Dividend
,
275 IN ULONGLONG Divisor
)
277 return (Dividend
+ Divisor
/ 2) / Divisor
;
284 PDISKENTRY DiskEntry
)
286 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
290 RtlInitUnicodeString(&DiskEntry
->DriverName
,
294 L
"\\Scsi\\Scsi Port %hu",
297 RtlZeroMemory(&QueryTable
,
300 QueryTable
[0].Name
= L
"Driver";
301 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
302 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
304 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
309 if (!NT_SUCCESS(Status
))
311 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
321 PDISKENTRY DiskEntry
;
322 PPARTENTRY PartEntry
;
329 /* Assign drive letters to primary partitions */
330 Entry1
= List
->DiskListHead
.Flink
;
331 while (Entry1
!= &List
->DiskListHead
)
333 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
335 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
336 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
338 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
340 PartEntry
->DriveLetter
= 0;
342 if (PartEntry
->IsPartitioned
&&
343 !IsContainerPartition(PartEntry
->PartitionType
))
345 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
346 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
347 PartEntry
->SectorCount
.QuadPart
!= 0LL))
351 PartEntry
->DriveLetter
= Letter
;
357 Entry2
= Entry2
->Flink
;
360 Entry1
= Entry1
->Flink
;
363 /* Assign drive letters to logical drives */
364 Entry1
= List
->DiskListHead
.Flink
;
365 while (Entry1
!= &List
->DiskListHead
)
367 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
369 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
370 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
372 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
374 PartEntry
->DriveLetter
= 0;
376 if (PartEntry
->IsPartitioned
)
378 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
379 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
380 PartEntry
->SectorCount
.QuadPart
!= 0LL))
384 PartEntry
->DriveLetter
= Letter
;
390 Entry2
= Entry2
->Flink
;
393 Entry1
= Entry1
->Flink
;
400 DiskIdentifierQueryRoutine(
408 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
409 UNICODE_STRING NameU
;
411 if (ValueType
== REG_SZ
&&
412 ValueLength
== 20 * sizeof(WCHAR
))
414 NameU
.Buffer
= (PWCHAR
)ValueData
;
415 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
416 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
418 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
419 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
421 return STATUS_SUCCESS
;
424 return STATUS_UNSUCCESSFUL
;
430 DiskConfigurationDataQueryRoutine(
438 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
439 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
440 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
443 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
444 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
445 return STATUS_UNSUCCESSFUL
;
447 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
449 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
451 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
452 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
453 return STATUS_UNSUCCESSFUL
;
456 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
458 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
459 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
462 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
463 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
465 return STATUS_SUCCESS
;
468 return STATUS_UNSUCCESSFUL
;
474 SystemConfigurationDataQueryRoutine(
482 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
483 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
486 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
487 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
488 return STATUS_UNSUCCESSFUL
;
490 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
492 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
494 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
495 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
496 return STATUS_UNSUCCESSFUL
;
499 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
501 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
502 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
505 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*)RtlAllocateHeap(ProcessHeap
, 0,
506 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
507 if (*Int13Drives
== NULL
)
508 return STATUS_NO_MEMORY
;
511 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
512 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
513 return STATUS_SUCCESS
;
516 return STATUS_UNSUCCESSFUL
;
520 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
523 EnumerateBiosDiskEntries(
526 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
531 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
532 PBIOSDISKENTRY BiosDiskEntry
;
534 memset(QueryTable
, 0, sizeof(QueryTable
));
536 QueryTable
[1].Name
= L
"Configuration Data";
537 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
539 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
540 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
544 if (!NT_SUCCESS(Status
))
546 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
553 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
554 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
559 if (!NT_SUCCESS(Status
))
564 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
565 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
570 if (NT_SUCCESS(Status
))
574 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
575 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
580 if (!NT_SUCCESS(Status
))
582 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
586 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
587 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
592 if (NT_SUCCESS(Status
))
594 QueryTable
[0].Name
= L
"Identifier";
595 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
596 QueryTable
[1].Name
= L
"Configuration Data";
597 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
602 BiosDiskEntry
= (BIOSDISKENTRY
*)RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
603 if (BiosDiskEntry
== NULL
)
608 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
609 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
612 (PVOID
)BiosDiskEntry
,
614 if (!NT_SUCCESS(Status
))
616 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
620 BiosDiskEntry
->DiskNumber
= DiskCount
;
621 BiosDiskEntry
->Recognized
= FALSE
;
623 if (DiskCount
< Int13Drives
[0].NumberDrives
)
625 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
629 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
632 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
634 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
635 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
636 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
637 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
638 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
639 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
640 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
641 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
642 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
643 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
644 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
650 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
658 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
666 PDISKENTRY DiskEntry
,
667 ULONG PartitionIndex
,
668 BOOLEAN LogicalPartition
)
670 PPARTITION_INFORMATION PartitionInfo
;
671 PPARTENTRY PartEntry
;
673 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
674 if (PartitionInfo
->PartitionType
== 0 ||
675 (LogicalPartition
== TRUE
&& IsContainerPartition(PartitionInfo
->PartitionType
)))
678 PartEntry
= RtlAllocateHeap(ProcessHeap
,
681 if (PartEntry
== NULL
)
686 PartEntry
->DiskEntry
= DiskEntry
;
688 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
689 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
691 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
692 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
693 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
695 PartEntry
->LogicalPartition
= LogicalPartition
;
696 PartEntry
->IsPartitioned
= TRUE
;
697 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
698 PartEntry
->PartitionIndex
= PartitionIndex
;
700 if (IsContainerPartition(PartEntry
->PartitionType
))
702 PartEntry
->FormatState
= Unformatted
;
704 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
705 DiskEntry
->ExtendedPartition
= PartEntry
;
707 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
708 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
709 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
710 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
711 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
712 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
715 if (CheckFatFormat())
717 PartEntry
->FormatState
= Preformatted
;
721 PartEntry
->FormatState
= Unformatted
;
724 PartEntry
->FormatState
= Preformatted
;
726 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
729 if (CheckExt2Format())
731 PartEntry
->FormatState
= Preformatted
;
735 PartEntry
->FormatState
= Unformatted
;
738 PartEntry
->FormatState
= Preformatted
;
740 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
743 if (CheckNtfsFormat())
745 PartEntry
->FormatState
= Preformatted
;
747 else if (CheckHpfsFormat())
749 PartEntry
->FormatState
= Preformatted
;
753 PartEntry
->FormatState
= Unformatted
;
756 PartEntry
->FormatState
= Preformatted
;
760 PartEntry
->FormatState
= UnknownFormat
;
763 if (LogicalPartition
)
764 InsertTailList(&DiskEntry
->LogicalPartListHead
,
765 &PartEntry
->ListEntry
);
767 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
768 &PartEntry
->ListEntry
);
774 ScanForUnpartitionedDiskSpace(
775 PDISKENTRY DiskEntry
)
777 ULONGLONG LastStartSector
;
778 ULONGLONG LastSectorCount
;
779 ULONGLONG LastUnusedSectorCount
;
780 PPARTENTRY PartEntry
;
781 PPARTENTRY NewPartEntry
;
784 DPRINT("ScanForUnpartitionedDiskSpace()\n");
786 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
788 DPRINT1("No primary partition!\n");
790 /* Create a partition table that represents the empty disk */
791 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
794 if (NewPartEntry
== NULL
)
797 NewPartEntry
->DiskEntry
= DiskEntry
;
799 NewPartEntry
->IsPartitioned
= FALSE
;
800 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
801 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
802 NewPartEntry
->StartSector
.QuadPart
;
804 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
805 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
806 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
808 NewPartEntry
->FormatState
= Unformatted
;
810 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
811 &NewPartEntry
->ListEntry
);
816 /* Start partition at head 1, cylinder 0 */
817 LastStartSector
= DiskEntry
->SectorAlignment
;
818 LastSectorCount
= 0ULL;
819 LastUnusedSectorCount
= 0ULL;
821 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
822 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
824 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
826 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
827 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
829 LastUnusedSectorCount
=
830 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
832 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
833 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
835 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
837 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
840 if (NewPartEntry
== NULL
)
843 NewPartEntry
->DiskEntry
= DiskEntry
;
845 NewPartEntry
->IsPartitioned
= FALSE
;
846 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
847 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
848 NewPartEntry
->StartSector
.QuadPart
;
850 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
851 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
852 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
854 NewPartEntry
->FormatState
= Unformatted
;
856 /* Insert the table into the list */
857 InsertTailList(&PartEntry
->ListEntry
,
858 &NewPartEntry
->ListEntry
);
861 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
862 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
865 Entry
= Entry
->Flink
;
868 /* Check for trailing unpartitioned disk space */
869 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
871 LastUnusedSectorCount
= AlignDown(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
873 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
875 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
877 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
880 if (NewPartEntry
== NULL
)
883 NewPartEntry
->DiskEntry
= DiskEntry
;
885 NewPartEntry
->IsPartitioned
= FALSE
;
886 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
887 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
888 NewPartEntry
->StartSector
.QuadPart
;
890 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
891 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
892 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
894 NewPartEntry
->FormatState
= Unformatted
;
896 /* Append the table to the list */
897 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
898 &NewPartEntry
->ListEntry
);
902 if (DiskEntry
->ExtendedPartition
!= NULL
)
904 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
906 DPRINT1("No logical partition!\n");
908 /* Create a partition table entry that represents the empty extended partition */
909 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
912 if (NewPartEntry
== NULL
)
915 NewPartEntry
->DiskEntry
= DiskEntry
;
916 NewPartEntry
->LogicalPartition
= TRUE
;
918 NewPartEntry
->IsPartitioned
= FALSE
;
919 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
920 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
922 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
923 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
924 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
926 NewPartEntry
->FormatState
= Unformatted
;
928 InsertTailList(&DiskEntry
->LogicalPartListHead
,
929 &NewPartEntry
->ListEntry
);
934 /* Start partition at head 1, cylinder 0 */
935 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
936 LastSectorCount
= 0ULL;
937 LastUnusedSectorCount
= 0ULL;
939 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
940 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
942 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
944 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
945 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
947 LastUnusedSectorCount
=
948 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
950 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
951 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
953 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
955 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
958 if (NewPartEntry
== NULL
)
961 NewPartEntry
->DiskEntry
= DiskEntry
;
962 NewPartEntry
->LogicalPartition
= TRUE
;
964 NewPartEntry
->IsPartitioned
= FALSE
;
965 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
966 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
967 NewPartEntry
->StartSector
.QuadPart
;
969 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
970 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
971 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
973 NewPartEntry
->FormatState
= Unformatted
;
975 /* Insert the table into the list */
976 InsertTailList(&PartEntry
->ListEntry
,
977 &NewPartEntry
->ListEntry
);
980 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
981 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
984 Entry
= Entry
->Flink
;
987 /* Check for trailing unpartitioned disk space */
988 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
990 LastUnusedSectorCount
= AlignDown(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
992 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
994 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
996 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
999 if (NewPartEntry
== NULL
)
1002 NewPartEntry
->DiskEntry
= DiskEntry
;
1003 NewPartEntry
->LogicalPartition
= TRUE
;
1005 NewPartEntry
->IsPartitioned
= FALSE
;
1006 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
1007 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
1008 NewPartEntry
->StartSector
.QuadPart
;
1010 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
1011 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
1012 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
1014 NewPartEntry
->FormatState
= Unformatted
;
1016 /* Append the table to the list */
1017 InsertTailList(&DiskEntry
->LogicalPartListHead
,
1018 &NewPartEntry
->ListEntry
);
1023 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1031 IN PDISKENTRY DiskEntry
)
1033 LARGE_INTEGER SystemTime
;
1034 TIME_FIELDS TimeFields
;
1036 PDISKENTRY DiskEntry2
;
1039 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
1043 NtQuerySystemTime(&SystemTime
);
1044 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
1046 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
1047 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
1048 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
1049 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
1051 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
1056 /* check if the signature already exist */
1058 * Check also signatures from disks, which are
1059 * not visible (bootable) by the bios.
1061 Entry2
= List
->DiskListHead
.Flink
;
1062 while (Entry2
!= &List
->DiskListHead
)
1064 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
1066 if (DiskEntry
!= DiskEntry2
&&
1067 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
1070 Entry2
= Entry2
->Flink
;
1073 if (Entry2
== &List
->DiskListHead
)
1081 UpdateDiskSignatures(
1085 PDISKENTRY DiskEntry
;
1087 /* Print partition lines*/
1088 Entry
= List
->DiskListHead
.Flink
;
1089 while (Entry
!= &List
->DiskListHead
)
1091 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1093 if (DiskEntry
->LayoutBuffer
&&
1094 DiskEntry
->LayoutBuffer
->Signature
== 0)
1096 SetDiskSignature(List
, DiskEntry
);
1097 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
1100 Entry
= Entry
->Flink
;
1112 DISK_GEOMETRY DiskGeometry
;
1113 SCSI_ADDRESS ScsiAddress
;
1114 PDISKENTRY DiskEntry
;
1115 IO_STATUS_BLOCK Iosb
;
1117 PPARTITION_SECTOR Mbr
;
1119 LARGE_INTEGER FileOffset
;
1120 WCHAR Identifier
[20];
1124 PLIST_ENTRY ListEntry
;
1125 PBIOSDISKENTRY BiosDiskEntry
;
1126 ULONG LayoutBufferSize
;
1127 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
1129 Status
= NtDeviceIoControlFile(FileHandle
,
1134 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1138 sizeof(DISK_GEOMETRY
));
1139 if (!NT_SUCCESS(Status
))
1144 if (DiskGeometry
.MediaType
!= FixedMedia
&&
1145 DiskGeometry
.MediaType
!= RemovableMedia
)
1150 Status
= NtDeviceIoControlFile(FileHandle
,
1155 IOCTL_SCSI_GET_ADDRESS
,
1159 sizeof(SCSI_ADDRESS
));
1160 if (!NT_SUCCESS(Status
))
1165 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1167 DiskGeometry
.BytesPerSector
);
1173 FileOffset
.QuadPart
= 0;
1174 Status
= NtReadFile(FileHandle
,
1180 DiskGeometry
.BytesPerSector
,
1183 if (!NT_SUCCESS(Status
))
1185 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1186 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1189 Signature
= Mbr
->Signature
;
1191 /* Calculate the MBR checksum */
1193 Buffer
= (PULONG
)Mbr
;
1194 for (i
= 0; i
< 128; i
++)
1196 Checksum
+= Buffer
[i
];
1198 Checksum
= ~Checksum
+ 1;
1200 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1201 DPRINT("Identifier: %S\n", Identifier
);
1203 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1206 if (DiskEntry
== NULL
)
1211 // DiskEntry->Checksum = Checksum;
1212 // DiskEntry->Signature = Signature;
1213 DiskEntry
->BiosFound
= FALSE
;
1215 /* Check if this disk has a valid MBR */
1216 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1217 DiskEntry
->NoMbr
= TRUE
;
1219 DiskEntry
->NoMbr
= FALSE
;
1221 /* Free Mbr sector buffer */
1222 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1224 ListEntry
= List
->BiosDiskListHead
.Flink
;
1225 while (ListEntry
!= &List
->BiosDiskListHead
)
1227 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1229 * Compare the size from bios and the reported size from driver.
1230 * If we have more than one disk with a zero or with the same signatur
1231 * we must create new signatures and reboot. After the reboot,
1232 * it is possible to identify the disks.
1234 if (BiosDiskEntry
->Signature
== Signature
&&
1235 BiosDiskEntry
->Checksum
== Checksum
&&
1236 !BiosDiskEntry
->Recognized
)
1238 if (!DiskEntry
->BiosFound
)
1240 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1241 DiskEntry
->BiosFound
= TRUE
;
1242 BiosDiskEntry
->Recognized
= TRUE
;
1248 ListEntry
= ListEntry
->Flink
;
1251 if (!DiskEntry
->BiosFound
)
1254 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1257 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1261 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1262 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1264 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1265 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1266 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1267 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1269 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1270 DPRINT("TracksPerCylinder %lu\n", DiskEntry
->TracksPerCylinder
);
1271 DPRINT("SectorsPerTrack %lu\n", DiskEntry
->SectorsPerTrack
);
1272 DPRINT("BytesPerSector %lu\n", DiskEntry
->BytesPerSector
);
1274 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1275 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1276 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1278 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1279 DiskEntry
->CylinderAlignment
= DiskGeometry
.TracksPerCylinder
*
1280 DiskGeometry
.SectorsPerTrack
;
1282 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
.QuadPart
);
1283 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1285 DiskEntry
->DiskNumber
= DiskNumber
;
1286 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1287 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1288 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1290 GetDriverName(DiskEntry
);
1292 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1294 /* Allocate a layout buffer with 4 partition entries first */
1295 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1296 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1297 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1300 if (DiskEntry
->LayoutBuffer
== NULL
)
1302 DPRINT1("Failed to allocate the disk layout buffer!\n");
1308 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1309 Status
= NtDeviceIoControlFile(FileHandle
,
1314 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1317 DiskEntry
->LayoutBuffer
,
1319 if (NT_SUCCESS(Status
))
1322 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1324 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1328 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1329 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1331 DiskEntry
->LayoutBuffer
,
1333 if (NewLayoutBuffer
== NULL
)
1335 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1339 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1342 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1344 #ifdef DUMP_PARTITION_TABLE
1345 DumpPartitionTable(DiskEntry
);
1348 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1349 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1350 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1352 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1354 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1356 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1358 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1362 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1367 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1371 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1373 DiskEntry
->NewDisk
= TRUE
;
1374 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1376 for (i
= 0; i
< 4; i
++)
1377 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1381 for (i
= 0; i
< 4; i
++)
1383 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, FALSE
);
1386 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1388 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, TRUE
);
1392 ScanForUnpartitionedDiskSpace(DiskEntry
);
1397 CreatePartitionList(
1404 OBJECT_ATTRIBUTES ObjectAttributes
;
1405 SYSTEM_DEVICE_INFORMATION Sdi
;
1406 IO_STATUS_BLOCK Iosb
;
1410 WCHAR Buffer
[MAX_PATH
];
1411 UNICODE_STRING Name
;
1414 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1422 List
->Right
= Right
;
1423 List
->Bottom
= Bottom
;
1428 List
->CurrentDisk
= NULL
;
1429 List
->CurrentPartition
= NULL
;
1431 List
->SystemDisk
= NULL
;
1432 List
->SystemPartition
= NULL
;
1433 List
->OriginalSystemDisk
= NULL
;
1434 List
->OriginalSystemPartition
= NULL
;
1436 List
->TempDisk
= NULL
;
1437 List
->TempPartition
= NULL
;
1438 List
->FormatState
= Start
;
1440 InitializeListHead(&List
->DiskListHead
);
1441 InitializeListHead(&List
->BiosDiskListHead
);
1443 EnumerateBiosDiskEntries(List
);
1445 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1447 sizeof(SYSTEM_DEVICE_INFORMATION
),
1449 if (!NT_SUCCESS(Status
))
1451 RtlFreeHeap(ProcessHeap
, 0, List
);
1455 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1458 L
"\\Device\\Harddisk%d\\Partition0",
1460 RtlInitUnicodeString(&Name
,
1463 InitializeObjectAttributes(&ObjectAttributes
,
1469 Status
= NtOpenFile(&FileHandle
,
1470 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1474 FILE_SYNCHRONOUS_IO_NONALERT
);
1475 if (NT_SUCCESS(Status
))
1477 AddDiskToList(FileHandle
, DiskNumber
, List
);
1479 NtClose(FileHandle
);
1483 UpdateDiskSignatures(List
);
1485 AssignDriveLetters(List
);
1487 /* Search for first usable disk and partition */
1488 if (IsListEmpty(&List
->DiskListHead
))
1490 List
->CurrentDisk
= NULL
;
1491 List
->CurrentPartition
= NULL
;
1495 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1499 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1501 List
->CurrentPartition
= 0;
1505 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1516 DestroyPartitionList(
1519 PDISKENTRY DiskEntry
;
1520 PBIOSDISKENTRY BiosDiskEntry
;
1521 PPARTENTRY PartEntry
;
1524 /* Release disk and partition info */
1525 while (!IsListEmpty(&List
->DiskListHead
))
1527 Entry
= RemoveHeadList(&List
->DiskListHead
);
1528 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1530 /* Release driver name */
1531 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1533 /* Release primary partition list */
1534 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1536 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1537 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1539 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1542 /* Release logical partition list */
1543 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1545 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1546 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1548 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1551 /* Release layout buffer */
1552 if (DiskEntry
->LayoutBuffer
!= NULL
)
1553 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1556 /* Release disk entry */
1557 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1560 /* Release the bios disk info */
1561 while (!IsListEmpty(&List
->BiosDiskListHead
))
1563 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1564 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1566 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1569 /* Release list head */
1570 RtlFreeHeap(ProcessHeap
, 0, List
);
1584 Width
= List
->Right
- List
->Left
- 1;
1585 Height
= List
->Bottom
- List
->Top
- 2;
1587 coPos
.X
= List
->Left
+ 1;
1588 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1590 if (List
->Line
>= 0 && List
->Line
<= Height
)
1592 FillConsoleOutputAttribute(StdOutput
,
1593 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1598 FillConsoleOutputCharacterA(StdOutput
,
1613 PDISKENTRY DiskEntry
,
1614 PPARTENTRY PartEntry
)
1616 CHAR LineBuffer
[128];
1621 LARGE_INTEGER PartSize
;
1624 CHAR PartTypeString
[32];
1626 PartType
= PartTypeString
;
1628 Width
= List
->Right
- List
->Left
- 1;
1629 Height
= List
->Bottom
- List
->Top
- 2;
1631 coPos
.X
= List
->Left
+ 1;
1632 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1634 if (PartEntry
->IsPartitioned
== FALSE
)
1636 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1638 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1640 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1641 Unit
= MUIGetString(STRING_GB
);
1645 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1647 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1648 Unit
= MUIGetString(STRING_MB
);
1652 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1653 Unit
= MUIGetString(STRING_KB
);
1657 MUIGetString(STRING_UNPSPACE
),
1658 PartEntry
->LogicalPartition
? " " : "",
1659 PartEntry
->LogicalPartition
? "" : " ",
1665 /* Determine partition type */
1666 PartTypeString
[0] = '\0';
1667 if (PartEntry
->New
== TRUE
)
1669 PartType
= MUIGetString(STRING_UNFORMATTED
);
1671 else if (PartEntry
->IsPartitioned
== TRUE
)
1673 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
1675 ARRAYSIZE(PartTypeString
));
1676 PartType
= PartTypeString
;
1679 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1681 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1683 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1684 Unit
= MUIGetString(STRING_GB
);
1688 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1690 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1691 Unit
= MUIGetString(STRING_MB
);
1695 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1696 Unit
= MUIGetString(STRING_KB
);
1699 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
1702 MUIGetString(STRING_HDDINFOUNK5
),
1703 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1704 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1705 PartEntry
->BootIndicator
? '*' : ' ',
1706 PartEntry
->LogicalPartition
? " " : "",
1707 PartEntry
->PartitionType
,
1708 PartEntry
->LogicalPartition
? "" : " ",
1715 "%c%c %c %s%-24s%s %6lu %s",
1716 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1717 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1718 PartEntry
->BootIndicator
? '*' : ' ',
1719 PartEntry
->LogicalPartition
? " " : "",
1721 PartEntry
->LogicalPartition
? "" : " ",
1727 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1728 List
->CurrentPartition
== PartEntry
) ?
1729 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1730 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1732 if (List
->Line
>= 0 && List
->Line
<= Height
)
1734 FillConsoleOutputCharacterA(StdOutput
,
1742 if (List
->Line
>= 0 && List
->Line
<= Height
)
1744 FillConsoleOutputAttribute(StdOutput
,
1752 if (List
->Line
>= 0 && List
->Line
<= Height
)
1754 WriteConsoleOutputCharacterA(StdOutput
,
1756 min(strlen(LineBuffer
), Width
),
1769 PDISKENTRY DiskEntry
)
1771 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1772 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1773 CHAR LineBuffer
[128];
1778 ULARGE_INTEGER DiskSize
;
1781 Width
= List
->Right
- List
->Left
- 1;
1782 Height
= List
->Bottom
- List
->Top
- 2;
1784 coPos
.X
= List
->Left
+ 1;
1785 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1787 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1788 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1790 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1791 Unit
= MUIGetString(STRING_GB
);
1795 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1796 if (DiskSize
.QuadPart
== 0)
1797 DiskSize
.QuadPart
= 1;
1798 Unit
= MUIGetString(STRING_MB
);
1801 if (DiskEntry
->DriverName
.Length
> 0)
1804 MUIGetString(STRING_HDINFOPARTSELECT
),
1807 DiskEntry
->DiskNumber
,
1811 DiskEntry
->DriverName
.Buffer
);
1816 MUIGetString(STRING_HDDINFOUNK6
),
1819 DiskEntry
->DiskNumber
,
1825 if (List
->Line
>= 0 && List
->Line
<= Height
)
1827 FillConsoleOutputAttribute(StdOutput
,
1828 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1833 FillConsoleOutputCharacterA(StdOutput
,
1841 if (List
->Line
>= 0 && List
->Line
<= Height
)
1843 WriteConsoleOutputCharacterA(StdOutput
,
1845 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1852 /* Print separator line */
1853 PrintEmptyLine(List
);
1855 /* Print partition lines */
1856 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1857 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1859 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1861 PrintPartitionData(List
,
1865 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1867 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1868 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1870 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1872 PrintPartitionData(List
,
1876 LogicalEntry
= LogicalEntry
->Flink
;
1880 PrimaryEntry
= PrimaryEntry
->Flink
;
1883 /* Print separator line */
1884 PrintEmptyLine(List
);
1892 PLIST_ENTRY Entry
, Entry2
;
1893 PDISKENTRY DiskEntry
;
1894 PPARTENTRY PartEntry
= NULL
;
1898 SHORT CurrentDiskLine
;
1899 SHORT CurrentPartLine
;
1901 BOOL CurrentPartLineFound
= FALSE
;
1902 BOOL CurrentDiskLineFound
= FALSE
;
1904 /* Calculate the line of the current disk and partition */
1905 CurrentDiskLine
= 0;
1906 CurrentPartLine
= 0;
1909 Entry
= List
->DiskListHead
.Flink
;
1910 while (Entry
!= &List
->DiskListHead
)
1912 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1915 if (CurrentPartLineFound
== FALSE
)
1917 CurrentPartLine
+= 2;
1920 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1921 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1923 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1924 if (PartEntry
== List
->CurrentPartition
)
1926 CurrentPartLineFound
= TRUE
;
1929 Entry2
= Entry2
->Flink
;
1930 if (CurrentPartLineFound
== FALSE
)
1938 if (CurrentPartLineFound
== FALSE
)
1940 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
1941 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
1943 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1944 if (PartEntry
== List
->CurrentPartition
)
1946 CurrentPartLineFound
= TRUE
;
1949 Entry2
= Entry2
->Flink
;
1950 if (CurrentPartLineFound
== FALSE
)
1959 if (DiskEntry
== List
->CurrentDisk
)
1961 CurrentDiskLineFound
= TRUE
;
1964 Entry
= Entry
->Flink
;
1965 if (Entry
!= &List
->DiskListHead
)
1967 if (CurrentDiskLineFound
== FALSE
)
1970 CurrentDiskLine
= CurrentPartLine
;
1981 /* If it possible, make the disk name visible */
1982 if (CurrentPartLine
< List
->Offset
)
1984 List
->Offset
= CurrentPartLine
;
1986 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1988 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1991 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1993 List
->Offset
= CurrentDiskLine
;
1996 /* draw upper left corner */
1997 coPos
.X
= List
->Left
;
1998 coPos
.Y
= List
->Top
;
1999 FillConsoleOutputCharacterA(StdOutput
,
2005 /* draw upper edge */
2006 coPos
.X
= List
->Left
+ 1;
2007 coPos
.Y
= List
->Top
;
2008 if (List
->Offset
== 0)
2010 FillConsoleOutputCharacterA(StdOutput
,
2012 List
->Right
- List
->Left
- 1,
2018 FillConsoleOutputCharacterA(StdOutput
,
2020 List
->Right
- List
->Left
- 5,
2023 coPos
.X
= List
->Right
- 5;
2024 WriteConsoleOutputCharacterA(StdOutput
,
2029 coPos
.X
= List
->Right
- 2;
2030 FillConsoleOutputCharacterA(StdOutput
,
2037 /* draw upper right corner */
2038 coPos
.X
= List
->Right
;
2039 coPos
.Y
= List
->Top
;
2040 FillConsoleOutputCharacterA(StdOutput
,
2046 /* draw left and right edge */
2047 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
2049 coPos
.X
= List
->Left
;
2051 FillConsoleOutputCharacterA(StdOutput
,
2057 coPos
.X
= List
->Right
;
2058 FillConsoleOutputCharacterA(StdOutput
,
2065 /* draw lower left corner */
2066 coPos
.X
= List
->Left
;
2067 coPos
.Y
= List
->Bottom
;
2068 FillConsoleOutputCharacterA(StdOutput
,
2074 /* draw lower edge */
2075 coPos
.X
= List
->Left
+ 1;
2076 coPos
.Y
= List
->Bottom
;
2077 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
2079 FillConsoleOutputCharacterA(StdOutput
,
2081 List
->Right
- List
->Left
- 1,
2087 FillConsoleOutputCharacterA(StdOutput
,
2089 List
->Right
- List
->Left
- 5,
2092 coPos
.X
= List
->Right
- 5;
2093 WriteConsoleOutputCharacterA(StdOutput
,
2094 "(\x19)", // "(down)"
2098 coPos
.X
= List
->Right
- 2;
2099 FillConsoleOutputCharacterA(StdOutput
,
2106 /* draw lower right corner */
2107 coPos
.X
= List
->Right
;
2108 coPos
.Y
= List
->Bottom
;
2109 FillConsoleOutputCharacterA(StdOutput
,
2115 /* print list entries */
2116 List
->Line
= - List
->Offset
;
2118 Entry
= List
->DiskListHead
.Flink
;
2119 while (Entry
!= &List
->DiskListHead
)
2121 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2123 /* Print disk entry */
2127 Entry
= Entry
->Flink
;
2136 ULONG PartitionNumber
)
2138 PDISKENTRY DiskEntry
;
2139 PPARTENTRY PartEntry
;
2143 /* Check for empty disks */
2144 if (IsListEmpty(&List
->DiskListHead
))
2147 /* Check for first usable entry on next disk */
2148 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
2149 while (Entry1
!= &List
->DiskListHead
)
2151 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
2153 if (DiskEntry
->DiskNumber
== DiskNumber
)
2155 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2156 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2158 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2160 if (PartEntry
->PartitionNumber
== PartitionNumber
)
2162 List
->CurrentDisk
= DiskEntry
;
2163 List
->CurrentPartition
= PartEntry
;
2164 DrawPartitionList(List
);
2168 Entry2
= Entry2
->Flink
;
2174 Entry1
= Entry1
->Flink
;
2182 ScrollDownPartitionList(
2185 PLIST_ENTRY DiskListEntry
;
2186 PLIST_ENTRY PartListEntry
;
2187 PDISKENTRY DiskEntry
;
2188 PPARTENTRY PartEntry
;
2190 /* Fail, if no disks are available */
2191 if (IsListEmpty(&List
->DiskListHead
))
2194 /* Check for next usable entry on current disk */
2195 if (List
->CurrentPartition
!= NULL
)
2197 if (List
->CurrentPartition
->LogicalPartition
)
2199 /* Logical partition */
2201 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2202 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2204 /* Next logical partition */
2205 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2207 List
->CurrentPartition
= PartEntry
;
2212 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2213 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2215 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2217 List
->CurrentPartition
= PartEntry
;
2224 /* Primary or extended partition */
2226 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2227 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2229 /* First logical partition */
2230 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2231 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2233 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2235 List
->CurrentPartition
= PartEntry
;
2241 /* Next primary partition */
2242 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2243 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2245 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2247 List
->CurrentPartition
= PartEntry
;
2254 /* Search for the first partition entry on the next disk */
2255 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2256 while (DiskListEntry
!= &List
->DiskListHead
)
2258 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2260 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2261 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2263 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2265 List
->CurrentDisk
= DiskEntry
;
2266 List
->CurrentPartition
= PartEntry
;
2270 DiskListEntry
= DiskListEntry
->Flink
;
2278 ScrollUpPartitionList(
2281 PLIST_ENTRY DiskListEntry
;
2282 PLIST_ENTRY PartListEntry
;
2283 PDISKENTRY DiskEntry
;
2284 PPARTENTRY PartEntry
;
2286 /* Fail, if no disks are available */
2287 if (IsListEmpty(&List
->DiskListHead
))
2290 /* Check for previous usable entry on current disk */
2291 if (List
->CurrentPartition
!= NULL
)
2293 if (List
->CurrentPartition
->LogicalPartition
)
2295 /* Logical partition */
2296 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2297 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2299 /* Previous logical partition */
2300 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2304 /* Extended partition*/
2305 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2308 List
->CurrentPartition
= PartEntry
;
2313 /* Primary or extended partition */
2315 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2316 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2318 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2320 if (PartEntry
->IsPartitioned
== TRUE
&&
2321 IsContainerPartition(PartEntry
->PartitionType
))
2323 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2324 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2327 List
->CurrentPartition
= PartEntry
;
2334 /* Search for the last partition entry on the previous disk */
2335 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2336 while (DiskListEntry
!= &List
->DiskListHead
)
2338 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2340 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2341 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2343 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2345 if (PartEntry
->IsPartitioned
== TRUE
&&
2346 IsContainerPartition(PartEntry
->PartitionType
))
2348 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2349 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2351 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2353 List
->CurrentDisk
= DiskEntry
;
2354 List
->CurrentPartition
= PartEntry
;
2360 List
->CurrentDisk
= DiskEntry
;
2361 List
->CurrentPartition
= PartEntry
;
2366 DiskListEntry
= DiskListEntry
->Blink
;
2376 PPARTITION_INFORMATION PartitionInfo
)
2378 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2379 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2388 IsSamePrimaryLayoutEntry(
2389 IN PPARTITION_INFORMATION PartitionInfo
,
2390 IN PDISKENTRY DiskEntry
,
2391 IN PPARTENTRY PartEntry
)
2393 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2394 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2395 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2396 // PartitionInfo->PartitionType == PartEntry->PartitionType
2405 GetPrimaryPartitionCount(
2406 IN PDISKENTRY DiskEntry
)
2409 PPARTENTRY PartEntry
;
2412 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2413 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2415 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2416 if (PartEntry
->IsPartitioned
== TRUE
)
2419 Entry
= Entry
->Flink
;
2428 GetLogicalPartitionCount(
2429 PDISKENTRY DiskEntry
)
2431 PLIST_ENTRY ListEntry
;
2432 PPARTENTRY PartEntry
;
2435 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2436 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2438 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2439 if (PartEntry
->IsPartitioned
)
2442 ListEntry
= ListEntry
->Flink
;
2451 ReAllocateLayoutBuffer(
2452 PDISKENTRY DiskEntry
)
2454 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
2455 ULONG NewPartitionCount
;
2456 ULONG CurrentPartitionCount
= 0;
2457 ULONG LayoutBufferSize
;
2460 DPRINT1("ReAllocateLayoutBuffer()\n");
2462 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
2464 if (DiskEntry
->LayoutBuffer
)
2465 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
2467 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2468 CurrentPartitionCount
, NewPartitionCount
);
2470 if (CurrentPartitionCount
== NewPartitionCount
)
2473 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2474 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
2475 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
2477 DiskEntry
->LayoutBuffer
,
2479 if (NewLayoutBuffer
== NULL
)
2481 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
2485 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2486 if (NewPartitionCount
> CurrentPartitionCount
)
2488 for (i
= CurrentPartitionCount
; i
< NewPartitionCount
; i
++)
2489 NewLayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
2492 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
2493 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
2502 IN PDISKENTRY DiskEntry
)
2504 PPARTITION_INFORMATION PartitionInfo
;
2505 PPARTITION_INFORMATION LinkInfo
= NULL
;
2506 PLIST_ENTRY ListEntry
;
2507 PPARTENTRY PartEntry
;
2508 LARGE_INTEGER HiddenSectors64
;
2510 ULONG PartitionNumber
= 1;
2512 DPRINT1("UpdateDiskLayout()\n");
2514 /* Resize the layout buffer if necessary */
2515 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
2517 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2521 /* Update the primary partition table */
2523 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2524 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2526 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2528 if (PartEntry
->IsPartitioned
== TRUE
)
2530 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2532 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2534 DPRINT1("Updating primary partition entry %lu\n", Index
);
2536 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2537 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2538 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
2539 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2540 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2541 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2542 PartitionInfo
->RecognizedPartition
= FALSE
;
2543 PartitionInfo
->RewritePartition
= TRUE
;
2546 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2547 PartEntry
->PartitionIndex
= Index
;
2549 if (!IsContainerPartition(PartEntry
->PartitionType
))
2555 ListEntry
= ListEntry
->Flink
;
2558 /* Update the logical partition tables */
2560 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2561 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2563 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2565 if (PartEntry
->IsPartitioned
)
2567 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2569 DPRINT1("Updating logical partition entry %lu\n", Index
);
2571 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2572 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2573 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
2574 PartitionInfo
->PartitionNumber
= PartitionNumber
;
2575 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2576 PartitionInfo
->BootIndicator
= FALSE
;
2577 PartitionInfo
->RecognizedPartition
= FALSE
;
2578 PartitionInfo
->RewritePartition
= TRUE
;
2580 PartEntry
->PartitionNumber
= PartitionNumber
;
2581 PartEntry
->PartitionIndex
= Index
;
2583 /* Fill the link entry of the previous partition table */
2584 if (LinkInfo
!= NULL
)
2586 LinkInfo
->StartingOffset
.QuadPart
= (PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2587 LinkInfo
->PartitionLength
.QuadPart
= (PartEntry
->StartSector
.QuadPart
+ DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2588 HiddenSectors64
.QuadPart
= PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
- DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
;
2589 LinkInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
2590 LinkInfo
->PartitionNumber
= 0;
2591 LinkInfo
->PartitionType
= PARTITION_EXTENDED
;
2592 LinkInfo
->BootIndicator
= FALSE
;
2593 LinkInfo
->RecognizedPartition
= FALSE
;
2594 LinkInfo
->RewritePartition
= TRUE
;
2597 /* Save a pointer to the link entry of the current partition table */
2598 LinkInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
+ 1];
2604 ListEntry
= ListEntry
->Flink
;
2607 /* Wipe unused primary partition table entries */
2608 for (Index
= GetPrimaryPartitionCount(DiskEntry
); Index
< 4; Index
++)
2610 DPRINT1("Primary partition entry %lu\n", Index
);
2612 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2614 if (!IsEmptyLayoutEntry(PartitionInfo
))
2616 DPRINT1("Wiping primary partition entry %lu\n", Index
);
2618 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2619 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2620 PartitionInfo
->HiddenSectors
= 0;
2621 PartitionInfo
->PartitionNumber
= 0;
2622 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2623 PartitionInfo
->BootIndicator
= FALSE
;
2624 PartitionInfo
->RecognizedPartition
= FALSE
;
2625 PartitionInfo
->RewritePartition
= TRUE
;
2629 /* Wipe unused logical partition table entries */
2630 for (Index
= 4; Index
< DiskEntry
->LayoutBuffer
->PartitionCount
; Index
++)
2634 DPRINT1("Logical partition entry %lu\n", Index
);
2636 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2638 if (!IsEmptyLayoutEntry(PartitionInfo
))
2640 DPRINT1("Wiping partition entry %lu\n", Index
);
2642 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2643 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2644 PartitionInfo
->HiddenSectors
= 0;
2645 PartitionInfo
->PartitionNumber
= 0;
2646 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2647 PartitionInfo
->BootIndicator
= FALSE
;
2648 PartitionInfo
->RecognizedPartition
= FALSE
;
2649 PartitionInfo
->RewritePartition
= TRUE
;
2654 #ifdef DUMP_PARTITION_TABLE
2655 DumpPartitionTable(DiskEntry
);
2662 GetPrevUnpartitionedEntry(
2663 PDISKENTRY DiskEntry
,
2664 PPARTENTRY PartEntry
)
2666 PPARTENTRY PrevPartEntry
;
2667 PLIST_ENTRY ListHead
;
2669 if (PartEntry
->LogicalPartition
)
2670 ListHead
= &DiskEntry
->LogicalPartListHead
;
2672 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2674 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2676 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2679 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2680 return PrevPartEntry
;
2689 GetNextUnpartitionedEntry(
2690 PDISKENTRY DiskEntry
,
2691 PPARTENTRY PartEntry
)
2693 PPARTENTRY NextPartEntry
;
2694 PLIST_ENTRY ListHead
;
2696 if (PartEntry
->LogicalPartition
)
2697 ListHead
= &DiskEntry
->LogicalPartListHead
;
2699 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2701 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2703 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2706 if (NextPartEntry
->IsPartitioned
== FALSE
)
2707 return NextPartEntry
;
2715 CreatePrimaryPartition(
2717 ULONGLONG SectorCount
,
2720 PDISKENTRY DiskEntry
;
2721 PPARTENTRY PartEntry
;
2722 PPARTENTRY NewPartEntry
;
2724 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2727 List
->CurrentDisk
== NULL
||
2728 List
->CurrentPartition
== NULL
||
2729 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2734 DiskEntry
= List
->CurrentDisk
;
2735 PartEntry
= List
->CurrentPartition
;
2737 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2739 if (AutoCreate
== TRUE
||
2740 AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2742 DPRINT1("Convert existing partition entry\n");
2744 /* Convert current entry to 'new (unformatted)' */
2745 PartEntry
->IsPartitioned
= TRUE
;
2746 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2747 PartEntry
->FormatState
= Unformatted
;
2748 PartEntry
->AutoCreate
= AutoCreate
;
2749 PartEntry
->New
= TRUE
;
2750 PartEntry
->BootIndicator
= FALSE
;
2752 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2753 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2754 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2758 DPRINT1("Add new partition entry\n");
2760 /* Insert and initialize a new partition entry */
2761 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2764 if (NewPartEntry
== NULL
)
2767 /* Insert the new entry into the list */
2768 InsertTailList(&PartEntry
->ListEntry
,
2769 &NewPartEntry
->ListEntry
);
2771 NewPartEntry
->DiskEntry
= DiskEntry
;
2773 NewPartEntry
->IsPartitioned
= TRUE
;
2774 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2775 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2776 NewPartEntry
->StartSector
.QuadPart
;
2777 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2779 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2780 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2781 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2783 NewPartEntry
->New
= TRUE
;
2784 NewPartEntry
->FormatState
= Unformatted
;
2785 NewPartEntry
->BootIndicator
= FALSE
;
2787 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2788 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2791 UpdateDiskLayout(DiskEntry
);
2793 DiskEntry
->Dirty
= TRUE
;
2795 AssignDriveLetters(List
);
2801 AddLogicalDiskSpace(
2802 PDISKENTRY DiskEntry
)
2804 PPARTENTRY NewPartEntry
;
2806 DPRINT1("AddLogicalDiskSpace()\n");
2808 /* Create a partition table entry that represents the empty space in the container partition */
2809 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2812 if (NewPartEntry
== NULL
)
2815 NewPartEntry
->DiskEntry
= DiskEntry
;
2816 NewPartEntry
->LogicalPartition
= TRUE
;
2818 NewPartEntry
->IsPartitioned
= FALSE
;
2819 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2820 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2822 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2823 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2824 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2826 NewPartEntry
->FormatState
= Unformatted
;
2828 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2829 &NewPartEntry
->ListEntry
);
2834 CreateExtendedPartition(
2836 ULONGLONG SectorCount
)
2838 PDISKENTRY DiskEntry
;
2839 PPARTENTRY PartEntry
;
2840 PPARTENTRY NewPartEntry
;
2842 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2845 List
->CurrentDisk
== NULL
||
2846 List
->CurrentPartition
== NULL
||
2847 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2852 DiskEntry
= List
->CurrentDisk
;
2853 PartEntry
= List
->CurrentPartition
;
2855 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2857 if (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2859 DPRINT1("Convert existing partition entry\n");
2861 /* Convert current entry to 'new (unformatted)' */
2862 PartEntry
->IsPartitioned
= TRUE
;
2863 PartEntry
->FormatState
= Formatted
;
2864 PartEntry
->AutoCreate
= FALSE
;
2865 PartEntry
->New
= FALSE
;
2866 PartEntry
->BootIndicator
= FALSE
;
2868 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2870 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2871 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2875 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2876 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2879 DiskEntry
->ExtendedPartition
= PartEntry
;
2881 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2882 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2883 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2887 DPRINT1("Add new partition entry\n");
2889 /* Insert and initialize a new partition entry */
2890 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2893 if (NewPartEntry
== NULL
)
2896 /* Insert the new entry into the list */
2897 InsertTailList(&PartEntry
->ListEntry
,
2898 &NewPartEntry
->ListEntry
);
2900 NewPartEntry
->DiskEntry
= DiskEntry
;
2902 NewPartEntry
->IsPartitioned
= TRUE
;
2903 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2904 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2905 NewPartEntry
->StartSector
.QuadPart
;
2907 NewPartEntry
->New
= FALSE
;
2908 NewPartEntry
->FormatState
= Formatted
;
2909 NewPartEntry
->BootIndicator
= FALSE
;
2911 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2913 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2914 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2918 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2919 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2922 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2924 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2925 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2927 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2928 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2929 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2932 AddLogicalDiskSpace(DiskEntry
);
2934 UpdateDiskLayout(DiskEntry
);
2936 DiskEntry
->Dirty
= TRUE
;
2938 AssignDriveLetters(List
);
2943 CreateLogicalPartition(
2945 ULONGLONG SectorCount
,
2948 PDISKENTRY DiskEntry
;
2949 PPARTENTRY PartEntry
;
2950 PPARTENTRY NewPartEntry
;
2952 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2955 List
->CurrentDisk
== NULL
||
2956 List
->CurrentPartition
== NULL
||
2957 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2962 DiskEntry
= List
->CurrentDisk
;
2963 PartEntry
= List
->CurrentPartition
;
2965 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2967 if (AutoCreate
== TRUE
||
2968 AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2970 DPRINT1("Convert existing partition entry\n");
2972 /* Convert current entry to 'new (unformatted)' */
2973 PartEntry
->IsPartitioned
= TRUE
;
2974 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2975 PartEntry
->FormatState
= Unformatted
;
2976 PartEntry
->AutoCreate
= FALSE
;
2977 PartEntry
->New
= TRUE
;
2978 PartEntry
->BootIndicator
= FALSE
;
2979 PartEntry
->LogicalPartition
= TRUE
;
2981 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2982 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2983 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2987 DPRINT1("Add new partition entry\n");
2989 /* Insert and initialize a new partition entry */
2990 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2993 if (NewPartEntry
== NULL
)
2996 /* Insert the new entry into the list */
2997 InsertTailList(&PartEntry
->ListEntry
,
2998 &NewPartEntry
->ListEntry
);
3000 NewPartEntry
->DiskEntry
= DiskEntry
;
3002 NewPartEntry
->IsPartitioned
= TRUE
;
3003 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
3004 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
3005 NewPartEntry
->StartSector
.QuadPart
;
3006 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
3008 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
3009 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
3010 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
3012 NewPartEntry
->New
= TRUE
;
3013 NewPartEntry
->FormatState
= Unformatted
;
3014 NewPartEntry
->BootIndicator
= FALSE
;
3015 NewPartEntry
->LogicalPartition
= TRUE
;
3017 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
3018 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
3021 UpdateDiskLayout(DiskEntry
);
3023 DiskEntry
->Dirty
= TRUE
;
3025 AssignDriveLetters(List
);
3030 DeleteCurrentPartition(
3033 PDISKENTRY DiskEntry
;
3034 PPARTENTRY PartEntry
;
3035 PPARTENTRY PrevPartEntry
;
3036 PPARTENTRY NextPartEntry
;
3037 PPARTENTRY LogicalPartEntry
;
3041 List
->CurrentDisk
== NULL
||
3042 List
->CurrentPartition
== NULL
||
3043 List
->CurrentPartition
->IsPartitioned
== FALSE
)
3048 /* Clear the system disk and partition pointers if the system partition will be deleted */
3049 if (List
->SystemPartition
== List
->CurrentPartition
)
3051 List
->SystemDisk
= NULL
;
3052 List
->SystemPartition
= NULL
;
3055 DiskEntry
= List
->CurrentDisk
;
3056 PartEntry
= List
->CurrentPartition
;
3058 /* Delete all logical partition entries if an extended partition will be deleted */
3059 if (DiskEntry
->ExtendedPartition
== PartEntry
)
3061 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
3063 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
3064 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3066 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
3069 DiskEntry
->ExtendedPartition
= NULL
;
3072 /* Adjust unpartitioned disk space entries */
3074 /* Get pointer to previous and next unpartitioned entries */
3075 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
, PartEntry
);
3076 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
, PartEntry
);
3078 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
3080 /* Merge previous, current and next unpartitioned entry */
3082 /* Adjust the previous entries length */
3083 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
3085 /* Remove the current entry */
3086 RemoveEntryList(&PartEntry
->ListEntry
);
3087 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3089 /* Remove the next entry */
3090 RemoveEntryList (&NextPartEntry
->ListEntry
);
3091 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
3093 /* Update current partition */
3094 List
->CurrentPartition
= PrevPartEntry
;
3096 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
3098 /* Merge current and previous unpartitioned entry */
3100 /* Adjust the previous entries length */
3101 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
3103 /* Remove the current entry */
3104 RemoveEntryList(&PartEntry
->ListEntry
);
3105 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3107 /* Update current partition */
3108 List
->CurrentPartition
= PrevPartEntry
;
3110 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
3112 /* Merge current and next unpartitioned entry */
3114 /* Adjust the next entries offset and length */
3115 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
3116 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
3118 /* Remove the current entry */
3119 RemoveEntryList(&PartEntry
->ListEntry
);
3120 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3122 /* Update current partition */
3123 List
->CurrentPartition
= NextPartEntry
;
3127 /* Nothing to merge but change current entry */
3128 PartEntry
->IsPartitioned
= FALSE
;
3129 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
3130 PartEntry
->FormatState
= Unformatted
;
3131 PartEntry
->DriveLetter
= 0;
3134 UpdateDiskLayout(DiskEntry
);
3136 DiskEntry
->Dirty
= TRUE
;
3138 AssignDriveLetters(List
);
3143 CheckActiveSystemPartition(
3145 IN PFILE_SYSTEM_LIST FileSystemList
/* Needed for checking the FS of the candidate system partition */
3148 PDISKENTRY DiskEntry
;
3149 PPARTENTRY PartEntry
;
3150 PLIST_ENTRY ListEntry
;
3152 PFILE_SYSTEM_ITEM FileSystem
;
3154 /* Check for empty disk list */
3155 if (IsListEmpty(&List
->DiskListHead
))
3157 List
->SystemDisk
= NULL
;
3158 List
->SystemPartition
= NULL
;
3159 List
->OriginalSystemDisk
= NULL
;
3160 List
->OriginalSystemPartition
= NULL
;
3164 /* Choose the currently selected disk */
3165 DiskEntry
= List
->CurrentDisk
;
3167 /* Check for empty partition list */
3168 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
3170 List
->SystemDisk
= NULL
;
3171 List
->SystemPartition
= NULL
;
3172 List
->OriginalSystemDisk
= NULL
;
3173 List
->OriginalSystemPartition
= NULL
;
3177 if (List
->SystemDisk
!= NULL
&& List
->SystemPartition
!= NULL
)
3179 /* We already have an active system partition */
3180 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
3181 List
->SystemPartition
->PartitionNumber
,
3182 List
->SystemDisk
->DiskNumber
,
3183 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3187 DPRINT1("We are here (1)!\n");
3189 List
->SystemDisk
= NULL
;
3190 List
->SystemPartition
= NULL
;
3191 List
->OriginalSystemDisk
= NULL
;
3192 List
->OriginalSystemPartition
= NULL
;
3194 /* Retrieve the first partition of the disk */
3195 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
3198 List
->SystemDisk
= DiskEntry
;
3199 List
->SystemPartition
= PartEntry
;
3202 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
3205 /* Check if the disk is new and if so, use its first partition as the active system partition */
3206 if (DiskEntry
->NewDisk
)
3208 if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
== FALSE
)
3210 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3211 List
->SystemDisk
= DiskEntry
;
3212 List
->SystemPartition
= PartEntry
;
3214 List
->OriginalSystemDisk
= List
->SystemDisk
;
3215 List
->OriginalSystemPartition
= List
->SystemPartition
;
3217 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
3218 List
->SystemPartition
->PartitionNumber
,
3219 List
->SystemDisk
->DiskNumber
,
3220 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3222 goto SetSystemPartition
;
3225 // FIXME: What to do??
3226 DPRINT1("NewDisk TRUE but first partition is used?\n");
3229 DPRINT1("We are here (2)!\n");
3232 * The disk is not new, check if any partition is initialized;
3233 * if not, the first one becomes the system partition.
3235 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3236 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
3238 /* Retrieve the partition and go to the next one */
3239 PartEntry
= CONTAINING_RECORD(ListEntry
,
3243 /* Check if the partition is partitioned and is used */
3244 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
!= FALSE
)
3249 /* Go to the next one */
3250 ListEntry
= ListEntry
->Flink
;
3252 if (ListEntry
== &DiskEntry
->PrimaryPartListHead
)
3255 * OK we haven't encountered any used and active partition,
3256 * so use the first one as the system partition.
3259 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3260 List
->OriginalSystemDisk
= List
->SystemDisk
; // DiskEntry
3261 List
->OriginalSystemPartition
= List
->SystemPartition
; // First PartEntry
3263 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
3264 List
->SystemPartition
->PartitionNumber
,
3265 List
->SystemDisk
->DiskNumber
,
3266 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3268 goto SetSystemPartition
;
3271 List
->SystemDisk
= NULL
;
3272 List
->SystemPartition
= NULL
;
3273 List
->OriginalSystemDisk
= NULL
;
3274 List
->OriginalSystemPartition
= NULL
;
3276 DPRINT1("We are here (3)!\n");
3278 /* The disk is not new, scan all partitions to find the (active) system partition */
3279 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3280 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
3282 /* Retrieve the partition and go to the next one */
3283 PartEntry
= CONTAINING_RECORD(ListEntry
,
3286 ListEntry
= ListEntry
->Flink
;
3288 /* Check if the partition is partitioned and used */
3289 if (PartEntry
->IsPartitioned
&&
3290 PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
)
3292 /* Check if the partition is active */
3293 if (PartEntry
->BootIndicator
)
3295 /* Yes, we found it */
3296 List
->SystemDisk
= DiskEntry
;
3297 List
->SystemPartition
= PartEntry
;
3299 DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
3300 PartEntry
->PartitionNumber
,
3301 DiskEntry
->DiskNumber
,
3302 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
);
3308 /* Check if we have found the system partition */
3309 if (List
->SystemDisk
== NULL
|| List
->SystemPartition
== NULL
)
3311 /* Nothing, use the alternative system partition */
3312 DPRINT1("No system partition found, use the alternative partition!\n");
3313 goto UseAlternativeSystemPartition
;
3317 List
->OriginalSystemDisk
= List
->SystemDisk
;
3318 List
->OriginalSystemPartition
= List
->SystemPartition
;
3321 * ADDITIONAL CHECKS / BIG HACK:
3323 * Retrieve its file system and check whether we have
3324 * write support for it. If that is the case we are fine
3325 * and we can use it directly. However if we don't have
3326 * write support we will need to change the active system
3329 * NOTE that this is completely useless on architectures
3330 * where a real system partition is required, as on these
3331 * architectures the partition uses the FAT FS, for which
3332 * we do have write support.
3333 * NOTE also that for those architectures looking for a
3334 * partition boot indicator is insufficient.
3336 FileSystem
= GetFileSystem(FileSystemList
, List
->OriginalSystemPartition
);
3337 if (FileSystem
== NULL
)
3339 DPRINT1("System partition %lu in disk %lu with no FS?!\n",
3340 List
->OriginalSystemPartition
->PartitionNumber
,
3341 List
->OriginalSystemDisk
->DiskNumber
);
3342 goto FindAndUseAlternativeSystemPartition
;
3344 // HACK: WARNING: We cannot write on this FS yet!
3345 // See fslist.c:GetFileSystem()
3346 if (List
->OriginalSystemPartition
->PartitionType
== PARTITION_EXT2
||
3347 List
->OriginalSystemPartition
->PartitionType
== PARTITION_IFS
)
3349 DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
3350 FileSystem
->FileSystemName
);
3351 goto FindAndUseAlternativeSystemPartition
;
3354 DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
3355 List
->SystemPartition
->PartitionNumber
,
3356 List
->SystemDisk
->DiskNumber
,
3357 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3361 FindAndUseAlternativeSystemPartition
:
3363 * We are here because we have not found any (active) candidate
3364 * system partition that we know how to support. What we are going
3365 * to do is to change the existing system partition and use the
3366 * partition on which we install ReactOS as the new system partition,
3367 * and then we will need to add in FreeLdr's entry a boot entry to boot
3368 * from the original system partition.
3371 /* Unset the old system partition */
3372 List
->SystemPartition
->BootIndicator
= FALSE
;
3373 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= FALSE
;
3374 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3375 List
->SystemDisk
->Dirty
= TRUE
;
3377 UseAlternativeSystemPartition
:
3378 List
->SystemDisk
= List
->CurrentDisk
;
3379 List
->SystemPartition
= List
->CurrentPartition
;
3381 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
3382 List
->SystemPartition
->PartitionNumber
,
3383 List
->SystemDisk
->DiskNumber
,
3384 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3387 /* Set the new active system partition */
3388 List
->SystemPartition
->BootIndicator
= TRUE
;
3389 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= TRUE
;
3390 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3391 List
->SystemDisk
->Dirty
= TRUE
;
3399 IN PDISKENTRY DiskEntry
)
3401 WCHAR DstPath
[MAX_PATH
];
3402 OBJECT_ATTRIBUTES ObjectAttributes
;
3403 IO_STATUS_BLOCK Iosb
;
3404 UNICODE_STRING Name
;
3406 HANDLE FileHandle
= NULL
;
3409 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
3412 L
"\\Device\\Harddisk%d\\Partition0",
3413 DiskEntry
->DiskNumber
);
3414 RtlInitUnicodeString(&Name
,
3416 InitializeObjectAttributes(&ObjectAttributes
,
3422 Status
= NtOpenFile(&FileHandle
,
3423 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
3427 FILE_SYNCHRONOUS_IO_NONALERT
);
3428 if (!NT_SUCCESS(Status
))
3430 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
3434 #ifdef DUMP_PARTITION_TABLE
3435 DumpPartitionTable(DiskEntry
);
3438 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
3439 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
3440 Status
= NtDeviceIoControlFile(FileHandle
,
3445 IOCTL_DISK_SET_DRIVE_LAYOUT
,
3446 DiskEntry
->LayoutBuffer
,
3450 if (!NT_SUCCESS(Status
))
3452 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
3455 if (FileHandle
!= NULL
)
3456 NtClose(FileHandle
);
3463 WritePartitionsToDisk(
3467 PDISKENTRY DiskEntry
;
3472 Entry
= List
->DiskListHead
.Flink
;
3473 while (Entry
!= &List
->DiskListHead
)
3475 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3477 if (DiskEntry
->Dirty
== TRUE
)
3479 WritePartitions(List
, DiskEntry
);
3480 DiskEntry
->Dirty
= FALSE
;
3483 Entry
= Entry
->Flink
;
3491 SetMountedDeviceValues(
3494 PLIST_ENTRY Entry1
, Entry2
;
3495 PDISKENTRY DiskEntry
;
3496 PPARTENTRY PartEntry
;
3497 LARGE_INTEGER StartingOffset
;
3504 Entry1
= List
->DiskListHead
.Flink
;
3505 while (Entry1
!= &List
->DiskListHead
)
3507 DiskEntry
= CONTAINING_RECORD(Entry1
,
3511 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3512 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3514 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3515 if (PartEntry
->IsPartitioned
)
3517 if (PartEntry
->DriveLetter
)
3519 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3520 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3521 DiskEntry
->LayoutBuffer
->Signature
,
3529 Entry2
= Entry2
->Flink
;
3532 Entry1
= Entry1
->Flink
;
3540 PrimaryPartitionCreationChecks(
3543 PDISKENTRY DiskEntry
;
3544 PPARTENTRY PartEntry
;
3546 DiskEntry
= List
->CurrentDisk
;
3547 PartEntry
= List
->CurrentPartition
;
3549 /* Fail if partition is already in use */
3550 if (PartEntry
->IsPartitioned
== TRUE
)
3551 return ERROR_NEW_PARTITION
;
3553 /* Fail if there are already 4 primary partitions in the list */
3554 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3555 return ERROR_PARTITION_TABLE_FULL
;
3557 return ERROR_SUCCESS
;
3562 ExtendedPartitionCreationChecks(
3565 PDISKENTRY DiskEntry
;
3566 PPARTENTRY PartEntry
;
3568 DiskEntry
= List
->CurrentDisk
;
3569 PartEntry
= List
->CurrentPartition
;
3571 /* Fail if partition is already in use */
3572 if (PartEntry
->IsPartitioned
== TRUE
)
3573 return ERROR_NEW_PARTITION
;
3575 /* Fail if there are already 4 primary partitions in the list */
3576 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3577 return ERROR_PARTITION_TABLE_FULL
;
3579 /* Fail if there is another extended partition in the list */
3580 if (DiskEntry
->ExtendedPartition
!= NULL
)
3581 return ERROR_ONLY_ONE_EXTENDED
;
3583 return ERROR_SUCCESS
;
3588 LogicalPartitionCreationChecks(
3591 // PDISKENTRY DiskEntry;
3592 PPARTENTRY PartEntry
;
3594 // DiskEntry = List->CurrentDisk;
3595 PartEntry
= List
->CurrentPartition
;
3597 /* Fail if partition is already in use */
3598 if (PartEntry
->IsPartitioned
== TRUE
)
3599 return ERROR_NEW_PARTITION
;
3601 return ERROR_SUCCESS
;
3606 GetNextUnformattedPartition(
3608 OUT PDISKENTRY
*pDiskEntry
,
3609 OUT PPARTENTRY
*pPartEntry
)
3611 PLIST_ENTRY Entry1
, Entry2
;
3612 PDISKENTRY DiskEntry
;
3613 PPARTENTRY PartEntry
;
3615 Entry1
= List
->DiskListHead
.Flink
;
3616 while (Entry1
!= &List
->DiskListHead
)
3618 DiskEntry
= CONTAINING_RECORD(Entry1
,
3622 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3623 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3625 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3626 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3628 *pDiskEntry
= DiskEntry
;
3629 *pPartEntry
= PartEntry
;
3633 Entry2
= Entry2
->Flink
;
3636 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3637 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3639 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3640 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3642 *pDiskEntry
= DiskEntry
;
3643 *pPartEntry
= PartEntry
;
3647 Entry2
= Entry2
->Flink
;
3650 Entry1
= Entry1
->Flink
;
3661 GetNextUncheckedPartition(
3663 OUT PDISKENTRY
*pDiskEntry
,
3664 OUT PPARTENTRY
*pPartEntry
)
3666 PLIST_ENTRY Entry1
, Entry2
;
3667 PDISKENTRY DiskEntry
;
3668 PPARTENTRY PartEntry
;
3670 Entry1
= List
->DiskListHead
.Flink
;
3671 while (Entry1
!= &List
->DiskListHead
)
3673 DiskEntry
= CONTAINING_RECORD(Entry1
,
3677 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3678 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3680 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3681 if (PartEntry
->NeedsCheck
== TRUE
)
3683 *pDiskEntry
= DiskEntry
;
3684 *pPartEntry
= PartEntry
;
3688 Entry2
= Entry2
->Flink
;
3691 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3692 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3694 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3695 if (PartEntry
->NeedsCheck
== TRUE
)
3697 *pDiskEntry
= DiskEntry
;
3698 *pPartEntry
= PartEntry
;
3702 Entry2
= Entry2
->Flink
;
3705 Entry1
= Entry1
->Flink
;