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 DPRINT("\n%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
->DiskEntry
= DiskEntry
;
547 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
548 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
550 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
551 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
552 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
554 PartEntry
->LogicalPartition
= LogicalPartition
;
555 PartEntry
->IsPartitioned
= TRUE
;
556 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
557 PartEntry
->PartitionIndex
= PartitionIndex
;
559 if (IsContainerPartition(PartEntry
->PartitionType
))
561 PartEntry
->FormatState
= Unformatted
;
563 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
564 DiskEntry
->ExtendedPartition
= PartEntry
;
566 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
567 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
568 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
569 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
570 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
571 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
574 if (CheckFatFormat())
576 PartEntry
->FormatState
= Preformatted
;
580 PartEntry
->FormatState
= Unformatted
;
583 PartEntry
->FormatState
= Preformatted
;
585 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
588 if (CheckExt2Format())
590 PartEntry
->FormatState
= Preformatted
;
594 PartEntry
->FormatState
= Unformatted
;
597 PartEntry
->FormatState
= Preformatted
;
599 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
602 if (CheckNtfsFormat())
604 PartEntry
->FormatState
= Preformatted
;
606 else if (CheckHpfsFormat())
608 PartEntry
->FormatState
= Preformatted
;
612 PartEntry
->FormatState
= Unformatted
;
615 PartEntry
->FormatState
= Preformatted
;
619 PartEntry
->FormatState
= UnknownFormat
;
622 if (LogicalPartition
)
623 InsertTailList(&DiskEntry
->LogicalPartListHead
,
624 &PartEntry
->ListEntry
);
626 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
627 &PartEntry
->ListEntry
);
633 ScanForUnpartitionedDiskSpace(
634 PDISKENTRY DiskEntry
)
636 ULONGLONG LastStartSector
;
637 ULONGLONG LastSectorCount
;
638 ULONGLONG LastUnusedSectorCount
;
639 PPARTENTRY PartEntry
;
640 PPARTENTRY NewPartEntry
;
643 DPRINT("ScanForUnpartitionedDiskSpace()\n");
645 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
647 DPRINT1("No primary partition!\n");
649 /* Create a partition table that represents the empty disk */
650 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
653 if (NewPartEntry
== NULL
)
656 NewPartEntry
->DiskEntry
= DiskEntry
;
658 NewPartEntry
->IsPartitioned
= FALSE
;
659 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
660 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
661 DiskEntry
->SectorsPerTrack
;
662 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
663 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
664 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
666 NewPartEntry
->FormatState
= Unformatted
;
668 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
669 &NewPartEntry
->ListEntry
);
674 /* Start partition at head 1, cylinder 0 */
675 LastStartSector
= DiskEntry
->SectorsPerTrack
;
676 LastSectorCount
= 0ULL;
677 LastUnusedSectorCount
= 0ULL;
679 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
680 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
682 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
684 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
685 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
687 LastUnusedSectorCount
=
688 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
690 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
691 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
693 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
695 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
698 if (NewPartEntry
== NULL
)
701 NewPartEntry
->DiskEntry
= DiskEntry
;
703 NewPartEntry
->IsPartitioned
= FALSE
;
704 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
705 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
706 NewPartEntry
->StartSector
.QuadPart
;
707 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
708 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
709 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
711 NewPartEntry
->FormatState
= Unformatted
;
713 /* Insert the table into the list */
714 InsertTailList(&PartEntry
->ListEntry
,
715 &NewPartEntry
->ListEntry
);
718 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
719 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
722 Entry
= Entry
->Flink
;
725 /* Check for trailing unpartitioned disk space */
726 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
728 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
730 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
732 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
734 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
737 if (NewPartEntry
== NULL
)
740 NewPartEntry
->DiskEntry
= DiskEntry
;
742 NewPartEntry
->IsPartitioned
= FALSE
;
743 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
744 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
745 NewPartEntry
->StartSector
.QuadPart
;
746 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
747 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
748 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
750 NewPartEntry
->FormatState
= Unformatted
;
752 /* Append the table to the list */
753 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
754 &NewPartEntry
->ListEntry
);
758 if (DiskEntry
->ExtendedPartition
!= NULL
)
760 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
762 DPRINT1("No logical partition!\n");
764 /* Create a partition table entry that represents the empty extended partition */
765 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
768 if (NewPartEntry
== NULL
)
771 NewPartEntry
->DiskEntry
= DiskEntry
;
772 NewPartEntry
->LogicalPartition
= TRUE
;
774 NewPartEntry
->IsPartitioned
= FALSE
;
775 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
776 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
778 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
779 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
780 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
782 NewPartEntry
->FormatState
= Unformatted
;
784 InsertTailList(&DiskEntry
->LogicalPartListHead
,
785 &NewPartEntry
->ListEntry
);
790 /* Start partition at head 1, cylinder 0 */
791 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
792 LastSectorCount
= 0ULL;
793 LastUnusedSectorCount
= 0ULL;
795 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
796 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
798 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
800 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
801 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
803 LastUnusedSectorCount
=
804 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
- (LastStartSector
+ LastSectorCount
);
806 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
) > (LastStartSector
+ LastSectorCount
) &&
807 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
809 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
811 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
814 if (NewPartEntry
== NULL
)
817 NewPartEntry
->DiskEntry
= DiskEntry
;
818 NewPartEntry
->LogicalPartition
= TRUE
;
820 NewPartEntry
->IsPartitioned
= FALSE
;
821 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
822 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
823 NewPartEntry
->StartSector
.QuadPart
;
824 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
825 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
826 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
828 NewPartEntry
->FormatState
= Unformatted
;
830 /* Insert the table into the list */
831 InsertTailList(&PartEntry
->ListEntry
,
832 &NewPartEntry
->ListEntry
);
835 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
836 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
839 Entry
= Entry
->Flink
;
842 /* Check for trailing unpartitioned disk space */
843 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
845 LastUnusedSectorCount
= Align(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
847 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
849 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
851 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
854 if (NewPartEntry
== NULL
)
857 NewPartEntry
->DiskEntry
= DiskEntry
;
858 NewPartEntry
->LogicalPartition
= TRUE
;
860 NewPartEntry
->IsPartitioned
= FALSE
;
861 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
862 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
863 NewPartEntry
->StartSector
.QuadPart
;
864 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
865 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
866 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
868 NewPartEntry
->FormatState
= Unformatted
;
870 /* Append the table to the list */
871 InsertTailList(&DiskEntry
->LogicalPartListHead
,
872 &NewPartEntry
->ListEntry
);
877 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
885 IN PDISKENTRY DiskEntry
)
887 LARGE_INTEGER SystemTime
;
888 TIME_FIELDS TimeFields
;
890 PDISKENTRY DiskEntry2
;
893 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
897 NtQuerySystemTime(&SystemTime
);
898 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
900 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
901 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
902 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
903 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
905 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
910 /* check if the signature already exist */
912 * Check also signatures from disks, which are
913 * not visible (bootable) by the bios.
915 Entry2
= List
->DiskListHead
.Flink
;
916 while (Entry2
!= &List
->DiskListHead
)
918 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
920 if (DiskEntry
!= DiskEntry2
&&
921 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
924 Entry2
= Entry2
->Flink
;
927 if (Entry2
== &List
->DiskListHead
)
935 UpdateDiskSignatures(
939 PDISKENTRY DiskEntry
;
941 /* Print partition lines*/
942 Entry
= List
->DiskListHead
.Flink
;
943 while (Entry
!= &List
->DiskListHead
)
945 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
947 if (DiskEntry
->LayoutBuffer
&&
948 DiskEntry
->LayoutBuffer
->Signature
== 0)
950 SetDiskSignature(List
, DiskEntry
);
951 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
954 Entry
= Entry
->Flink
;
966 DISK_GEOMETRY DiskGeometry
;
967 SCSI_ADDRESS ScsiAddress
;
968 PDISKENTRY DiskEntry
;
969 IO_STATUS_BLOCK Iosb
;
971 PPARTITION_SECTOR Mbr
;
973 LARGE_INTEGER FileOffset
;
974 WCHAR Identifier
[20];
978 PLIST_ENTRY ListEntry
;
979 PBIOSDISKENTRY BiosDiskEntry
;
980 ULONG LayoutBufferSize
;
982 Status
= NtDeviceIoControlFile(FileHandle
,
987 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
991 sizeof(DISK_GEOMETRY
));
992 if (!NT_SUCCESS(Status
))
997 if (DiskGeometry
.MediaType
!= FixedMedia
&&
998 DiskGeometry
.MediaType
!= RemovableMedia
)
1003 Status
= NtDeviceIoControlFile(FileHandle
,
1008 IOCTL_SCSI_GET_ADDRESS
,
1012 sizeof(SCSI_ADDRESS
));
1013 if (!NT_SUCCESS(Status
))
1018 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1020 DiskGeometry
.BytesPerSector
);
1026 FileOffset
.QuadPart
= 0;
1027 Status
= NtReadFile(FileHandle
,
1033 DiskGeometry
.BytesPerSector
,
1036 if (!NT_SUCCESS(Status
))
1038 RtlFreeHeap(ProcessHeap
,
1041 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1044 Signature
= Mbr
->Signature
;
1046 /* Calculate the MBR checksum */
1048 Buffer
= (PULONG
)Mbr
;
1049 for (i
= 0; i
< 128; i
++)
1051 Checksum
+= Buffer
[i
];
1053 Checksum
= ~Checksum
+ 1;
1055 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1056 DPRINT("Identifier: %S\n", Identifier
);
1058 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1061 if (DiskEntry
== NULL
)
1066 // DiskEntry->Checksum = Checksum;
1067 // DiskEntry->Signature = Signature;
1068 DiskEntry
->BiosFound
= FALSE
;
1070 /* Check if this disk has a valid MBR */
1071 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1072 DiskEntry
->NoMbr
= TRUE
;
1074 DiskEntry
->NoMbr
= FALSE
;
1076 /* Free Mbr sector buffer */
1077 RtlFreeHeap(ProcessHeap
,
1081 ListEntry
= List
->BiosDiskListHead
.Flink
;
1082 while(ListEntry
!= &List
->BiosDiskListHead
)
1084 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1086 * Compare the size from bios and the reported size from driver.
1087 * If we have more than one disk with a zero or with the same signatur
1088 * we must create new signatures and reboot. After the reboot,
1089 * it is possible to identify the disks.
1091 if (BiosDiskEntry
->Signature
== Signature
&&
1092 BiosDiskEntry
->Checksum
== Checksum
&&
1093 !BiosDiskEntry
->Recognized
)
1095 if (!DiskEntry
->BiosFound
)
1097 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1098 DiskEntry
->BiosFound
= TRUE
;
1099 BiosDiskEntry
->Recognized
= TRUE
;
1105 ListEntry
= ListEntry
->Flink
;
1108 if (!DiskEntry
->BiosFound
)
1111 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1114 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1118 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1119 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1121 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1122 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1123 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1124 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1126 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1127 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1128 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1129 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1131 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1132 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1133 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1135 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1137 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1138 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1140 DiskEntry
->DiskNumber
= DiskNumber
;
1141 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1142 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1143 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1145 GetDriverName(DiskEntry
);
1147 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1150 * Allocate a buffer for 26 logical drives (2 entries each == 52)
1151 * plus the main partiton table (4 entries). Total 56 entries.
1153 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1154 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1155 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1158 if (DiskEntry
->LayoutBuffer
== NULL
)
1163 Status
= NtDeviceIoControlFile(FileHandle
,
1168 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1171 DiskEntry
->LayoutBuffer
,
1173 if (NT_SUCCESS(Status
))
1175 #ifdef DUMP_PARTITION_TABLE
1176 DumpPartitionTable(DiskEntry
);
1179 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1180 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1181 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1183 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1185 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1187 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% 1048756 == 0)
1189 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry
->BytesPerSector
);
1193 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1198 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry
->BytesPerSector
);
1202 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1204 DiskEntry
->NewDisk
= TRUE
;
1205 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1207 for (i
= 0; i
< 4; i
++)
1208 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1212 for (i
= 0; i
< 4; i
++)
1214 AddPartitionToDisk(DiskNumber
,
1220 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1222 AddPartitionToDisk(DiskNumber
,
1230 ScanForUnpartitionedDiskSpace(DiskEntry
);
1235 CreatePartitionList(
1242 OBJECT_ATTRIBUTES ObjectAttributes
;
1243 SYSTEM_DEVICE_INFORMATION Sdi
;
1244 IO_STATUS_BLOCK Iosb
;
1248 WCHAR Buffer
[MAX_PATH
];
1249 UNICODE_STRING Name
;
1252 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1260 List
->Right
= Right
;
1261 List
->Bottom
= Bottom
;
1266 List
->TopDisk
= (ULONG
)-1;
1267 List
->TopPartition
= (ULONG
)-1;
1269 List
->CurrentDisk
= NULL
;
1270 List
->CurrentPartition
= NULL
;
1272 InitializeListHead(&List
->DiskListHead
);
1273 InitializeListHead(&List
->BiosDiskListHead
);
1275 EnumerateBiosDiskEntries(List
);
1277 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1279 sizeof(SYSTEM_DEVICE_INFORMATION
),
1281 if (!NT_SUCCESS(Status
))
1283 RtlFreeHeap(ProcessHeap
, 0, List
);
1287 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1290 L
"\\Device\\Harddisk%d\\Partition0",
1292 RtlInitUnicodeString(&Name
,
1295 InitializeObjectAttributes(&ObjectAttributes
,
1301 Status
= NtOpenFile(&FileHandle
,
1302 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1306 FILE_SYNCHRONOUS_IO_NONALERT
);
1307 if (NT_SUCCESS(Status
))
1309 AddDiskToList(FileHandle
,
1313 NtClose(FileHandle
);
1317 UpdateDiskSignatures(List
);
1319 AssignDriveLetters(List
);
1322 List
->TopPartition
= 0;
1324 /* Search for first usable disk and partition */
1325 if (IsListEmpty(&List
->DiskListHead
))
1327 List
->CurrentDisk
= NULL
;
1328 List
->CurrentPartition
= NULL
;
1332 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1336 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1338 List
->CurrentPartition
= 0;
1342 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1353 DestroyPartitionList(
1356 PDISKENTRY DiskEntry
;
1357 PBIOSDISKENTRY BiosDiskEntry
;
1358 PPARTENTRY PartEntry
;
1361 /* Release disk and partition info */
1362 while (!IsListEmpty(&List
->DiskListHead
))
1364 Entry
= RemoveHeadList(&List
->DiskListHead
);
1365 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1367 /* Release driver name */
1368 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1370 /* Release primary partition list */
1371 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1373 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1374 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1376 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1379 /* Release logical partition list */
1380 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1382 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1383 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1385 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1388 /* Release layout buffer */
1389 if (DiskEntry
->LayoutBuffer
!= NULL
)
1390 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1393 /* Release disk entry */
1394 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1397 /* release the bios disk info */
1398 while(!IsListEmpty(&List
->BiosDiskListHead
))
1400 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1401 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1403 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1406 /* Release list head */
1407 RtlFreeHeap(ProcessHeap
, 0, List
);
1421 Width
= List
->Right
- List
->Left
- 1;
1422 Height
= List
->Bottom
- List
->Top
- 2;
1424 coPos
.X
= List
->Left
+ 1;
1425 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1427 if (List
->Line
>= 0 && List
->Line
<= Height
)
1429 FillConsoleOutputAttribute(StdOutput
,
1430 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1435 FillConsoleOutputCharacterA(StdOutput
,
1450 PDISKENTRY DiskEntry
,
1451 PPARTENTRY PartEntry
)
1453 CHAR LineBuffer
[128];
1458 LARGE_INTEGER PartSize
;
1463 Width
= List
->Right
- List
->Left
- 1;
1464 Height
= List
->Bottom
- List
->Top
- 2;
1466 coPos
.X
= List
->Left
+ 1;
1467 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1469 if (PartEntry
->IsPartitioned
== FALSE
)
1471 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1473 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1475 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1476 Unit
= MUIGetString(STRING_GB
);
1480 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1482 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1483 Unit
= MUIGetString(STRING_MB
);
1487 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1488 Unit
= MUIGetString(STRING_KB
);
1492 MUIGetString(STRING_UNPSPACE
),
1493 PartEntry
->LogicalPartition
? " " : "",
1494 PartEntry
->LogicalPartition
? "" : " ",
1500 /* Determine partition type */
1502 if (PartEntry
->New
== TRUE
)
1504 PartType
= MUIGetString(STRING_UNFORMATTED
);
1506 else if (PartEntry
->IsPartitioned
== TRUE
)
1508 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1509 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1510 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1511 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1515 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1516 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1520 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1524 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1526 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1528 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1529 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1531 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1535 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1537 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1539 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1540 Unit
= MUIGetString(STRING_GB
);
1544 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1546 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1547 Unit
= MUIGetString(STRING_MB
);
1551 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1552 Unit
= MUIGetString(STRING_KB
);
1555 if (PartType
== NULL
)
1558 MUIGetString(STRING_HDDINFOUNK5
),
1559 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1560 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1561 PartEntry
->BootIndicator
? '*' : ' ',
1562 PartEntry
->LogicalPartition
? " " : "",
1563 PartEntry
->PartitionType
,
1564 PartEntry
->LogicalPartition
? "" : " ",
1571 "%c%c %c %s%-24s%s %6lu %s",
1572 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1573 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1574 PartEntry
->BootIndicator
? '*' : ' ',
1575 PartEntry
->LogicalPartition
? " " : "",
1577 PartEntry
->LogicalPartition
? "" : " ",
1583 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1584 List
->CurrentPartition
== PartEntry
) ?
1585 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1586 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1588 if (List
->Line
>= 0 && List
->Line
<= Height
)
1590 FillConsoleOutputCharacterA(StdOutput
,
1598 if (List
->Line
>= 0 && List
->Line
<= Height
)
1600 FillConsoleOutputAttribute(StdOutput
,
1608 if (List
->Line
>= 0 && List
->Line
<= Height
)
1610 WriteConsoleOutputCharacterA(StdOutput
,
1612 min(strlen(LineBuffer
), Width
),
1625 PDISKENTRY DiskEntry
)
1627 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1628 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1629 CHAR LineBuffer
[128];
1634 ULARGE_INTEGER DiskSize
;
1637 Width
= List
->Right
- List
->Left
- 1;
1638 Height
= List
->Bottom
- List
->Top
- 2;
1640 coPos
.X
= List
->Left
+ 1;
1641 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1643 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1644 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1646 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1647 Unit
= MUIGetString(STRING_GB
);
1651 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1652 if (DiskSize
.QuadPart
== 0)
1653 DiskSize
.QuadPart
= 1;
1654 Unit
= MUIGetString(STRING_MB
);
1657 if (DiskEntry
->DriverName
.Length
> 0)
1660 MUIGetString(STRING_HDINFOPARTSELECT
),
1663 DiskEntry
->DiskNumber
,
1667 DiskEntry
->DriverName
.Buffer
);
1672 MUIGetString(STRING_HDDINFOUNK6
),
1675 DiskEntry
->DiskNumber
,
1681 if (List
->Line
>= 0 && List
->Line
<= Height
)
1683 FillConsoleOutputAttribute(StdOutput
,
1684 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1689 FillConsoleOutputCharacterA(StdOutput
,
1697 if (List
->Line
>= 0 && List
->Line
<= Height
)
1699 WriteConsoleOutputCharacterA(StdOutput
,
1701 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1708 /* Print separator line */
1709 PrintEmptyLine(List
);
1711 /* Print partition lines*/
1712 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1713 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1715 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1717 PrintPartitionData(List
,
1721 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1723 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1724 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1726 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1728 PrintPartitionData(List
,
1732 LogicalEntry
= LogicalEntry
->Flink
;
1736 PrimaryEntry
= PrimaryEntry
->Flink
;
1739 /* Print separator line */
1740 PrintEmptyLine(List
);
1748 PLIST_ENTRY Entry
, Entry2
;
1749 PDISKENTRY DiskEntry
;
1750 PPARTENTRY PartEntry
= NULL
;
1754 SHORT CurrentDiskLine
;
1755 SHORT CurrentPartLine
;
1757 BOOL CurrentPartLineFound
= FALSE
;
1758 BOOL CurrentDiskLineFound
= FALSE
;
1760 /* Calculate the line of the current disk and partition */
1761 CurrentDiskLine
= 0;
1762 CurrentPartLine
= 0;
1765 Entry
= List
->DiskListHead
.Flink
;
1766 while (Entry
!= &List
->DiskListHead
)
1768 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1771 if (CurrentPartLineFound
== FALSE
)
1773 CurrentPartLine
+= 2;
1776 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1777 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1779 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1780 if (PartEntry
== List
->CurrentPartition
)
1782 CurrentPartLineFound
= TRUE
;
1785 Entry2
= Entry2
->Flink
;
1786 if (CurrentPartLineFound
== FALSE
)
1794 if (DiskEntry
== List
->CurrentDisk
)
1796 CurrentDiskLineFound
= TRUE
;
1799 Entry
= Entry
->Flink
;
1800 if (Entry
!= &List
->DiskListHead
)
1802 if (CurrentDiskLineFound
== FALSE
)
1805 CurrentDiskLine
= CurrentPartLine
;
1816 /* If it possible, make the disk name visible */
1817 if (CurrentPartLine
< List
->Offset
)
1819 List
->Offset
= CurrentPartLine
;
1821 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1823 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1826 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1828 List
->Offset
= CurrentDiskLine
;
1831 /* draw upper left corner */
1832 coPos
.X
= List
->Left
;
1833 coPos
.Y
= List
->Top
;
1834 FillConsoleOutputCharacterA(StdOutput
,
1840 /* draw upper edge */
1841 coPos
.X
= List
->Left
+ 1;
1842 coPos
.Y
= List
->Top
;
1843 if (List
->Offset
== 0)
1845 FillConsoleOutputCharacterA(StdOutput
,
1847 List
->Right
- List
->Left
- 1,
1853 FillConsoleOutputCharacterA(StdOutput
,
1855 List
->Right
- List
->Left
- 5,
1858 coPos
.X
= List
->Right
- 5;
1859 WriteConsoleOutputCharacterA(StdOutput
,
1864 coPos
.X
= List
->Right
- 2;
1865 FillConsoleOutputCharacterA(StdOutput
,
1872 /* draw upper right corner */
1873 coPos
.X
= List
->Right
;
1874 coPos
.Y
= List
->Top
;
1875 FillConsoleOutputCharacterA(StdOutput
,
1881 /* draw left and right edge */
1882 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1884 coPos
.X
= List
->Left
;
1886 FillConsoleOutputCharacterA(StdOutput
,
1892 coPos
.X
= List
->Right
;
1893 FillConsoleOutputCharacterA(StdOutput
,
1900 /* draw lower left corner */
1901 coPos
.X
= List
->Left
;
1902 coPos
.Y
= List
->Bottom
;
1903 FillConsoleOutputCharacterA(StdOutput
,
1909 /* draw lower edge */
1910 coPos
.X
= List
->Left
+ 1;
1911 coPos
.Y
= List
->Bottom
;
1912 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1914 FillConsoleOutputCharacterA(StdOutput
,
1916 List
->Right
- List
->Left
- 1,
1922 FillConsoleOutputCharacterA(StdOutput
,
1924 List
->Right
- List
->Left
- 5,
1927 coPos
.X
= List
->Right
- 5;
1928 WriteConsoleOutputCharacterA(StdOutput
,
1929 "(\x19)", // "(down)"
1933 coPos
.X
= List
->Right
- 2;
1934 FillConsoleOutputCharacterA(StdOutput
,
1941 /* draw lower right corner */
1942 coPos
.X
= List
->Right
;
1943 coPos
.Y
= List
->Bottom
;
1944 FillConsoleOutputCharacterA(StdOutput
,
1950 /* print list entries */
1951 List
->Line
= - List
->Offset
;
1953 Entry
= List
->DiskListHead
.Flink
;
1954 while (Entry
!= &List
->DiskListHead
)
1956 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1958 /* Print disk entry */
1962 Entry
= Entry
->Flink
;
1971 ULONG PartitionNumber
)
1973 PDISKENTRY DiskEntry
;
1974 PPARTENTRY PartEntry
;
1978 /* Check for empty disks */
1979 if (IsListEmpty(&List
->DiskListHead
))
1982 /* Check for first usable entry on next disk */
1983 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1984 while (Entry1
!= &List
->DiskListHead
)
1986 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1988 if (DiskEntry
->DiskNumber
== DiskNumber
)
1990 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1991 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1993 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1995 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1997 List
->CurrentDisk
= DiskEntry
;
1998 List
->CurrentPartition
= PartEntry
;
1999 DrawPartitionList(List
);
2003 Entry2
= Entry2
->Flink
;
2009 Entry1
= Entry1
->Flink
;
2017 ScrollDownPartitionList(
2020 PLIST_ENTRY DiskListEntry
;
2021 PLIST_ENTRY PartListEntry
;
2022 PDISKENTRY DiskEntry
;
2023 PPARTENTRY PartEntry
;
2025 /* Fail, if no disks are available */
2026 if (IsListEmpty(&List
->DiskListHead
))
2029 /* Check for next usable entry on current disk */
2030 if (List
->CurrentPartition
!= NULL
)
2032 if (List
->CurrentPartition
->LogicalPartition
)
2034 /* Logical partition */
2036 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2037 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2039 /* Next logical partition */
2040 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2042 List
->CurrentPartition
= PartEntry
;
2047 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2048 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2050 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2052 List
->CurrentPartition
= PartEntry
;
2059 /* Primary or extended partition */
2061 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2062 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2064 /* First logical partition */
2065 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2066 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2068 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2070 List
->CurrentPartition
= PartEntry
;
2076 /* Next primary partition */
2077 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2078 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2080 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2082 List
->CurrentPartition
= PartEntry
;
2089 /* Search for the first partition entry on the next disk */
2090 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2091 while (DiskListEntry
!= &List
->DiskListHead
)
2093 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2095 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2096 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2098 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2100 List
->CurrentDisk
= DiskEntry
;
2101 List
->CurrentPartition
= PartEntry
;
2105 DiskListEntry
= DiskListEntry
->Flink
;
2113 ScrollUpPartitionList(
2116 PLIST_ENTRY DiskListEntry
;
2117 PLIST_ENTRY PartListEntry
;
2118 PDISKENTRY DiskEntry
;
2119 PPARTENTRY PartEntry
;
2121 /* Fail, if no disks are available */
2122 if (IsListEmpty(&List
->DiskListHead
))
2125 /* Check for previous usable entry on current disk */
2126 if (List
->CurrentPartition
!= NULL
)
2128 if (List
->CurrentPartition
->LogicalPartition
)
2130 /* Logical partition */
2131 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2132 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2134 /* Previous logical partition */
2135 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2139 /* Extended partition*/
2140 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2143 List
->CurrentPartition
= PartEntry
;
2148 /* Primary or extended partition */
2150 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2151 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2153 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2155 if (PartEntry
->IsPartitioned
== TRUE
&&
2156 IsContainerPartition(PartEntry
->PartitionType
))
2158 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2159 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2162 List
->CurrentPartition
= PartEntry
;
2169 /* Search for the last partition entry on the previous disk */
2170 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2171 while (DiskListEntry
!= &List
->DiskListHead
)
2173 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2175 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2176 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2178 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2180 if (PartEntry
->IsPartitioned
== TRUE
&&
2181 IsContainerPartition(PartEntry
->PartitionType
))
2183 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2184 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2186 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2188 List
->CurrentDisk
= DiskEntry
;
2189 List
->CurrentPartition
= PartEntry
;
2195 List
->CurrentDisk
= DiskEntry
;
2196 List
->CurrentPartition
= PartEntry
;
2201 DiskListEntry
= DiskListEntry
->Blink
;
2211 PPARTITION_INFORMATION PartitionInfo
)
2213 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2214 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2215 // PartitionInfo->PartitionType == 0)
2224 IsSamePrimaryLayoutEntry(
2225 IN PPARTITION_INFORMATION PartitionInfo
,
2226 IN PDISKENTRY DiskEntry
,
2227 IN PPARTENTRY PartEntry
)
2229 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2230 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2231 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2232 // PartitionInfo->PartitionType == PartEntry->PartitionType
2242 IN PDISKENTRY DiskEntry
)
2244 PPARTITION_INFORMATION PartitionInfo
;
2245 PLIST_ENTRY ListEntry
;
2246 PPARTENTRY PartEntry
;
2248 ULONG PartitionNumber
= 1;
2250 DPRINT1("UpdateDiskLayout()\n");
2252 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2253 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2255 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2257 if (PartEntry
->IsPartitioned
== TRUE
)
2259 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2261 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2263 DPRINT1("Updating partition entry %lu\n", Index
);
2264 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2265 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2266 PartitionInfo
->HiddenSectors
= 0;
2267 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2268 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2269 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2270 PartitionInfo
->RecognizedPartition
= FALSE
;
2271 PartitionInfo
->RewritePartition
= TRUE
;
2273 PartEntry
->PartitionNumber
= PartitionNumber
;
2274 PartEntry
->PartitionIndex
= Index
;
2278 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2286 ListEntry
= ListEntry
->Flink
;
2289 for (;Index
< 4; Index
++)
2291 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2293 if (!IsEmptyLayoutEntry(PartitionInfo
))
2295 DPRINT1("Wiping partition entry %lu\n", Index
);
2296 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2297 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2298 PartitionInfo
->HiddenSectors
= 0;
2299 PartitionInfo
->PartitionNumber
= 0;
2300 PartitionInfo
->PartitionType
= 0;
2301 PartitionInfo
->BootIndicator
= FALSE
;
2302 PartitionInfo
->RecognizedPartition
= FALSE
;
2303 PartitionInfo
->RewritePartition
= TRUE
;
2307 #ifdef DUMP_PARTITION_TABLE
2308 DumpPartitionTable(DiskEntry
);
2315 GetPrevUnpartitionedEntry(
2316 PDISKENTRY DiskEntry
,
2317 PPARTENTRY PartEntry
)
2319 PPARTENTRY PrevPartEntry
;
2321 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PrimaryPartListHead
)
2323 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2326 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2327 return PrevPartEntry
;
2336 GetNextUnpartitionedEntry(
2337 PDISKENTRY DiskEntry
,
2338 PPARTENTRY PartEntry
)
2340 PPARTENTRY NextPartEntry
;
2342 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PrimaryPartListHead
)
2344 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2347 if (NextPartEntry
->IsPartitioned
== FALSE
)
2348 return NextPartEntry
;
2356 CreatePrimaryPartition(
2358 ULONGLONG SectorCount
,
2361 PDISKENTRY DiskEntry
;
2362 PPARTENTRY PartEntry
;
2363 PPARTENTRY NewPartEntry
;
2365 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2368 List
->CurrentDisk
== NULL
||
2369 List
->CurrentPartition
== NULL
||
2370 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2375 DiskEntry
= List
->CurrentDisk
;
2376 PartEntry
= List
->CurrentPartition
;
2378 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2380 if (AutoCreate
== TRUE
||
2381 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2383 DPRINT1("Convert existing partition entry\n");
2384 /* Convert current entry to 'new (unformatted)' */
2385 PartEntry
->IsPartitioned
= TRUE
;
2386 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2387 PartEntry
->FormatState
= Unformatted
;
2388 PartEntry
->AutoCreate
= AutoCreate
;
2389 PartEntry
->New
= TRUE
;
2390 PartEntry
->BootIndicator
= FALSE
;
2392 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2393 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2394 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2398 DPRINT1("Add new partition entry\n");
2400 /* Insert and initialize a new partition entry */
2401 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2404 if (NewPartEntry
== NULL
)
2407 /* Insert the new entry into the list */
2408 InsertTailList(&PartEntry
->ListEntry
,
2409 &NewPartEntry
->ListEntry
);
2411 NewPartEntry
->DiskEntry
= DiskEntry
;
2413 NewPartEntry
->IsPartitioned
= TRUE
;
2414 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2415 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2416 NewPartEntry
->StartSector
.QuadPart
;
2417 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2419 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2420 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2421 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2423 NewPartEntry
->New
= TRUE
;
2424 NewPartEntry
->FormatState
= Unformatted
;
2425 NewPartEntry
->BootIndicator
= FALSE
;
2427 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2428 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2431 UpdateDiskLayout(DiskEntry
);
2433 DiskEntry
->Dirty
= TRUE
;
2435 UpdatePartitionNumbers(DiskEntry
);
2437 AssignDriveLetters(List
);
2443 AddLogicalDiskSpace(
2444 PDISKENTRY DiskEntry
)
2446 PPARTENTRY NewPartEntry
;
2448 DPRINT1("AddLogicalDiskSpace()\n");
2450 /* Create a partition table entry that represents the empty space in the container partition */
2451 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2454 if (NewPartEntry
== NULL
)
2457 NewPartEntry
->DiskEntry
= DiskEntry
;
2458 NewPartEntry
->LogicalPartition
= TRUE
;
2460 NewPartEntry
->IsPartitioned
= FALSE
;
2461 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
2462 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
2464 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2465 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2466 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2468 NewPartEntry
->FormatState
= Unformatted
;
2470 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2471 &NewPartEntry
->ListEntry
);
2476 CreateExtendedPartition(
2478 ULONGLONG SectorCount
)
2480 PDISKENTRY DiskEntry
;
2481 PPARTENTRY PartEntry
;
2482 PPARTENTRY NewPartEntry
;
2484 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2487 List
->CurrentDisk
== NULL
||
2488 List
->CurrentPartition
== NULL
||
2489 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2494 DiskEntry
= List
->CurrentDisk
;
2495 PartEntry
= List
->CurrentPartition
;
2497 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2499 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2501 DPRINT1("Convert existing partition entry\n");
2502 /* Convert current entry to 'new (unformatted)' */
2503 PartEntry
->IsPartitioned
= TRUE
;
2504 PartEntry
->FormatState
= Formatted
;
2505 PartEntry
->AutoCreate
= FALSE
;
2506 PartEntry
->New
= FALSE
;
2507 PartEntry
->BootIndicator
= FALSE
;
2509 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2511 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2512 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2516 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2517 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2520 DiskEntry
->ExtendedPartition
= PartEntry
;
2522 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2523 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2524 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2528 DPRINT1("Add new partition entry\n");
2530 /* Insert and initialize a new partition entry */
2531 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2534 if (NewPartEntry
== NULL
)
2537 /* Insert the new entry into the list */
2538 InsertTailList(&PartEntry
->ListEntry
,
2539 &NewPartEntry
->ListEntry
);
2541 NewPartEntry
->DiskEntry
= DiskEntry
;
2543 NewPartEntry
->IsPartitioned
= TRUE
;
2544 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2545 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2546 NewPartEntry
->StartSector
.QuadPart
;
2548 NewPartEntry
->New
= FALSE
;
2549 NewPartEntry
->FormatState
= Formatted
;
2550 NewPartEntry
->BootIndicator
= FALSE
;
2552 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2554 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2555 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2559 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2560 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2563 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2565 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2566 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2568 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2569 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2570 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2573 AddLogicalDiskSpace(DiskEntry
);
2575 UpdateDiskLayout(DiskEntry
);
2577 DiskEntry
->Dirty
= TRUE
;
2579 UpdatePartitionNumbers(DiskEntry
);
2581 AssignDriveLetters(List
);
2586 CreateLogicalPartition(
2588 ULONGLONG SectorCount
)
2590 // PDISKENTRY DiskEntry;
2591 PPARTENTRY PartEntry
;
2592 // PPARTENTRY NewPartEntry;
2594 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2597 List
->CurrentDisk
== NULL
||
2598 List
->CurrentPartition
== NULL
||
2599 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2604 // DiskEntry = List->CurrentDisk;
2605 PartEntry
= List
->CurrentPartition
;
2607 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2612 DeleteCurrentPartition(
2615 PDISKENTRY DiskEntry
;
2616 PPARTENTRY PartEntry
;
2617 PPARTENTRY PrevPartEntry
;
2618 PPARTENTRY NextPartEntry
;
2619 PPARTENTRY LogicalPartEntry
;
2623 List
->CurrentDisk
== NULL
||
2624 List
->CurrentPartition
== NULL
||
2625 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2630 DiskEntry
= List
->CurrentDisk
;
2631 PartEntry
= List
->CurrentPartition
;
2633 /* Delete all logical partiton entries if an extended partition will be deleted */
2634 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2636 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2638 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2639 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2641 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2644 DiskEntry
->ExtendedPartition
= NULL
;
2647 /* Adjust unpartitioned disk space entries */
2649 /* Get pointer to previous and next unpartitioned entries */
2650 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2653 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2656 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2658 /* Merge previous, current and next unpartitioned entry */
2660 /* Adjust the previous entries length */
2661 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2663 /* Remove the current entry */
2664 RemoveEntryList(&PartEntry
->ListEntry
);
2665 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2667 /* Remove the next entry */
2668 RemoveEntryList (&NextPartEntry
->ListEntry
);
2669 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2671 /* Update current partition */
2672 List
->CurrentPartition
= PrevPartEntry
;
2674 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2676 /* Merge current and previous unpartitioned entry */
2678 /* Adjust the previous entries length */
2679 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2681 /* Remove the current entry */
2682 RemoveEntryList(&PartEntry
->ListEntry
);
2683 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2685 /* Update current partition */
2686 List
->CurrentPartition
= PrevPartEntry
;
2688 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2690 /* Merge current and next unpartitioned entry */
2692 /* Adjust the next entries offset and length */
2693 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2694 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2696 /* Remove the current entry */
2697 RemoveEntryList(&PartEntry
->ListEntry
);
2698 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2700 /* Update current partition */
2701 List
->CurrentPartition
= NextPartEntry
;
2705 /* Nothing to merge but change current entry */
2706 PartEntry
->IsPartitioned
= FALSE
;
2707 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2708 PartEntry
->FormatState
= Unformatted
;
2709 PartEntry
->DriveLetter
= 0;
2712 UpdateDiskLayout(DiskEntry
);
2714 DiskEntry
->Dirty
= TRUE
;
2716 UpdatePartitionNumbers(DiskEntry
);
2718 AssignDriveLetters(List
);
2723 CheckActiveBootPartition(
2726 PDISKENTRY DiskEntry
;
2727 PPARTENTRY PartEntry
;
2728 PLIST_ENTRY ListEntry
;
2730 /* Check for empty disk list */
2731 if (IsListEmpty (&List
->DiskListHead
))
2733 List
->ActiveBootDisk
= NULL
;
2734 List
->ActiveBootPartition
= NULL
;
2739 if (List
->ActiveBootDisk
!= NULL
&&
2740 List
->ActiveBootPartition
!= NULL
)
2742 /* We already have an active boot partition */
2747 /* Choose the currently selected disk */
2748 DiskEntry
= List
->CurrentDisk
;
2750 /* Check for empty partition list */
2751 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2753 List
->ActiveBootDisk
= NULL
;
2754 List
->ActiveBootPartition
= NULL
;
2758 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2762 /* Set active boot partition */
2763 if ((DiskEntry
->NewDisk
== TRUE
) ||
2764 (PartEntry
->BootIndicator
== FALSE
))
2766 PartEntry
->BootIndicator
= TRUE
;
2767 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2768 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2769 DiskEntry
->Dirty
= TRUE
;
2771 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2772 List
->ActiveBootDisk
= DiskEntry
;
2773 List
->ActiveBootPartition
= PartEntry
;
2778 /* Disk is not new, scan all partitions to find a bootable one */
2779 List
->ActiveBootDisk
= NULL
;
2780 List
->ActiveBootPartition
= NULL
;
2782 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2783 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2785 PartEntry
= CONTAINING_RECORD(ListEntry
,
2789 /* Check if it is partitioned */
2790 if (PartEntry
->IsPartitioned
)
2792 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2793 PartEntry
->BootIndicator
)
2795 /* Yes, we found it */
2796 List
->ActiveBootDisk
= DiskEntry
;
2797 List
->ActiveBootPartition
= PartEntry
;
2799 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2800 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2805 /* Go to the next one */
2806 ListEntry
= ListEntry
->Flink
;
2812 CheckForLinuxFdiskPartitions(
2816 PDISKENTRY DiskEntry
;
2817 PPARTENTRY PartEntry
;
2820 ULONG PartitionCount
;
2823 Entry1
= List
->DiskListHead
.Flink
;
2824 while (Entry1
!= &List
->DiskListHead
)
2826 DiskEntry
= CONTAINING_RECORD(Entry1
,
2830 Entry2
= DiskEntry
->PartListHead
.Flink
;
2831 while (Entry2
!= &DiskEntry
->PartListHead
)
2833 PartEntry
= CONTAINING_RECORD(Entry2
,
2837 if (PartEntry
->Unpartitioned
== FALSE
)
2841 for (i
= 0; i
< 4; i
++)
2843 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2844 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2850 if (PartitionCount
> 1)
2856 Entry2
= Entry2
->Flink
;
2859 Entry1
= Entry1
->Flink
;
2871 IN PDISKENTRY DiskEntry
)
2873 WCHAR DstPath
[MAX_PATH
];
2874 OBJECT_ATTRIBUTES ObjectAttributes
;
2875 IO_STATUS_BLOCK Iosb
;
2876 UNICODE_STRING Name
;
2878 HANDLE FileHandle
= NULL
;
2881 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2884 L
"\\Device\\Harddisk%d\\Partition0",
2885 DiskEntry
->DiskNumber
);
2886 RtlInitUnicodeString(&Name
,
2888 InitializeObjectAttributes(&ObjectAttributes
,
2894 Status
= NtOpenFile(&FileHandle
,
2895 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2899 FILE_SYNCHRONOUS_IO_NONALERT
);
2900 if (!NT_SUCCESS(Status
))
2902 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2906 #ifdef DUMP_PARTITION_TABLE
2907 DumpPartitionTable(DiskEntry
);
2910 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2911 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2912 Status
= NtDeviceIoControlFile(FileHandle
,
2917 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2918 DiskEntry
->LayoutBuffer
,
2922 if (!NT_SUCCESS(Status
))
2924 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2927 if (FileHandle
!= NULL
)
2928 NtClose(FileHandle
);
2935 WritePartitionsToDisk(
2939 PDISKENTRY DiskEntry
;
2944 Entry
= List
->DiskListHead
.Flink
;
2945 while (Entry
!= &List
->DiskListHead
)
2947 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2949 if (DiskEntry
->Dirty
== TRUE
)
2951 WritePartitons(List
, DiskEntry
);
2954 Entry
= Entry
->Flink
;
2962 SetMountedDeviceValues(
2965 PLIST_ENTRY Entry1
, Entry2
;
2966 PDISKENTRY DiskEntry
;
2967 PPARTENTRY PartEntry
;
2968 LARGE_INTEGER StartingOffset
;
2975 Entry1
= List
->DiskListHead
.Flink
;
2976 while (Entry1
!= &List
->DiskListHead
)
2978 DiskEntry
= CONTAINING_RECORD(Entry1
,
2982 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2983 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2985 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2986 if (PartEntry
->IsPartitioned
)
2988 if (PartEntry
->DriveLetter
)
2990 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2991 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2992 DiskEntry
->LayoutBuffer
->Signature
,
3000 Entry2
= Entry2
->Flink
;
3003 Entry1
= Entry1
->Flink
;
3012 GetPrimaryPartitionCount(
3013 IN PDISKENTRY DiskEntry
)
3016 PPARTENTRY PartEntry
;
3019 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3020 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
3022 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3023 if (PartEntry
->IsPartitioned
== TRUE
)
3026 Entry
= Entry
->Flink
;
3034 PrimaryPartitionCreationChecks(
3037 PDISKENTRY DiskEntry
;
3038 PPARTENTRY PartEntry
;
3040 DiskEntry
= List
->CurrentDisk
;
3041 PartEntry
= List
->CurrentPartition
;
3043 /* Fail if partition is already in use */
3044 if (PartEntry
->IsPartitioned
== TRUE
)
3045 return ERROR_NEW_PARTITION
;
3047 /* Fail if there are more than 4 partitions in the list */
3048 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3049 return ERROR_PARTITION_TABLE_FULL
;
3051 return ERROR_SUCCESS
;
3056 ExtendedPartitionCreationChecks(
3059 PDISKENTRY DiskEntry
;
3060 PPARTENTRY PartEntry
;
3062 DiskEntry
= List
->CurrentDisk
;
3063 PartEntry
= List
->CurrentPartition
;
3065 /* Fail if partition is already in use */
3066 if (PartEntry
->IsPartitioned
== TRUE
)
3067 return ERROR_NEW_PARTITION
;
3069 /* Fail if there are more than 4 partitions in the list */
3070 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3071 return ERROR_PARTITION_TABLE_FULL
;
3073 /* Fail if there is another extended partition in the list */
3074 if (DiskEntry
->ExtendedPartition
!= NULL
)
3075 return ERROR_ONLY_ONE_EXTENDED
;
3077 return ERROR_SUCCESS
;
3082 LogicalPartitionCreationChecks(
3085 // PDISKENTRY DiskEntry;
3086 PPARTENTRY PartEntry
;
3088 // DiskEntry = List->CurrentDisk;
3089 PartEntry
= List
->CurrentPartition
;
3091 /* Fail if partition is already in use */
3092 if (PartEntry
->IsPartitioned
== TRUE
)
3093 return ERROR_NEW_PARTITION
;
3095 return ERROR_SUCCESS
;