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: subsys/system/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 /* FUNCTIONS ****************************************************************/
38 #ifdef DUMP_PARTITION_TABLE
44 PPARTITION_INFORMATION PartitionInfo
;
47 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
49 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
50 DbgPrint("%lu: %12I64u %12I64u %10lu %2lu %2x %c %c\n",
52 PartitionInfo
->StartingOffset
.QuadPart
,
53 PartitionInfo
->PartitionLength
.QuadPart
,
54 PartitionInfo
->HiddenSectors
,
55 PartitionInfo
->PartitionNumber
,
56 PartitionInfo
->PartitionType
,
57 PartitionInfo
->BootIndicator
? '*': ' ',
58 PartitionInfo
->RewritePartition
? 'Y': 'N');
71 Temp
= Value
/ Alignment
;
73 return Temp
* Alignment
;
79 IN ULONGLONG Dividend
,
82 return (Dividend
+ Divisor
/ 2) / Divisor
;
91 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
95 RtlInitUnicodeString(&DiskEntry
->DriverName
,
99 L
"\\Scsi\\Scsi Port %lu",
102 RtlZeroMemory(&QueryTable
,
105 QueryTable
[0].Name
= L
"Driver";
106 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
107 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
109 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
114 if (!NT_SUCCESS(Status
))
116 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
126 PDISKENTRY DiskEntry
;
127 PPARTENTRY PartEntry
;
134 /* Assign drive letters to primary partitions */
135 Entry1
= List
->DiskListHead
.Flink
;
136 while (Entry1
!= &List
->DiskListHead
)
138 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
140 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
141 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
143 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
145 PartEntry
->DriveLetter
= 0;
147 if (PartEntry
->IsPartitioned
&&
148 !IsContainerPartition(PartEntry
->PartitionType
))
150 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
151 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
152 PartEntry
->SectorCount
.QuadPart
!= 0LL))
156 PartEntry
->DriveLetter
= Letter
;
162 Entry2
= Entry2
->Flink
;
165 Entry1
= Entry1
->Flink
;
168 /* Assign drive letters to logical drives */
170 Entry1
= List
->DiskListHead
.Flink
;
171 while (Entry1
!= &List
->DiskListHead
)
173 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
175 Entry2
= DiskEntry
->PartListHead
.Flink
;
176 if (Entry2
!= &DiskEntry
->PartListHead
)
178 Entry2
= Entry2
->Flink
;
179 while (Entry2
!= &DiskEntry
->PartListHead
)
181 PartEntry
= CONTAINING_RECORD(Entry2
,
185 PartEntry
->DriveLetter
= 0;
187 if (PartEntry
->Unpartitioned
== FALSE
&&
188 !IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
190 if (IsRecognizedPartition(PartEntry
->PartInfo
[0].PartitionType
) ||
191 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
192 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
196 PartEntry
->DriveLetter
= Letter
;
202 Entry2
= Entry2
->Flink
;
206 Entry1
= Entry1
->Flink
;
214 UpdatePartitionNumbers(
215 PDISKENTRY DiskEntry
)
217 PPARTENTRY PartEntry
;
219 // ULONG PartitionNumber = 1;
220 ULONG PartitionIndex
= 0;
222 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
223 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
225 PartEntry
= CONTAINING_RECORD(Entry
,
229 if (PartEntry
->IsPartitioned
== FALSE
)
231 // PartEntry->PartitionNumber = 0;
232 PartEntry
->PartitionIndex
= (ULONG
)-1;
236 if (IsContainerPartition(PartEntry
->PartitionType
))
238 // PartEntry->PartitionNumber = 0;
240 else if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
241 PartEntry
->SectorCount
.QuadPart
== 0ULL)
243 // PartEntry->PartitionNumber = 0;
247 // PartEntry->PartitionNumber = PartitionNumber++;
250 PartEntry
->PartitionIndex
= PartitionIndex
++;
253 Entry
= Entry
->Flink
;
260 DiskIdentifierQueryRoutine(
268 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
269 UNICODE_STRING NameU
;
271 if (ValueType
== REG_SZ
&&
272 ValueLength
== 20 * sizeof(WCHAR
))
274 NameU
.Buffer
= (PWCHAR
)ValueData
;
275 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
276 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
278 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
279 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
281 return STATUS_SUCCESS
;
284 return STATUS_UNSUCCESSFUL
;
290 DiskConfigurationDataQueryRoutine(
298 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
299 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
300 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
303 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
304 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
305 return STATUS_UNSUCCESSFUL
;
307 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
309 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
311 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
312 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
313 return STATUS_UNSUCCESSFUL
;
316 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
318 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
319 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
322 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
323 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
325 return STATUS_SUCCESS
;
328 return STATUS_UNSUCCESSFUL
;
334 SystemConfigurationDataQueryRoutine(
342 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
343 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
346 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
347 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
348 return STATUS_UNSUCCESSFUL
;
350 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
352 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
354 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
355 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
356 return STATUS_UNSUCCESSFUL
;
359 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
361 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
362 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
365 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
366 if (*Int13Drives
== NULL
)
367 return STATUS_NO_MEMORY
;
370 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
371 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
372 return STATUS_SUCCESS
;
375 return STATUS_UNSUCCESSFUL
;
379 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
382 EnumerateBiosDiskEntries(
385 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
390 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
391 PBIOSDISKENTRY BiosDiskEntry
;
393 memset(QueryTable
, 0, sizeof(QueryTable
));
395 QueryTable
[1].Name
= L
"Configuration Data";
396 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
398 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
399 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
403 if (!NT_SUCCESS(Status
))
405 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
412 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
413 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
418 if (!NT_SUCCESS(Status
))
423 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
424 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
429 if (NT_SUCCESS(Status
))
433 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
434 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
439 if (!NT_SUCCESS(Status
))
441 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
445 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
446 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
451 if (NT_SUCCESS(Status
))
453 QueryTable
[0].Name
= L
"Identifier";
454 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
455 QueryTable
[1].Name
= L
"Configuration Data";
456 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
461 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
462 if (BiosDiskEntry
== NULL
)
467 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
468 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
471 (PVOID
)BiosDiskEntry
,
473 if (!NT_SUCCESS(Status
))
475 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
479 BiosDiskEntry
->DiskNumber
= DiskCount
;
480 BiosDiskEntry
->Recognized
= FALSE
;
482 if (DiskCount
< Int13Drives
[0].NumberDrives
)
484 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
488 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
491 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
493 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
494 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
495 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
496 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
497 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
498 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
499 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
500 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
501 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
502 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
503 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
509 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
517 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
525 PDISKENTRY DiskEntry
,
526 ULONG PartitionIndex
,
527 BOOLEAN LogicalPartition
)
529 PPARTITION_INFORMATION PartitionInfo
;
530 PPARTENTRY PartEntry
;
532 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
533 if (PartitionInfo
->PartitionType
== 0 ||
534 (LogicalPartition
== TRUE
&& IsContainerPartition(PartitionInfo
->PartitionType
)))
537 PartEntry
= RtlAllocateHeap(ProcessHeap
,
540 if (PartEntry
== NULL
)
545 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
546 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
548 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
549 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
550 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
552 PartEntry
->LogicalPartition
= LogicalPartition
;
553 PartEntry
->IsPartitioned
= TRUE
;
554 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
555 PartEntry
->PartitionIndex
= PartitionIndex
;
557 if (IsContainerPartition(PartEntry
->PartitionType
))
559 PartEntry
->FormatState
= Unformatted
;
561 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
562 DiskEntry
->ExtendedPartition
= PartEntry
;
564 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
565 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
566 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
567 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
568 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
569 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
572 if (CheckFatFormat())
574 PartEntry
->FormatState
= Preformatted
;
578 PartEntry
->FormatState
= Unformatted
;
581 PartEntry
->FormatState
= Preformatted
;
583 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
586 if (CheckExt2Format())
588 PartEntry
->FormatState
= Preformatted
;
592 PartEntry
->FormatState
= Unformatted
;
595 PartEntry
->FormatState
= Preformatted
;
597 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
600 if (CheckNtfsFormat())
602 PartEntry
->FormatState
= Preformatted
;
604 else if (CheckHpfsFormat())
606 PartEntry
->FormatState
= Preformatted
;
610 PartEntry
->FormatState
= Unformatted
;
613 PartEntry
->FormatState
= Preformatted
;
617 PartEntry
->FormatState
= UnknownFormat
;
620 if (LogicalPartition
)
621 InsertTailList(&DiskEntry
->LogicalPartListHead
,
622 &PartEntry
->ListEntry
);
624 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
625 &PartEntry
->ListEntry
);
631 ScanForUnpartitionedDiskSpace(
632 PDISKENTRY DiskEntry
)
634 ULONGLONG LastStartSector
;
635 ULONGLONG LastSectorCount
;
636 ULONGLONG LastUnusedSectorCount
;
637 PPARTENTRY PartEntry
;
638 PPARTENTRY NewPartEntry
;
641 DPRINT1("ScanForUnpartitionedDiskSpace()\n");
643 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
645 DPRINT1("No primary partition!\n");
647 /* Create a partition table that represents the empty disk */
648 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
651 if (NewPartEntry
== NULL
)
654 NewPartEntry
->DiskEntry
= DiskEntry
;
656 NewPartEntry
->IsPartitioned
= FALSE
;
657 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
658 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
659 DiskEntry
->SectorsPerTrack
;
660 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
661 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
662 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
664 NewPartEntry
->FormatState
= Unformatted
;
666 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
667 &NewPartEntry
->ListEntry
);
672 /* Start partition at head 1, cylinder 0 */
673 LastStartSector
= DiskEntry
->SectorsPerTrack
;
674 LastSectorCount
= 0ULL;
675 LastUnusedSectorCount
= 0ULL;
677 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
678 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
680 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
682 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
683 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
685 LastUnusedSectorCount
=
686 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
688 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
689 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
691 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
693 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
696 if (NewPartEntry
== NULL
)
699 NewPartEntry
->DiskEntry
= DiskEntry
;
701 NewPartEntry
->IsPartitioned
= FALSE
;
702 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
703 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
704 NewPartEntry
->StartSector
.QuadPart
;
705 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
706 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
707 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
709 NewPartEntry
->FormatState
= Unformatted
;
711 /* Insert the table into the list */
712 InsertTailList(&PartEntry
->ListEntry
,
713 &NewPartEntry
->ListEntry
);
716 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
717 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
720 Entry
= Entry
->Flink
;
723 /* Check for trailing unpartitioned disk space */
724 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
726 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
728 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
730 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
732 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
735 if (NewPartEntry
== NULL
)
738 NewPartEntry
->DiskEntry
= DiskEntry
;
740 NewPartEntry
->IsPartitioned
= FALSE
;
741 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
742 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
743 NewPartEntry
->StartSector
.QuadPart
;
744 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
745 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
746 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
748 NewPartEntry
->FormatState
= Unformatted
;
750 /* Append the table to the list */
751 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
752 &NewPartEntry
->ListEntry
);
756 if (DiskEntry
->ExtendedPartition
!= NULL
)
758 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
760 DPRINT1("No logical partition!\n");
762 /* Create a partition table entry that represents the empty extended partition */
763 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
766 if (NewPartEntry
== NULL
)
769 NewPartEntry
->DiskEntry
= DiskEntry
;
770 NewPartEntry
->LogicalPartition
= TRUE
;
772 NewPartEntry
->IsPartitioned
= FALSE
;
773 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
774 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
776 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
777 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
778 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
780 NewPartEntry
->FormatState
= Unformatted
;
782 InsertTailList(&DiskEntry
->LogicalPartListHead
,
783 &NewPartEntry
->ListEntry
);
788 /* Start partition at head 1, cylinder 0 */
789 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
790 LastSectorCount
= 0ULL;
791 LastUnusedSectorCount
= 0ULL;
793 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
794 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
796 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
798 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
799 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
801 LastUnusedSectorCount
=
802 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
- (LastStartSector
+ LastSectorCount
);
804 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
) > (LastStartSector
+ LastSectorCount
) &&
805 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
807 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
809 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
812 if (NewPartEntry
== NULL
)
815 NewPartEntry
->DiskEntry
= DiskEntry
;
816 NewPartEntry
->LogicalPartition
= TRUE
;
818 NewPartEntry
->IsPartitioned
= FALSE
;
819 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
820 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
821 NewPartEntry
->StartSector
.QuadPart
;
822 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
823 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
824 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
826 NewPartEntry
->FormatState
= Unformatted
;
828 /* Insert the table into the list */
829 InsertTailList(&PartEntry
->ListEntry
,
830 &NewPartEntry
->ListEntry
);
833 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
834 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
837 Entry
= Entry
->Flink
;
840 /* Check for trailing unpartitioned disk space */
841 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
843 LastUnusedSectorCount
= Align(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
845 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
847 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
849 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
852 if (NewPartEntry
== NULL
)
855 NewPartEntry
->DiskEntry
= DiskEntry
;
856 NewPartEntry
->LogicalPartition
= TRUE
;
858 NewPartEntry
->IsPartitioned
= FALSE
;
859 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
860 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
861 NewPartEntry
->StartSector
.QuadPart
;
862 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
863 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
864 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
866 NewPartEntry
->FormatState
= Unformatted
;
868 /* Append the table to the list */
869 InsertTailList(&DiskEntry
->LogicalPartListHead
,
870 &NewPartEntry
->ListEntry
);
875 DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
883 IN PDISKENTRY DiskEntry
)
885 LARGE_INTEGER SystemTime
;
886 TIME_FIELDS TimeFields
;
888 PDISKENTRY DiskEntry2
;
891 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
895 NtQuerySystemTime(&SystemTime
);
896 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
898 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
899 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
900 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
901 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
903 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
908 /* check if the signature already exist */
910 * Check also signatures from disks, which are
911 * not visible (bootable) by the bios.
913 Entry2
= List
->DiskListHead
.Flink
;
914 while (Entry2
!= &List
->DiskListHead
)
916 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
918 if (DiskEntry
!= DiskEntry2
&&
919 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
922 Entry2
= Entry2
->Flink
;
925 if (Entry2
== &List
->DiskListHead
)
933 UpdateDiskSignatures(
937 PDISKENTRY DiskEntry
;
939 /* Print partition lines*/
940 Entry
= List
->DiskListHead
.Flink
;
941 while (Entry
!= &List
->DiskListHead
)
943 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
945 if (DiskEntry
->LayoutBuffer
&&
946 DiskEntry
->LayoutBuffer
->Signature
== 0)
948 SetDiskSignature(List
, DiskEntry
);
949 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
952 Entry
= Entry
->Flink
;
964 DISK_GEOMETRY DiskGeometry
;
965 SCSI_ADDRESS ScsiAddress
;
966 PDISKENTRY DiskEntry
;
967 IO_STATUS_BLOCK Iosb
;
969 PPARTITION_SECTOR Mbr
;
971 LARGE_INTEGER FileOffset
;
972 WCHAR Identifier
[20];
976 PLIST_ENTRY ListEntry
;
977 PBIOSDISKENTRY BiosDiskEntry
;
978 ULONG LayoutBufferSize
;
980 Status
= NtDeviceIoControlFile(FileHandle
,
985 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
989 sizeof(DISK_GEOMETRY
));
990 if (!NT_SUCCESS(Status
))
995 if (DiskGeometry
.MediaType
!= FixedMedia
&&
996 DiskGeometry
.MediaType
!= RemovableMedia
)
1001 Status
= NtDeviceIoControlFile(FileHandle
,
1006 IOCTL_SCSI_GET_ADDRESS
,
1010 sizeof(SCSI_ADDRESS
));
1011 if (!NT_SUCCESS(Status
))
1016 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1018 DiskGeometry
.BytesPerSector
);
1024 FileOffset
.QuadPart
= 0;
1025 Status
= NtReadFile(FileHandle
,
1031 DiskGeometry
.BytesPerSector
,
1034 if (!NT_SUCCESS(Status
))
1036 RtlFreeHeap(ProcessHeap
,
1039 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1042 Signature
= Mbr
->Signature
;
1044 /* Calculate the MBR checksum */
1046 Buffer
= (PULONG
)Mbr
;
1047 for (i
= 0; i
< 128; i
++)
1049 Checksum
+= Buffer
[i
];
1051 Checksum
= ~Checksum
+ 1;
1053 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1054 DPRINT("Identifier: %S\n", Identifier
);
1056 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1059 if (DiskEntry
== NULL
)
1064 // DiskEntry->Checksum = Checksum;
1065 // DiskEntry->Signature = Signature;
1066 DiskEntry
->BiosFound
= FALSE
;
1068 /* Check if this disk has a valid MBR */
1069 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1070 DiskEntry
->NoMbr
= TRUE
;
1072 DiskEntry
->NoMbr
= FALSE
;
1074 /* Free Mbr sector buffer */
1075 RtlFreeHeap(ProcessHeap
,
1079 ListEntry
= List
->BiosDiskListHead
.Flink
;
1080 while(ListEntry
!= &List
->BiosDiskListHead
)
1082 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1084 * Compare the size from bios and the reported size from driver.
1085 * If we have more than one disk with a zero or with the same signatur
1086 * we must create new signatures and reboot. After the reboot,
1087 * it is possible to identify the disks.
1089 if (BiosDiskEntry
->Signature
== Signature
&&
1090 BiosDiskEntry
->Checksum
== Checksum
&&
1091 !BiosDiskEntry
->Recognized
)
1093 if (!DiskEntry
->BiosFound
)
1095 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1096 DiskEntry
->BiosFound
= TRUE
;
1097 BiosDiskEntry
->Recognized
= TRUE
;
1103 ListEntry
= ListEntry
->Flink
;
1106 if (!DiskEntry
->BiosFound
)
1109 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1112 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1116 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1117 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1119 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1120 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1121 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1122 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1124 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1125 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1126 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1127 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1129 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1130 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1131 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1133 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1135 DPRINT1("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1136 DPRINT1("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1138 DiskEntry
->DiskNumber
= DiskNumber
;
1139 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1140 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1141 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1143 GetDriverName(DiskEntry
);
1145 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1148 * Allocate a buffer for 26 logical drives (2 entries each == 52)
1149 * plus the main partiton table (4 entries). Total 56 entries.
1151 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1152 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1153 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1156 if (DiskEntry
->LayoutBuffer
== NULL
)
1161 Status
= NtDeviceIoControlFile(FileHandle
,
1166 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1169 DiskEntry
->LayoutBuffer
,
1171 if (NT_SUCCESS(Status
))
1173 #ifdef DUMP_PARTITION_TABLE
1174 DumpPartitionTable(DiskEntry
);
1177 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1178 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1179 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1181 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1183 DPRINT1("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1185 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% 1048756 == 0)
1187 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry
->BytesPerSector
);
1191 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1196 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry
->BytesPerSector
);
1200 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1202 DiskEntry
->NewDisk
= TRUE
;
1203 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1205 for (i
= 0; i
< 4; i
++)
1206 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1210 for (i
= 0; i
< 4; i
++)
1212 AddPartitionToDisk(DiskNumber
,
1218 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1220 AddPartitionToDisk(DiskNumber
,
1228 ScanForUnpartitionedDiskSpace(DiskEntry
);
1233 CreatePartitionList(
1240 OBJECT_ATTRIBUTES ObjectAttributes
;
1241 SYSTEM_DEVICE_INFORMATION Sdi
;
1242 IO_STATUS_BLOCK Iosb
;
1246 WCHAR Buffer
[MAX_PATH
];
1247 UNICODE_STRING Name
;
1250 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1258 List
->Right
= Right
;
1259 List
->Bottom
= Bottom
;
1264 List
->TopDisk
= (ULONG
)-1;
1265 List
->TopPartition
= (ULONG
)-1;
1267 List
->CurrentDisk
= NULL
;
1268 List
->CurrentPartition
= NULL
;
1270 InitializeListHead(&List
->DiskListHead
);
1271 InitializeListHead(&List
->BiosDiskListHead
);
1273 EnumerateBiosDiskEntries(List
);
1275 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1277 sizeof(SYSTEM_DEVICE_INFORMATION
),
1279 if (!NT_SUCCESS(Status
))
1281 RtlFreeHeap(ProcessHeap
, 0, List
);
1285 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1288 L
"\\Device\\Harddisk%d\\Partition0",
1290 RtlInitUnicodeString(&Name
,
1293 InitializeObjectAttributes(&ObjectAttributes
,
1299 Status
= NtOpenFile(&FileHandle
,
1300 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1304 FILE_SYNCHRONOUS_IO_NONALERT
);
1305 if (NT_SUCCESS(Status
))
1307 AddDiskToList(FileHandle
,
1311 NtClose(FileHandle
);
1315 UpdateDiskSignatures(List
);
1317 AssignDriveLetters(List
);
1320 List
->TopPartition
= 0;
1322 /* Search for first usable disk and partition */
1323 if (IsListEmpty(&List
->DiskListHead
))
1325 List
->CurrentDisk
= NULL
;
1326 List
->CurrentPartition
= NULL
;
1330 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1334 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1336 List
->CurrentPartition
= 0;
1340 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1351 DestroyPartitionList(
1354 PDISKENTRY DiskEntry
;
1355 PBIOSDISKENTRY BiosDiskEntry
;
1356 PPARTENTRY PartEntry
;
1359 /* Release disk and partition info */
1360 while (!IsListEmpty(&List
->DiskListHead
))
1362 Entry
= RemoveHeadList(&List
->DiskListHead
);
1363 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1365 /* Release driver name */
1366 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1368 /* Release primary partition list */
1369 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1371 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1372 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1374 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1377 /* Release logical partition list */
1378 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1380 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1381 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1383 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1386 /* Release layout buffer */
1387 if (DiskEntry
->LayoutBuffer
!= NULL
)
1388 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1391 /* Release disk entry */
1392 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1395 /* release the bios disk info */
1396 while(!IsListEmpty(&List
->BiosDiskListHead
))
1398 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1399 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1401 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1404 /* Release list head */
1405 RtlFreeHeap(ProcessHeap
, 0, List
);
1419 Width
= List
->Right
- List
->Left
- 1;
1420 Height
= List
->Bottom
- List
->Top
- 2;
1422 coPos
.X
= List
->Left
+ 1;
1423 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1425 if (List
->Line
>= 0 && List
->Line
<= Height
)
1427 FillConsoleOutputAttribute(StdOutput
,
1428 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1433 FillConsoleOutputCharacterA(StdOutput
,
1448 PDISKENTRY DiskEntry
,
1449 PPARTENTRY PartEntry
)
1451 CHAR LineBuffer
[128];
1456 LARGE_INTEGER PartSize
;
1461 Width
= List
->Right
- List
->Left
- 1;
1462 Height
= List
->Bottom
- List
->Top
- 2;
1464 coPos
.X
= List
->Left
+ 1;
1465 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1467 if (PartEntry
->IsPartitioned
== FALSE
)
1469 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1471 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1473 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1474 Unit
= MUIGetString(STRING_GB
);
1478 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1480 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1481 Unit
= MUIGetString(STRING_MB
);
1485 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1486 Unit
= MUIGetString(STRING_KB
);
1490 MUIGetString(STRING_UNPSPACE
),
1491 PartEntry
->LogicalPartition
? " " : "",
1492 PartEntry
->LogicalPartition
? "" : " ",
1498 /* Determine partition type */
1500 if (PartEntry
->New
== TRUE
)
1502 PartType
= MUIGetString(STRING_UNFORMATTED
);
1504 else if (PartEntry
->IsPartitioned
== TRUE
)
1506 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1507 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1508 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1509 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1513 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1514 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1518 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1522 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1524 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1526 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1527 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1529 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1533 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1535 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1537 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1538 Unit
= MUIGetString(STRING_GB
);
1542 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1544 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1545 Unit
= MUIGetString(STRING_MB
);
1549 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1550 Unit
= MUIGetString(STRING_KB
);
1553 if (PartType
== NULL
)
1556 MUIGetString(STRING_HDDINFOUNK5
),
1557 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1558 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1559 PartEntry
->LogicalPartition
? " " : "",
1560 PartEntry
->PartitionType
,
1561 PartEntry
->LogicalPartition
? "" : " ",
1568 "%c%c %s%-24s%s %6lu %s",
1569 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1570 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1571 PartEntry
->LogicalPartition
? " " : "",
1573 PartEntry
->LogicalPartition
? "" : " ",
1579 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1580 List
->CurrentPartition
== PartEntry
) ?
1581 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1582 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1584 if (List
->Line
>= 0 && List
->Line
<= Height
)
1586 FillConsoleOutputCharacterA(StdOutput
,
1594 if (List
->Line
>= 0 && List
->Line
<= Height
)
1596 FillConsoleOutputAttribute(StdOutput
,
1604 if (List
->Line
>= 0 && List
->Line
<= Height
)
1606 WriteConsoleOutputCharacterA(StdOutput
,
1608 min(strlen(LineBuffer
), Width
),
1621 PDISKENTRY DiskEntry
)
1623 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1624 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1625 CHAR LineBuffer
[128];
1630 ULARGE_INTEGER DiskSize
;
1633 Width
= List
->Right
- List
->Left
- 1;
1634 Height
= List
->Bottom
- List
->Top
- 2;
1636 coPos
.X
= List
->Left
+ 1;
1637 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1639 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1640 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1642 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1643 Unit
= MUIGetString(STRING_GB
);
1647 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1648 if (DiskSize
.QuadPart
== 0)
1649 DiskSize
.QuadPart
= 1;
1650 Unit
= MUIGetString(STRING_MB
);
1653 if (DiskEntry
->DriverName
.Length
> 0)
1656 MUIGetString(STRING_HDINFOPARTSELECT
),
1659 DiskEntry
->DiskNumber
,
1663 DiskEntry
->DriverName
.Buffer
);
1668 MUIGetString(STRING_HDDINFOUNK6
),
1671 DiskEntry
->DiskNumber
,
1677 if (List
->Line
>= 0 && List
->Line
<= Height
)
1679 FillConsoleOutputAttribute(StdOutput
,
1680 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1685 FillConsoleOutputCharacterA(StdOutput
,
1693 if (List
->Line
>= 0 && List
->Line
<= Height
)
1695 WriteConsoleOutputCharacterA(StdOutput
,
1697 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1704 /* Print separator line */
1705 PrintEmptyLine(List
);
1707 /* Print partition lines*/
1708 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1709 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1711 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1713 PrintPartitionData(List
,
1717 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1719 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1720 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1722 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1724 PrintPartitionData(List
,
1728 LogicalEntry
= LogicalEntry
->Flink
;
1732 PrimaryEntry
= PrimaryEntry
->Flink
;
1735 /* Print separator line */
1736 PrintEmptyLine(List
);
1744 PLIST_ENTRY Entry
, Entry2
;
1745 PDISKENTRY DiskEntry
;
1746 PPARTENTRY PartEntry
= NULL
;
1750 SHORT CurrentDiskLine
;
1751 SHORT CurrentPartLine
;
1753 BOOL CurrentPartLineFound
= FALSE
;
1754 BOOL CurrentDiskLineFound
= FALSE
;
1756 /* Calculate the line of the current disk and partition */
1757 CurrentDiskLine
= 0;
1758 CurrentPartLine
= 0;
1761 Entry
= List
->DiskListHead
.Flink
;
1762 while (Entry
!= &List
->DiskListHead
)
1764 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1767 if (CurrentPartLineFound
== FALSE
)
1769 CurrentPartLine
+= 2;
1772 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1773 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1775 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1776 if (PartEntry
== List
->CurrentPartition
)
1778 CurrentPartLineFound
= TRUE
;
1781 Entry2
= Entry2
->Flink
;
1782 if (CurrentPartLineFound
== FALSE
)
1790 if (DiskEntry
== List
->CurrentDisk
)
1792 CurrentDiskLineFound
= TRUE
;
1795 Entry
= Entry
->Flink
;
1796 if (Entry
!= &List
->DiskListHead
)
1798 if (CurrentDiskLineFound
== FALSE
)
1801 CurrentDiskLine
= CurrentPartLine
;
1812 /* If it possible, make the disk name visible */
1813 if (CurrentPartLine
< List
->Offset
)
1815 List
->Offset
= CurrentPartLine
;
1817 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1819 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1822 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1824 List
->Offset
= CurrentDiskLine
;
1827 /* draw upper left corner */
1828 coPos
.X
= List
->Left
;
1829 coPos
.Y
= List
->Top
;
1830 FillConsoleOutputCharacterA(StdOutput
,
1836 /* draw upper edge */
1837 coPos
.X
= List
->Left
+ 1;
1838 coPos
.Y
= List
->Top
;
1839 if (List
->Offset
== 0)
1841 FillConsoleOutputCharacterA(StdOutput
,
1843 List
->Right
- List
->Left
- 1,
1849 FillConsoleOutputCharacterA(StdOutput
,
1851 List
->Right
- List
->Left
- 5,
1854 coPos
.X
= List
->Right
- 5;
1855 WriteConsoleOutputCharacterA(StdOutput
,
1860 coPos
.X
= List
->Right
- 2;
1861 FillConsoleOutputCharacterA(StdOutput
,
1868 /* draw upper right corner */
1869 coPos
.X
= List
->Right
;
1870 coPos
.Y
= List
->Top
;
1871 FillConsoleOutputCharacterA(StdOutput
,
1877 /* draw left and right edge */
1878 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1880 coPos
.X
= List
->Left
;
1882 FillConsoleOutputCharacterA(StdOutput
,
1888 coPos
.X
= List
->Right
;
1889 FillConsoleOutputCharacterA(StdOutput
,
1896 /* draw lower left corner */
1897 coPos
.X
= List
->Left
;
1898 coPos
.Y
= List
->Bottom
;
1899 FillConsoleOutputCharacterA(StdOutput
,
1905 /* draw lower edge */
1906 coPos
.X
= List
->Left
+ 1;
1907 coPos
.Y
= List
->Bottom
;
1908 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1910 FillConsoleOutputCharacterA(StdOutput
,
1912 List
->Right
- List
->Left
- 1,
1918 FillConsoleOutputCharacterA(StdOutput
,
1920 List
->Right
- List
->Left
- 5,
1923 coPos
.X
= List
->Right
- 5;
1924 WriteConsoleOutputCharacterA(StdOutput
,
1925 "(\x19)", // "(down)"
1929 coPos
.X
= List
->Right
- 2;
1930 FillConsoleOutputCharacterA(StdOutput
,
1937 /* draw lower right corner */
1938 coPos
.X
= List
->Right
;
1939 coPos
.Y
= List
->Bottom
;
1940 FillConsoleOutputCharacterA(StdOutput
,
1946 /* print list entries */
1947 List
->Line
= - List
->Offset
;
1949 Entry
= List
->DiskListHead
.Flink
;
1950 while (Entry
!= &List
->DiskListHead
)
1952 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1954 /* Print disk entry */
1958 Entry
= Entry
->Flink
;
1967 ULONG PartitionNumber
)
1969 PDISKENTRY DiskEntry
;
1970 PPARTENTRY PartEntry
;
1974 /* Check for empty disks */
1975 if (IsListEmpty(&List
->DiskListHead
))
1978 /* Check for first usable entry on next disk */
1979 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1980 while (Entry1
!= &List
->DiskListHead
)
1982 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1984 if (DiskEntry
->DiskNumber
== DiskNumber
)
1986 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1987 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1989 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1991 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1993 List
->CurrentDisk
= DiskEntry
;
1994 List
->CurrentPartition
= PartEntry
;
1995 DrawPartitionList(List
);
1999 Entry2
= Entry2
->Flink
;
2005 Entry1
= Entry1
->Flink
;
2013 ScrollDownPartitionList(
2016 PLIST_ENTRY DiskListEntry
;
2017 PLIST_ENTRY PartListEntry
;
2018 PDISKENTRY DiskEntry
;
2019 PPARTENTRY PartEntry
;
2021 /* Fail, if no disks are available */
2022 if (IsListEmpty(&List
->DiskListHead
))
2025 /* Check for next usable entry on current disk */
2026 if (List
->CurrentPartition
!= NULL
)
2028 if (List
->CurrentPartition
->LogicalPartition
)
2030 /* Logical partition */
2032 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2033 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2035 /* Next logical partition */
2036 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2038 List
->CurrentPartition
= PartEntry
;
2043 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2044 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2046 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2048 List
->CurrentPartition
= PartEntry
;
2055 /* Primary or extended partition */
2057 if (IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2059 /* First logical partition */
2060 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2061 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2063 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2065 List
->CurrentPartition
= PartEntry
;
2071 /* Next primary partition */
2072 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2073 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2075 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2077 List
->CurrentPartition
= PartEntry
;
2084 /* Search for the first partition entry on the next disk */
2085 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2086 while (DiskListEntry
!= &List
->DiskListHead
)
2088 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2090 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2091 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2093 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2095 List
->CurrentDisk
= DiskEntry
;
2096 List
->CurrentPartition
= PartEntry
;
2100 DiskListEntry
= DiskListEntry
->Flink
;
2108 ScrollUpPartitionList(
2111 PLIST_ENTRY DiskListEntry
;
2112 PLIST_ENTRY PartListEntry
;
2113 PDISKENTRY DiskEntry
;
2114 PPARTENTRY PartEntry
;
2116 /* Fail, if no disks are available */
2117 if (IsListEmpty(&List
->DiskListHead
))
2120 /* Check for previous usable entry on current disk */
2121 if (List
->CurrentPartition
!= NULL
)
2123 if (List
->CurrentPartition
->LogicalPartition
)
2125 /* Logical partition */
2126 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2127 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2129 /* Previous logical partition */
2130 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2134 /* Extended partition*/
2135 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2138 List
->CurrentPartition
= PartEntry
;
2143 /* Primary or extended partition */
2145 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2146 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2148 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2150 if (IsContainerPartition(PartEntry
->PartitionType
))
2152 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2153 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2156 List
->CurrentPartition
= PartEntry
;
2163 /* Search for the last partition entry on the previous disk */
2164 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2165 while (DiskListEntry
!= &List
->DiskListHead
)
2167 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2169 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2170 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2172 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2174 if (IsContainerPartition(PartEntry
->PartitionType
))
2176 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2177 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2179 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2181 List
->CurrentDisk
= DiskEntry
;
2182 List
->CurrentPartition
= PartEntry
;
2188 List
->CurrentDisk
= DiskEntry
;
2189 List
->CurrentPartition
= PartEntry
;
2194 DiskListEntry
= DiskListEntry
->Blink
;
2204 PPARTITION_INFORMATION PartitionInfo
)
2206 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2207 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2208 // PartitionInfo->PartitionType == 0)
2217 IsSamePrimaryLayoutEntry(
2218 IN PPARTITION_INFORMATION PartitionInfo
,
2219 IN PDISKENTRY DiskEntry
,
2220 IN PPARTENTRY PartEntry
)
2222 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2223 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2224 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2225 // PartitionInfo->PartitionType == PartEntry->PartitionType
2235 IN PDISKENTRY DiskEntry
)
2237 PPARTITION_INFORMATION PartitionInfo
;
2238 PLIST_ENTRY ListEntry
;
2239 PPARTENTRY PartEntry
;
2241 ULONG PartitionNumber
= 1;
2243 DPRINT1("UpdateDiskLayout()\n");
2245 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2246 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2248 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2250 if (PartEntry
->IsPartitioned
== TRUE
)
2252 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2254 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2256 DPRINT1("Updating partition entry %lu\n", Index
);
2257 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2258 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2259 PartitionInfo
->HiddenSectors
= 0;
2260 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2261 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2262 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2263 PartitionInfo
->RecognizedPartition
= FALSE
;
2264 PartitionInfo
->RewritePartition
= TRUE
;
2266 PartEntry
->PartitionNumber
= PartitionNumber
;
2267 PartEntry
->PartitionIndex
= Index
;
2271 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2279 ListEntry
= ListEntry
->Flink
;
2282 for (;Index
< 4; Index
++)
2284 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2286 if (!IsEmptyLayoutEntry(PartitionInfo
))
2288 DPRINT1("Wiping partition entry %lu\n", Index
);
2289 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2290 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2291 PartitionInfo
->HiddenSectors
= 0;
2292 PartitionInfo
->PartitionNumber
= 0;
2293 PartitionInfo
->PartitionType
= 0;
2294 PartitionInfo
->BootIndicator
= FALSE
;
2295 PartitionInfo
->RecognizedPartition
= FALSE
;
2296 PartitionInfo
->RewritePartition
= TRUE
;
2300 #ifdef DUMP_PARTITION_TABLE
2301 DumpPartitionTable(DiskEntry
);
2308 GetPrevUnpartitionedEntry(
2309 PDISKENTRY DiskEntry
,
2310 PPARTENTRY PartEntry
)
2312 PPARTENTRY PrevPartEntry
;
2314 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PrimaryPartListHead
)
2316 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2319 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2320 return PrevPartEntry
;
2329 GetNextUnpartitionedEntry(
2330 PDISKENTRY DiskEntry
,
2331 PPARTENTRY PartEntry
)
2333 PPARTENTRY NextPartEntry
;
2335 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PrimaryPartListHead
)
2337 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2340 if (NextPartEntry
->IsPartitioned
== FALSE
)
2341 return NextPartEntry
;
2349 CreatePrimaryPartition(
2351 ULONGLONG SectorCount
,
2354 PDISKENTRY DiskEntry
;
2355 PPARTENTRY PartEntry
;
2356 PPARTENTRY NewPartEntry
;
2358 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2361 List
->CurrentDisk
== NULL
||
2362 List
->CurrentPartition
== NULL
||
2363 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2368 DiskEntry
= List
->CurrentDisk
;
2369 PartEntry
= List
->CurrentPartition
;
2371 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2373 if (AutoCreate
== TRUE
||
2374 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2376 DPRINT1("Convert existing partition entry\n");
2377 /* Convert current entry to 'new (unformatted)' */
2378 PartEntry
->IsPartitioned
= TRUE
;
2379 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2380 PartEntry
->FormatState
= Unformatted
;
2381 PartEntry
->AutoCreate
= AutoCreate
;
2382 PartEntry
->New
= TRUE
;
2383 PartEntry
->BootIndicator
= FALSE
; /* FIXME */
2385 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2386 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2387 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2391 DPRINT1("Add new partition entry\n");
2393 /* Insert and initialize a new partition entry */
2394 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2397 if (NewPartEntry
== NULL
)
2400 /* Insert the new entry into the list */
2401 InsertTailList(&PartEntry
->ListEntry
,
2402 &NewPartEntry
->ListEntry
);
2404 NewPartEntry
->DiskEntry
= DiskEntry
;
2406 NewPartEntry
->IsPartitioned
= TRUE
;
2407 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2408 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2409 NewPartEntry
->StartSector
.QuadPart
;
2410 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2412 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2413 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2414 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2416 NewPartEntry
->New
= TRUE
;
2417 NewPartEntry
->FormatState
= Unformatted
;
2418 NewPartEntry
->BootIndicator
= FALSE
; /* FIXME */
2420 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2421 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2424 UpdateDiskLayout(DiskEntry
);
2426 DiskEntry
->Dirty
= TRUE
;
2428 UpdatePartitionNumbers(DiskEntry
);
2430 AssignDriveLetters(List
);
2436 AddLogicalDiskSpace(
2437 PDISKENTRY DiskEntry
)
2439 PPARTENTRY NewPartEntry
;
2441 DPRINT1("AddLogicalDiskSpace()\n");
2443 /* Create a partition table entry that represents the empty space in the container partition */
2444 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2447 if (NewPartEntry
== NULL
)
2450 NewPartEntry
->DiskEntry
= DiskEntry
;
2451 NewPartEntry
->LogicalPartition
= TRUE
;
2453 NewPartEntry
->IsPartitioned
= FALSE
;
2454 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
2455 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
2457 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2458 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2459 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2461 NewPartEntry
->FormatState
= Unformatted
;
2463 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2464 &NewPartEntry
->ListEntry
);
2469 CreateExtendedPartition(
2471 ULONGLONG SectorCount
)
2473 PDISKENTRY DiskEntry
;
2474 PPARTENTRY PartEntry
;
2475 PPARTENTRY NewPartEntry
;
2477 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2480 List
->CurrentDisk
== NULL
||
2481 List
->CurrentPartition
== NULL
||
2482 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2487 DiskEntry
= List
->CurrentDisk
;
2488 PartEntry
= List
->CurrentPartition
;
2490 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2492 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2494 DPRINT1("Convert existing partition entry\n");
2495 /* Convert current entry to 'new (unformatted)' */
2496 PartEntry
->IsPartitioned
= TRUE
;
2497 PartEntry
->FormatState
= Formatted
;
2498 PartEntry
->AutoCreate
= FALSE
;
2499 PartEntry
->New
= FALSE
;
2500 PartEntry
->BootIndicator
= FALSE
; /* FIXME */
2502 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2504 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2505 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2509 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2510 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2513 DiskEntry
->ExtendedPartition
= PartEntry
;
2515 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2516 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2517 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2521 DPRINT1("Add new partition entry\n");
2523 /* Insert and initialize a new partition entry */
2524 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2527 if (NewPartEntry
== NULL
)
2530 /* Insert the new entry into the list */
2531 InsertTailList(&PartEntry
->ListEntry
,
2532 &NewPartEntry
->ListEntry
);
2534 NewPartEntry
->DiskEntry
= DiskEntry
;
2536 NewPartEntry
->IsPartitioned
= TRUE
;
2537 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2538 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2539 NewPartEntry
->StartSector
.QuadPart
;
2541 NewPartEntry
->New
= FALSE
;
2542 NewPartEntry
->FormatState
= Formatted
;
2543 NewPartEntry
->BootIndicator
= FALSE
; /* FIXME */
2545 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2547 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2548 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2552 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2553 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2556 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2558 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2559 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2561 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2562 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2563 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2566 AddLogicalDiskSpace(DiskEntry
);
2568 UpdateDiskLayout(DiskEntry
);
2570 DiskEntry
->Dirty
= TRUE
;
2572 UpdatePartitionNumbers(DiskEntry
);
2574 AssignDriveLetters(List
);
2579 CreateLogicalPartition(
2581 ULONGLONG SectorCount
)
2583 // PDISKENTRY DiskEntry;
2584 PPARTENTRY PartEntry
;
2585 // PPARTENTRY NewPartEntry;
2587 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2590 List
->CurrentDisk
== NULL
||
2591 List
->CurrentPartition
== NULL
||
2592 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2597 // DiskEntry = List->CurrentDisk;
2598 PartEntry
= List
->CurrentPartition
;
2600 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2605 DeleteCurrentPartition(
2608 PDISKENTRY DiskEntry
;
2609 PPARTENTRY PartEntry
;
2610 PPARTENTRY PrevPartEntry
;
2611 PPARTENTRY NextPartEntry
;
2612 PPARTENTRY LogicalPartEntry
;
2616 List
->CurrentDisk
== NULL
||
2617 List
->CurrentPartition
== NULL
||
2618 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2623 DiskEntry
= List
->CurrentDisk
;
2624 PartEntry
= List
->CurrentPartition
;
2626 /* Delete all logical partiton entries if an extended partition will be deleted */
2627 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2629 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2631 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2632 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2634 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2637 DiskEntry
->ExtendedPartition
= NULL
;
2640 /* Adjust unpartitioned disk space entries */
2642 /* Get pointer to previous and next unpartitioned entries */
2643 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2646 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2649 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2651 /* Merge previous, current and next unpartitioned entry */
2653 /* Adjust the previous entries length */
2654 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2656 /* Remove the current entry */
2657 RemoveEntryList(&PartEntry
->ListEntry
);
2658 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2660 /* Remove the next entry */
2661 RemoveEntryList (&NextPartEntry
->ListEntry
);
2662 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2664 /* Update current partition */
2665 List
->CurrentPartition
= PrevPartEntry
;
2667 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2669 /* Merge current and previous unpartitioned entry */
2671 /* Adjust the previous entries length */
2672 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2674 /* Remove the current entry */
2675 RemoveEntryList(&PartEntry
->ListEntry
);
2676 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2678 /* Update current partition */
2679 List
->CurrentPartition
= PrevPartEntry
;
2681 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2683 /* Merge current and next unpartitioned entry */
2685 /* Adjust the next entries offset and length */
2686 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2687 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2689 /* Remove the current entry */
2690 RemoveEntryList(&PartEntry
->ListEntry
);
2691 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2693 /* Update current partition */
2694 List
->CurrentPartition
= NextPartEntry
;
2698 /* Nothing to merge but change current entry */
2699 PartEntry
->IsPartitioned
= FALSE
;
2700 PartEntry
->FormatState
= Unformatted
;
2701 PartEntry
->DriveLetter
= 0;
2704 UpdateDiskLayout(DiskEntry
);
2706 DiskEntry
->Dirty
= TRUE
;
2708 UpdatePartitionNumbers(DiskEntry
);
2710 AssignDriveLetters(List
);
2715 CheckActiveBootPartition(
2718 PDISKENTRY DiskEntry
;
2719 PPARTENTRY PartEntry
;
2720 PLIST_ENTRY ListEntry
;
2722 /* Check for empty disk list */
2723 if (IsListEmpty (&List
->DiskListHead
))
2725 List
->ActiveBootDisk
= NULL
;
2726 List
->ActiveBootPartition
= NULL
;
2731 if (List
->ActiveBootDisk
!= NULL
&&
2732 List
->ActiveBootPartition
!= NULL
)
2734 /* We already have an active boot partition */
2739 /* Choose the currently selected disk */
2740 DiskEntry
= List
->CurrentDisk
;
2742 /* Check for empty partition list */
2743 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2745 List
->ActiveBootDisk
= NULL
;
2746 List
->ActiveBootPartition
= NULL
;
2750 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2754 /* Set active boot partition */
2755 if ((DiskEntry
->NewDisk
== TRUE
) ||
2756 (PartEntry
->BootIndicator
== FALSE
))
2758 PartEntry
->BootIndicator
= TRUE
;
2759 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2760 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2761 DiskEntry
->Dirty
= TRUE
;
2763 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2764 List
->ActiveBootDisk
= DiskEntry
;
2765 List
->ActiveBootPartition
= PartEntry
;
2770 /* Disk is not new, scan all partitions to find a bootable one */
2771 List
->ActiveBootDisk
= NULL
;
2772 List
->ActiveBootPartition
= NULL
;
2774 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2775 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2777 PartEntry
= CONTAINING_RECORD(ListEntry
,
2781 /* Check if it is partitioned */
2782 if (PartEntry
->IsPartitioned
)
2784 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2785 PartEntry
->BootIndicator
)
2787 /* Yes, we found it */
2788 List
->ActiveBootDisk
= DiskEntry
;
2789 List
->ActiveBootPartition
= PartEntry
;
2791 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2792 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2797 /* Go to the next one */
2798 ListEntry
= ListEntry
->Flink
;
2804 CheckForLinuxFdiskPartitions(
2808 PDISKENTRY DiskEntry
;
2809 PPARTENTRY PartEntry
;
2812 ULONG PartitionCount
;
2815 Entry1
= List
->DiskListHead
.Flink
;
2816 while (Entry1
!= &List
->DiskListHead
)
2818 DiskEntry
= CONTAINING_RECORD(Entry1
,
2822 Entry2
= DiskEntry
->PartListHead
.Flink
;
2823 while (Entry2
!= &DiskEntry
->PartListHead
)
2825 PartEntry
= CONTAINING_RECORD(Entry2
,
2829 if (PartEntry
->Unpartitioned
== FALSE
)
2833 for (i
= 0; i
< 4; i
++)
2835 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2836 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2842 if (PartitionCount
> 1)
2848 Entry2
= Entry2
->Flink
;
2851 Entry1
= Entry1
->Flink
;
2863 IN PDISKENTRY DiskEntry
)
2865 WCHAR DstPath
[MAX_PATH
];
2866 OBJECT_ATTRIBUTES ObjectAttributes
;
2867 IO_STATUS_BLOCK Iosb
;
2868 UNICODE_STRING Name
;
2870 HANDLE FileHandle
= NULL
;
2873 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2876 L
"\\Device\\Harddisk%d\\Partition0",
2877 DiskEntry
->DiskNumber
);
2878 RtlInitUnicodeString(&Name
,
2880 InitializeObjectAttributes(&ObjectAttributes
,
2886 Status
= NtOpenFile(&FileHandle
,
2887 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2891 FILE_SYNCHRONOUS_IO_NONALERT
);
2892 if (!NT_SUCCESS(Status
))
2894 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2898 #ifdef DUMP_PARTITION_TABLE
2899 DumpPartitionTable(DiskEntry
);
2902 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2903 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2904 Status
= NtDeviceIoControlFile(FileHandle
,
2909 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2910 DiskEntry
->LayoutBuffer
,
2914 if (!NT_SUCCESS(Status
))
2916 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2919 if (FileHandle
!= NULL
)
2920 NtClose(FileHandle
);
2927 WritePartitionsToDisk(
2931 PDISKENTRY DiskEntry
;
2936 Entry
= List
->DiskListHead
.Flink
;
2937 while (Entry
!= &List
->DiskListHead
)
2939 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2941 if (DiskEntry
->Dirty
== TRUE
)
2943 WritePartitons(List
, DiskEntry
);
2946 Entry
= Entry
->Flink
;
2954 SetMountedDeviceValues(
2957 PLIST_ENTRY Entry1
, Entry2
;
2958 PDISKENTRY DiskEntry
;
2959 PPARTENTRY PartEntry
;
2960 LARGE_INTEGER StartingOffset
;
2967 Entry1
= List
->DiskListHead
.Flink
;
2968 while (Entry1
!= &List
->DiskListHead
)
2970 DiskEntry
= CONTAINING_RECORD(Entry1
,
2974 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2975 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2977 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2978 if (PartEntry
->IsPartitioned
)
2980 if (PartEntry
->DriveLetter
)
2982 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2983 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2984 DiskEntry
->LayoutBuffer
->Signature
,
2992 Entry2
= Entry2
->Flink
;
2995 Entry1
= Entry1
->Flink
;
3004 IsLastPrimaryPartiton(
3005 IN PPARTENTRY PartEntry
)
3007 return (PartEntry
->ListEntry
.Flink
== &PartEntry
->DiskEntry
->PrimaryPartListHead
);
3013 IsPreviousPartitionExtended(
3014 IN PPARTENTRY PartEntry
,
3015 IN PDISKENTRY DiskEntry
)
3017 PPARTENTRY PrevPartEntry
;
3020 Entry
= PartEntry
->ListEntry
.Blink
;
3022 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
3024 PrevPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3026 if (IsContainerPartition(PrevPartEntry
->PartitionType
))
3029 Entry
= Entry
->Blink
;
3039 GetPrimaryPartitionCount(
3040 IN PDISKENTRY DiskEntry
)
3043 PPARTENTRY PartEntry
;
3046 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3047 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
3049 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3050 if (PartEntry
->IsPartitioned
== TRUE
)
3053 Entry
= Entry
->Flink
;
3061 PrimaryPartitionCreationChecks(
3064 PDISKENTRY DiskEntry
;
3065 PPARTENTRY PartEntry
;
3067 DiskEntry
= List
->CurrentDisk
;
3068 PartEntry
= List
->CurrentPartition
;
3070 /* Fail if partition is already in use */
3071 if (PartEntry
->IsPartitioned
== TRUE
)
3072 return ERROR_NEW_PARTITION
;
3074 /* Fail if there are more than 4 partitions in the list */
3075 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3076 return ERROR_PARTITION_TABLE_FULL
;
3078 /* Fail if this partiton is located behind an extended partition */
3079 if (IsPreviousPartitionExtended(PartEntry
, DiskEntry
))
3080 return ERROR_NOT_BEHIND_EXTENDED
;
3082 return ERROR_SUCCESS
;
3087 ExtendedPartitionCreationChecks(
3090 PDISKENTRY DiskEntry
;
3091 PPARTENTRY PartEntry
;
3093 DiskEntry
= List
->CurrentDisk
;
3094 PartEntry
= List
->CurrentPartition
;
3096 /* Fail if partition is already in use */
3097 if (PartEntry
->IsPartitioned
== TRUE
)
3098 return ERROR_NEW_PARTITION
;
3100 /* Fail if there are more than 4 partitions in the list */
3101 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3102 return ERROR_PARTITION_TABLE_FULL
;
3104 /* Fail if there is another extended partition in the list */
3105 if (DiskEntry
->ExtendedPartition
!= NULL
)
3106 return ERROR_ONLY_ONE_EXTENDED
;
3108 /* Fail if the partition is not the last list entry */
3109 if (!IsLastPrimaryPartiton(PartEntry
))
3110 return ERROR_EXTENDED_NOT_LAST
;
3112 return ERROR_SUCCESS
;
3117 LogicalPartitionCreationChecks(
3120 // PDISKENTRY DiskEntry;
3121 PPARTENTRY PartEntry
;
3123 // DiskEntry = List->CurrentDisk;
3124 PartEntry
= List
->CurrentPartition
;
3126 /* Fail if partition is already in use */
3127 if (PartEntry
->IsPartitioned
== TRUE
)
3128 return ERROR_NEW_PARTITION
;
3130 return ERROR_SUCCESS
;