3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI disk class driver
27 #pragma alloc_text(PAGE, DiskConvertExtendedToLayout)
28 #pragma alloc_text(PAGE, DiskConvertPartitionToExtended)
29 #pragma alloc_text(PAGE, DiskConvertLayoutToExtended)
30 #pragma alloc_text(PAGE, DiskCreatePdo)
31 #pragma alloc_text(PAGE, DiskEnumerateDevice)
32 #pragma alloc_text(PAGE, DiskUpdateRemovablePartitions)
33 #pragma alloc_text(PAGE, DiskUpdatePartitions)
34 #pragma alloc_text(PAGE, DiskCreatePdo)
38 PDRIVE_LAYOUT_INFORMATION
39 DiskConvertExtendedToLayout(
40 IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx
45 PDRIVE_LAYOUT_INFORMATION Layout
;
46 PPARTITION_INFORMATION Partition
;
47 PPARTITION_INFORMATION_EX PartitionEx
;
55 // The only valid conversion is from an MBR extended layout structure to
59 if (LayoutEx
->PartitionStyle
!= PARTITION_STYLE_MBR
) {
64 LayoutSize
= FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION
, PartitionEntry
[0]) +
65 LayoutEx
->PartitionCount
* sizeof (PARTITION_INFORMATION
);
67 Layout
= ExAllocatePoolWithTag (
73 if ( Layout
== NULL
) {
77 Layout
->Signature
= LayoutEx
->Mbr
.Signature
;
78 Layout
->PartitionCount
= LayoutEx
->PartitionCount
;
80 for (i
= 0; i
< LayoutEx
->PartitionCount
; i
++) {
82 Partition
= &Layout
->PartitionEntry
[i
];
83 PartitionEx
= &LayoutEx
->PartitionEntry
[i
];
85 Partition
->StartingOffset
= PartitionEx
->StartingOffset
;
86 Partition
->PartitionLength
= PartitionEx
->PartitionLength
;
87 Partition
->RewritePartition
= PartitionEx
->RewritePartition
;
88 Partition
->PartitionNumber
= PartitionEx
->PartitionNumber
;
90 Partition
->PartitionType
= PartitionEx
->Mbr
.PartitionType
;
91 Partition
->BootIndicator
= PartitionEx
->Mbr
.BootIndicator
;
92 Partition
->RecognizedPartition
= PartitionEx
->Mbr
.RecognizedPartition
;
93 Partition
->HiddenSectors
= PartitionEx
->Mbr
.HiddenSectors
;
100 DiskConvertPartitionToExtended(
101 IN PPARTITION_INFORMATION Partition
,
102 OUT PPARTITION_INFORMATION_EX PartitionEx
109 Convert a PARTITION_INFORMATION structure to a PARTITION_INFORMATION_EX
114 Partition - A pointer to the PARTITION_INFORMATION structure to convert.
116 PartitionEx - A pointer to a buffer where the converted
117 PARTITION_INFORMATION_EX structure is to be stored.
128 ASSERT ( PartitionEx
!= NULL
);
129 ASSERT ( Partition
!= NULL
);
131 PartitionEx
->PartitionStyle
= PARTITION_STYLE_MBR
;
132 PartitionEx
->StartingOffset
= Partition
->StartingOffset
;
133 PartitionEx
->PartitionLength
= Partition
->PartitionLength
;
134 PartitionEx
->RewritePartition
= Partition
->RewritePartition
;
135 PartitionEx
->PartitionNumber
= Partition
->PartitionNumber
;
137 PartitionEx
->Mbr
.PartitionType
= Partition
->PartitionType
;
138 PartitionEx
->Mbr
.BootIndicator
= Partition
->BootIndicator
;
139 PartitionEx
->Mbr
.RecognizedPartition
= Partition
->RecognizedPartition
;
140 PartitionEx
->Mbr
.HiddenSectors
= Partition
->HiddenSectors
;
144 PDRIVE_LAYOUT_INFORMATION_EX
145 DiskConvertLayoutToExtended(
146 IN CONST PDRIVE_LAYOUT_INFORMATION Layout
153 Convert a DRIVE_LAYOUT_INFORMATION structure into a
154 DRIVE_LAYOUT_INFORMATION_EX structure.
158 Layout - The source DRIVE_LAYOUT_INFORMATION structure.
162 The resultant DRIVE_LAYOUT_INFORMATION_EX structure. This buffer must
163 be freed by the callee using ExFreePool.
170 PDRIVE_LAYOUT_INFORMATION_EX layoutEx
;
174 ASSERT ( Layout
!= NULL
);
178 // Allocate enough space for a DRIVE_LAYOUT_INFORMATION_EX structure
179 // plus as many PARTITION_INFORMATION_EX structures as are in the
183 size
= FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION_EX
, PartitionEntry
[0]) +
184 Layout
->PartitionCount
* sizeof ( PARTITION_INFORMATION_EX
);
186 layoutEx
= ExAllocatePoolWithTag(
192 if ( layoutEx
== NULL
) {
197 // Convert the disk information.
200 layoutEx
->PartitionStyle
= PARTITION_STYLE_MBR
;
201 layoutEx
->PartitionCount
= Layout
->PartitionCount
;
202 layoutEx
->Mbr
.Signature
= Layout
->Signature
;
204 for (i
= 0; i
< Layout
->PartitionCount
; i
++) {
207 // Convert each entry.
210 DiskConvertPartitionToExtended (
211 &Layout
->PartitionEntry
[i
],
212 &layoutEx
->PartitionEntry
[i
]
223 IN PDEVICE_OBJECT Fdo
230 This routine is called by the class driver to update the PDO list off
231 of this FDO. The disk driver also calls it internally to re-create
234 This routine will read the partition table and create new PDO objects as
235 necessary. PDO's that no longer exist will be pulled out of the PDO list
236 so that pnp will destroy them.
240 Fdo - a pointer to the FDO being re-enumerated
249 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
250 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
252 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
254 PDISK_DATA diskData
= (PDISK_DATA
) commonExtension
->DriverData
;
256 PDEVICE_OBJECT pdo
= NULL
;
258 ULONG numberListElements
= 0;
260 PDRIVE_LAYOUT_INFORMATION_EX partitionList
;
264 ASSERT(commonExtension
->IsFdo
);
269 // Update our image of the size of the drive. This may be necessary if
270 // the drive size is extended or we just released a reservation to
271 // ensure the kernel doesn't reject the partition table.
274 DiskReadDriveCapacity(Fdo
);
277 // Lock out anyone else trying to repartition the disk.
280 DiskAcquirePartitioningLock(fdoExtension
);
283 // Create objects for all the partitions on the device.
286 status
= DiskReadPartitionTableEx(fdoExtension
, FALSE
, &partitionList
);
289 // If the I/O read partition table failed and this is a removable device,
290 // then fix up the partition list to make it look like there is one
291 // zero length partition.
294 if ((!NT_SUCCESS(status
) || partitionList
->PartitionCount
== 0) &&
295 Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
) {
297 SIZE_T partitionListSize
;
300 // Remember whether the drive is ready.
303 diskData
->ReadyStatus
= status
;
306 // Allocate and zero a partition list.
310 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX
, PartitionEntry
[1]);
312 partitionList
= ExAllocatePoolWithTag(NonPagedPool
,
316 if (partitionList
!= NULL
) {
318 RtlZeroMemory( partitionList
, partitionListSize
);
321 // Set the partition count to one and the status to success
322 // so one device object will be created. Set the partition type
326 partitionList
->PartitionStyle
= PARTITION_STYLE_MBR
;
327 partitionList
->PartitionCount
= 1;
329 status
= STATUS_SUCCESS
;
331 status
= STATUS_INSUFFICIENT_RESOURCES
;
335 if (NT_SUCCESS(status
)) {
337 diskData
->UpdatePartitionRoutine(Fdo
, partitionList
);
340 // Record disk signature.
343 if (partitionList
->PartitionStyle
== PARTITION_STYLE_MBR
) {
345 diskData
->PartitionStyle
= PARTITION_STYLE_MBR
;
346 diskData
->Mbr
.Signature
= partitionList
->Mbr
.Signature
;
350 diskData
->PartitionStyle
= PARTITION_STYLE_GPT
;
351 diskData
->Efi
.DiskId
= partitionList
->Gpt
.DiskId
;
355 DiskReleasePartitioningLock(fdoExtension
);
357 return(STATUS_SUCCESS
);
359 } // end DiskEnumerateDevice()
363 DiskUpdateRemovablePartitions(
364 IN PDEVICE_OBJECT Fdo
,
365 IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
372 This routine is called by the class DLL to update the PDO list off of this
373 FDO. The disk driver also calls it internally to re-create device objects.
375 This routine will read the partition table and update the size of the
376 single partition device object which always exists for removable devices.
380 Fdo - a pointer to the FDO being reenumerated.
390 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
392 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
394 ULONG partitionCount
;
396 ULONG partitionNumber
;
397 ULONG partitionOrdinal
= 0;
398 ULONG newPartitionNumber
;
403 PPARTITION_INFORMATION_EX partitionEntry
;
404 PARTITION_STYLE partitionStyle
;
408 ASSERT(Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
);
410 partitionStyle
= PartitionList
->PartitionStyle
;
411 partitionCount
= PartitionList
->PartitionCount
;
413 for(partitionNumber
= 0;
414 partitionNumber
< partitionCount
;
417 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
419 partitionEntry
->PartitionNumber
= 0;
423 // Get exclusive access to the child list while repartitioning.
426 ClassAcquireChildLock(fdoExtension
);
429 // Removable media should never have more than one PDO.
432 pdoExtension
= fdoExtension
->CommonExtension
.ChildList
;
434 if(pdoExtension
== NULL
) {
436 PARTITION_INFORMATION_EX tmpPartitionEntry
;
440 // There is no PDO currently. Create one and pre-initialize it with
444 RtlZeroMemory(&tmpPartitionEntry
, sizeof(tmpPartitionEntry
));
446 tmpPartitionEntry
.PartitionNumber
= 1;
448 DebugPrint((1, "DiskUpdateRemovablePartitions: Creating RM partition\n"));
450 status
= DiskCreatePdo(Fdo
,
456 if(!NT_SUCCESS(status
)) {
458 DebugPrint((1, "DiskUpdateRemovablePartitions: error %lx creating "
459 "new PDO for RM partition\n",
462 ClassReleaseChildLock(fdoExtension
);
467 // mark the new device as enumerated
470 pdoExtension
= pdo
->DeviceExtension
;
471 pdoExtension
->IsMissing
= FALSE
;
475 pdoData
= pdoExtension
->CommonExtension
.DriverData
;
478 // Search the partition list for a valid entry. We're looking for a
479 // primary partition since we only support the one.
482 for(partitionNumber
= 0;
483 partitionNumber
< partitionCount
;
486 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
490 // Is this partition interesting?
493 if (partitionStyle
== PARTITION_STYLE_MBR
) {
495 if(partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
||
496 IsContainerPartition(partitionEntry
->Mbr
.PartitionType
)) {
505 // We have found the first and thus only partition allowed on
506 // this disk. Update the information in the PDO to match the new
509 DebugPrint((1, "DiskUpdateRemovablePartitions: Matched %wZ to #%d, "
511 &pdoExtension
->CommonExtension
.DeviceName
,
512 partitionEntry
->PartitionNumber
,
516 partitionEntry
->PartitionNumber
= 1;
518 pdoData
->PartitionStyle
= partitionStyle
;
519 pdoData
->PartitionOrdinal
= partitionOrdinal
;
520 ASSERT(partitionEntry
->PartitionLength
.LowPart
!= 0x23456789);
522 pdoExtension
->CommonExtension
.StartingOffset
=
523 partitionEntry
->StartingOffset
;
525 pdoExtension
->CommonExtension
.PartitionLength
=
526 partitionEntry
->PartitionLength
;
529 if (partitionStyle
== PARTITION_STYLE_MBR
) {
531 pdoData
->Mbr
.HiddenSectors
= partitionEntry
->Mbr
.HiddenSectors
;
532 pdoData
->Mbr
.BootIndicator
= partitionEntry
->Mbr
.BootIndicator
;
536 // If this partition is being re-written then update the type
537 // information as well
540 if (partitionEntry
->RewritePartition
) {
541 pdoData
->Mbr
.PartitionType
= partitionEntry
->Mbr
.PartitionType
;
546 pdoData
->Efi
.PartitionType
= partitionEntry
->Gpt
.PartitionType
;
547 pdoData
->Efi
.PartitionId
= partitionEntry
->Gpt
.PartitionId
;
548 pdoData
->Efi
.Attributes
= partitionEntry
->Gpt
.Attributes
;
551 pdoData
->Efi
.PartitionName
,
552 partitionEntry
->Gpt
.Name
,
553 sizeof (pdoData
->Efi
.PartitionName
)
558 // Mark this one as found
561 pdoExtension
->IsMissing
= FALSE
;
562 ClassReleaseChildLock(fdoExtension
);
567 // No interesting partition was found.
570 if (partitionStyle
== PARTITION_STYLE_MBR
) {
572 pdoData
->Mbr
.HiddenSectors
= 0;
573 pdoData
->Mbr
.PartitionType
= PARTITION_ENTRY_UNUSED
;
577 RtlZeroMemory (&pdoData
->Efi
,
578 sizeof (pdoData
->Efi
)
582 pdoExtension
->CommonExtension
.StartingOffset
.QuadPart
= 0;
583 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
= 0;
585 ClassReleaseChildLock(fdoExtension
);
591 DiskUpdatePartitions(
592 IN PDEVICE_OBJECT Fdo
,
593 IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
600 This routine will synchronize the information held in the partition list
601 with the device objects hanging off this Fdo. Any new partition objects
602 will be created, any non-existant ones will be marked as un-enumerated.
604 This will be done in several stages:
606 * Clear state (partition number) from every entry in the partition
609 * Set IsMissing flag on every child of this FDO
611 * For each child of the FDO:
612 if a matching partition exists in the partition list,
613 update the partition number in the table, update the
614 ordinal in the object and mark the object as enumerated
616 * For each un-enumerated device object
617 zero out the partition information to invalidate the device
618 delete the symbolic link if any
620 * For each un-matched entry in the partition list:
621 create a new partition object
622 update the partition number in the list entry
623 create a new symbolic link if necessary
627 Fdo - a pointer to the functional device object this partition list is for
629 PartitionList - a pointer to the partition list being updated
638 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
640 PPHYSICAL_DEVICE_EXTENSION oldChildList
= NULL
;
641 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
643 ULONG partitionCount
;
645 ULONG partitionNumber
;
646 ULONG partitionOrdinal
;
647 ULONG newPartitionNumber
;
649 PPARTITION_INFORMATION_EX partitionEntry
= NULL
;
651 PARTITION_STYLE partitionStyle
;
658 // Get exclusive access to the child list.
661 ClassAcquireChildLock(fdoExtension
);
663 partitionStyle
= PartitionList
->PartitionStyle
;
665 partitionCount
= PartitionList
->PartitionCount
;
668 // Pull all the child device objects off the children list. We'll
669 // add them back later.
672 oldChildList
= fdoExtension
->CommonExtension
.ChildList
;
673 fdoExtension
->CommonExtension
.ChildList
= NULL
;
676 // Clear the partition numbers from the list entries
679 for(partitionNumber
= 0;
680 partitionNumber
< partitionCount
;
683 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
684 partitionEntry
->PartitionNumber
= 0;
688 // Now match each child partition to it's entry (if any) in the partition
692 while(oldChildList
!= NULL
) {
694 pdoExtension
= oldChildList
;
695 pdoData
= pdoExtension
->CommonExtension
.DriverData
;
698 // Check all partition entries for a match on offset and length
701 partitionOrdinal
= 0;
703 for(partitionNumber
= 0;
704 partitionNumber
< partitionCount
;
707 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
710 // Is this an interesting partition entry?
713 if (partitionStyle
== PARTITION_STYLE_MBR
) {
715 if((partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
) ||
716 (IsContainerPartition(partitionEntry
->Mbr
.PartitionType
))) {
724 if(partitionEntry
->PartitionNumber
) {
727 // This partition has already been found - skip it
734 // Let's see if the partition information matches
737 if(partitionEntry
->StartingOffset
.QuadPart
!=
738 pdoExtension
->CommonExtension
.StartingOffset
.QuadPart
) {
742 if(partitionEntry
->PartitionLength
.QuadPart
!=
743 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
) {
748 // Yep - it matches. Update the information in the entry
751 partitionEntry
->PartitionNumber
= pdoExtension
->CommonExtension
.PartitionNumber
;
753 if (partitionStyle
== PARTITION_STYLE_MBR
) {
755 pdoData
->Mbr
.HiddenSectors
= partitionEntry
->Mbr
.HiddenSectors
;
762 if(partitionNumber
!= partitionCount
) {
764 DebugPrint((1, "DiskUpdatePartitions: Matched %wZ to #%d, ordinal "
766 &pdoExtension
->CommonExtension
.DeviceName
,
767 partitionEntry
->PartitionNumber
,
770 ASSERT(partitionEntry
->PartitionLength
.LowPart
!= 0x23456789);
771 // ASSERT(pdoExtension->CommonExtension.PartitionLength.QuadPart != 0);
773 pdoData
->PartitionStyle
= partitionStyle
;
776 // we found a match - update the information in the device object
777 // extension and driverdata
780 pdoData
->PartitionOrdinal
= partitionOrdinal
;
783 // If this partition is being re-written then update the type
784 // information as well
788 if (partitionStyle
== PARTITION_STYLE_MBR
) {
790 if(partitionEntry
->RewritePartition
) {
791 pdoData
->Mbr
.PartitionType
= partitionEntry
->Mbr
.PartitionType
;
796 DebugPrint((1, "DiskUpdatePartitions: EFI Partition %ws\n",
797 pdoData
->Efi
.PartitionName
800 pdoData
->Efi
.PartitionType
= partitionEntry
->Gpt
.PartitionType
;
801 pdoData
->Efi
.PartitionId
= partitionEntry
->Gpt
.PartitionId
;
802 pdoData
->Efi
.Attributes
= partitionEntry
->Gpt
.Attributes
;
805 pdoData
->Efi
.PartitionName
,
806 partitionEntry
->Gpt
.Name
,
807 sizeof (pdoData
->Efi
.PartitionName
)
812 // Mark this one as found.
815 pdoExtension
->IsMissing
= FALSE
;
818 // Pull it out of the old child list and add it into the
822 oldChildList
= pdoExtension
->CommonExtension
.ChildList
;
824 pdoExtension
->CommonExtension
.ChildList
=
825 fdoExtension
->CommonExtension
.ChildList
;
827 fdoExtension
->CommonExtension
.ChildList
= pdoExtension
;
831 PDEVICE_OBJECT nextPdo
;
833 DebugPrint ((1, "DiskUpdatePartitions: Deleting %wZ\n",
834 &pdoExtension
->CommonExtension
.DeviceName
));
836 if (partitionStyle
== PARTITION_STYLE_GPT
) {
838 DebugPrint ((1, "DiskUpdatePartitions: EFI Partition %ws\n",
839 pdoData
->Efi
.PartitionName
843 // no matching entry in the partition list - throw this partition
847 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
= 0;
850 // grab a pointer to the next child before we mark this one as
851 // missing since missing devices could vanish at any time.
854 oldChildList
= pdoExtension
->CommonExtension
.ChildList
;
855 pdoExtension
->CommonExtension
.ChildList
= (PVOID
) -1;
858 // Now tell the class driver that this child is "missing" - this
859 // will cause it to be deleted.
863 ClassMarkChildMissing(pdoExtension
, FALSE
);
868 // At this point the old child list had best be empty.
871 ASSERT(oldChildList
== NULL
);
874 // Iterate through the partition entries and create any partition
875 // objects that don't already exist
878 partitionOrdinal
= 0;
879 newPartitionNumber
= 0;
881 for(partitionNumber
= 0;
882 partitionNumber
< partitionCount
;
887 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
890 // Is this partition interesting
893 if (partitionStyle
== PARTITION_STYLE_MBR
) {
895 if((partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
) ||
896 (IsContainerPartition(partitionEntry
->Mbr
.PartitionType
))) {
903 // Increment the count of interesting partitions
907 newPartitionNumber
++;
910 // Has this already been matched
913 if(partitionEntry
->PartitionNumber
== 0) {
918 // find the first safe partition number for this device
921 for(i
= 0; i
< (LONG
) partitionCount
; i
++) {
924 PPARTITION_INFORMATION_EX tmp
= &(PartitionList
->PartitionEntry
[i
]);
926 if (partitionStyle
== PARTITION_STYLE_MBR
) {
927 if (tmp
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
||
928 IsContainerPartition(tmp
->Mbr
.PartitionType
)) {
933 if(tmp
->PartitionNumber
== newPartitionNumber
) {
936 // Found a matching partition number - increment the count
937 // and restart the scan.
940 newPartitionNumber
++;
947 // Assign this partition a partition number
950 partitionEntry
->PartitionNumber
= newPartitionNumber
;
952 DebugPrint((1, "DiskUpdatePartitions: Found new partition #%d, ord %d "
953 "starting at %#016I64x and running for %#016I64x\n",
954 partitionEntry
->PartitionNumber
,
956 partitionEntry
->StartingOffset
.QuadPart
,
957 partitionEntry
->PartitionLength
.QuadPart
));
959 ClassReleaseChildLock(fdoExtension
);
961 status
= DiskCreatePdo(Fdo
,
967 ClassAcquireChildLock(fdoExtension
);
969 if(!NT_SUCCESS(status
)) {
971 DebugPrint((1, "DiskUpdatePartitions: error %lx creating "
972 "new PDO for partition ordinal %d, number %d\n",
975 partitionEntry
->PartitionNumber
));
978 // don't increment the partition number - we'll try to reuse
979 // it for the next child.
982 partitionEntry
->PartitionNumber
= 0;
983 newPartitionNumber
--;
989 // mark the new device as enumerated
992 pdoExtension
= pdo
->DeviceExtension
;
993 pdoExtension
->IsMissing
= FALSE
;
996 // This number's taken already - try to scanning the partition
997 // table more than once for a new number.
1004 // ISSUE - 2000/02/09 - math: Review.
1005 // Is PartitionStyle the only field that needs updating?
1009 PCOMMON_DEVICE_EXTENSION commonExtension
;
1010 PDISK_DATA diskData
;
1012 commonExtension
= Fdo
->DeviceExtension
;
1013 diskData
= (PDISK_DATA
)(commonExtension
->DriverData
);
1015 diskData
->PartitionStyle
= partitionStyle
;
1018 ClassReleaseChildLock(fdoExtension
);
1025 IN PDEVICE_OBJECT Fdo
,
1026 IN ULONG PartitionOrdinal
,
1027 IN PPARTITION_INFORMATION_EX PartitionEntry
,
1028 IN PARTITION_STYLE PartitionStyle
,
1029 OUT PDEVICE_OBJECT
*Pdo
1034 Routine Description:
1036 This routine will create and initialize a new partition device object
1037 (PDO) and insert it into the FDO partition list.
1041 Fdo - a pointer to the functional device object this PDO will be a child
1044 PartitionOrdinal - the partition ordinal for this PDO
1046 PartitionEntry - the partition information for this device object
1048 PartitionStyle - what style of partition table entry PartitionEntry is;
1049 currently either MBR or EFI
1051 Pdo - a location to store the pdo pointer upon successful completion
1060 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1062 PDEVICE_OBJECT pdo
= NULL
;
1063 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
1065 PUCHAR deviceName
= NULL
;
1067 PDISK_DATA diskData
= fdoExtension
->CommonExtension
.DriverData
;
1069 ULONG numberListElements
;
1071 NTSTATUS status
= STATUS_SUCCESS
;
1076 // Create partition object and set up partition parameters.
1079 status
= DiskGenerateDeviceName(FALSE
,
1080 fdoExtension
->DeviceNumber
,
1081 PartitionEntry
->PartitionNumber
,
1082 &PartitionEntry
->StartingOffset
,
1083 &PartitionEntry
->PartitionLength
,
1086 if(!NT_SUCCESS(status
)) {
1088 DebugPrint((1, "DiskCreatePdo - Can't generate name %lx\n", status
));
1092 DebugPrint((2, "DiskCreatePdo: Create device object %s\n", deviceName
));
1094 status
= ClassCreateDeviceObject(Fdo
->DriverObject
,
1100 if (!NT_SUCCESS(status
)) {
1102 DebugPrint((1, "DiskEnumerateDevice: Can't create device object for %s\n", deviceName
));
1108 // Set up device extension fields.
1111 pdoExtension
= pdo
->DeviceExtension
;
1114 // Set up device object fields.
1117 SET_FLAG(pdo
->Flags
, DO_DIRECT_IO
);
1119 pdo
->StackSize
= (CCHAR
)
1120 pdoExtension
->CommonExtension
.LowerDeviceObject
->StackSize
+ 1;
1123 // Get pointer to new disk data.
1126 diskData
= (PDISK_DATA
) pdoExtension
->CommonExtension
.DriverData
;
1129 // Set the alignment requirements for the device based on the
1130 // host adapter requirements
1133 if (Fdo
->AlignmentRequirement
> pdo
->AlignmentRequirement
) {
1134 pdo
->AlignmentRequirement
= Fdo
->AlignmentRequirement
;
1137 if (fdoExtension
->SrbFlags
& SRB_FLAGS_QUEUE_ACTION_ENABLE
) {
1138 numberListElements
= 30;
1140 numberListElements
= 8;
1144 // Build the lookaside list for srb's for this partition based on
1145 // whether the adapter and disk can do tagged queueing. Don't bother to
1146 // check the status - this can't fail when called for a PDO.
1149 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION
) pdoExtension
,
1150 numberListElements
);
1153 // Set the sense-data pointer in the device extension.
1156 diskData
->PartitionOrdinal
= PartitionOrdinal
;
1157 pdoExtension
->CommonExtension
.PartitionNumber
= PartitionEntry
->PartitionNumber
;
1160 // Initialize relevant data.
1163 if (PartitionStyle
== PARTITION_STYLE_MBR
) {
1165 diskData
->Mbr
.PartitionType
= PartitionEntry
->Mbr
.PartitionType
;
1166 diskData
->Mbr
.BootIndicator
= PartitionEntry
->Mbr
.BootIndicator
;
1167 diskData
->Mbr
.HiddenSectors
= PartitionEntry
->Mbr
.HiddenSectors
;
1171 diskData
->Efi
.PartitionType
= PartitionEntry
->Gpt
.PartitionType
;
1172 diskData
->Efi
.PartitionId
= PartitionEntry
->Gpt
.PartitionType
;
1173 diskData
->Efi
.Attributes
= PartitionEntry
->Gpt
.Attributes
;
1174 RtlCopyMemory (diskData
->Efi
.PartitionName
,
1175 PartitionEntry
->Gpt
.Name
,
1176 sizeof (diskData
->Efi
.PartitionName
)
1180 DebugPrint((2, "DiskEnumerateDevice: Partition type is %x\n",
1181 diskData
->Mbr
.PartitionType
));
1183 pdoExtension
->CommonExtension
.StartingOffset
=
1184 PartitionEntry
->StartingOffset
;
1186 pdoExtension
->CommonExtension
.PartitionLength
=
1187 PartitionEntry
->PartitionLength
;
1190 DebugPrint((1, "DiskCreatePdo: hidden sectors value for pdo %#p set to %#x\n",
1192 diskData
->Mbr
.HiddenSectors
));
1195 // Check for removable media support.
1198 if (fdoExtension
->DeviceDescriptor
->RemovableMedia
) {
1199 SET_FLAG(pdo
->Characteristics
, FILE_REMOVABLE_MEDIA
);
1202 pdoExtension
->CommonExtension
.DeviceObject
= pdo
;
1204 CLEAR_FLAG(pdo
->Flags
, DO_DEVICE_INITIALIZING
);
1216 DiskAcquirePartitioningLock(
1217 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1220 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1224 ASSERT_FDO(FdoExtension
->DeviceObject
);
1226 KeWaitForSingleObject(&(diskData
->PartitioningEvent
),
1236 DiskReleasePartitioningLock(
1237 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1240 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1244 ASSERT_FDO(FdoExtension
->DeviceObject
);
1246 KeSetEvent(&(diskData
->PartitioningEvent
), IO_NO_INCREMENT
, FALSE
);