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" },
129 { 0x96, "CDFS/ISO-9660" },
131 { 0xA0, "Laptop hibernation" },
132 { 0xA1, "Laptop hibernation" },
133 { 0xA5, "BSD, NetBSD, FreeBSD" },
135 { 0xA7, "NeXTSTEP" },
136 { 0xA8, "OS-X UFS" },
138 { 0xAB, "OS-X boot" },
139 { 0xAF, "OS-X HFS" },
140 { 0xB6, "NT corrupt mirror" },
142 { 0xB8, "BSDI swap" },
143 { 0xBE, "Solaris 8 boot" },
144 { 0xBF, "Solaris x86" },
146 { 0xC1, "DR-DOS FAT12" },
147 { 0xC2, "Hidden Linux" },
148 { 0xC3, "Hidden Linux swap" },
149 { 0xC4, "DR-DOS FAT16 (small)" },
150 { 0xC5, "DR-DOS Extended" },
151 { 0xC6, "DR-DOS FAT16" },
152 { 0xC7, "HPFS mirrored" },
153 { 0xCB, "DR-DOS FAT32" },
154 { 0xCC, "DR-DOS FAT32 (LBA)" },
155 { 0xCE, "DR-DOS FAT16 (LBA)" },
157 { 0xD1, "MDOS FAT12" },
158 { 0xD4, "MDOS FAT16 (small)" },
159 { 0xD5, "MDOS Extended" },
160 { 0xD6, "MDOS FAT16" },
162 { 0xDF, "BootIt EMBRM(FAT16/32)" },
163 { 0xEB, "BeOS BFS" },
164 { 0xEE, "EFI GPT protective" },
165 { 0xEF, "EFI filesystem" },
166 { 0xF0, "Linux/PA-RISC boot" },
167 { 0xF2, "DOS 3.3+ second" },
170 { 0xFC, "VmWare swap" },
171 { 0xFD, "Linux RAID" },
172 { 0xFE, "NT hidden" },
176 GetPartTypeStringFromPartitionType(
181 /* Determine partition type */
183 if (IsContainerPartition(partitionType
))
185 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
187 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
189 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
195 /* Do the table lookup */
196 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
198 if (partitionType
== PartitionTypes
[i
].Type
)
200 StringCchCopy(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
205 /* We are here because the partition type is unknown */
206 StringCchCopy(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
210 /* FUNCTIONS ****************************************************************/
212 #ifdef DUMP_PARTITION_TABLE
216 PDISKENTRY DiskEntry
)
218 PPARTITION_INFORMATION PartitionInfo
;
222 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
223 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
225 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
227 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
228 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
230 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
231 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
232 PartitionInfo
->HiddenSectors
,
233 PartitionInfo
->PartitionNumber
,
234 PartitionInfo
->PartitionType
,
235 PartitionInfo
->BootIndicator
? '*': ' ',
236 PartitionInfo
->RewritePartition
? 'Y': 'N');
251 Temp
= Value
/ Alignment
;
253 return Temp
* Alignment
;
262 ULONGLONG Temp
, Result
;
264 Temp
= Value
/ Alignment
;
266 Result
= Temp
* Alignment
;
267 if (Value
% Alignment
)
275 IN ULONGLONG Dividend
,
276 IN ULONGLONG Divisor
)
278 return (Dividend
+ Divisor
/ 2) / Divisor
;
285 PDISKENTRY DiskEntry
)
287 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
291 RtlInitUnicodeString(&DiskEntry
->DriverName
,
295 L
"\\Scsi\\Scsi Port %hu",
298 RtlZeroMemory(&QueryTable
,
301 QueryTable
[0].Name
= L
"Driver";
302 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
303 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
305 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
310 if (!NT_SUCCESS(Status
))
312 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
322 PDISKENTRY DiskEntry
;
323 PPARTENTRY PartEntry
;
330 /* Assign drive letters to primary partitions */
331 Entry1
= List
->DiskListHead
.Flink
;
332 while (Entry1
!= &List
->DiskListHead
)
334 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
336 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
337 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
339 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
341 PartEntry
->DriveLetter
= 0;
343 if (PartEntry
->IsPartitioned
&&
344 !IsContainerPartition(PartEntry
->PartitionType
))
346 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
347 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
348 PartEntry
->SectorCount
.QuadPart
!= 0LL))
352 PartEntry
->DriveLetter
= Letter
;
358 Entry2
= Entry2
->Flink
;
361 Entry1
= Entry1
->Flink
;
364 /* Assign drive letters to logical drives */
365 Entry1
= List
->DiskListHead
.Flink
;
366 while (Entry1
!= &List
->DiskListHead
)
368 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
370 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
371 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
373 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
375 PartEntry
->DriveLetter
= 0;
377 if (PartEntry
->IsPartitioned
)
379 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
380 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
381 PartEntry
->SectorCount
.QuadPart
!= 0LL))
385 PartEntry
->DriveLetter
= Letter
;
391 Entry2
= Entry2
->Flink
;
394 Entry1
= Entry1
->Flink
;
401 DiskIdentifierQueryRoutine(
409 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
410 UNICODE_STRING NameU
;
412 if (ValueType
== REG_SZ
&&
413 ValueLength
== 20 * sizeof(WCHAR
))
415 NameU
.Buffer
= (PWCHAR
)ValueData
;
416 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
417 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
419 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
420 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
422 return STATUS_SUCCESS
;
425 return STATUS_UNSUCCESSFUL
;
431 DiskConfigurationDataQueryRoutine(
439 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
440 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
441 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
444 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
445 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
446 return STATUS_UNSUCCESSFUL
;
448 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
450 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
452 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
453 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
454 return STATUS_UNSUCCESSFUL
;
457 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
459 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
460 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
463 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
464 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
466 return STATUS_SUCCESS
;
469 return STATUS_UNSUCCESSFUL
;
475 SystemConfigurationDataQueryRoutine(
483 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
484 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
487 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
488 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
489 return STATUS_UNSUCCESSFUL
;
491 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
493 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
495 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
496 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
497 return STATUS_UNSUCCESSFUL
;
500 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
502 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
503 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
506 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*)RtlAllocateHeap(ProcessHeap
, 0,
507 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
508 if (*Int13Drives
== NULL
)
509 return STATUS_NO_MEMORY
;
512 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
513 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
514 return STATUS_SUCCESS
;
517 return STATUS_UNSUCCESSFUL
;
521 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
524 EnumerateBiosDiskEntries(
527 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
532 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
533 PBIOSDISKENTRY BiosDiskEntry
;
535 memset(QueryTable
, 0, sizeof(QueryTable
));
537 QueryTable
[1].Name
= L
"Configuration Data";
538 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
540 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
541 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
545 if (!NT_SUCCESS(Status
))
547 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
554 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
555 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
560 if (!NT_SUCCESS(Status
))
565 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
566 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
571 if (NT_SUCCESS(Status
))
575 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
576 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
581 if (!NT_SUCCESS(Status
))
583 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
587 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
588 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
593 if (NT_SUCCESS(Status
))
595 QueryTable
[0].Name
= L
"Identifier";
596 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
597 QueryTable
[1].Name
= L
"Configuration Data";
598 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
603 BiosDiskEntry
= (BIOSDISKENTRY
*)RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
604 if (BiosDiskEntry
== NULL
)
609 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
610 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
613 (PVOID
)BiosDiskEntry
,
615 if (!NT_SUCCESS(Status
))
617 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
621 BiosDiskEntry
->DiskNumber
= DiskCount
;
622 BiosDiskEntry
->Recognized
= FALSE
;
624 if (DiskCount
< Int13Drives
[0].NumberDrives
)
626 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
630 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
633 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
635 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
636 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
637 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
638 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
639 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
640 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
641 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
642 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
643 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
644 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
645 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
651 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
659 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
667 PDISKENTRY DiskEntry
,
668 ULONG PartitionIndex
,
669 BOOLEAN LogicalPartition
)
671 PPARTITION_INFORMATION PartitionInfo
;
672 PPARTENTRY PartEntry
;
674 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
675 if (PartitionInfo
->PartitionType
== 0 ||
676 ((LogicalPartition
!= FALSE
) && IsContainerPartition(PartitionInfo
->PartitionType
)))
679 PartEntry
= RtlAllocateHeap(ProcessHeap
,
682 if (PartEntry
== NULL
)
687 PartEntry
->DiskEntry
= DiskEntry
;
689 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
690 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
692 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
693 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
694 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
696 PartEntry
->LogicalPartition
= LogicalPartition
;
697 PartEntry
->IsPartitioned
= TRUE
;
698 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
699 PartEntry
->PartitionIndex
= PartitionIndex
;
701 if (IsContainerPartition(PartEntry
->PartitionType
))
703 PartEntry
->FormatState
= Unformatted
;
705 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
706 DiskEntry
->ExtendedPartition
= PartEntry
;
708 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
709 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
710 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
711 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
712 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
713 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
716 if (CheckFatFormat())
718 PartEntry
->FormatState
= Preformatted
;
722 PartEntry
->FormatState
= Unformatted
;
725 PartEntry
->FormatState
= Preformatted
;
727 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
730 if (CheckExt2Format())
732 PartEntry
->FormatState
= Preformatted
;
736 PartEntry
->FormatState
= Unformatted
;
739 PartEntry
->FormatState
= Preformatted
;
741 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
744 if (CheckNtfsFormat())
746 PartEntry
->FormatState
= Preformatted
;
748 else if (CheckHpfsFormat())
750 PartEntry
->FormatState
= Preformatted
;
754 PartEntry
->FormatState
= Unformatted
;
757 PartEntry
->FormatState
= Preformatted
;
761 PartEntry
->FormatState
= UnknownFormat
;
764 if (LogicalPartition
)
765 InsertTailList(&DiskEntry
->LogicalPartListHead
,
766 &PartEntry
->ListEntry
);
768 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
769 &PartEntry
->ListEntry
);
775 ScanForUnpartitionedDiskSpace(
776 PDISKENTRY DiskEntry
)
778 ULONGLONG LastStartSector
;
779 ULONGLONG LastSectorCount
;
780 ULONGLONG LastUnusedSectorCount
;
781 PPARTENTRY PartEntry
;
782 PPARTENTRY NewPartEntry
;
785 DPRINT("ScanForUnpartitionedDiskSpace()\n");
787 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
789 DPRINT1("No primary partition!\n");
791 /* Create a partition table that represents the empty disk */
792 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
795 if (NewPartEntry
== NULL
)
798 NewPartEntry
->DiskEntry
= DiskEntry
;
800 NewPartEntry
->IsPartitioned
= FALSE
;
801 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
802 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
803 NewPartEntry
->StartSector
.QuadPart
;
805 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
806 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
807 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
809 NewPartEntry
->FormatState
= Unformatted
;
811 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
812 &NewPartEntry
->ListEntry
);
817 /* Start partition at head 1, cylinder 0 */
818 LastStartSector
= DiskEntry
->SectorAlignment
;
819 LastSectorCount
= 0ULL;
820 LastUnusedSectorCount
= 0ULL;
822 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
823 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
825 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
827 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
828 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
830 LastUnusedSectorCount
=
831 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
833 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
834 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
836 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
838 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
841 if (NewPartEntry
== NULL
)
844 NewPartEntry
->DiskEntry
= DiskEntry
;
846 NewPartEntry
->IsPartitioned
= FALSE
;
847 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
848 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
849 NewPartEntry
->StartSector
.QuadPart
;
851 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
852 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
853 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
855 NewPartEntry
->FormatState
= Unformatted
;
857 /* Insert the table into the list */
858 InsertTailList(&PartEntry
->ListEntry
,
859 &NewPartEntry
->ListEntry
);
862 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
863 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
866 Entry
= Entry
->Flink
;
869 /* Check for trailing unpartitioned disk space */
870 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
872 LastUnusedSectorCount
= AlignDown(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
874 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
876 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
878 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
881 if (NewPartEntry
== NULL
)
884 NewPartEntry
->DiskEntry
= DiskEntry
;
886 NewPartEntry
->IsPartitioned
= FALSE
;
887 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
888 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
889 NewPartEntry
->StartSector
.QuadPart
;
891 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
892 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
893 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
895 NewPartEntry
->FormatState
= Unformatted
;
897 /* Append the table to the list */
898 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
899 &NewPartEntry
->ListEntry
);
903 if (DiskEntry
->ExtendedPartition
!= NULL
)
905 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
907 DPRINT1("No logical partition!\n");
909 /* Create a partition table entry that represents the empty extended partition */
910 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
913 if (NewPartEntry
== NULL
)
916 NewPartEntry
->DiskEntry
= DiskEntry
;
917 NewPartEntry
->LogicalPartition
= TRUE
;
919 NewPartEntry
->IsPartitioned
= FALSE
;
920 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
921 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
923 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
924 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
925 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
927 NewPartEntry
->FormatState
= Unformatted
;
929 InsertTailList(&DiskEntry
->LogicalPartListHead
,
930 &NewPartEntry
->ListEntry
);
935 /* Start partition at head 1, cylinder 0 */
936 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
937 LastSectorCount
= 0ULL;
938 LastUnusedSectorCount
= 0ULL;
940 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
941 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
943 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
945 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
946 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
948 LastUnusedSectorCount
=
949 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
951 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
952 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
954 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
956 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
959 if (NewPartEntry
== NULL
)
962 NewPartEntry
->DiskEntry
= DiskEntry
;
963 NewPartEntry
->LogicalPartition
= TRUE
;
965 NewPartEntry
->IsPartitioned
= FALSE
;
966 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
967 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
968 NewPartEntry
->StartSector
.QuadPart
;
970 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
971 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
972 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
974 NewPartEntry
->FormatState
= Unformatted
;
976 /* Insert the table into the list */
977 InsertTailList(&PartEntry
->ListEntry
,
978 &NewPartEntry
->ListEntry
);
981 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
982 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
985 Entry
= Entry
->Flink
;
988 /* Check for trailing unpartitioned disk space */
989 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
991 LastUnusedSectorCount
= AlignDown(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
993 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
995 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
997 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
1000 if (NewPartEntry
== NULL
)
1003 NewPartEntry
->DiskEntry
= DiskEntry
;
1004 NewPartEntry
->LogicalPartition
= TRUE
;
1006 NewPartEntry
->IsPartitioned
= FALSE
;
1007 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
1008 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
1009 NewPartEntry
->StartSector
.QuadPart
;
1011 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
1012 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
1013 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
1015 NewPartEntry
->FormatState
= Unformatted
;
1017 /* Append the table to the list */
1018 InsertTailList(&DiskEntry
->LogicalPartListHead
,
1019 &NewPartEntry
->ListEntry
);
1024 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1032 IN PDISKENTRY DiskEntry
)
1034 LARGE_INTEGER SystemTime
;
1035 TIME_FIELDS TimeFields
;
1037 PDISKENTRY DiskEntry2
;
1040 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
1044 NtQuerySystemTime(&SystemTime
);
1045 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
1047 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
1048 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
1049 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
1050 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
1052 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
1057 /* check if the signature already exist */
1059 * Check also signatures from disks, which are
1060 * not visible (bootable) by the bios.
1062 Entry2
= List
->DiskListHead
.Flink
;
1063 while (Entry2
!= &List
->DiskListHead
)
1065 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
1067 if (DiskEntry
!= DiskEntry2
&&
1068 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
1071 Entry2
= Entry2
->Flink
;
1074 if (Entry2
== &List
->DiskListHead
)
1082 UpdateDiskSignatures(
1086 PDISKENTRY DiskEntry
;
1088 /* Print partition lines*/
1089 Entry
= List
->DiskListHead
.Flink
;
1090 while (Entry
!= &List
->DiskListHead
)
1092 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1094 if (DiskEntry
->LayoutBuffer
&&
1095 DiskEntry
->LayoutBuffer
->Signature
== 0)
1097 SetDiskSignature(List
, DiskEntry
);
1098 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
1101 Entry
= Entry
->Flink
;
1113 DISK_GEOMETRY DiskGeometry
;
1114 SCSI_ADDRESS ScsiAddress
;
1115 PDISKENTRY DiskEntry
;
1116 IO_STATUS_BLOCK Iosb
;
1118 PPARTITION_SECTOR Mbr
;
1120 LARGE_INTEGER FileOffset
;
1121 WCHAR Identifier
[20];
1125 PLIST_ENTRY ListEntry
;
1126 PBIOSDISKENTRY BiosDiskEntry
;
1127 ULONG LayoutBufferSize
;
1128 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
1130 Status
= NtDeviceIoControlFile(FileHandle
,
1135 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1139 sizeof(DISK_GEOMETRY
));
1140 if (!NT_SUCCESS(Status
))
1145 if (DiskGeometry
.MediaType
!= FixedMedia
&&
1146 DiskGeometry
.MediaType
!= RemovableMedia
)
1151 Status
= NtDeviceIoControlFile(FileHandle
,
1156 IOCTL_SCSI_GET_ADDRESS
,
1160 sizeof(SCSI_ADDRESS
));
1161 if (!NT_SUCCESS(Status
))
1166 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1168 DiskGeometry
.BytesPerSector
);
1174 FileOffset
.QuadPart
= 0;
1175 Status
= NtReadFile(FileHandle
,
1181 DiskGeometry
.BytesPerSector
,
1184 if (!NT_SUCCESS(Status
))
1186 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1187 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1190 Signature
= Mbr
->Signature
;
1192 /* Calculate the MBR checksum */
1194 Buffer
= (PULONG
)Mbr
;
1195 for (i
= 0; i
< 128; i
++)
1197 Checksum
+= Buffer
[i
];
1199 Checksum
= ~Checksum
+ 1;
1201 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1202 DPRINT("Identifier: %S\n", Identifier
);
1204 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1207 if (DiskEntry
== NULL
)
1212 // DiskEntry->Checksum = Checksum;
1213 // DiskEntry->Signature = Signature;
1214 DiskEntry
->BiosFound
= FALSE
;
1216 /* Check if this disk has a valid MBR */
1217 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1218 DiskEntry
->NoMbr
= TRUE
;
1220 DiskEntry
->NoMbr
= FALSE
;
1222 /* Free Mbr sector buffer */
1223 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1225 ListEntry
= List
->BiosDiskListHead
.Flink
;
1226 while (ListEntry
!= &List
->BiosDiskListHead
)
1228 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1230 * Compare the size from bios and the reported size from driver.
1231 * If we have more than one disk with a zero or with the same signatur
1232 * we must create new signatures and reboot. After the reboot,
1233 * it is possible to identify the disks.
1235 if (BiosDiskEntry
->Signature
== Signature
&&
1236 BiosDiskEntry
->Checksum
== Checksum
&&
1237 !BiosDiskEntry
->Recognized
)
1239 if (!DiskEntry
->BiosFound
)
1241 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1242 DiskEntry
->BiosFound
= TRUE
;
1243 BiosDiskEntry
->Recognized
= TRUE
;
1249 ListEntry
= ListEntry
->Flink
;
1252 if (!DiskEntry
->BiosFound
)
1255 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1258 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1262 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1263 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1265 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1266 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1267 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1268 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1270 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1271 DPRINT("TracksPerCylinder %lu\n", DiskEntry
->TracksPerCylinder
);
1272 DPRINT("SectorsPerTrack %lu\n", DiskEntry
->SectorsPerTrack
);
1273 DPRINT("BytesPerSector %lu\n", DiskEntry
->BytesPerSector
);
1275 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1276 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1277 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1279 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1280 DiskEntry
->CylinderAlignment
= DiskGeometry
.TracksPerCylinder
*
1281 DiskGeometry
.SectorsPerTrack
;
1283 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
.QuadPart
);
1284 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1286 DiskEntry
->DiskNumber
= DiskNumber
;
1287 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1288 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1289 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1291 GetDriverName(DiskEntry
);
1293 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1295 /* Allocate a layout buffer with 4 partition entries first */
1296 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1297 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1298 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1301 if (DiskEntry
->LayoutBuffer
== NULL
)
1303 DPRINT1("Failed to allocate the disk layout buffer!\n");
1309 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1310 Status
= NtDeviceIoControlFile(FileHandle
,
1315 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1318 DiskEntry
->LayoutBuffer
,
1320 if (NT_SUCCESS(Status
))
1323 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1325 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1329 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1330 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1332 DiskEntry
->LayoutBuffer
,
1334 if (NewLayoutBuffer
== NULL
)
1336 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1340 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1343 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1345 #ifdef DUMP_PARTITION_TABLE
1346 DumpPartitionTable(DiskEntry
);
1349 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1350 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1351 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1353 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1355 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1357 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1359 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1363 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1368 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1372 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1374 DiskEntry
->NewDisk
= TRUE
;
1375 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1377 for (i
= 0; i
< 4; i
++)
1378 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1382 for (i
= 0; i
< 4; i
++)
1384 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, FALSE
);
1387 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1389 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, TRUE
);
1393 ScanForUnpartitionedDiskSpace(DiskEntry
);
1398 CreatePartitionList(
1405 OBJECT_ATTRIBUTES ObjectAttributes
;
1406 SYSTEM_DEVICE_INFORMATION Sdi
;
1407 IO_STATUS_BLOCK Iosb
;
1411 WCHAR Buffer
[MAX_PATH
];
1412 UNICODE_STRING Name
;
1415 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1423 List
->Right
= Right
;
1424 List
->Bottom
= Bottom
;
1429 List
->CurrentDisk
= NULL
;
1430 List
->CurrentPartition
= NULL
;
1432 List
->SystemDisk
= NULL
;
1433 List
->SystemPartition
= NULL
;
1434 List
->OriginalSystemDisk
= NULL
;
1435 List
->OriginalSystemPartition
= NULL
;
1437 List
->TempDisk
= NULL
;
1438 List
->TempPartition
= NULL
;
1439 List
->FormatState
= Start
;
1441 InitializeListHead(&List
->DiskListHead
);
1442 InitializeListHead(&List
->BiosDiskListHead
);
1444 EnumerateBiosDiskEntries(List
);
1446 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1448 sizeof(SYSTEM_DEVICE_INFORMATION
),
1450 if (!NT_SUCCESS(Status
))
1452 RtlFreeHeap(ProcessHeap
, 0, List
);
1456 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1459 L
"\\Device\\Harddisk%d\\Partition0",
1461 RtlInitUnicodeString(&Name
,
1464 InitializeObjectAttributes(&ObjectAttributes
,
1470 Status
= NtOpenFile(&FileHandle
,
1471 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1475 FILE_SYNCHRONOUS_IO_NONALERT
);
1476 if (NT_SUCCESS(Status
))
1478 AddDiskToList(FileHandle
, DiskNumber
, List
);
1480 NtClose(FileHandle
);
1484 UpdateDiskSignatures(List
);
1486 AssignDriveLetters(List
);
1488 /* Search for first usable disk and partition */
1489 if (IsListEmpty(&List
->DiskListHead
))
1491 List
->CurrentDisk
= NULL
;
1492 List
->CurrentPartition
= NULL
;
1496 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1500 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1502 List
->CurrentPartition
= 0;
1506 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1517 DestroyPartitionList(
1520 PDISKENTRY DiskEntry
;
1521 PBIOSDISKENTRY BiosDiskEntry
;
1522 PPARTENTRY PartEntry
;
1525 /* Release disk and partition info */
1526 while (!IsListEmpty(&List
->DiskListHead
))
1528 Entry
= RemoveHeadList(&List
->DiskListHead
);
1529 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1531 /* Release driver name */
1532 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1534 /* Release primary partition list */
1535 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1537 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1538 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1540 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1543 /* Release logical partition list */
1544 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1546 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1547 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1549 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1552 /* Release layout buffer */
1553 if (DiskEntry
->LayoutBuffer
!= NULL
)
1554 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1557 /* Release disk entry */
1558 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1561 /* Release the bios disk info */
1562 while (!IsListEmpty(&List
->BiosDiskListHead
))
1564 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1565 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1567 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1570 /* Release list head */
1571 RtlFreeHeap(ProcessHeap
, 0, List
);
1585 Width
= List
->Right
- List
->Left
- 1;
1586 Height
= List
->Bottom
- List
->Top
- 2;
1588 coPos
.X
= List
->Left
+ 1;
1589 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1591 if (List
->Line
>= 0 && List
->Line
<= Height
)
1593 FillConsoleOutputAttribute(StdOutput
,
1594 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1599 FillConsoleOutputCharacterA(StdOutput
,
1614 PDISKENTRY DiskEntry
,
1615 PPARTENTRY PartEntry
)
1617 CHAR LineBuffer
[128];
1622 LARGE_INTEGER PartSize
;
1625 CHAR PartTypeString
[32];
1627 PartType
= PartTypeString
;
1629 Width
= List
->Right
- List
->Left
- 1;
1630 Height
= List
->Bottom
- List
->Top
- 2;
1632 coPos
.X
= List
->Left
+ 1;
1633 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1635 if (PartEntry
->IsPartitioned
== FALSE
)
1637 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1639 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1641 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1642 Unit
= MUIGetString(STRING_GB
);
1646 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1648 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1649 Unit
= MUIGetString(STRING_MB
);
1653 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1654 Unit
= MUIGetString(STRING_KB
);
1658 MUIGetString(STRING_UNPSPACE
),
1659 PartEntry
->LogicalPartition
? " " : "",
1660 PartEntry
->LogicalPartition
? "" : " ",
1666 /* Determine partition type */
1667 PartTypeString
[0] = '\0';
1668 if (PartEntry
->New
!= FALSE
)
1670 PartType
= MUIGetString(STRING_UNFORMATTED
);
1672 else if (PartEntry
->IsPartitioned
!= FALSE
)
1674 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
1676 ARRAYSIZE(PartTypeString
));
1677 PartType
= PartTypeString
;
1680 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1682 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1684 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1685 Unit
= MUIGetString(STRING_GB
);
1689 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1691 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1692 Unit
= MUIGetString(STRING_MB
);
1696 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1697 Unit
= MUIGetString(STRING_KB
);
1700 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
1703 MUIGetString(STRING_HDDINFOUNK5
),
1704 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1705 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1706 PartEntry
->BootIndicator
? '*' : ' ',
1707 PartEntry
->LogicalPartition
? " " : "",
1708 PartEntry
->PartitionType
,
1709 PartEntry
->LogicalPartition
? "" : " ",
1716 "%c%c %c %s%-24s%s %6lu %s",
1717 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1718 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1719 PartEntry
->BootIndicator
? '*' : ' ',
1720 PartEntry
->LogicalPartition
? " " : "",
1722 PartEntry
->LogicalPartition
? "" : " ",
1728 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1729 List
->CurrentPartition
== PartEntry
) ?
1730 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1731 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1733 if (List
->Line
>= 0 && List
->Line
<= Height
)
1735 FillConsoleOutputCharacterA(StdOutput
,
1743 if (List
->Line
>= 0 && List
->Line
<= Height
)
1745 FillConsoleOutputAttribute(StdOutput
,
1753 if (List
->Line
>= 0 && List
->Line
<= Height
)
1755 WriteConsoleOutputCharacterA(StdOutput
,
1757 min(strlen(LineBuffer
), Width
),
1770 PDISKENTRY DiskEntry
)
1772 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1773 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1774 CHAR LineBuffer
[128];
1779 ULARGE_INTEGER DiskSize
;
1782 Width
= List
->Right
- List
->Left
- 1;
1783 Height
= List
->Bottom
- List
->Top
- 2;
1785 coPos
.X
= List
->Left
+ 1;
1786 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1788 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1789 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1791 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1792 Unit
= MUIGetString(STRING_GB
);
1796 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1797 if (DiskSize
.QuadPart
== 0)
1798 DiskSize
.QuadPart
= 1;
1799 Unit
= MUIGetString(STRING_MB
);
1802 if (DiskEntry
->DriverName
.Length
> 0)
1805 MUIGetString(STRING_HDINFOPARTSELECT
),
1808 DiskEntry
->DiskNumber
,
1812 DiskEntry
->DriverName
.Buffer
);
1817 MUIGetString(STRING_HDDINFOUNK6
),
1820 DiskEntry
->DiskNumber
,
1826 if (List
->Line
>= 0 && List
->Line
<= Height
)
1828 FillConsoleOutputAttribute(StdOutput
,
1829 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1834 FillConsoleOutputCharacterA(StdOutput
,
1842 if (List
->Line
>= 0 && List
->Line
<= Height
)
1844 WriteConsoleOutputCharacterA(StdOutput
,
1846 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1853 /* Print separator line */
1854 PrintEmptyLine(List
);
1856 /* Print partition lines */
1857 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1858 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1860 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1862 PrintPartitionData(List
,
1866 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1868 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1869 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1871 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1873 PrintPartitionData(List
,
1877 LogicalEntry
= LogicalEntry
->Flink
;
1881 PrimaryEntry
= PrimaryEntry
->Flink
;
1884 /* Print separator line */
1885 PrintEmptyLine(List
);
1893 PLIST_ENTRY Entry
, Entry2
;
1894 PDISKENTRY DiskEntry
;
1895 PPARTENTRY PartEntry
= NULL
;
1899 SHORT CurrentDiskLine
;
1900 SHORT CurrentPartLine
;
1902 BOOL CurrentPartLineFound
= FALSE
;
1903 BOOL CurrentDiskLineFound
= FALSE
;
1905 /* Calculate the line of the current disk and partition */
1906 CurrentDiskLine
= 0;
1907 CurrentPartLine
= 0;
1910 Entry
= List
->DiskListHead
.Flink
;
1911 while (Entry
!= &List
->DiskListHead
)
1913 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1916 if (CurrentPartLineFound
== FALSE
)
1918 CurrentPartLine
+= 2;
1921 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1922 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1924 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1925 if (PartEntry
== List
->CurrentPartition
)
1927 CurrentPartLineFound
= TRUE
;
1930 Entry2
= Entry2
->Flink
;
1931 if (CurrentPartLineFound
== FALSE
)
1939 if (CurrentPartLineFound
== FALSE
)
1941 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
1942 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
1944 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1945 if (PartEntry
== List
->CurrentPartition
)
1947 CurrentPartLineFound
= TRUE
;
1950 Entry2
= Entry2
->Flink
;
1951 if (CurrentPartLineFound
== FALSE
)
1960 if (DiskEntry
== List
->CurrentDisk
)
1962 CurrentDiskLineFound
= TRUE
;
1965 Entry
= Entry
->Flink
;
1966 if (Entry
!= &List
->DiskListHead
)
1968 if (CurrentDiskLineFound
== FALSE
)
1971 CurrentDiskLine
= CurrentPartLine
;
1982 /* If it possible, make the disk name visible */
1983 if (CurrentPartLine
< List
->Offset
)
1985 List
->Offset
= CurrentPartLine
;
1987 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1989 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1992 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1994 List
->Offset
= CurrentDiskLine
;
1997 /* draw upper left corner */
1998 coPos
.X
= List
->Left
;
1999 coPos
.Y
= List
->Top
;
2000 FillConsoleOutputCharacterA(StdOutput
,
2006 /* draw upper edge */
2007 coPos
.X
= List
->Left
+ 1;
2008 coPos
.Y
= List
->Top
;
2009 if (List
->Offset
== 0)
2011 FillConsoleOutputCharacterA(StdOutput
,
2013 List
->Right
- List
->Left
- 1,
2019 FillConsoleOutputCharacterA(StdOutput
,
2021 List
->Right
- List
->Left
- 5,
2024 coPos
.X
= List
->Right
- 5;
2025 WriteConsoleOutputCharacterA(StdOutput
,
2030 coPos
.X
= List
->Right
- 2;
2031 FillConsoleOutputCharacterA(StdOutput
,
2038 /* draw upper right corner */
2039 coPos
.X
= List
->Right
;
2040 coPos
.Y
= List
->Top
;
2041 FillConsoleOutputCharacterA(StdOutput
,
2047 /* draw left and right edge */
2048 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
2050 coPos
.X
= List
->Left
;
2052 FillConsoleOutputCharacterA(StdOutput
,
2058 coPos
.X
= List
->Right
;
2059 FillConsoleOutputCharacterA(StdOutput
,
2066 /* draw lower left corner */
2067 coPos
.X
= List
->Left
;
2068 coPos
.Y
= List
->Bottom
;
2069 FillConsoleOutputCharacterA(StdOutput
,
2075 /* draw lower edge */
2076 coPos
.X
= List
->Left
+ 1;
2077 coPos
.Y
= List
->Bottom
;
2078 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
2080 FillConsoleOutputCharacterA(StdOutput
,
2082 List
->Right
- List
->Left
- 1,
2088 FillConsoleOutputCharacterA(StdOutput
,
2090 List
->Right
- List
->Left
- 5,
2093 coPos
.X
= List
->Right
- 5;
2094 WriteConsoleOutputCharacterA(StdOutput
,
2095 "(\x19)", // "(down)"
2099 coPos
.X
= List
->Right
- 2;
2100 FillConsoleOutputCharacterA(StdOutput
,
2107 /* draw lower right corner */
2108 coPos
.X
= List
->Right
;
2109 coPos
.Y
= List
->Bottom
;
2110 FillConsoleOutputCharacterA(StdOutput
,
2116 /* print list entries */
2117 List
->Line
= - List
->Offset
;
2119 Entry
= List
->DiskListHead
.Flink
;
2120 while (Entry
!= &List
->DiskListHead
)
2122 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2124 /* Print disk entry */
2128 Entry
= Entry
->Flink
;
2137 ULONG PartitionNumber
)
2139 PDISKENTRY DiskEntry
;
2140 PPARTENTRY PartEntry
;
2144 /* Check for empty disks */
2145 if (IsListEmpty(&List
->DiskListHead
))
2148 /* Check for first usable entry on next disk */
2149 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
2150 while (Entry1
!= &List
->DiskListHead
)
2152 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
2154 if (DiskEntry
->DiskNumber
== DiskNumber
)
2156 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2157 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2159 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2161 if (PartEntry
->PartitionNumber
== PartitionNumber
)
2163 List
->CurrentDisk
= DiskEntry
;
2164 List
->CurrentPartition
= PartEntry
;
2165 DrawPartitionList(List
);
2169 Entry2
= Entry2
->Flink
;
2175 Entry1
= Entry1
->Flink
;
2183 ScrollDownPartitionList(
2186 PLIST_ENTRY DiskListEntry
;
2187 PLIST_ENTRY PartListEntry
;
2188 PDISKENTRY DiskEntry
;
2189 PPARTENTRY PartEntry
;
2191 /* Fail, if no disks are available */
2192 if (IsListEmpty(&List
->DiskListHead
))
2195 /* Check for next usable entry on current disk */
2196 if (List
->CurrentPartition
!= NULL
)
2198 if (List
->CurrentPartition
->LogicalPartition
)
2200 /* Logical partition */
2202 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2203 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2205 /* Next logical partition */
2206 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2208 List
->CurrentPartition
= PartEntry
;
2213 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2214 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2216 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2218 List
->CurrentPartition
= PartEntry
;
2225 /* Primary or extended partition */
2227 if ((List
->CurrentPartition
->IsPartitioned
!= FALSE
) &&
2228 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2230 /* First logical partition */
2231 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2232 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2234 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2236 List
->CurrentPartition
= PartEntry
;
2242 /* Next primary partition */
2243 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2244 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2246 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2248 List
->CurrentPartition
= PartEntry
;
2255 /* Search for the first partition entry on the next disk */
2256 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2257 while (DiskListEntry
!= &List
->DiskListHead
)
2259 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2261 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2262 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2264 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2266 List
->CurrentDisk
= DiskEntry
;
2267 List
->CurrentPartition
= PartEntry
;
2271 DiskListEntry
= DiskListEntry
->Flink
;
2279 ScrollUpPartitionList(
2282 PLIST_ENTRY DiskListEntry
;
2283 PLIST_ENTRY PartListEntry
;
2284 PDISKENTRY DiskEntry
;
2285 PPARTENTRY PartEntry
;
2287 /* Fail, if no disks are available */
2288 if (IsListEmpty(&List
->DiskListHead
))
2291 /* Check for previous usable entry on current disk */
2292 if (List
->CurrentPartition
!= NULL
)
2294 if (List
->CurrentPartition
->LogicalPartition
)
2296 /* Logical partition */
2297 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2298 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2300 /* Previous logical partition */
2301 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2305 /* Extended partition*/
2306 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2309 List
->CurrentPartition
= PartEntry
;
2314 /* Primary or extended partition */
2316 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2317 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2319 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2321 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
2322 IsContainerPartition(PartEntry
->PartitionType
))
2324 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2325 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2328 List
->CurrentPartition
= PartEntry
;
2335 /* Search for the last partition entry on the previous disk */
2336 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2337 while (DiskListEntry
!= &List
->DiskListHead
)
2339 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2341 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2342 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2344 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2346 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
2347 IsContainerPartition(PartEntry
->PartitionType
))
2349 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2350 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2352 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2354 List
->CurrentDisk
= DiskEntry
;
2355 List
->CurrentPartition
= PartEntry
;
2361 List
->CurrentDisk
= DiskEntry
;
2362 List
->CurrentPartition
= PartEntry
;
2367 DiskListEntry
= DiskListEntry
->Blink
;
2377 PPARTITION_INFORMATION PartitionInfo
)
2379 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2380 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2389 IsSamePrimaryLayoutEntry(
2390 IN PPARTITION_INFORMATION PartitionInfo
,
2391 IN PDISKENTRY DiskEntry
,
2392 IN PPARTENTRY PartEntry
)
2394 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2395 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2396 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2397 // PartitionInfo->PartitionType == PartEntry->PartitionType
2406 GetPrimaryPartitionCount(
2407 IN PDISKENTRY DiskEntry
)
2410 PPARTENTRY PartEntry
;
2413 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2414 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2416 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2417 if (PartEntry
->IsPartitioned
== TRUE
)
2420 Entry
= Entry
->Flink
;
2429 GetLogicalPartitionCount(
2430 PDISKENTRY DiskEntry
)
2432 PLIST_ENTRY ListEntry
;
2433 PPARTENTRY PartEntry
;
2436 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2437 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2439 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2440 if (PartEntry
->IsPartitioned
)
2443 ListEntry
= ListEntry
->Flink
;
2452 ReAllocateLayoutBuffer(
2453 PDISKENTRY DiskEntry
)
2455 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
2456 ULONG NewPartitionCount
;
2457 ULONG CurrentPartitionCount
= 0;
2458 ULONG LayoutBufferSize
;
2461 DPRINT1("ReAllocateLayoutBuffer()\n");
2463 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
2465 if (DiskEntry
->LayoutBuffer
)
2466 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
2468 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2469 CurrentPartitionCount
, NewPartitionCount
);
2471 if (CurrentPartitionCount
== NewPartitionCount
)
2474 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2475 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
2476 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
2478 DiskEntry
->LayoutBuffer
,
2480 if (NewLayoutBuffer
== NULL
)
2482 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
2486 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2487 if (NewPartitionCount
> CurrentPartitionCount
)
2489 for (i
= CurrentPartitionCount
; i
< NewPartitionCount
; i
++)
2490 NewLayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
2493 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
2494 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
2503 IN PDISKENTRY DiskEntry
)
2505 PPARTITION_INFORMATION PartitionInfo
;
2506 PPARTITION_INFORMATION LinkInfo
= NULL
;
2507 PLIST_ENTRY ListEntry
;
2508 PPARTENTRY PartEntry
;
2509 LARGE_INTEGER HiddenSectors64
;
2511 ULONG PartitionNumber
= 1;
2513 DPRINT1("UpdateDiskLayout()\n");
2515 /* Resize the layout buffer if necessary */
2516 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
2518 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2522 /* Update the primary partition table */
2524 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2525 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2527 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2529 if (PartEntry
->IsPartitioned
!= FALSE
)
2531 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2533 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2535 DPRINT1("Updating primary partition entry %lu\n", Index
);
2537 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2538 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2539 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
2540 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2541 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2542 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2543 PartitionInfo
->RecognizedPartition
= FALSE
;
2544 PartitionInfo
->RewritePartition
= TRUE
;
2547 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2548 PartEntry
->PartitionIndex
= Index
;
2550 if (!IsContainerPartition(PartEntry
->PartitionType
))
2556 ListEntry
= ListEntry
->Flink
;
2559 /* Update the logical partition tables */
2561 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2562 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2564 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2566 if (PartEntry
->IsPartitioned
)
2568 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2570 DPRINT1("Updating logical partition entry %lu\n", Index
);
2572 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2573 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2574 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
2575 PartitionInfo
->PartitionNumber
= PartitionNumber
;
2576 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2577 PartitionInfo
->BootIndicator
= FALSE
;
2578 PartitionInfo
->RecognizedPartition
= FALSE
;
2579 PartitionInfo
->RewritePartition
= TRUE
;
2581 PartEntry
->PartitionNumber
= PartitionNumber
;
2582 PartEntry
->PartitionIndex
= Index
;
2584 /* Fill the link entry of the previous partition table */
2585 if (LinkInfo
!= NULL
)
2587 LinkInfo
->StartingOffset
.QuadPart
= (PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2588 LinkInfo
->PartitionLength
.QuadPart
= (PartEntry
->StartSector
.QuadPart
+ DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2589 HiddenSectors64
.QuadPart
= PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
- DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
;
2590 LinkInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
2591 LinkInfo
->PartitionNumber
= 0;
2592 LinkInfo
->PartitionType
= PARTITION_EXTENDED
;
2593 LinkInfo
->BootIndicator
= FALSE
;
2594 LinkInfo
->RecognizedPartition
= FALSE
;
2595 LinkInfo
->RewritePartition
= TRUE
;
2598 /* Save a pointer to the link entry of the current partition table */
2599 LinkInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
+ 1];
2605 ListEntry
= ListEntry
->Flink
;
2608 /* Wipe unused primary partition table entries */
2609 for (Index
= GetPrimaryPartitionCount(DiskEntry
); Index
< 4; Index
++)
2611 DPRINT1("Primary partition entry %lu\n", Index
);
2613 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2615 if (!IsEmptyLayoutEntry(PartitionInfo
))
2617 DPRINT1("Wiping primary partition entry %lu\n", Index
);
2619 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2620 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2621 PartitionInfo
->HiddenSectors
= 0;
2622 PartitionInfo
->PartitionNumber
= 0;
2623 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2624 PartitionInfo
->BootIndicator
= FALSE
;
2625 PartitionInfo
->RecognizedPartition
= FALSE
;
2626 PartitionInfo
->RewritePartition
= TRUE
;
2630 /* Wipe unused logical partition table entries */
2631 for (Index
= 4; Index
< DiskEntry
->LayoutBuffer
->PartitionCount
; Index
++)
2635 DPRINT1("Logical partition entry %lu\n", Index
);
2637 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2639 if (!IsEmptyLayoutEntry(PartitionInfo
))
2641 DPRINT1("Wiping partition entry %lu\n", Index
);
2643 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2644 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2645 PartitionInfo
->HiddenSectors
= 0;
2646 PartitionInfo
->PartitionNumber
= 0;
2647 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2648 PartitionInfo
->BootIndicator
= FALSE
;
2649 PartitionInfo
->RecognizedPartition
= FALSE
;
2650 PartitionInfo
->RewritePartition
= TRUE
;
2655 #ifdef DUMP_PARTITION_TABLE
2656 DumpPartitionTable(DiskEntry
);
2663 GetPrevUnpartitionedEntry(
2664 PDISKENTRY DiskEntry
,
2665 PPARTENTRY PartEntry
)
2667 PPARTENTRY PrevPartEntry
;
2668 PLIST_ENTRY ListHead
;
2670 if (PartEntry
->LogicalPartition
)
2671 ListHead
= &DiskEntry
->LogicalPartListHead
;
2673 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2675 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2677 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2680 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2681 return PrevPartEntry
;
2690 GetNextUnpartitionedEntry(
2691 PDISKENTRY DiskEntry
,
2692 PPARTENTRY PartEntry
)
2694 PPARTENTRY NextPartEntry
;
2695 PLIST_ENTRY ListHead
;
2697 if (PartEntry
->LogicalPartition
)
2698 ListHead
= &DiskEntry
->LogicalPartListHead
;
2700 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2702 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2704 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2707 if (NextPartEntry
->IsPartitioned
== FALSE
)
2708 return NextPartEntry
;
2716 CreatePrimaryPartition(
2718 ULONGLONG SectorCount
,
2721 PDISKENTRY DiskEntry
;
2722 PPARTENTRY PartEntry
;
2723 PPARTENTRY NewPartEntry
;
2725 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2728 List
->CurrentDisk
== NULL
||
2729 List
->CurrentPartition
== NULL
||
2730 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2735 DiskEntry
= List
->CurrentDisk
;
2736 PartEntry
= List
->CurrentPartition
;
2738 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2740 if ((AutoCreate
!= FALSE
) ||
2741 (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
))
2743 DPRINT1("Convert existing partition entry\n");
2745 /* Convert current entry to 'new (unformatted)' */
2746 PartEntry
->IsPartitioned
= TRUE
;
2747 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2748 PartEntry
->FormatState
= Unformatted
;
2749 PartEntry
->AutoCreate
= AutoCreate
;
2750 PartEntry
->New
= TRUE
;
2751 PartEntry
->BootIndicator
= FALSE
;
2753 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2754 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2755 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2759 DPRINT1("Add new partition entry\n");
2761 /* Insert and initialize a new partition entry */
2762 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2765 if (NewPartEntry
== NULL
)
2768 /* Insert the new entry into the list */
2769 InsertTailList(&PartEntry
->ListEntry
,
2770 &NewPartEntry
->ListEntry
);
2772 NewPartEntry
->DiskEntry
= DiskEntry
;
2774 NewPartEntry
->IsPartitioned
= TRUE
;
2775 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2776 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2777 NewPartEntry
->StartSector
.QuadPart
;
2778 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2780 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2781 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2782 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2784 NewPartEntry
->New
= TRUE
;
2785 NewPartEntry
->FormatState
= Unformatted
;
2786 NewPartEntry
->BootIndicator
= FALSE
;
2788 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2789 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2792 UpdateDiskLayout(DiskEntry
);
2794 DiskEntry
->Dirty
= TRUE
;
2796 AssignDriveLetters(List
);
2802 AddLogicalDiskSpace(
2803 PDISKENTRY DiskEntry
)
2805 PPARTENTRY NewPartEntry
;
2807 DPRINT1("AddLogicalDiskSpace()\n");
2809 /* Create a partition table entry that represents the empty space in the container partition */
2810 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2813 if (NewPartEntry
== NULL
)
2816 NewPartEntry
->DiskEntry
= DiskEntry
;
2817 NewPartEntry
->LogicalPartition
= TRUE
;
2819 NewPartEntry
->IsPartitioned
= FALSE
;
2820 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2821 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2823 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2824 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2825 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2827 NewPartEntry
->FormatState
= Unformatted
;
2829 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2830 &NewPartEntry
->ListEntry
);
2835 CreateExtendedPartition(
2837 ULONGLONG SectorCount
)
2839 PDISKENTRY DiskEntry
;
2840 PPARTENTRY PartEntry
;
2841 PPARTENTRY NewPartEntry
;
2843 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2846 List
->CurrentDisk
== NULL
||
2847 List
->CurrentPartition
== NULL
||
2848 (List
->CurrentPartition
->IsPartitioned
!= FALSE
))
2853 DiskEntry
= List
->CurrentDisk
;
2854 PartEntry
= List
->CurrentPartition
;
2856 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2858 if (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2860 DPRINT1("Convert existing partition entry\n");
2862 /* Convert current entry to 'new (unformatted)' */
2863 PartEntry
->IsPartitioned
= TRUE
;
2864 PartEntry
->FormatState
= Formatted
;
2865 PartEntry
->AutoCreate
= FALSE
;
2866 PartEntry
->New
= FALSE
;
2867 PartEntry
->BootIndicator
= FALSE
;
2869 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2871 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2872 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2876 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2877 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2880 DiskEntry
->ExtendedPartition
= PartEntry
;
2882 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2883 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2884 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2888 DPRINT1("Add new partition entry\n");
2890 /* Insert and initialize a new partition entry */
2891 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2894 if (NewPartEntry
== NULL
)
2897 /* Insert the new entry into the list */
2898 InsertTailList(&PartEntry
->ListEntry
,
2899 &NewPartEntry
->ListEntry
);
2901 NewPartEntry
->DiskEntry
= DiskEntry
;
2903 NewPartEntry
->IsPartitioned
= TRUE
;
2904 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2905 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2906 NewPartEntry
->StartSector
.QuadPart
;
2908 NewPartEntry
->New
= FALSE
;
2909 NewPartEntry
->FormatState
= Formatted
;
2910 NewPartEntry
->BootIndicator
= FALSE
;
2912 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2914 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2915 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2919 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2920 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2923 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2925 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2926 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2928 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2929 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2930 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2933 AddLogicalDiskSpace(DiskEntry
);
2935 UpdateDiskLayout(DiskEntry
);
2937 DiskEntry
->Dirty
= TRUE
;
2939 AssignDriveLetters(List
);
2944 CreateLogicalPartition(
2946 ULONGLONG SectorCount
,
2949 PDISKENTRY DiskEntry
;
2950 PPARTENTRY PartEntry
;
2951 PPARTENTRY NewPartEntry
;
2953 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2956 List
->CurrentDisk
== NULL
||
2957 List
->CurrentPartition
== NULL
||
2958 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2963 DiskEntry
= List
->CurrentDisk
;
2964 PartEntry
= List
->CurrentPartition
;
2966 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2968 if (AutoCreate
== TRUE
||
2969 AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2971 DPRINT1("Convert existing partition entry\n");
2973 /* Convert current entry to 'new (unformatted)' */
2974 PartEntry
->IsPartitioned
= TRUE
;
2975 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2976 PartEntry
->FormatState
= Unformatted
;
2977 PartEntry
->AutoCreate
= FALSE
;
2978 PartEntry
->New
= TRUE
;
2979 PartEntry
->BootIndicator
= FALSE
;
2980 PartEntry
->LogicalPartition
= TRUE
;
2982 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2983 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2984 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2988 DPRINT1("Add new partition entry\n");
2990 /* Insert and initialize a new partition entry */
2991 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2994 if (NewPartEntry
== NULL
)
2997 /* Insert the new entry into the list */
2998 InsertTailList(&PartEntry
->ListEntry
,
2999 &NewPartEntry
->ListEntry
);
3001 NewPartEntry
->DiskEntry
= DiskEntry
;
3003 NewPartEntry
->IsPartitioned
= TRUE
;
3004 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
3005 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
3006 NewPartEntry
->StartSector
.QuadPart
;
3007 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
3009 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
3010 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
3011 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
3013 NewPartEntry
->New
= TRUE
;
3014 NewPartEntry
->FormatState
= Unformatted
;
3015 NewPartEntry
->BootIndicator
= FALSE
;
3016 NewPartEntry
->LogicalPartition
= TRUE
;
3018 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
3019 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
3022 UpdateDiskLayout(DiskEntry
);
3024 DiskEntry
->Dirty
= TRUE
;
3026 AssignDriveLetters(List
);
3031 DeleteCurrentPartition(
3034 PDISKENTRY DiskEntry
;
3035 PPARTENTRY PartEntry
;
3036 PPARTENTRY PrevPartEntry
;
3037 PPARTENTRY NextPartEntry
;
3038 PPARTENTRY LogicalPartEntry
;
3042 List
->CurrentDisk
== NULL
||
3043 List
->CurrentPartition
== NULL
||
3044 List
->CurrentPartition
->IsPartitioned
== FALSE
)
3049 /* Clear the system disk and partition pointers if the system partition will be deleted */
3050 if (List
->SystemPartition
== List
->CurrentPartition
)
3052 List
->SystemDisk
= NULL
;
3053 List
->SystemPartition
= NULL
;
3056 DiskEntry
= List
->CurrentDisk
;
3057 PartEntry
= List
->CurrentPartition
;
3059 /* Delete all logical partition entries if an extended partition will be deleted */
3060 if (DiskEntry
->ExtendedPartition
== PartEntry
)
3062 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
3064 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
3065 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3067 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
3070 DiskEntry
->ExtendedPartition
= NULL
;
3073 /* Adjust unpartitioned disk space entries */
3075 /* Get pointer to previous and next unpartitioned entries */
3076 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
, PartEntry
);
3077 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
, PartEntry
);
3079 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
3081 /* Merge previous, current and next unpartitioned entry */
3083 /* Adjust the previous entries length */
3084 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
3086 /* Remove the current entry */
3087 RemoveEntryList(&PartEntry
->ListEntry
);
3088 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3090 /* Remove the next entry */
3091 RemoveEntryList (&NextPartEntry
->ListEntry
);
3092 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
3094 /* Update current partition */
3095 List
->CurrentPartition
= PrevPartEntry
;
3097 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
3099 /* Merge current and previous unpartitioned entry */
3101 /* Adjust the previous entries length */
3102 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
3104 /* Remove the current entry */
3105 RemoveEntryList(&PartEntry
->ListEntry
);
3106 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3108 /* Update current partition */
3109 List
->CurrentPartition
= PrevPartEntry
;
3111 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
3113 /* Merge current and next unpartitioned entry */
3115 /* Adjust the next entries offset and length */
3116 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
3117 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
3119 /* Remove the current entry */
3120 RemoveEntryList(&PartEntry
->ListEntry
);
3121 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
3123 /* Update current partition */
3124 List
->CurrentPartition
= NextPartEntry
;
3128 /* Nothing to merge but change current entry */
3129 PartEntry
->IsPartitioned
= FALSE
;
3130 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
3131 PartEntry
->FormatState
= Unformatted
;
3132 PartEntry
->DriveLetter
= 0;
3135 UpdateDiskLayout(DiskEntry
);
3137 DiskEntry
->Dirty
= TRUE
;
3139 AssignDriveLetters(List
);
3144 CheckActiveSystemPartition(
3146 IN PFILE_SYSTEM_LIST FileSystemList
/* Needed for checking the FS of the candidate system partition */
3149 PDISKENTRY DiskEntry
;
3150 PPARTENTRY PartEntry
;
3151 PLIST_ENTRY ListEntry
;
3153 PFILE_SYSTEM_ITEM FileSystem
;
3155 /* Check for empty disk list */
3156 if (IsListEmpty(&List
->DiskListHead
))
3158 List
->SystemDisk
= NULL
;
3159 List
->SystemPartition
= NULL
;
3160 List
->OriginalSystemDisk
= NULL
;
3161 List
->OriginalSystemPartition
= NULL
;
3165 /* Choose the currently selected disk */
3166 DiskEntry
= List
->CurrentDisk
;
3168 /* Check for empty partition list */
3169 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
3171 List
->SystemDisk
= NULL
;
3172 List
->SystemPartition
= NULL
;
3173 List
->OriginalSystemDisk
= NULL
;
3174 List
->OriginalSystemPartition
= NULL
;
3178 if (List
->SystemDisk
!= NULL
&& List
->SystemPartition
!= NULL
)
3180 /* We already have an active system partition */
3181 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
3182 List
->SystemPartition
->PartitionNumber
,
3183 List
->SystemDisk
->DiskNumber
,
3184 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3188 DPRINT1("We are here (1)!\n");
3190 List
->SystemDisk
= NULL
;
3191 List
->SystemPartition
= NULL
;
3192 List
->OriginalSystemDisk
= NULL
;
3193 List
->OriginalSystemPartition
= NULL
;
3195 /* Retrieve the first partition of the disk */
3196 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
3199 List
->SystemDisk
= DiskEntry
;
3200 List
->SystemPartition
= PartEntry
;
3203 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
3206 /* Check if the disk is new and if so, use its first partition as the active system partition */
3207 if (DiskEntry
->NewDisk
)
3209 if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
== FALSE
)
3211 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3212 List
->SystemDisk
= DiskEntry
;
3213 List
->SystemPartition
= PartEntry
;
3215 List
->OriginalSystemDisk
= List
->SystemDisk
;
3216 List
->OriginalSystemPartition
= List
->SystemPartition
;
3218 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
3219 List
->SystemPartition
->PartitionNumber
,
3220 List
->SystemDisk
->DiskNumber
,
3221 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3223 goto SetSystemPartition
;
3226 // FIXME: What to do??
3227 DPRINT1("NewDisk TRUE but first partition is used?\n");
3230 DPRINT1("We are here (2)!\n");
3233 * The disk is not new, check if any partition is initialized;
3234 * if not, the first one becomes the system partition.
3236 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3237 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
3239 /* Retrieve the partition and go to the next one */
3240 PartEntry
= CONTAINING_RECORD(ListEntry
,
3244 /* Check if the partition is partitioned and is used */
3245 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
!= FALSE
)
3250 /* Go to the next one */
3251 ListEntry
= ListEntry
->Flink
;
3253 if (ListEntry
== &DiskEntry
->PrimaryPartListHead
)
3256 * OK we haven't encountered any used and active partition,
3257 * so use the first one as the system partition.
3260 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3261 List
->OriginalSystemDisk
= List
->SystemDisk
; // DiskEntry
3262 List
->OriginalSystemPartition
= List
->SystemPartition
; // First PartEntry
3264 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
3265 List
->SystemPartition
->PartitionNumber
,
3266 List
->SystemDisk
->DiskNumber
,
3267 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3269 goto SetSystemPartition
;
3272 List
->SystemDisk
= NULL
;
3273 List
->SystemPartition
= NULL
;
3274 List
->OriginalSystemDisk
= NULL
;
3275 List
->OriginalSystemPartition
= NULL
;
3277 DPRINT1("We are here (3)!\n");
3279 /* The disk is not new, scan all partitions to find the (active) system partition */
3280 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3281 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
3283 /* Retrieve the partition and go to the next one */
3284 PartEntry
= CONTAINING_RECORD(ListEntry
,
3287 ListEntry
= ListEntry
->Flink
;
3289 /* Check if the partition is partitioned and used */
3290 if (PartEntry
->IsPartitioned
&&
3291 PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
)
3293 /* Check if the partition is active */
3294 if (PartEntry
->BootIndicator
)
3296 /* Yes, we found it */
3297 List
->SystemDisk
= DiskEntry
;
3298 List
->SystemPartition
= PartEntry
;
3300 DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
3301 PartEntry
->PartitionNumber
,
3302 DiskEntry
->DiskNumber
,
3303 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
);
3309 /* Check if we have found the system partition */
3310 if (List
->SystemDisk
== NULL
|| List
->SystemPartition
== NULL
)
3312 /* Nothing, use the alternative system partition */
3313 DPRINT1("No system partition found, use the alternative partition!\n");
3314 goto UseAlternativeSystemPartition
;
3318 List
->OriginalSystemDisk
= List
->SystemDisk
;
3319 List
->OriginalSystemPartition
= List
->SystemPartition
;
3322 * ADDITIONAL CHECKS / BIG HACK:
3324 * Retrieve its file system and check whether we have
3325 * write support for it. If that is the case we are fine
3326 * and we can use it directly. However if we don't have
3327 * write support we will need to change the active system
3330 * NOTE that this is completely useless on architectures
3331 * where a real system partition is required, as on these
3332 * architectures the partition uses the FAT FS, for which
3333 * we do have write support.
3334 * NOTE also that for those architectures looking for a
3335 * partition boot indicator is insufficient.
3337 FileSystem
= GetFileSystem(FileSystemList
, List
->OriginalSystemPartition
);
3338 if (FileSystem
== NULL
)
3340 DPRINT1("System partition %lu in disk %lu with no FS?!\n",
3341 List
->OriginalSystemPartition
->PartitionNumber
,
3342 List
->OriginalSystemDisk
->DiskNumber
);
3343 goto FindAndUseAlternativeSystemPartition
;
3345 // HACK: WARNING: We cannot write on this FS yet!
3346 // See fslist.c:GetFileSystem()
3347 if (List
->OriginalSystemPartition
->PartitionType
== PARTITION_EXT2
||
3348 List
->OriginalSystemPartition
->PartitionType
== PARTITION_IFS
)
3350 DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
3351 FileSystem
->FileSystemName
);
3352 goto FindAndUseAlternativeSystemPartition
;
3355 DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
3356 List
->SystemPartition
->PartitionNumber
,
3357 List
->SystemDisk
->DiskNumber
,
3358 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3362 FindAndUseAlternativeSystemPartition
:
3364 * We are here because we have not found any (active) candidate
3365 * system partition that we know how to support. What we are going
3366 * to do is to change the existing system partition and use the
3367 * partition on which we install ReactOS as the new system partition,
3368 * and then we will need to add in FreeLdr's entry a boot entry to boot
3369 * from the original system partition.
3372 /* Unset the old system partition */
3373 List
->SystemPartition
->BootIndicator
= FALSE
;
3374 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= FALSE
;
3375 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3376 List
->SystemDisk
->Dirty
= TRUE
;
3378 UseAlternativeSystemPartition
:
3379 List
->SystemDisk
= List
->CurrentDisk
;
3380 List
->SystemPartition
= List
->CurrentPartition
;
3382 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
3383 List
->SystemPartition
->PartitionNumber
,
3384 List
->SystemDisk
->DiskNumber
,
3385 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
3388 /* Set the new active system partition */
3389 List
->SystemPartition
->BootIndicator
= TRUE
;
3390 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= TRUE
;
3391 List
->SystemDisk
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
3392 List
->SystemDisk
->Dirty
= TRUE
;
3400 IN PDISKENTRY DiskEntry
)
3402 WCHAR DstPath
[MAX_PATH
];
3403 OBJECT_ATTRIBUTES ObjectAttributes
;
3404 IO_STATUS_BLOCK Iosb
;
3405 UNICODE_STRING Name
;
3407 HANDLE FileHandle
= NULL
;
3410 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
3413 L
"\\Device\\Harddisk%d\\Partition0",
3414 DiskEntry
->DiskNumber
);
3415 RtlInitUnicodeString(&Name
,
3417 InitializeObjectAttributes(&ObjectAttributes
,
3423 Status
= NtOpenFile(&FileHandle
,
3424 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
3428 FILE_SYNCHRONOUS_IO_NONALERT
);
3429 if (!NT_SUCCESS(Status
))
3431 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
3435 #ifdef DUMP_PARTITION_TABLE
3436 DumpPartitionTable(DiskEntry
);
3439 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
3440 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
3441 Status
= NtDeviceIoControlFile(FileHandle
,
3446 IOCTL_DISK_SET_DRIVE_LAYOUT
,
3447 DiskEntry
->LayoutBuffer
,
3451 if (!NT_SUCCESS(Status
))
3453 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
3456 if (FileHandle
!= NULL
)
3457 NtClose(FileHandle
);
3464 WritePartitionsToDisk(
3468 PDISKENTRY DiskEntry
;
3473 Entry
= List
->DiskListHead
.Flink
;
3474 while (Entry
!= &List
->DiskListHead
)
3476 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3478 if (DiskEntry
->Dirty
!= FALSE
)
3480 WritePartitions(List
, DiskEntry
);
3481 DiskEntry
->Dirty
= FALSE
;
3484 Entry
= Entry
->Flink
;
3492 SetMountedDeviceValues(
3495 PLIST_ENTRY Entry1
, Entry2
;
3496 PDISKENTRY DiskEntry
;
3497 PPARTENTRY PartEntry
;
3498 LARGE_INTEGER StartingOffset
;
3505 Entry1
= List
->DiskListHead
.Flink
;
3506 while (Entry1
!= &List
->DiskListHead
)
3508 DiskEntry
= CONTAINING_RECORD(Entry1
,
3512 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3513 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3515 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3516 if (PartEntry
->IsPartitioned
)
3518 if (PartEntry
->DriveLetter
)
3520 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3521 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3522 DiskEntry
->LayoutBuffer
->Signature
,
3530 Entry2
= Entry2
->Flink
;
3533 Entry1
= Entry1
->Flink
;
3541 PrimaryPartitionCreationChecks(
3544 PDISKENTRY DiskEntry
;
3545 PPARTENTRY PartEntry
;
3547 DiskEntry
= List
->CurrentDisk
;
3548 PartEntry
= List
->CurrentPartition
;
3550 /* Fail if partition is already in use */
3551 if (PartEntry
->IsPartitioned
!= FALSE
)
3552 return ERROR_NEW_PARTITION
;
3554 /* Fail if there are already 4 primary partitions in the list */
3555 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3556 return ERROR_PARTITION_TABLE_FULL
;
3558 return ERROR_SUCCESS
;
3563 ExtendedPartitionCreationChecks(
3566 PDISKENTRY DiskEntry
;
3567 PPARTENTRY PartEntry
;
3569 DiskEntry
= List
->CurrentDisk
;
3570 PartEntry
= List
->CurrentPartition
;
3572 /* Fail if partition is already in use */
3573 if (PartEntry
->IsPartitioned
!= FALSE
)
3574 return ERROR_NEW_PARTITION
;
3576 /* Fail if there are already 4 primary partitions in the list */
3577 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3578 return ERROR_PARTITION_TABLE_FULL
;
3580 /* Fail if there is another extended partition in the list */
3581 if (DiskEntry
->ExtendedPartition
!= NULL
)
3582 return ERROR_ONLY_ONE_EXTENDED
;
3584 return ERROR_SUCCESS
;
3589 LogicalPartitionCreationChecks(
3592 // PDISKENTRY DiskEntry;
3593 PPARTENTRY PartEntry
;
3595 // DiskEntry = List->CurrentDisk;
3596 PartEntry
= List
->CurrentPartition
;
3598 /* Fail if partition is already in use */
3599 if (PartEntry
->IsPartitioned
!= FALSE
)
3600 return ERROR_NEW_PARTITION
;
3602 return ERROR_SUCCESS
;
3607 GetNextUnformattedPartition(
3609 OUT PDISKENTRY
*pDiskEntry
,
3610 OUT PPARTENTRY
*pPartEntry
)
3612 PLIST_ENTRY Entry1
, Entry2
;
3613 PDISKENTRY DiskEntry
;
3614 PPARTENTRY PartEntry
;
3616 Entry1
= List
->DiskListHead
.Flink
;
3617 while (Entry1
!= &List
->DiskListHead
)
3619 DiskEntry
= CONTAINING_RECORD(Entry1
,
3623 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3624 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3626 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3627 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3629 *pDiskEntry
= DiskEntry
;
3630 *pPartEntry
= PartEntry
;
3634 Entry2
= Entry2
->Flink
;
3637 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3638 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3640 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3641 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3643 *pDiskEntry
= DiskEntry
;
3644 *pPartEntry
= PartEntry
;
3648 Entry2
= Entry2
->Flink
;
3651 Entry1
= Entry1
->Flink
;
3662 GetNextUncheckedPartition(
3664 OUT PDISKENTRY
*pDiskEntry
,
3665 OUT PPARTENTRY
*pPartEntry
)
3667 PLIST_ENTRY Entry1
, Entry2
;
3668 PDISKENTRY DiskEntry
;
3669 PPARTENTRY PartEntry
;
3671 Entry1
= List
->DiskListHead
.Flink
;
3672 while (Entry1
!= &List
->DiskListHead
)
3674 DiskEntry
= CONTAINING_RECORD(Entry1
,
3678 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3679 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3681 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3682 if (PartEntry
->NeedsCheck
== TRUE
)
3684 *pDiskEntry
= DiskEntry
;
3685 *pPartEntry
= PartEntry
;
3689 Entry2
= Entry2
->Flink
;
3692 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3693 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3695 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3696 if (PartEntry
->NeedsCheck
== TRUE
)
3698 *pDiskEntry
= DiskEntry
;
3699 *pPartEntry
= PartEntry
;
3703 Entry2
= Entry2
->Flink
;
3706 Entry1
= Entry1
->Flink
;