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
]
224 IN PDEVICE_OBJECT Fdo
231 This routine is called by the class driver to update the PDO list off
232 of this FDO. The disk driver also calls it internally to re-create
235 This routine will read the partition table and create new PDO objects as
236 necessary. PDO's that no longer exist will be pulled out of the PDO list
237 so that pnp will destroy them.
241 Fdo - a pointer to the FDO being re-enumerated
250 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
251 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
253 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
255 PDISK_DATA diskData
= (PDISK_DATA
) commonExtension
->DriverData
;
257 PDEVICE_OBJECT pdo
= NULL
;
259 ULONG numberListElements
= 0;
261 PDRIVE_LAYOUT_INFORMATION_EX partitionList
;
265 ASSERT(commonExtension
->IsFdo
);
270 // Update our image of the size of the drive. This may be necessary if
271 // the drive size is extended or we just released a reservation to
272 // ensure the kernel doesn't reject the partition table.
275 DiskReadDriveCapacity(Fdo
);
278 // Lock out anyone else trying to repartition the disk.
281 DiskAcquirePartitioningLock(fdoExtension
);
284 // Create objects for all the partitions on the device.
287 status
= DiskReadPartitionTableEx(fdoExtension
, FALSE
, &partitionList
);
290 // If the I/O read partition table failed and this is a removable device,
291 // then fix up the partition list to make it look like there is one
292 // zero length partition.
295 if ((!NT_SUCCESS(status
) || partitionList
->PartitionCount
== 0) &&
296 Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
) {
298 SIZE_T partitionListSize
;
301 // Remember whether the drive is ready.
304 diskData
->ReadyStatus
= status
;
307 // Allocate and zero a partition list.
311 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX
, PartitionEntry
[1]);
313 partitionList
= ExAllocatePoolWithTag(NonPagedPool
,
317 if (partitionList
!= NULL
) {
319 RtlZeroMemory( partitionList
, partitionListSize
);
322 // Set the partition count to one and the status to success
323 // so one device object will be created. Set the partition type
327 partitionList
->PartitionStyle
= PARTITION_STYLE_MBR
;
328 partitionList
->PartitionCount
= 1;
330 status
= STATUS_SUCCESS
;
332 status
= STATUS_INSUFFICIENT_RESOURCES
;
336 if (NT_SUCCESS(status
)) {
338 diskData
->UpdatePartitionRoutine(Fdo
, partitionList
);
341 // Record disk signature.
344 if (partitionList
->PartitionStyle
== PARTITION_STYLE_MBR
) {
346 diskData
->PartitionStyle
= PARTITION_STYLE_MBR
;
347 diskData
->Mbr
.Signature
= partitionList
->Mbr
.Signature
;
351 diskData
->PartitionStyle
= PARTITION_STYLE_GPT
;
352 diskData
->Efi
.DiskId
= partitionList
->Gpt
.DiskId
;
356 DiskReleasePartitioningLock(fdoExtension
);
358 return(STATUS_SUCCESS
);
360 } // end DiskEnumerateDevice()
364 DiskUpdateRemovablePartitions(
365 IN PDEVICE_OBJECT Fdo
,
366 IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
373 This routine is called by the class DLL to update the PDO list off of this
374 FDO. The disk driver also calls it internally to re-create device objects.
376 This routine will read the partition table and update the size of the
377 single partition device object which always exists for removable devices.
381 Fdo - a pointer to the FDO being reenumerated.
391 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
393 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
395 ULONG partitionCount
;
397 ULONG partitionNumber
;
398 ULONG partitionOrdinal
= 0;
399 ULONG newPartitionNumber
;
404 PPARTITION_INFORMATION_EX partitionEntry
;
405 PARTITION_STYLE partitionStyle
;
409 ASSERT(Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
);
411 partitionStyle
= PartitionList
->PartitionStyle
;
412 partitionCount
= PartitionList
->PartitionCount
;
414 for(partitionNumber
= 0;
415 partitionNumber
< partitionCount
;
418 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
420 partitionEntry
->PartitionNumber
= 0;
424 // Get exclusive access to the child list while repartitioning.
427 ClassAcquireChildLock(fdoExtension
);
430 // Removable media should never have more than one PDO.
433 pdoExtension
= fdoExtension
->CommonExtension
.ChildList
;
435 if(pdoExtension
== NULL
) {
437 PARTITION_INFORMATION_EX tmpPartitionEntry
;
441 // There is no PDO currently. Create one and pre-initialize it with
445 RtlZeroMemory(&tmpPartitionEntry
, sizeof(tmpPartitionEntry
));
447 tmpPartitionEntry
.PartitionNumber
= 1;
449 DebugPrint((1, "DiskUpdateRemovablePartitions: Creating RM partition\n"));
451 status
= DiskCreatePdo(Fdo
,
457 if(!NT_SUCCESS(status
)) {
459 DebugPrint((1, "DiskUpdateRemovablePartitions: error %lx creating "
460 "new PDO for RM partition\n",
463 ClassReleaseChildLock(fdoExtension
);
468 // mark the new device as enumerated
471 pdoExtension
= pdo
->DeviceExtension
;
472 pdoExtension
->IsMissing
= FALSE
;
476 pdoData
= pdoExtension
->CommonExtension
.DriverData
;
479 // Search the partition list for a valid entry. We're looking for a
480 // primary partition since we only support the one.
483 for(partitionNumber
= 0;
484 partitionNumber
< partitionCount
;
487 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
491 // Is this partition interesting?
494 if (partitionStyle
== PARTITION_STYLE_MBR
) {
496 if(partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
||
497 IsContainerPartition(partitionEntry
->Mbr
.PartitionType
)) {
506 // We have found the first and thus only partition allowed on
507 // this disk. Update the information in the PDO to match the new
510 DebugPrint((1, "DiskUpdateRemovablePartitions: Matched %wZ to #%d, "
512 &pdoExtension
->CommonExtension
.DeviceName
,
513 partitionEntry
->PartitionNumber
,
517 partitionEntry
->PartitionNumber
= 1;
519 pdoData
->PartitionStyle
= partitionStyle
;
520 pdoData
->PartitionOrdinal
= partitionOrdinal
;
521 ASSERT(partitionEntry
->PartitionLength
.LowPart
!= 0x23456789);
523 pdoExtension
->CommonExtension
.StartingOffset
=
524 partitionEntry
->StartingOffset
;
526 pdoExtension
->CommonExtension
.PartitionLength
=
527 partitionEntry
->PartitionLength
;
530 if (partitionStyle
== PARTITION_STYLE_MBR
) {
532 pdoData
->Mbr
.HiddenSectors
= partitionEntry
->Mbr
.HiddenSectors
;
533 pdoData
->Mbr
.BootIndicator
= partitionEntry
->Mbr
.BootIndicator
;
537 // If this partition is being re-written then update the type
538 // information as well
541 if (partitionEntry
->RewritePartition
) {
542 pdoData
->Mbr
.PartitionType
= partitionEntry
->Mbr
.PartitionType
;
547 pdoData
->Efi
.PartitionType
= partitionEntry
->Gpt
.PartitionType
;
548 pdoData
->Efi
.PartitionId
= partitionEntry
->Gpt
.PartitionId
;
549 pdoData
->Efi
.Attributes
= partitionEntry
->Gpt
.Attributes
;
552 pdoData
->Efi
.PartitionName
,
553 partitionEntry
->Gpt
.Name
,
554 sizeof (pdoData
->Efi
.PartitionName
)
559 // Mark this one as found
562 pdoExtension
->IsMissing
= FALSE
;
563 ClassReleaseChildLock(fdoExtension
);
568 // No interesting partition was found.
571 if (partitionStyle
== PARTITION_STYLE_MBR
) {
573 pdoData
->Mbr
.HiddenSectors
= 0;
574 pdoData
->Mbr
.PartitionType
= PARTITION_ENTRY_UNUSED
;
578 RtlZeroMemory (&pdoData
->Efi
,
579 sizeof (pdoData
->Efi
)
583 pdoExtension
->CommonExtension
.StartingOffset
.QuadPart
= 0;
584 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
= 0;
586 ClassReleaseChildLock(fdoExtension
);
592 DiskUpdatePartitions(
593 IN PDEVICE_OBJECT Fdo
,
594 IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
601 This routine will synchronize the information held in the partition list
602 with the device objects hanging off this Fdo. Any new partition objects
603 will be created, any non-existant ones will be marked as un-enumerated.
605 This will be done in several stages:
607 * Clear state (partition number) from every entry in the partition
610 * Set IsMissing flag on every child of this FDO
612 * For each child of the FDO:
613 if a matching partition exists in the partition list,
614 update the partition number in the table, update the
615 ordinal in the object and mark the object as enumerated
617 * For each un-enumerated device object
618 zero out the partition information to invalidate the device
619 delete the symbolic link if any
621 * For each un-matched entry in the partition list:
622 create a new partition object
623 update the partition number in the list entry
624 create a new symbolic link if necessary
628 Fdo - a pointer to the functional device object this partition list is for
630 PartitionList - a pointer to the partition list being updated
639 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
641 PPHYSICAL_DEVICE_EXTENSION oldChildList
= NULL
;
642 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
644 ULONG partitionCount
;
646 ULONG partitionNumber
;
647 ULONG partitionOrdinal
;
648 ULONG newPartitionNumber
;
650 PPARTITION_INFORMATION_EX partitionEntry
;
652 PARTITION_STYLE partitionStyle
;
659 // Get exclusive access to the child list.
662 ClassAcquireChildLock(fdoExtension
);
664 partitionStyle
= PartitionList
->PartitionStyle
;
666 partitionCount
= PartitionList
->PartitionCount
;
669 // Pull all the child device objects off the children list. We'll
670 // add them back later.
673 oldChildList
= fdoExtension
->CommonExtension
.ChildList
;
674 fdoExtension
->CommonExtension
.ChildList
= NULL
;
677 // Clear the partition numbers from the list entries
680 for(partitionNumber
= 0;
681 partitionNumber
< partitionCount
;
684 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
685 partitionEntry
->PartitionNumber
= 0;
689 // Now match each child partition to it's entry (if any) in the partition
693 while(oldChildList
!= NULL
) {
695 pdoExtension
= oldChildList
;
696 pdoData
= pdoExtension
->CommonExtension
.DriverData
;
699 // Check all partition entries for a match on offset and length
702 partitionOrdinal
= 0;
704 for(partitionNumber
= 0;
705 partitionNumber
< partitionCount
;
708 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
711 // Is this an interesting partition entry?
714 if (partitionStyle
== PARTITION_STYLE_MBR
) {
716 if((partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
) ||
717 (IsContainerPartition(partitionEntry
->Mbr
.PartitionType
))) {
725 if(partitionEntry
->PartitionNumber
) {
728 // This partition has already been found - skip it
735 // Let's see if the partition information matches
738 if(partitionEntry
->StartingOffset
.QuadPart
!=
739 pdoExtension
->CommonExtension
.StartingOffset
.QuadPart
) {
743 if(partitionEntry
->PartitionLength
.QuadPart
!=
744 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
) {
749 // Yep - it matches. Update the information in the entry
752 partitionEntry
->PartitionNumber
= pdoExtension
->CommonExtension
.PartitionNumber
;
754 if (partitionStyle
== PARTITION_STYLE_MBR
) {
756 pdoData
->Mbr
.HiddenSectors
= partitionEntry
->Mbr
.HiddenSectors
;
763 if(partitionNumber
!= partitionCount
) {
765 DebugPrint((1, "DiskUpdatePartitions: Matched %wZ to #%d, ordinal "
767 &pdoExtension
->CommonExtension
.DeviceName
,
768 partitionEntry
->PartitionNumber
,
771 ASSERT(partitionEntry
->PartitionLength
.LowPart
!= 0x23456789);
772 // ASSERT(pdoExtension->CommonExtension.PartitionLength.QuadPart != 0);
774 pdoData
->PartitionStyle
= partitionStyle
;
777 // we found a match - update the information in the device object
778 // extension and driverdata
781 pdoData
->PartitionOrdinal
= partitionOrdinal
;
784 // If this partition is being re-written then update the type
785 // information as well
789 if (partitionStyle
== PARTITION_STYLE_MBR
) {
791 if(partitionEntry
->RewritePartition
) {
792 pdoData
->Mbr
.PartitionType
= partitionEntry
->Mbr
.PartitionType
;
797 DebugPrint((1, "DiskUpdatePartitions: EFI Partition %ws\n",
798 pdoData
->Efi
.PartitionName
801 pdoData
->Efi
.PartitionType
= partitionEntry
->Gpt
.PartitionType
;
802 pdoData
->Efi
.PartitionId
= partitionEntry
->Gpt
.PartitionId
;
803 pdoData
->Efi
.Attributes
= partitionEntry
->Gpt
.Attributes
;
806 pdoData
->Efi
.PartitionName
,
807 partitionEntry
->Gpt
.Name
,
808 sizeof (pdoData
->Efi
.PartitionName
)
813 // Mark this one as found.
816 pdoExtension
->IsMissing
= FALSE
;
819 // Pull it out of the old child list and add it into the
823 oldChildList
= pdoExtension
->CommonExtension
.ChildList
;
825 pdoExtension
->CommonExtension
.ChildList
=
826 fdoExtension
->CommonExtension
.ChildList
;
828 fdoExtension
->CommonExtension
.ChildList
= pdoExtension
;
832 PDEVICE_OBJECT nextPdo
;
834 DebugPrint ((1, "DiskUpdatePartitions: Deleting %wZ\n",
835 &pdoExtension
->CommonExtension
.DeviceName
));
837 if (partitionStyle
== PARTITION_STYLE_GPT
) {
839 DebugPrint ((1, "DiskUpdatePartitions: EFI Partition %ws\n",
840 pdoData
->Efi
.PartitionName
844 // no matching entry in the partition list - throw this partition
848 pdoExtension
->CommonExtension
.PartitionLength
.QuadPart
= 0;
851 // grab a pointer to the next child before we mark this one as
852 // missing since missing devices could vanish at any time.
855 oldChildList
= pdoExtension
->CommonExtension
.ChildList
;
856 pdoExtension
->CommonExtension
.ChildList
= (PVOID
) -1;
859 // Now tell the class driver that this child is "missing" - this
860 // will cause it to be deleted.
864 ClassMarkChildMissing(pdoExtension
, FALSE
);
869 // At this point the old child list had best be empty.
872 ASSERT(oldChildList
== NULL
);
875 // Iterate through the partition entries and create any partition
876 // objects that don't already exist
879 partitionOrdinal
= 0;
880 newPartitionNumber
= 0;
882 for(partitionNumber
= 0;
883 partitionNumber
< partitionCount
;
888 partitionEntry
= &(PartitionList
->PartitionEntry
[partitionNumber
]);
891 // Is this partition interesting
894 if (partitionStyle
== PARTITION_STYLE_MBR
) {
896 if((partitionEntry
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
) ||
897 (IsContainerPartition(partitionEntry
->Mbr
.PartitionType
))) {
904 // Increment the count of interesting partitions
908 newPartitionNumber
++;
911 // Has this already been matched
914 if(partitionEntry
->PartitionNumber
== 0) {
919 // find the first safe partition number for this device
922 for(i
= 0; i
< (LONG
) partitionCount
; i
++) {
925 PPARTITION_INFORMATION_EX tmp
= &(PartitionList
->PartitionEntry
[i
]);
927 if (partitionStyle
== PARTITION_STYLE_MBR
) {
928 if (tmp
->Mbr
.PartitionType
== PARTITION_ENTRY_UNUSED
||
929 IsContainerPartition(tmp
->Mbr
.PartitionType
)) {
934 if(tmp
->PartitionNumber
== newPartitionNumber
) {
937 // Found a matching partition number - increment the count
938 // and restart the scan.
941 newPartitionNumber
++;
948 // Assign this partition a partition number
951 partitionEntry
->PartitionNumber
= newPartitionNumber
;
953 DebugPrint((1, "DiskUpdatePartitions: Found new partition #%d, ord %d "
954 "starting at %#016I64x and running for %#016I64x\n",
955 partitionEntry
->PartitionNumber
,
957 partitionEntry
->StartingOffset
.QuadPart
,
958 partitionEntry
->PartitionLength
.QuadPart
));
960 ClassReleaseChildLock(fdoExtension
);
962 status
= DiskCreatePdo(Fdo
,
968 ClassAcquireChildLock(fdoExtension
);
970 if(!NT_SUCCESS(status
)) {
972 DebugPrint((1, "DiskUpdatePartitions: error %lx creating "
973 "new PDO for partition ordinal %d, number %d\n",
976 partitionEntry
->PartitionNumber
));
979 // don't increment the partition number - we'll try to reuse
980 // it for the next child.
983 partitionEntry
->PartitionNumber
= 0;
984 newPartitionNumber
--;
990 // mark the new device as enumerated
993 pdoExtension
= pdo
->DeviceExtension
;
994 pdoExtension
->IsMissing
= FALSE
;
997 // This number's taken already - try to scanning the partition
998 // table more than once for a new number.
1005 // ISSUE - 2000/02/09 - math: Review.
1006 // Is PartitionStyle the only field that needs updating?
1010 PCOMMON_DEVICE_EXTENSION commonExtension
;
1011 PDISK_DATA diskData
;
1013 commonExtension
= Fdo
->DeviceExtension
;
1014 diskData
= (PDISK_DATA
)(commonExtension
->DriverData
);
1016 diskData
->PartitionStyle
= partitionStyle
;
1019 ClassReleaseChildLock(fdoExtension
);
1026 IN PDEVICE_OBJECT Fdo
,
1027 IN ULONG PartitionOrdinal
,
1028 IN PPARTITION_INFORMATION_EX PartitionEntry
,
1029 IN PARTITION_STYLE PartitionStyle
,
1030 OUT PDEVICE_OBJECT
*Pdo
1035 Routine Description:
1037 This routine will create and initialize a new partition device object
1038 (PDO) and insert it into the FDO partition list.
1042 Fdo - a pointer to the functional device object this PDO will be a child
1045 PartitionOrdinal - the partition ordinal for this PDO
1047 PartitionEntry - the partition information for this device object
1049 PartitionStyle - what style of partition table entry PartitionEntry is;
1050 currently either MBR or EFI
1052 Pdo - a location to store the pdo pointer upon successful completion
1061 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1063 PDEVICE_OBJECT pdo
= NULL
;
1064 PPHYSICAL_DEVICE_EXTENSION pdoExtension
= NULL
;
1066 PUCHAR deviceName
= NULL
;
1068 PDISK_DATA diskData
= fdoExtension
->CommonExtension
.DriverData
;
1070 ULONG numberListElements
;
1072 NTSTATUS status
= STATUS_SUCCESS
;
1077 // Create partition object and set up partition parameters.
1080 status
= DiskGenerateDeviceName(FALSE
,
1081 fdoExtension
->DeviceNumber
,
1082 PartitionEntry
->PartitionNumber
,
1083 &PartitionEntry
->StartingOffset
,
1084 &PartitionEntry
->PartitionLength
,
1087 if(!NT_SUCCESS(status
)) {
1089 DebugPrint((1, "DiskCreatePdo - Can't generate name %lx\n", status
));
1093 DebugPrint((2, "DiskCreatePdo: Create device object %s\n", deviceName
));
1095 status
= ClassCreateDeviceObject(Fdo
->DriverObject
,
1101 if (!NT_SUCCESS(status
)) {
1103 DebugPrint((1, "DiskEnumerateDevice: Can't create device object for %s\n", deviceName
));
1109 // Set up device extension fields.
1112 pdoExtension
= pdo
->DeviceExtension
;
1115 // Set up device object fields.
1118 SET_FLAG(pdo
->Flags
, DO_DIRECT_IO
);
1120 pdo
->StackSize
= (CCHAR
)
1121 pdoExtension
->CommonExtension
.LowerDeviceObject
->StackSize
+ 1;
1124 // Get pointer to new disk data.
1127 diskData
= (PDISK_DATA
) pdoExtension
->CommonExtension
.DriverData
;
1130 // Set the alignment requirements for the device based on the
1131 // host adapter requirements
1134 if (Fdo
->AlignmentRequirement
> pdo
->AlignmentRequirement
) {
1135 pdo
->AlignmentRequirement
= Fdo
->AlignmentRequirement
;
1138 if (fdoExtension
->SrbFlags
& SRB_FLAGS_QUEUE_ACTION_ENABLE
) {
1139 numberListElements
= 30;
1141 numberListElements
= 8;
1145 // Build the lookaside list for srb's for this partition based on
1146 // whether the adapter and disk can do tagged queueing. Don't bother to
1147 // check the status - this can't fail when called for a PDO.
1150 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION
) pdoExtension
,
1151 numberListElements
);
1154 // Set the sense-data pointer in the device extension.
1157 diskData
->PartitionOrdinal
= PartitionOrdinal
;
1158 pdoExtension
->CommonExtension
.PartitionNumber
= PartitionEntry
->PartitionNumber
;
1161 // Initialize relevant data.
1164 if (PartitionStyle
== PARTITION_STYLE_MBR
) {
1166 diskData
->Mbr
.PartitionType
= PartitionEntry
->Mbr
.PartitionType
;
1167 diskData
->Mbr
.BootIndicator
= PartitionEntry
->Mbr
.BootIndicator
;
1168 diskData
->Mbr
.HiddenSectors
= PartitionEntry
->Mbr
.HiddenSectors
;
1172 diskData
->Efi
.PartitionType
= PartitionEntry
->Gpt
.PartitionType
;
1173 diskData
->Efi
.PartitionId
= PartitionEntry
->Gpt
.PartitionType
;
1174 diskData
->Efi
.Attributes
= PartitionEntry
->Gpt
.Attributes
;
1175 RtlCopyMemory (diskData
->Efi
.PartitionName
,
1176 PartitionEntry
->Gpt
.Name
,
1177 sizeof (diskData
->Efi
.PartitionName
)
1181 DebugPrint((2, "DiskEnumerateDevice: Partition type is %x\n",
1182 diskData
->Mbr
.PartitionType
));
1184 pdoExtension
->CommonExtension
.StartingOffset
=
1185 PartitionEntry
->StartingOffset
;
1187 pdoExtension
->CommonExtension
.PartitionLength
=
1188 PartitionEntry
->PartitionLength
;
1191 DebugPrint((1, "DiskCreatePdo: hidden sectors value for pdo %#p set to %#x\n",
1193 diskData
->Mbr
.HiddenSectors
));
1196 // Check for removable media support.
1199 if (fdoExtension
->DeviceDescriptor
->RemovableMedia
) {
1200 SET_FLAG(pdo
->Characteristics
, FILE_REMOVABLE_MEDIA
);
1203 pdoExtension
->CommonExtension
.DeviceObject
= pdo
;
1205 CLEAR_FLAG(pdo
->Flags
, DO_DEVICE_INITIALIZING
);
1217 DiskAcquirePartitioningLock(
1218 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1221 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1225 ASSERT_FDO(FdoExtension
->DeviceObject
);
1227 KeWaitForSingleObject(&(diskData
->PartitioningEvent
),
1237 DiskReleasePartitioningLock(
1238 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1241 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1245 ASSERT_FDO(FdoExtension
->DeviceObject
);
1247 KeSetEvent(&(diskData
->PartitioningEvent
), IO_NO_INCREMENT
, FALSE
);