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 DPRINT1("\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
->SectorAlignment
;
660 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
661 NewPartEntry
->StartSector
.QuadPart
;
663 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
664 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
665 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
667 NewPartEntry
->FormatState
= Unformatted
;
669 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
670 &NewPartEntry
->ListEntry
);
675 /* Start partition at head 1, cylinder 0 */
676 LastStartSector
= DiskEntry
->SectorAlignment
;
677 LastSectorCount
= 0ULL;
678 LastUnusedSectorCount
= 0ULL;
680 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
681 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
683 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
685 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
686 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
688 LastUnusedSectorCount
=
689 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
691 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
692 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
694 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
696 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
699 if (NewPartEntry
== NULL
)
702 NewPartEntry
->DiskEntry
= DiskEntry
;
704 NewPartEntry
->IsPartitioned
= FALSE
;
705 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
706 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
707 NewPartEntry
->StartSector
.QuadPart
;
709 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
710 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
711 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
713 NewPartEntry
->FormatState
= Unformatted
;
715 /* Insert the table into the list */
716 InsertTailList(&PartEntry
->ListEntry
,
717 &NewPartEntry
->ListEntry
);
720 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
721 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
724 Entry
= Entry
->Flink
;
727 /* Check for trailing unpartitioned disk space */
728 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
730 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
732 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
734 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
736 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
739 if (NewPartEntry
== NULL
)
742 NewPartEntry
->DiskEntry
= DiskEntry
;
744 NewPartEntry
->IsPartitioned
= FALSE
;
745 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
746 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
747 NewPartEntry
->StartSector
.QuadPart
;
749 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
750 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
751 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
753 NewPartEntry
->FormatState
= Unformatted
;
755 /* Append the table to the list */
756 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
757 &NewPartEntry
->ListEntry
);
761 if (DiskEntry
->ExtendedPartition
!= NULL
)
763 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
765 DPRINT1("No logical partition!\n");
767 /* Create a partition table entry that represents the empty extended partition */
768 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
771 if (NewPartEntry
== NULL
)
774 NewPartEntry
->DiskEntry
= DiskEntry
;
775 NewPartEntry
->LogicalPartition
= TRUE
;
777 NewPartEntry
->IsPartitioned
= FALSE
;
778 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
779 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
781 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
782 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
783 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
785 NewPartEntry
->FormatState
= Unformatted
;
787 InsertTailList(&DiskEntry
->LogicalPartListHead
,
788 &NewPartEntry
->ListEntry
);
793 /* Start partition at head 1, cylinder 0 */
794 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
795 LastSectorCount
= 0ULL;
796 LastUnusedSectorCount
= 0ULL;
798 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
799 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
801 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
803 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
804 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
806 LastUnusedSectorCount
=
807 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
809 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
810 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
812 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
814 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
817 if (NewPartEntry
== NULL
)
820 NewPartEntry
->DiskEntry
= DiskEntry
;
821 NewPartEntry
->LogicalPartition
= TRUE
;
823 NewPartEntry
->IsPartitioned
= FALSE
;
824 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
825 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
826 NewPartEntry
->StartSector
.QuadPart
;
828 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
829 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
830 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
832 NewPartEntry
->FormatState
= Unformatted
;
834 /* Insert the table into the list */
835 InsertTailList(&PartEntry
->ListEntry
,
836 &NewPartEntry
->ListEntry
);
839 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
840 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
843 Entry
= Entry
->Flink
;
846 /* Check for trailing unpartitioned disk space */
847 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
849 LastUnusedSectorCount
= Align(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
851 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
853 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
855 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
858 if (NewPartEntry
== NULL
)
861 NewPartEntry
->DiskEntry
= DiskEntry
;
862 NewPartEntry
->LogicalPartition
= TRUE
;
864 NewPartEntry
->IsPartitioned
= FALSE
;
865 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
866 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
867 NewPartEntry
->StartSector
.QuadPart
;
869 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
870 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
871 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
873 NewPartEntry
->FormatState
= Unformatted
;
875 /* Append the table to the list */
876 InsertTailList(&DiskEntry
->LogicalPartListHead
,
877 &NewPartEntry
->ListEntry
);
882 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
890 IN PDISKENTRY DiskEntry
)
892 LARGE_INTEGER SystemTime
;
893 TIME_FIELDS TimeFields
;
895 PDISKENTRY DiskEntry2
;
898 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
902 NtQuerySystemTime(&SystemTime
);
903 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
905 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
906 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
907 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
908 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
910 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
915 /* check if the signature already exist */
917 * Check also signatures from disks, which are
918 * not visible (bootable) by the bios.
920 Entry2
= List
->DiskListHead
.Flink
;
921 while (Entry2
!= &List
->DiskListHead
)
923 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
925 if (DiskEntry
!= DiskEntry2
&&
926 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
929 Entry2
= Entry2
->Flink
;
932 if (Entry2
== &List
->DiskListHead
)
940 UpdateDiskSignatures(
944 PDISKENTRY DiskEntry
;
946 /* Print partition lines*/
947 Entry
= List
->DiskListHead
.Flink
;
948 while (Entry
!= &List
->DiskListHead
)
950 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
952 if (DiskEntry
->LayoutBuffer
&&
953 DiskEntry
->LayoutBuffer
->Signature
== 0)
955 SetDiskSignature(List
, DiskEntry
);
956 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
959 Entry
= Entry
->Flink
;
971 DISK_GEOMETRY DiskGeometry
;
972 SCSI_ADDRESS ScsiAddress
;
973 PDISKENTRY DiskEntry
;
974 IO_STATUS_BLOCK Iosb
;
976 PPARTITION_SECTOR Mbr
;
978 LARGE_INTEGER FileOffset
;
979 WCHAR Identifier
[20];
983 PLIST_ENTRY ListEntry
;
984 PBIOSDISKENTRY BiosDiskEntry
;
985 ULONG LayoutBufferSize
;
987 Status
= NtDeviceIoControlFile(FileHandle
,
992 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
996 sizeof(DISK_GEOMETRY
));
997 if (!NT_SUCCESS(Status
))
1002 if (DiskGeometry
.MediaType
!= FixedMedia
&&
1003 DiskGeometry
.MediaType
!= RemovableMedia
)
1008 Status
= NtDeviceIoControlFile(FileHandle
,
1013 IOCTL_SCSI_GET_ADDRESS
,
1017 sizeof(SCSI_ADDRESS
));
1018 if (!NT_SUCCESS(Status
))
1023 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1025 DiskGeometry
.BytesPerSector
);
1031 FileOffset
.QuadPart
= 0;
1032 Status
= NtReadFile(FileHandle
,
1038 DiskGeometry
.BytesPerSector
,
1041 if (!NT_SUCCESS(Status
))
1043 RtlFreeHeap(ProcessHeap
,
1046 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1049 Signature
= Mbr
->Signature
;
1051 /* Calculate the MBR checksum */
1053 Buffer
= (PULONG
)Mbr
;
1054 for (i
= 0; i
< 128; i
++)
1056 Checksum
+= Buffer
[i
];
1058 Checksum
= ~Checksum
+ 1;
1060 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1061 DPRINT("Identifier: %S\n", Identifier
);
1063 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1066 if (DiskEntry
== NULL
)
1071 // DiskEntry->Checksum = Checksum;
1072 // DiskEntry->Signature = Signature;
1073 DiskEntry
->BiosFound
= FALSE
;
1075 /* Check if this disk has a valid MBR */
1076 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1077 DiskEntry
->NoMbr
= TRUE
;
1079 DiskEntry
->NoMbr
= FALSE
;
1081 /* Free Mbr sector buffer */
1082 RtlFreeHeap(ProcessHeap
,
1086 ListEntry
= List
->BiosDiskListHead
.Flink
;
1087 while(ListEntry
!= &List
->BiosDiskListHead
)
1089 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1091 * Compare the size from bios and the reported size from driver.
1092 * If we have more than one disk with a zero or with the same signatur
1093 * we must create new signatures and reboot. After the reboot,
1094 * it is possible to identify the disks.
1096 if (BiosDiskEntry
->Signature
== Signature
&&
1097 BiosDiskEntry
->Checksum
== Checksum
&&
1098 !BiosDiskEntry
->Recognized
)
1100 if (!DiskEntry
->BiosFound
)
1102 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1103 DiskEntry
->BiosFound
= TRUE
;
1104 BiosDiskEntry
->Recognized
= TRUE
;
1110 ListEntry
= ListEntry
->Flink
;
1113 if (!DiskEntry
->BiosFound
)
1116 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1119 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1123 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1124 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1126 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1127 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1128 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1129 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1131 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1132 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1133 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1134 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1136 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1137 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1138 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1140 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1142 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1143 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1145 DiskEntry
->DiskNumber
= DiskNumber
;
1146 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1147 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1148 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1150 GetDriverName(DiskEntry
);
1152 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1155 * Allocate a buffer for 26 logical drives (2 entries each == 52)
1156 * plus the main partiton table (4 entries). Total 56 entries.
1158 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1159 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1160 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1163 if (DiskEntry
->LayoutBuffer
== NULL
)
1168 Status
= NtDeviceIoControlFile(FileHandle
,
1173 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1176 DiskEntry
->LayoutBuffer
,
1178 if (NT_SUCCESS(Status
))
1180 #ifdef DUMP_PARTITION_TABLE
1181 DumpPartitionTable(DiskEntry
);
1184 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1185 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1186 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1188 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1190 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1192 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1194 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1198 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1203 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1207 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1209 DiskEntry
->NewDisk
= TRUE
;
1210 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1212 for (i
= 0; i
< 4; i
++)
1213 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1217 for (i
= 0; i
< 4; i
++)
1219 AddPartitionToDisk(DiskNumber
,
1225 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1227 AddPartitionToDisk(DiskNumber
,
1235 ScanForUnpartitionedDiskSpace(DiskEntry
);
1240 CreatePartitionList(
1247 OBJECT_ATTRIBUTES ObjectAttributes
;
1248 SYSTEM_DEVICE_INFORMATION Sdi
;
1249 IO_STATUS_BLOCK Iosb
;
1253 WCHAR Buffer
[MAX_PATH
];
1254 UNICODE_STRING Name
;
1257 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1265 List
->Right
= Right
;
1266 List
->Bottom
= Bottom
;
1271 List
->TopDisk
= (ULONG
)-1;
1272 List
->TopPartition
= (ULONG
)-1;
1274 List
->CurrentDisk
= NULL
;
1275 List
->CurrentPartition
= NULL
;
1277 List
->BootDisk
= NULL
;
1278 List
->BootPartition
= NULL
;
1280 List
->TempDisk
= NULL
;
1281 List
->TempPartition
= NULL
;
1282 List
->FormatState
= Start
;
1284 InitializeListHead(&List
->DiskListHead
);
1285 InitializeListHead(&List
->BiosDiskListHead
);
1287 EnumerateBiosDiskEntries(List
);
1289 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1291 sizeof(SYSTEM_DEVICE_INFORMATION
),
1293 if (!NT_SUCCESS(Status
))
1295 RtlFreeHeap(ProcessHeap
, 0, List
);
1299 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1302 L
"\\Device\\Harddisk%d\\Partition0",
1304 RtlInitUnicodeString(&Name
,
1307 InitializeObjectAttributes(&ObjectAttributes
,
1313 Status
= NtOpenFile(&FileHandle
,
1314 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1318 FILE_SYNCHRONOUS_IO_NONALERT
);
1319 if (NT_SUCCESS(Status
))
1321 AddDiskToList(FileHandle
,
1325 NtClose(FileHandle
);
1329 UpdateDiskSignatures(List
);
1331 AssignDriveLetters(List
);
1334 List
->TopPartition
= 0;
1336 /* Search for first usable disk and partition */
1337 if (IsListEmpty(&List
->DiskListHead
))
1339 List
->CurrentDisk
= NULL
;
1340 List
->CurrentPartition
= NULL
;
1344 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1348 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1350 List
->CurrentPartition
= 0;
1354 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1365 DestroyPartitionList(
1368 PDISKENTRY DiskEntry
;
1369 PBIOSDISKENTRY BiosDiskEntry
;
1370 PPARTENTRY PartEntry
;
1373 /* Release disk and partition info */
1374 while (!IsListEmpty(&List
->DiskListHead
))
1376 Entry
= RemoveHeadList(&List
->DiskListHead
);
1377 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1379 /* Release driver name */
1380 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1382 /* Release primary partition list */
1383 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1385 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1386 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1388 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1391 /* Release logical partition list */
1392 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1394 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1395 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1397 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1400 /* Release layout buffer */
1401 if (DiskEntry
->LayoutBuffer
!= NULL
)
1402 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1405 /* Release disk entry */
1406 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1409 /* release the bios disk info */
1410 while(!IsListEmpty(&List
->BiosDiskListHead
))
1412 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1413 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1415 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1418 /* Release list head */
1419 RtlFreeHeap(ProcessHeap
, 0, List
);
1433 Width
= List
->Right
- List
->Left
- 1;
1434 Height
= List
->Bottom
- List
->Top
- 2;
1436 coPos
.X
= List
->Left
+ 1;
1437 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1439 if (List
->Line
>= 0 && List
->Line
<= Height
)
1441 FillConsoleOutputAttribute(StdOutput
,
1442 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1447 FillConsoleOutputCharacterA(StdOutput
,
1462 PDISKENTRY DiskEntry
,
1463 PPARTENTRY PartEntry
)
1465 CHAR LineBuffer
[128];
1470 LARGE_INTEGER PartSize
;
1475 Width
= List
->Right
- List
->Left
- 1;
1476 Height
= List
->Bottom
- List
->Top
- 2;
1478 coPos
.X
= List
->Left
+ 1;
1479 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1481 if (PartEntry
->IsPartitioned
== FALSE
)
1483 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1485 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1487 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1488 Unit
= MUIGetString(STRING_GB
);
1492 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1494 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1495 Unit
= MUIGetString(STRING_MB
);
1499 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1500 Unit
= MUIGetString(STRING_KB
);
1504 MUIGetString(STRING_UNPSPACE
),
1505 PartEntry
->LogicalPartition
? " " : "",
1506 PartEntry
->LogicalPartition
? "" : " ",
1512 /* Determine partition type */
1514 if (PartEntry
->New
== TRUE
)
1516 PartType
= MUIGetString(STRING_UNFORMATTED
);
1518 else if (PartEntry
->IsPartitioned
== TRUE
)
1520 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1521 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1522 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1523 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1527 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1528 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1532 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1536 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1538 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1540 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1541 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1543 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1547 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1549 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1551 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1552 Unit
= MUIGetString(STRING_GB
);
1556 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1558 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1559 Unit
= MUIGetString(STRING_MB
);
1563 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1564 Unit
= MUIGetString(STRING_KB
);
1567 if (PartType
== NULL
)
1570 MUIGetString(STRING_HDDINFOUNK5
),
1571 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1572 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1573 PartEntry
->BootIndicator
? '*' : ' ',
1574 PartEntry
->LogicalPartition
? " " : "",
1575 PartEntry
->PartitionType
,
1576 PartEntry
->LogicalPartition
? "" : " ",
1583 "%c%c %c %s%-24s%s %6lu %s",
1584 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1585 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1586 PartEntry
->BootIndicator
? '*' : ' ',
1587 PartEntry
->LogicalPartition
? " " : "",
1589 PartEntry
->LogicalPartition
? "" : " ",
1595 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1596 List
->CurrentPartition
== PartEntry
) ?
1597 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1598 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1600 if (List
->Line
>= 0 && List
->Line
<= Height
)
1602 FillConsoleOutputCharacterA(StdOutput
,
1610 if (List
->Line
>= 0 && List
->Line
<= Height
)
1612 FillConsoleOutputAttribute(StdOutput
,
1620 if (List
->Line
>= 0 && List
->Line
<= Height
)
1622 WriteConsoleOutputCharacterA(StdOutput
,
1624 min(strlen(LineBuffer
), Width
),
1637 PDISKENTRY DiskEntry
)
1639 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1640 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1641 CHAR LineBuffer
[128];
1646 ULARGE_INTEGER DiskSize
;
1649 Width
= List
->Right
- List
->Left
- 1;
1650 Height
= List
->Bottom
- List
->Top
- 2;
1652 coPos
.X
= List
->Left
+ 1;
1653 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1655 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1656 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1658 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1659 Unit
= MUIGetString(STRING_GB
);
1663 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1664 if (DiskSize
.QuadPart
== 0)
1665 DiskSize
.QuadPart
= 1;
1666 Unit
= MUIGetString(STRING_MB
);
1669 if (DiskEntry
->DriverName
.Length
> 0)
1672 MUIGetString(STRING_HDINFOPARTSELECT
),
1675 DiskEntry
->DiskNumber
,
1679 DiskEntry
->DriverName
.Buffer
);
1684 MUIGetString(STRING_HDDINFOUNK6
),
1687 DiskEntry
->DiskNumber
,
1693 if (List
->Line
>= 0 && List
->Line
<= Height
)
1695 FillConsoleOutputAttribute(StdOutput
,
1696 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1701 FillConsoleOutputCharacterA(StdOutput
,
1709 if (List
->Line
>= 0 && List
->Line
<= Height
)
1711 WriteConsoleOutputCharacterA(StdOutput
,
1713 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1720 /* Print separator line */
1721 PrintEmptyLine(List
);
1723 /* Print partition lines*/
1724 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1725 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1727 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1729 PrintPartitionData(List
,
1733 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1735 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1736 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1738 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1740 PrintPartitionData(List
,
1744 LogicalEntry
= LogicalEntry
->Flink
;
1748 PrimaryEntry
= PrimaryEntry
->Flink
;
1751 /* Print separator line */
1752 PrintEmptyLine(List
);
1760 PLIST_ENTRY Entry
, Entry2
;
1761 PDISKENTRY DiskEntry
;
1762 PPARTENTRY PartEntry
= NULL
;
1766 SHORT CurrentDiskLine
;
1767 SHORT CurrentPartLine
;
1769 BOOL CurrentPartLineFound
= FALSE
;
1770 BOOL CurrentDiskLineFound
= FALSE
;
1772 /* Calculate the line of the current disk and partition */
1773 CurrentDiskLine
= 0;
1774 CurrentPartLine
= 0;
1777 Entry
= List
->DiskListHead
.Flink
;
1778 while (Entry
!= &List
->DiskListHead
)
1780 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1783 if (CurrentPartLineFound
== FALSE
)
1785 CurrentPartLine
+= 2;
1788 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1789 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1791 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1792 if (PartEntry
== List
->CurrentPartition
)
1794 CurrentPartLineFound
= TRUE
;
1797 Entry2
= Entry2
->Flink
;
1798 if (CurrentPartLineFound
== FALSE
)
1806 if (DiskEntry
== List
->CurrentDisk
)
1808 CurrentDiskLineFound
= TRUE
;
1811 Entry
= Entry
->Flink
;
1812 if (Entry
!= &List
->DiskListHead
)
1814 if (CurrentDiskLineFound
== FALSE
)
1817 CurrentDiskLine
= CurrentPartLine
;
1828 /* If it possible, make the disk name visible */
1829 if (CurrentPartLine
< List
->Offset
)
1831 List
->Offset
= CurrentPartLine
;
1833 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1835 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1838 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1840 List
->Offset
= CurrentDiskLine
;
1843 /* draw upper left corner */
1844 coPos
.X
= List
->Left
;
1845 coPos
.Y
= List
->Top
;
1846 FillConsoleOutputCharacterA(StdOutput
,
1852 /* draw upper edge */
1853 coPos
.X
= List
->Left
+ 1;
1854 coPos
.Y
= List
->Top
;
1855 if (List
->Offset
== 0)
1857 FillConsoleOutputCharacterA(StdOutput
,
1859 List
->Right
- List
->Left
- 1,
1865 FillConsoleOutputCharacterA(StdOutput
,
1867 List
->Right
- List
->Left
- 5,
1870 coPos
.X
= List
->Right
- 5;
1871 WriteConsoleOutputCharacterA(StdOutput
,
1876 coPos
.X
= List
->Right
- 2;
1877 FillConsoleOutputCharacterA(StdOutput
,
1884 /* draw upper right corner */
1885 coPos
.X
= List
->Right
;
1886 coPos
.Y
= List
->Top
;
1887 FillConsoleOutputCharacterA(StdOutput
,
1893 /* draw left and right edge */
1894 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1896 coPos
.X
= List
->Left
;
1898 FillConsoleOutputCharacterA(StdOutput
,
1904 coPos
.X
= List
->Right
;
1905 FillConsoleOutputCharacterA(StdOutput
,
1912 /* draw lower left corner */
1913 coPos
.X
= List
->Left
;
1914 coPos
.Y
= List
->Bottom
;
1915 FillConsoleOutputCharacterA(StdOutput
,
1921 /* draw lower edge */
1922 coPos
.X
= List
->Left
+ 1;
1923 coPos
.Y
= List
->Bottom
;
1924 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1926 FillConsoleOutputCharacterA(StdOutput
,
1928 List
->Right
- List
->Left
- 1,
1934 FillConsoleOutputCharacterA(StdOutput
,
1936 List
->Right
- List
->Left
- 5,
1939 coPos
.X
= List
->Right
- 5;
1940 WriteConsoleOutputCharacterA(StdOutput
,
1941 "(\x19)", // "(down)"
1945 coPos
.X
= List
->Right
- 2;
1946 FillConsoleOutputCharacterA(StdOutput
,
1953 /* draw lower right corner */
1954 coPos
.X
= List
->Right
;
1955 coPos
.Y
= List
->Bottom
;
1956 FillConsoleOutputCharacterA(StdOutput
,
1962 /* print list entries */
1963 List
->Line
= - List
->Offset
;
1965 Entry
= List
->DiskListHead
.Flink
;
1966 while (Entry
!= &List
->DiskListHead
)
1968 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1970 /* Print disk entry */
1974 Entry
= Entry
->Flink
;
1983 ULONG PartitionNumber
)
1985 PDISKENTRY DiskEntry
;
1986 PPARTENTRY PartEntry
;
1990 /* Check for empty disks */
1991 if (IsListEmpty(&List
->DiskListHead
))
1994 /* Check for first usable entry on next disk */
1995 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1996 while (Entry1
!= &List
->DiskListHead
)
1998 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
2000 if (DiskEntry
->DiskNumber
== DiskNumber
)
2002 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2003 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2005 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2007 if (PartEntry
->PartitionNumber
== PartitionNumber
)
2009 List
->CurrentDisk
= DiskEntry
;
2010 List
->CurrentPartition
= PartEntry
;
2011 DrawPartitionList(List
);
2015 Entry2
= Entry2
->Flink
;
2021 Entry1
= Entry1
->Flink
;
2029 ScrollDownPartitionList(
2032 PLIST_ENTRY DiskListEntry
;
2033 PLIST_ENTRY PartListEntry
;
2034 PDISKENTRY DiskEntry
;
2035 PPARTENTRY PartEntry
;
2037 /* Fail, if no disks are available */
2038 if (IsListEmpty(&List
->DiskListHead
))
2041 /* Check for next usable entry on current disk */
2042 if (List
->CurrentPartition
!= NULL
)
2044 if (List
->CurrentPartition
->LogicalPartition
)
2046 /* Logical partition */
2048 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2049 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2051 /* Next logical partition */
2052 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2054 List
->CurrentPartition
= PartEntry
;
2059 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2060 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2062 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2064 List
->CurrentPartition
= PartEntry
;
2071 /* Primary or extended partition */
2073 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2074 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2076 /* First logical partition */
2077 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2078 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2080 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2082 List
->CurrentPartition
= PartEntry
;
2088 /* Next primary partition */
2089 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2090 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2092 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2094 List
->CurrentPartition
= PartEntry
;
2101 /* Search for the first partition entry on the next disk */
2102 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2103 while (DiskListEntry
!= &List
->DiskListHead
)
2105 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2107 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2108 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2110 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2112 List
->CurrentDisk
= DiskEntry
;
2113 List
->CurrentPartition
= PartEntry
;
2117 DiskListEntry
= DiskListEntry
->Flink
;
2125 ScrollUpPartitionList(
2128 PLIST_ENTRY DiskListEntry
;
2129 PLIST_ENTRY PartListEntry
;
2130 PDISKENTRY DiskEntry
;
2131 PPARTENTRY PartEntry
;
2133 /* Fail, if no disks are available */
2134 if (IsListEmpty(&List
->DiskListHead
))
2137 /* Check for previous usable entry on current disk */
2138 if (List
->CurrentPartition
!= NULL
)
2140 if (List
->CurrentPartition
->LogicalPartition
)
2142 /* Logical partition */
2143 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2144 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2146 /* Previous logical partition */
2147 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2151 /* Extended partition*/
2152 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2155 List
->CurrentPartition
= PartEntry
;
2160 /* Primary or extended partition */
2162 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2163 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2165 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2167 if (PartEntry
->IsPartitioned
== TRUE
&&
2168 IsContainerPartition(PartEntry
->PartitionType
))
2170 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2171 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2174 List
->CurrentPartition
= PartEntry
;
2181 /* Search for the last partition entry on the previous disk */
2182 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2183 while (DiskListEntry
!= &List
->DiskListHead
)
2185 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2187 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2188 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2190 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2192 if (PartEntry
->IsPartitioned
== TRUE
&&
2193 IsContainerPartition(PartEntry
->PartitionType
))
2195 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2196 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2198 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2200 List
->CurrentDisk
= DiskEntry
;
2201 List
->CurrentPartition
= PartEntry
;
2207 List
->CurrentDisk
= DiskEntry
;
2208 List
->CurrentPartition
= PartEntry
;
2213 DiskListEntry
= DiskListEntry
->Blink
;
2223 PPARTITION_INFORMATION PartitionInfo
)
2225 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2226 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2227 // PartitionInfo->PartitionType == 0)
2236 IsSamePrimaryLayoutEntry(
2237 IN PPARTITION_INFORMATION PartitionInfo
,
2238 IN PDISKENTRY DiskEntry
,
2239 IN PPARTENTRY PartEntry
)
2241 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2242 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2243 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2244 // PartitionInfo->PartitionType == PartEntry->PartitionType
2254 IN PDISKENTRY DiskEntry
)
2256 PPARTITION_INFORMATION PartitionInfo
;
2257 PLIST_ENTRY ListEntry
;
2258 PPARTENTRY PartEntry
;
2260 ULONG PartitionNumber
= 1;
2262 DPRINT1("UpdateDiskLayout()\n");
2264 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2265 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2267 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2269 if (PartEntry
->IsPartitioned
== TRUE
)
2271 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2273 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2275 DPRINT1("Updating partition entry %lu\n", Index
);
2277 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2278 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2279 PartitionInfo
->HiddenSectors
= 0;
2280 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2281 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2282 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2283 PartitionInfo
->RecognizedPartition
= FALSE
;
2284 PartitionInfo
->RewritePartition
= TRUE
;
2286 PartEntry
->PartitionNumber
= PartitionNumber
;
2287 PartEntry
->PartitionIndex
= Index
;
2291 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2299 ListEntry
= ListEntry
->Flink
;
2302 for (;Index
< 4; Index
++)
2304 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2306 if (!IsEmptyLayoutEntry(PartitionInfo
))
2308 DPRINT1("Wiping partition entry %lu\n", Index
);
2310 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2311 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2312 PartitionInfo
->HiddenSectors
= 0;
2313 PartitionInfo
->PartitionNumber
= 0;
2314 PartitionInfo
->PartitionType
= 0;
2315 PartitionInfo
->BootIndicator
= FALSE
;
2316 PartitionInfo
->RecognizedPartition
= FALSE
;
2317 PartitionInfo
->RewritePartition
= TRUE
;
2321 #ifdef DUMP_PARTITION_TABLE
2322 DumpPartitionTable(DiskEntry
);
2329 GetPrevUnpartitionedEntry(
2330 PDISKENTRY DiskEntry
,
2331 PPARTENTRY PartEntry
)
2333 PPARTENTRY PrevPartEntry
;
2335 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PrimaryPartListHead
)
2337 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2340 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2341 return PrevPartEntry
;
2350 GetNextUnpartitionedEntry(
2351 PDISKENTRY DiskEntry
,
2352 PPARTENTRY PartEntry
)
2354 PPARTENTRY NextPartEntry
;
2356 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PrimaryPartListHead
)
2358 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2361 if (NextPartEntry
->IsPartitioned
== FALSE
)
2362 return NextPartEntry
;
2370 CreatePrimaryPartition(
2372 ULONGLONG SectorCount
,
2375 PDISKENTRY DiskEntry
;
2376 PPARTENTRY PartEntry
;
2377 PPARTENTRY NewPartEntry
;
2379 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2382 List
->CurrentDisk
== NULL
||
2383 List
->CurrentPartition
== NULL
||
2384 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2389 DiskEntry
= List
->CurrentDisk
;
2390 PartEntry
= List
->CurrentPartition
;
2392 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2394 if (AutoCreate
== TRUE
||
2395 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2397 DPRINT1("Convert existing partition entry\n");
2399 /* Convert current entry to 'new (unformatted)' */
2400 PartEntry
->IsPartitioned
= TRUE
;
2401 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2402 PartEntry
->FormatState
= Unformatted
;
2403 PartEntry
->AutoCreate
= AutoCreate
;
2404 PartEntry
->New
= TRUE
;
2405 PartEntry
->BootIndicator
= FALSE
;
2407 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2408 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2409 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2413 DPRINT1("Add new partition entry\n");
2415 /* Insert and initialize a new partition entry */
2416 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2419 if (NewPartEntry
== NULL
)
2422 /* Insert the new entry into the list */
2423 InsertTailList(&PartEntry
->ListEntry
,
2424 &NewPartEntry
->ListEntry
);
2426 NewPartEntry
->DiskEntry
= DiskEntry
;
2428 NewPartEntry
->IsPartitioned
= TRUE
;
2429 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2430 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2431 NewPartEntry
->StartSector
.QuadPart
;
2432 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2434 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2435 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2436 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2438 NewPartEntry
->New
= TRUE
;
2439 NewPartEntry
->FormatState
= Unformatted
;
2440 NewPartEntry
->BootIndicator
= FALSE
;
2442 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2443 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2446 UpdateDiskLayout(DiskEntry
);
2448 DiskEntry
->Dirty
= TRUE
;
2450 UpdatePartitionNumbers(DiskEntry
);
2452 AssignDriveLetters(List
);
2458 AddLogicalDiskSpace(
2459 PDISKENTRY DiskEntry
)
2461 PPARTENTRY NewPartEntry
;
2463 DPRINT1("AddLogicalDiskSpace()\n");
2465 /* Create a partition table entry that represents the empty space in the container partition */
2466 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2469 if (NewPartEntry
== NULL
)
2472 NewPartEntry
->DiskEntry
= DiskEntry
;
2473 NewPartEntry
->LogicalPartition
= TRUE
;
2475 NewPartEntry
->IsPartitioned
= FALSE
;
2476 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2477 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2479 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2480 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2481 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2483 NewPartEntry
->FormatState
= Unformatted
;
2485 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2486 &NewPartEntry
->ListEntry
);
2491 CreateExtendedPartition(
2493 ULONGLONG SectorCount
)
2495 PDISKENTRY DiskEntry
;
2496 PPARTENTRY PartEntry
;
2497 PPARTENTRY NewPartEntry
;
2499 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2502 List
->CurrentDisk
== NULL
||
2503 List
->CurrentPartition
== NULL
||
2504 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2509 DiskEntry
= List
->CurrentDisk
;
2510 PartEntry
= List
->CurrentPartition
;
2512 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2514 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2516 DPRINT1("Convert existing partition entry\n");
2518 /* Convert current entry to 'new (unformatted)' */
2519 PartEntry
->IsPartitioned
= TRUE
;
2520 PartEntry
->FormatState
= Formatted
;
2521 PartEntry
->AutoCreate
= FALSE
;
2522 PartEntry
->New
= FALSE
;
2523 PartEntry
->BootIndicator
= FALSE
;
2525 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2527 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2528 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2532 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2533 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2536 DiskEntry
->ExtendedPartition
= PartEntry
;
2538 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2539 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2540 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2544 DPRINT1("Add new partition entry\n");
2546 /* Insert and initialize a new partition entry */
2547 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2550 if (NewPartEntry
== NULL
)
2553 /* Insert the new entry into the list */
2554 InsertTailList(&PartEntry
->ListEntry
,
2555 &NewPartEntry
->ListEntry
);
2557 NewPartEntry
->DiskEntry
= DiskEntry
;
2559 NewPartEntry
->IsPartitioned
= TRUE
;
2560 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2561 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2562 NewPartEntry
->StartSector
.QuadPart
;
2564 NewPartEntry
->New
= FALSE
;
2565 NewPartEntry
->FormatState
= Formatted
;
2566 NewPartEntry
->BootIndicator
= FALSE
;
2568 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2570 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2571 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2575 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2576 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2579 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2581 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2582 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2584 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2585 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2586 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2589 AddLogicalDiskSpace(DiskEntry
);
2591 UpdateDiskLayout(DiskEntry
);
2593 DiskEntry
->Dirty
= TRUE
;
2595 UpdatePartitionNumbers(DiskEntry
);
2597 AssignDriveLetters(List
);
2602 CreateLogicalPartition(
2604 ULONGLONG SectorCount
)
2606 // PDISKENTRY DiskEntry;
2607 PPARTENTRY PartEntry
;
2608 // PPARTENTRY NewPartEntry;
2610 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2613 List
->CurrentDisk
== NULL
||
2614 List
->CurrentPartition
== NULL
||
2615 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2620 // DiskEntry = List->CurrentDisk;
2621 PartEntry
= List
->CurrentPartition
;
2623 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2628 DeleteCurrentPartition(
2631 PDISKENTRY DiskEntry
;
2632 PPARTENTRY PartEntry
;
2633 PPARTENTRY PrevPartEntry
;
2634 PPARTENTRY NextPartEntry
;
2635 PPARTENTRY LogicalPartEntry
;
2639 List
->CurrentDisk
== NULL
||
2640 List
->CurrentPartition
== NULL
||
2641 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2646 DiskEntry
= List
->CurrentDisk
;
2647 PartEntry
= List
->CurrentPartition
;
2649 /* Delete all logical partiton entries if an extended partition will be deleted */
2650 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2652 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2654 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2655 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2657 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2660 DiskEntry
->ExtendedPartition
= NULL
;
2663 /* Adjust unpartitioned disk space entries */
2665 /* Get pointer to previous and next unpartitioned entries */
2666 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2669 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2672 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2674 /* Merge previous, current and next unpartitioned entry */
2676 /* Adjust the previous entries length */
2677 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2679 /* Remove the current entry */
2680 RemoveEntryList(&PartEntry
->ListEntry
);
2681 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2683 /* Remove the next entry */
2684 RemoveEntryList (&NextPartEntry
->ListEntry
);
2685 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2687 /* Update current partition */
2688 List
->CurrentPartition
= PrevPartEntry
;
2690 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2692 /* Merge current and previous unpartitioned entry */
2694 /* Adjust the previous entries length */
2695 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2697 /* Remove the current entry */
2698 RemoveEntryList(&PartEntry
->ListEntry
);
2699 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2701 /* Update current partition */
2702 List
->CurrentPartition
= PrevPartEntry
;
2704 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2706 /* Merge current and next unpartitioned entry */
2708 /* Adjust the next entries offset and length */
2709 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2710 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2712 /* Remove the current entry */
2713 RemoveEntryList(&PartEntry
->ListEntry
);
2714 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2716 /* Update current partition */
2717 List
->CurrentPartition
= NextPartEntry
;
2721 /* Nothing to merge but change current entry */
2722 PartEntry
->IsPartitioned
= FALSE
;
2723 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2724 PartEntry
->FormatState
= Unformatted
;
2725 PartEntry
->DriveLetter
= 0;
2728 UpdateDiskLayout(DiskEntry
);
2730 DiskEntry
->Dirty
= TRUE
;
2732 UpdatePartitionNumbers(DiskEntry
);
2734 AssignDriveLetters(List
);
2739 CheckActiveBootPartition(
2742 PDISKENTRY DiskEntry
;
2743 PPARTENTRY PartEntry
;
2744 PLIST_ENTRY ListEntry
;
2746 /* Check for empty disk list */
2747 if (IsListEmpty (&List
->DiskListHead
))
2749 List
->BootDisk
= NULL
;
2750 List
->BootPartition
= NULL
;
2755 if (List
->BootDisk
!= NULL
&&
2756 List
->BootPartition
!= NULL
)
2758 /* We already have an active boot partition */
2763 /* Choose the currently selected disk */
2764 DiskEntry
= List
->CurrentDisk
;
2766 /* Check for empty partition list */
2767 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2769 List
->BootDisk
= NULL
;
2770 List
->BootPartition
= NULL
;
2774 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2778 /* Set active boot partition */
2779 if ((DiskEntry
->NewDisk
== TRUE
) ||
2780 (PartEntry
->BootIndicator
== FALSE
))
2782 PartEntry
->BootIndicator
= TRUE
;
2783 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2784 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2785 DiskEntry
->Dirty
= TRUE
;
2787 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2788 List
->BootDisk
= DiskEntry
;
2789 List
->BootPartition
= PartEntry
;
2794 /* Disk is not new, scan all partitions to find a bootable one */
2795 List
->BootDisk
= NULL
;
2796 List
->BootPartition
= NULL
;
2798 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2799 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2801 PartEntry
= CONTAINING_RECORD(ListEntry
,
2805 /* Check if it is partitioned */
2806 if (PartEntry
->IsPartitioned
)
2808 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2809 PartEntry
->BootIndicator
)
2811 /* Yes, we found it */
2812 List
->BootDisk
= DiskEntry
;
2813 List
->BootPartition
= PartEntry
;
2815 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2816 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2821 /* Go to the next one */
2822 ListEntry
= ListEntry
->Flink
;
2828 CheckForLinuxFdiskPartitions(
2832 PDISKENTRY DiskEntry
;
2833 PPARTENTRY PartEntry
;
2836 ULONG PartitionCount
;
2839 Entry1
= List
->DiskListHead
.Flink
;
2840 while (Entry1
!= &List
->DiskListHead
)
2842 DiskEntry
= CONTAINING_RECORD(Entry1
,
2846 Entry2
= DiskEntry
->PartListHead
.Flink
;
2847 while (Entry2
!= &DiskEntry
->PartListHead
)
2849 PartEntry
= CONTAINING_RECORD(Entry2
,
2853 if (PartEntry
->Unpartitioned
== FALSE
)
2857 for (i
= 0; i
< 4; i
++)
2859 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2860 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2866 if (PartitionCount
> 1)
2872 Entry2
= Entry2
->Flink
;
2875 Entry1
= Entry1
->Flink
;
2887 IN PDISKENTRY DiskEntry
)
2889 WCHAR DstPath
[MAX_PATH
];
2890 OBJECT_ATTRIBUTES ObjectAttributes
;
2891 IO_STATUS_BLOCK Iosb
;
2892 UNICODE_STRING Name
;
2894 HANDLE FileHandle
= NULL
;
2897 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2900 L
"\\Device\\Harddisk%d\\Partition0",
2901 DiskEntry
->DiskNumber
);
2902 RtlInitUnicodeString(&Name
,
2904 InitializeObjectAttributes(&ObjectAttributes
,
2910 Status
= NtOpenFile(&FileHandle
,
2911 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2915 FILE_SYNCHRONOUS_IO_NONALERT
);
2916 if (!NT_SUCCESS(Status
))
2918 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2922 #ifdef DUMP_PARTITION_TABLE
2923 DumpPartitionTable(DiskEntry
);
2926 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2927 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2928 Status
= NtDeviceIoControlFile(FileHandle
,
2933 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2934 DiskEntry
->LayoutBuffer
,
2938 if (!NT_SUCCESS(Status
))
2940 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2943 if (FileHandle
!= NULL
)
2944 NtClose(FileHandle
);
2951 WritePartitionsToDisk(
2955 PDISKENTRY DiskEntry
;
2960 Entry
= List
->DiskListHead
.Flink
;
2961 while (Entry
!= &List
->DiskListHead
)
2963 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2965 if (DiskEntry
->Dirty
== TRUE
)
2967 WritePartitons(List
, DiskEntry
);
2968 DiskEntry
->Dirty
= FALSE
;
2971 Entry
= Entry
->Flink
;
2979 SetMountedDeviceValues(
2982 PLIST_ENTRY Entry1
, Entry2
;
2983 PDISKENTRY DiskEntry
;
2984 PPARTENTRY PartEntry
;
2985 LARGE_INTEGER StartingOffset
;
2992 Entry1
= List
->DiskListHead
.Flink
;
2993 while (Entry1
!= &List
->DiskListHead
)
2995 DiskEntry
= CONTAINING_RECORD(Entry1
,
2999 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3000 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3002 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3003 if (PartEntry
->IsPartitioned
)
3005 if (PartEntry
->DriveLetter
)
3007 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3008 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3009 DiskEntry
->LayoutBuffer
->Signature
,
3017 Entry2
= Entry2
->Flink
;
3020 Entry1
= Entry1
->Flink
;
3029 GetPrimaryPartitionCount(
3030 IN PDISKENTRY DiskEntry
)
3033 PPARTENTRY PartEntry
;
3036 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3037 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
3039 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3040 if (PartEntry
->IsPartitioned
== TRUE
)
3043 Entry
= Entry
->Flink
;
3051 PrimaryPartitionCreationChecks(
3054 PDISKENTRY DiskEntry
;
3055 PPARTENTRY PartEntry
;
3057 DiskEntry
= List
->CurrentDisk
;
3058 PartEntry
= List
->CurrentPartition
;
3060 /* Fail if partition is already in use */
3061 if (PartEntry
->IsPartitioned
== TRUE
)
3062 return ERROR_NEW_PARTITION
;
3064 /* Fail if there are more than 4 partitions in the list */
3065 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3066 return ERROR_PARTITION_TABLE_FULL
;
3068 return ERROR_SUCCESS
;
3073 ExtendedPartitionCreationChecks(
3076 PDISKENTRY DiskEntry
;
3077 PPARTENTRY PartEntry
;
3079 DiskEntry
= List
->CurrentDisk
;
3080 PartEntry
= List
->CurrentPartition
;
3082 /* Fail if partition is already in use */
3083 if (PartEntry
->IsPartitioned
== TRUE
)
3084 return ERROR_NEW_PARTITION
;
3086 /* Fail if there are more than 4 partitions in the list */
3087 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3088 return ERROR_PARTITION_TABLE_FULL
;
3090 /* Fail if there is another extended partition in the list */
3091 if (DiskEntry
->ExtendedPartition
!= NULL
)
3092 return ERROR_ONLY_ONE_EXTENDED
;
3094 return ERROR_SUCCESS
;
3099 LogicalPartitionCreationChecks(
3102 // PDISKENTRY DiskEntry;
3103 PPARTENTRY PartEntry
;
3105 // DiskEntry = List->CurrentDisk;
3106 PartEntry
= List
->CurrentPartition
;
3108 /* Fail if partition is already in use */
3109 if (PartEntry
->IsPartitioned
== TRUE
)
3110 return ERROR_NEW_PARTITION
;
3112 return ERROR_SUCCESS
;
3117 GetNextUnformattedPartition(
3119 OUT PDISKENTRY
*pDiskEntry
,
3120 OUT PPARTENTRY
*pPartEntry
)
3122 PLIST_ENTRY Entry1
, Entry2
;
3123 PDISKENTRY DiskEntry
;
3124 PPARTENTRY PartEntry
;
3126 Entry1
= List
->DiskListHead
.Flink
;
3127 while (Entry1
!= &List
->DiskListHead
)
3129 DiskEntry
= CONTAINING_RECORD(Entry1
,
3133 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3134 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3136 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3137 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3139 *pDiskEntry
= DiskEntry
;
3140 *pPartEntry
= PartEntry
;
3144 Entry2
= Entry2
->Flink
;
3147 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3148 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3150 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3151 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3153 *pDiskEntry
= DiskEntry
;
3154 *pPartEntry
= PartEntry
;
3158 Entry2
= Entry2
->Flink
;
3161 Entry1
= Entry1
->Flink
;
3172 GetNextUncheckedPartition(
3174 OUT PDISKENTRY
*pDiskEntry
,
3175 OUT PPARTENTRY
*pPartEntry
)
3177 PLIST_ENTRY Entry1
, Entry2
;
3178 PDISKENTRY DiskEntry
;
3179 PPARTENTRY PartEntry
;
3181 Entry1
= List
->DiskListHead
.Flink
;
3182 while (Entry1
!= &List
->DiskListHead
)
3184 DiskEntry
= CONTAINING_RECORD(Entry1
,
3188 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3189 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3191 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3192 if (PartEntry
->NeedsCheck
== TRUE
)
3194 *pDiskEntry
= DiskEntry
;
3195 *pPartEntry
= PartEntry
;
3199 Entry2
= Entry2
->Flink
;
3202 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3203 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3205 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3206 if (PartEntry
->NeedsCheck
== TRUE
)
3208 *pDiskEntry
= DiskEntry
;
3209 *pPartEntry
= PartEntry
;
3213 Entry2
= Entry2
->Flink
;
3216 Entry1
= Entry1
->Flink
;