/*++ Copyright (C) Microsoft Corporation, 1991 - 1999 Module Name: pnp.c Abstract: SCSI disk class driver Environment: kernel mode only Notes: Revision History: --*/ #include "disk.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, DiskConvertExtendedToLayout) #pragma alloc_text(PAGE, DiskConvertPartitionToExtended) #pragma alloc_text(PAGE, DiskConvertLayoutToExtended) #pragma alloc_text(PAGE, DiskCreatePdo) #pragma alloc_text(PAGE, DiskEnumerateDevice) #pragma alloc_text(PAGE, DiskUpdateRemovablePartitions) #pragma alloc_text(PAGE, DiskUpdatePartitions) #pragma alloc_text(PAGE, DiskCreatePdo) #endif PDRIVE_LAYOUT_INFORMATION DiskConvertExtendedToLayout( IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx ) { ULONG i; ULONG LayoutSize; PDRIVE_LAYOUT_INFORMATION Layout; PPARTITION_INFORMATION Partition; PPARTITION_INFORMATION_EX PartitionEx; PAGED_CODE (); ASSERT ( LayoutEx ); // // The only valid conversion is from an MBR extended layout structure to // the old structure. // if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR) { ASSERT ( FALSE ); return NULL; } LayoutSize = FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]) + LayoutEx->PartitionCount * sizeof (PARTITION_INFORMATION); Layout = ExAllocatePoolWithTag ( NonPagedPool, LayoutSize, DISK_TAG_PART_LIST ); if ( Layout == NULL ) { return NULL; } Layout->Signature = LayoutEx->Mbr.Signature; Layout->PartitionCount = LayoutEx->PartitionCount; for (i = 0; i < LayoutEx->PartitionCount; i++) { Partition = &Layout->PartitionEntry[i]; PartitionEx = &LayoutEx->PartitionEntry[i]; Partition->StartingOffset = PartitionEx->StartingOffset; Partition->PartitionLength = PartitionEx->PartitionLength; Partition->RewritePartition = PartitionEx->RewritePartition; Partition->PartitionNumber = PartitionEx->PartitionNumber; Partition->PartitionType = PartitionEx->Mbr.PartitionType; Partition->BootIndicator = PartitionEx->Mbr.BootIndicator; Partition->RecognizedPartition = PartitionEx->Mbr.RecognizedPartition; Partition->HiddenSectors = PartitionEx->Mbr.HiddenSectors; } return Layout; } VOID DiskConvertPartitionToExtended( IN PPARTITION_INFORMATION Partition, OUT PPARTITION_INFORMATION_EX PartitionEx ) /*++ Routine Description: Convert a PARTITION_INFORMATION structure to a PARTITION_INFORMATION_EX structure. Arguments: Partition - A pointer to the PARTITION_INFORMATION structure to convert. PartitionEx - A pointer to a buffer where the converted PARTITION_INFORMATION_EX structure is to be stored. Return Values: None. --*/ { PAGED_CODE (); ASSERT ( PartitionEx != NULL ); ASSERT ( Partition != NULL ); PartitionEx->PartitionStyle = PARTITION_STYLE_MBR; PartitionEx->StartingOffset = Partition->StartingOffset; PartitionEx->PartitionLength = Partition->PartitionLength; PartitionEx->RewritePartition = Partition->RewritePartition; PartitionEx->PartitionNumber = Partition->PartitionNumber; PartitionEx->Mbr.PartitionType = Partition->PartitionType; PartitionEx->Mbr.BootIndicator = Partition->BootIndicator; PartitionEx->Mbr.RecognizedPartition = Partition->RecognizedPartition; PartitionEx->Mbr.HiddenSectors = Partition->HiddenSectors; } PDRIVE_LAYOUT_INFORMATION_EX DiskConvertLayoutToExtended( IN CONST PDRIVE_LAYOUT_INFORMATION Layout ) /*++ Routine Description: Convert a DRIVE_LAYOUT_INFORMATION structure into a DRIVE_LAYOUT_INFORMATION_EX structure. Arguments: Layout - The source DRIVE_LAYOUT_INFORMATION structure. Return Values: The resultant DRIVE_LAYOUT_INFORMATION_EX structure. This buffer must be freed by the callee using ExFreePool. --*/ { ULONG i; ULONG size; PDRIVE_LAYOUT_INFORMATION_EX layoutEx; PAGED_CODE (); ASSERT ( Layout != NULL ); // // Allocate enough space for a DRIVE_LAYOUT_INFORMATION_EX structure // plus as many PARTITION_INFORMATION_EX structures as are in the // source array. // size = FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]) + Layout->PartitionCount * sizeof ( PARTITION_INFORMATION_EX ); layoutEx = ExAllocatePoolWithTag( NonPagedPool, size, DISK_TAG_PART_LIST ); if ( layoutEx == NULL ) { return NULL; } // // Convert the disk information. // layoutEx->PartitionStyle = PARTITION_STYLE_MBR; layoutEx->PartitionCount = Layout->PartitionCount; layoutEx->Mbr.Signature = Layout->Signature; for (i = 0; i < Layout->PartitionCount; i++) { // // Convert each entry. // DiskConvertPartitionToExtended ( &Layout->PartitionEntry[i], &layoutEx->PartitionEntry[i] ); } return layoutEx; } NTSTATUS DiskEnumerateDevice( IN PDEVICE_OBJECT Fdo ) /*++ Routine Description: This routine is called by the class driver to update the PDO list off of this FDO. The disk driver also calls it internally to re-create device objects. This routine will read the partition table and create new PDO objects as necessary. PDO's that no longer exist will be pulled out of the PDO list so that pnp will destroy them. Arguments: Fdo - a pointer to the FDO being re-enumerated Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; PDISK_DATA diskData = (PDISK_DATA) commonExtension->DriverData; PDEVICE_OBJECT pdo = NULL; ULONG numberListElements = 0; PDRIVE_LAYOUT_INFORMATION_EX partitionList; NTSTATUS status; ASSERT(commonExtension->IsFdo); PAGED_CODE(); // // Update our image of the size of the drive. This may be necessary if // the drive size is extended or we just released a reservation to // ensure the kernel doesn't reject the partition table. // DiskReadDriveCapacity(Fdo); // // Lock out anyone else trying to repartition the disk. // DiskAcquirePartitioningLock(fdoExtension); // // Create objects for all the partitions on the device. // status = DiskReadPartitionTableEx(fdoExtension, FALSE, &partitionList); // // If the I/O read partition table failed and this is a removable device, // then fix up the partition list to make it look like there is one // zero length partition. // if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) && Fdo->Characteristics & FILE_REMOVABLE_MEDIA) { SIZE_T partitionListSize; // // Remember whether the drive is ready. // diskData->ReadyStatus = status; // // Allocate and zero a partition list. // partitionListSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]); partitionList = ExAllocatePoolWithTag(NonPagedPool, partitionListSize, DISK_TAG_PART_LIST); if (partitionList != NULL) { RtlZeroMemory( partitionList, partitionListSize ); // // Set the partition count to one and the status to success // so one device object will be created. Set the partition type // to a bogus value. // partitionList->PartitionStyle = PARTITION_STYLE_MBR; partitionList->PartitionCount = 1; status = STATUS_SUCCESS; } else { status = STATUS_INSUFFICIENT_RESOURCES; } } if (NT_SUCCESS(status)) { diskData->UpdatePartitionRoutine(Fdo, partitionList); // // Record disk signature. // if (partitionList->PartitionStyle == PARTITION_STYLE_MBR) { diskData->PartitionStyle = PARTITION_STYLE_MBR; diskData->Mbr.Signature = partitionList->Mbr.Signature; } else { diskData->PartitionStyle = PARTITION_STYLE_GPT; diskData->Efi.DiskId = partitionList->Gpt.DiskId; } } DiskReleasePartitioningLock(fdoExtension); return(STATUS_SUCCESS); } // end DiskEnumerateDevice() VOID DiskUpdateRemovablePartitions( IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList ) /*++ Routine Description: This routine is called by the class DLL to update the PDO list off of this FDO. The disk driver also calls it internally to re-create device objects. This routine will read the partition table and update the size of the single partition device object which always exists for removable devices. Arguments: Fdo - a pointer to the FDO being reenumerated. Return Value: status --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; ULONG partitionCount; ULONG partitionNumber; ULONG partitionOrdinal = 0; ULONG newPartitionNumber; PDISK_DATA pdoData; NTSTATUS status; PPARTITION_INFORMATION_EX partitionEntry; PARTITION_STYLE partitionStyle; PAGED_CODE(); ASSERT(Fdo->Characteristics & FILE_REMOVABLE_MEDIA); partitionStyle = PartitionList->PartitionStyle; partitionCount = PartitionList->PartitionCount; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); partitionEntry->PartitionNumber = 0; } // // Get exclusive access to the child list while repartitioning. // ClassAcquireChildLock(fdoExtension); // // Removable media should never have more than one PDO. // pdoExtension = fdoExtension->CommonExtension.ChildList; if(pdoExtension == NULL) { PARTITION_INFORMATION_EX tmpPartitionEntry; PDEVICE_OBJECT pdo; // // There is no PDO currently. Create one and pre-initialize it with // a zero length. // RtlZeroMemory(&tmpPartitionEntry, sizeof(tmpPartitionEntry)); tmpPartitionEntry.PartitionNumber = 1; DebugPrint((1, "DiskUpdateRemovablePartitions: Creating RM partition\n")); status = DiskCreatePdo(Fdo, 0, &tmpPartitionEntry, partitionStyle, &pdo); if(!NT_SUCCESS(status)) { DebugPrint((1, "DiskUpdateRemovablePartitions: error %lx creating " "new PDO for RM partition\n", status)); ClassReleaseChildLock(fdoExtension); return; } // // mark the new device as enumerated // pdoExtension = pdo->DeviceExtension; pdoExtension->IsMissing = FALSE; } pdoData = pdoExtension->CommonExtension.DriverData; // // Search the partition list for a valid entry. We're looking for a // primary partition since we only support the one. // for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this partition interesting? // if (partitionStyle == PARTITION_STYLE_MBR) { if(partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || IsContainerPartition(partitionEntry->Mbr.PartitionType)) { continue; } } partitionOrdinal++; // // We have found the first and thus only partition allowed on // this disk. Update the information in the PDO to match the new // partition. // DebugPrint((1, "DiskUpdateRemovablePartitions: Matched %wZ to #%d, " "ordinal %d\n", &pdoExtension->CommonExtension.DeviceName, partitionEntry->PartitionNumber, partitionOrdinal)); partitionEntry->PartitionNumber = 1; pdoData->PartitionStyle = partitionStyle; pdoData->PartitionOrdinal = partitionOrdinal; ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789); pdoExtension->CommonExtension.StartingOffset = partitionEntry->StartingOffset; pdoExtension->CommonExtension.PartitionLength = partitionEntry->PartitionLength; if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors; pdoData->Mbr.BootIndicator = partitionEntry->Mbr.BootIndicator; // // If this partition is being re-written then update the type // information as well // if (partitionEntry->RewritePartition) { pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType; } } else { pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType; pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId; pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes; RtlCopyMemory( pdoData->Efi.PartitionName, partitionEntry->Gpt.Name, sizeof (pdoData->Efi.PartitionName) ); } // // Mark this one as found // pdoExtension->IsMissing = FALSE; ClassReleaseChildLock(fdoExtension); return; } // // No interesting partition was found. // if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = 0; pdoData->Mbr.PartitionType = PARTITION_ENTRY_UNUSED; } else { RtlZeroMemory (&pdoData->Efi, sizeof (pdoData->Efi) ); } pdoExtension->CommonExtension.StartingOffset.QuadPart = 0; pdoExtension->CommonExtension.PartitionLength.QuadPart = 0; ClassReleaseChildLock(fdoExtension); return; } VOID DiskUpdatePartitions( IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList ) /*++ Routine Description: This routine will synchronize the information held in the partition list with the device objects hanging off this Fdo. Any new partition objects will be created, any non-existant ones will be marked as un-enumerated. This will be done in several stages: * Clear state (partition number) from every entry in the partition list * Set IsMissing flag on every child of this FDO * For each child of the FDO: if a matching partition exists in the partition list, update the partition number in the table, update the ordinal in the object and mark the object as enumerated * For each un-enumerated device object zero out the partition information to invalidate the device delete the symbolic link if any * For each un-matched entry in the partition list: create a new partition object update the partition number in the list entry create a new symbolic link if necessary Arguments: Fdo - a pointer to the functional device object this partition list is for PartitionList - a pointer to the partition list being updated Return Value: none --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PPHYSICAL_DEVICE_EXTENSION oldChildList = NULL; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; ULONG partitionCount; ULONG partitionNumber; ULONG partitionOrdinal; ULONG newPartitionNumber; PPARTITION_INFORMATION_EX partitionEntry; PDISK_DATA pdoData; PARTITION_STYLE partitionStyle; NTSTATUS status; PAGED_CODE(); // // Get exclusive access to the child list. // ClassAcquireChildLock(fdoExtension); partitionStyle = PartitionList->PartitionStyle; partitionCount = PartitionList->PartitionCount; // // Pull all the child device objects off the children list. We'll // add them back later. // oldChildList = fdoExtension->CommonExtension.ChildList; fdoExtension->CommonExtension.ChildList = NULL; // // Clear the partition numbers from the list entries // for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); partitionEntry->PartitionNumber = 0; } // // Now match each child partition to it's entry (if any) in the partition // list. // while(oldChildList != NULL) { pdoExtension = oldChildList; pdoData = pdoExtension->CommonExtension.DriverData; // // Check all partition entries for a match on offset and length // partitionOrdinal = 0; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this an interesting partition entry? // if (partitionStyle == PARTITION_STYLE_MBR) { if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) || (IsContainerPartition(partitionEntry->Mbr.PartitionType))) { continue; } } partitionOrdinal++; if(partitionEntry->PartitionNumber) { // // This partition has already been found - skip it // continue; } // // Let's see if the partition information matches // if(partitionEntry->StartingOffset.QuadPart != pdoExtension->CommonExtension.StartingOffset.QuadPart) { continue; } if(partitionEntry->PartitionLength.QuadPart != pdoExtension->CommonExtension.PartitionLength.QuadPart) { continue; } // // Yep - it matches. Update the information in the entry // partitionEntry->PartitionNumber = pdoExtension->CommonExtension.PartitionNumber; if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors; } break; } if(partitionNumber != partitionCount) { DebugPrint((1, "DiskUpdatePartitions: Matched %wZ to #%d, ordinal " "%d\n", &pdoExtension->CommonExtension.DeviceName, partitionEntry->PartitionNumber, partitionOrdinal)); ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789); // ASSERT(pdoExtension->CommonExtension.PartitionLength.QuadPart != 0); pdoData->PartitionStyle = partitionStyle; // // we found a match - update the information in the device object // extension and driverdata // pdoData->PartitionOrdinal = partitionOrdinal; // // If this partition is being re-written then update the type // information as well // if (partitionStyle == PARTITION_STYLE_MBR) { if(partitionEntry->RewritePartition) { pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType; } } else { DebugPrint((1, "DiskUpdatePartitions: EFI Partition %ws\n", pdoData->Efi.PartitionName )); pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType; pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId; pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes; RtlCopyMemory( pdoData->Efi.PartitionName, partitionEntry->Gpt.Name, sizeof (pdoData->Efi.PartitionName) ); } // // Mark this one as found. // pdoExtension->IsMissing = FALSE; // // Pull it out of the old child list and add it into the // real one. // oldChildList = pdoExtension->CommonExtension.ChildList; pdoExtension->CommonExtension.ChildList = fdoExtension->CommonExtension.ChildList; fdoExtension->CommonExtension.ChildList = pdoExtension; } else { PDEVICE_OBJECT nextPdo; DebugPrint ((1, "DiskUpdatePartitions: Deleting %wZ\n", &pdoExtension->CommonExtension.DeviceName)); if (partitionStyle == PARTITION_STYLE_GPT) { DebugPrint ((1, "DiskUpdatePartitions: EFI Partition %ws\n", pdoData->Efi.PartitionName )); } // // no matching entry in the partition list - throw this partition // object away // pdoExtension->CommonExtension.PartitionLength.QuadPart = 0; // // grab a pointer to the next child before we mark this one as // missing since missing devices could vanish at any time. // oldChildList = pdoExtension->CommonExtension.ChildList; pdoExtension->CommonExtension.ChildList = (PVOID) -1; // // Now tell the class driver that this child is "missing" - this // will cause it to be deleted. // ClassMarkChildMissing(pdoExtension, FALSE); } } // // At this point the old child list had best be empty. // ASSERT(oldChildList == NULL); // // Iterate through the partition entries and create any partition // objects that don't already exist // partitionOrdinal = 0; newPartitionNumber = 0; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { PDEVICE_OBJECT pdo; partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this partition interesting // if (partitionStyle == PARTITION_STYLE_MBR) { if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) || (IsContainerPartition(partitionEntry->Mbr.PartitionType))) { continue; } } // // Increment the count of interesting partitions // partitionOrdinal++; newPartitionNumber++; // // Has this already been matched // if(partitionEntry->PartitionNumber == 0) { LONG i; // // find the first safe partition number for this device // for(i = 0; i < (LONG) partitionCount; i++) { PPARTITION_INFORMATION_EX tmp = &(PartitionList->PartitionEntry[i]); if (partitionStyle == PARTITION_STYLE_MBR) { if (tmp->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || IsContainerPartition(tmp->Mbr.PartitionType)) { continue; } } if(tmp->PartitionNumber == newPartitionNumber) { // // Found a matching partition number - increment the count // and restart the scan. // newPartitionNumber++; i = -1; continue; } } // // Assign this partition a partition number // partitionEntry->PartitionNumber = newPartitionNumber; DebugPrint((1, "DiskUpdatePartitions: Found new partition #%d, ord %d " "starting at %#016I64x and running for %#016I64x\n", partitionEntry->PartitionNumber, partitionOrdinal, partitionEntry->StartingOffset.QuadPart, partitionEntry->PartitionLength.QuadPart)); ClassReleaseChildLock(fdoExtension); status = DiskCreatePdo(Fdo, partitionOrdinal, partitionEntry, partitionStyle, &pdo); ClassAcquireChildLock(fdoExtension); if(!NT_SUCCESS(status)) { DebugPrint((1, "DiskUpdatePartitions: error %lx creating " "new PDO for partition ordinal %d, number %d\n", status, partitionOrdinal, partitionEntry->PartitionNumber)); // // don't increment the partition number - we'll try to reuse // it for the next child. // partitionEntry->PartitionNumber = 0; newPartitionNumber--; continue; } // // mark the new device as enumerated // pdoExtension = pdo->DeviceExtension; pdoExtension->IsMissing = FALSE; // // This number's taken already - try to scanning the partition // table more than once for a new number. // } } // // ISSUE - 2000/02/09 - math: Review. // Is PartitionStyle the only field that needs updating? // { PCOMMON_DEVICE_EXTENSION commonExtension; PDISK_DATA diskData; commonExtension = Fdo->DeviceExtension; diskData = (PDISK_DATA)(commonExtension->DriverData); diskData->PartitionStyle = partitionStyle; } ClassReleaseChildLock(fdoExtension); return; } NTSTATUS DiskCreatePdo( IN PDEVICE_OBJECT Fdo, IN ULONG PartitionOrdinal, IN PPARTITION_INFORMATION_EX PartitionEntry, IN PARTITION_STYLE PartitionStyle, OUT PDEVICE_OBJECT *Pdo ) /*++ Routine Description: This routine will create and initialize a new partition device object (PDO) and insert it into the FDO partition list. Arguments: Fdo - a pointer to the functional device object this PDO will be a child of PartitionOrdinal - the partition ordinal for this PDO PartitionEntry - the partition information for this device object PartitionStyle - what style of partition table entry PartitionEntry is; currently either MBR or EFI Pdo - a location to store the pdo pointer upon successful completion Return Value: status --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PDEVICE_OBJECT pdo = NULL; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; PUCHAR deviceName = NULL; PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData; ULONG numberListElements; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // // Create partition object and set up partition parameters. // status = DiskGenerateDeviceName(FALSE, fdoExtension->DeviceNumber, PartitionEntry->PartitionNumber, &PartitionEntry->StartingOffset, &PartitionEntry->PartitionLength, &deviceName); if(!NT_SUCCESS(status)) { DebugPrint((1, "DiskCreatePdo - Can't generate name %lx\n", status)); return status; } DebugPrint((2, "DiskCreatePdo: Create device object %s\n", deviceName)); status = ClassCreateDeviceObject(Fdo->DriverObject, deviceName, Fdo, FALSE, &pdo); if (!NT_SUCCESS(status)) { DebugPrint((1, "DiskEnumerateDevice: Can't create device object for %s\n", deviceName)); return status; } // // Set up device extension fields. // pdoExtension = pdo->DeviceExtension; // // Set up device object fields. // SET_FLAG(pdo->Flags, DO_DIRECT_IO); pdo->StackSize = (CCHAR) pdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1; // // Get pointer to new disk data. // diskData = (PDISK_DATA) pdoExtension->CommonExtension.DriverData; // // Set the alignment requirements for the device based on the // host adapter requirements // if (Fdo->AlignmentRequirement > pdo->AlignmentRequirement) { pdo->AlignmentRequirement = Fdo->AlignmentRequirement; } if (fdoExtension->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) { numberListElements = 30; } else { numberListElements = 8; } // // Build the lookaside list for srb's for this partition based on // whether the adapter and disk can do tagged queueing. Don't bother to // check the status - this can't fail when called for a PDO. // ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION) pdoExtension, numberListElements); // // Set the sense-data pointer in the device extension. // diskData->PartitionOrdinal = PartitionOrdinal; pdoExtension->CommonExtension.PartitionNumber = PartitionEntry->PartitionNumber; // // Initialize relevant data. // if (PartitionStyle == PARTITION_STYLE_MBR) { diskData->Mbr.PartitionType = PartitionEntry->Mbr.PartitionType; diskData->Mbr.BootIndicator = PartitionEntry->Mbr.BootIndicator; diskData->Mbr.HiddenSectors = PartitionEntry->Mbr.HiddenSectors; } else { diskData->Efi.PartitionType = PartitionEntry->Gpt.PartitionType; diskData->Efi.PartitionId = PartitionEntry->Gpt.PartitionType; diskData->Efi.Attributes = PartitionEntry->Gpt.Attributes; RtlCopyMemory (diskData->Efi.PartitionName, PartitionEntry->Gpt.Name, sizeof (diskData->Efi.PartitionName) ); } DebugPrint((2, "DiskEnumerateDevice: Partition type is %x\n", diskData->Mbr.PartitionType)); pdoExtension->CommonExtension.StartingOffset = PartitionEntry->StartingOffset; pdoExtension->CommonExtension.PartitionLength = PartitionEntry->PartitionLength; DebugPrint((1, "DiskCreatePdo: hidden sectors value for pdo %#p set to %#x\n", pdo, diskData->Mbr.HiddenSectors)); // // Check for removable media support. // if (fdoExtension->DeviceDescriptor->RemovableMedia) { SET_FLAG(pdo->Characteristics, FILE_REMOVABLE_MEDIA); } pdoExtension->CommonExtension.DeviceObject = pdo; CLEAR_FLAG(pdo->Flags, DO_DEVICE_INITIALIZING); *Pdo = pdo; return status; } VOID DiskAcquirePartitioningLock( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) { PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData; PAGED_CODE(); ASSERT_FDO(FdoExtension->DeviceObject); KeWaitForSingleObject(&(diskData->PartitioningEvent), UserRequest, UserMode, FALSE, NULL); return; } VOID DiskReleasePartitioningLock( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) { PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData; PAGED_CODE(); ASSERT_FDO(FdoExtension->DeviceObject); KeSetEvent(&(diskData->PartitioningEvent), IO_NO_INCREMENT, FALSE); return; }