- Separate creating partitions objects into a different function (CreatePartitionsObject()).

- Slightly improve the logic of accessing the partitions list.

svn path=/trunk/; revision=28993
This commit is contained in:
Aleksey Bragin 2007-09-10 16:25:48 +00:00
parent 743a10f834
commit 6f31706927

View file

@ -28,6 +28,12 @@
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'DscS') #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'DscS')
#endif #endif
typedef enum {
NotInitialized,
Initializing,
Initialized
} PARTITION_LIST_STATE;
// //
// Disk device data // Disk device data
// //
@ -100,11 +106,17 @@ typedef struct _DISK_DATA {
// //
// DriveNotReady - inidicates that the this device is currenly not ready // DriveNotReady - inidicates that the this device is currenly not ready
// beacasue there is no media in the device. // because there is no media in the device.
// //
BOOLEAN DriveNotReady; BOOLEAN DriveNotReady;
//
// State of PartitionList initialization
//
PARTITION_LIST_STATE PartitionListState;
} DISK_DATA, *PDISK_DATA; } DISK_DATA, *PDISK_DATA;
// //
@ -270,6 +282,13 @@ CreateDiskDeviceObject(
IN PCLASS_INIT_DATA InitData IN PCLASS_INIT_DATA InitData
); );
NTSTATUS
STDCALL
CreatePartitionDeviceObjects(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PUNICODE_STRING RegistryPath
);
VOID VOID
STDCALL STDCALL
UpdateDeviceObjects( UpdateDeviceObjects(
@ -628,30 +647,21 @@ Return Value:
CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH]; CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
STRING ntNameString; STRING ntNameString;
UNICODE_STRING ntUnicodeString; UNICODE_STRING ntUnicodeString;
ULONG partitionNumber = 0;
OBJECT_ATTRIBUTES objectAttributes; OBJECT_ATTRIBUTES objectAttributes;
HANDLE handle; HANDLE handle;
NTSTATUS status; NTSTATUS status;
PDEVICE_OBJECT deviceObject = NULL; PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_OBJECT physicalDevice; PDEVICE_OBJECT physicalDevice;
PDISK_GEOMETRY diskGeometry = NULL; PDISK_GEOMETRY diskGeometry = NULL;
PDRIVE_LAYOUT_INFORMATION partitionList;
PDEVICE_EXTENSION deviceExtension = NULL; PDEVICE_EXTENSION deviceExtension = NULL;
PDEVICE_EXTENSION physicalDeviceExtension; PDEVICE_EXTENSION physicalDeviceExtension;
PDISK_DATA diskData;
ULONG bytesPerSector;
UCHAR sectorShift;
UCHAR pathId = LunInfo->PathId; UCHAR pathId = LunInfo->PathId;
UCHAR targetId = LunInfo->TargetId; UCHAR targetId = LunInfo->TargetId;
UCHAR lun = LunInfo->Lun; UCHAR lun = LunInfo->Lun;
BOOLEAN writeCache; BOOLEAN writeCache;
PVOID senseData = NULL; PVOID senseData = NULL;
ULONG srbFlags; ULONG srbFlags;
ULONG dmByteSkew = 0;
PULONG dmSkew;
BOOLEAN dmActive = FALSE;
ULONG timeOut = 0; ULONG timeOut = 0;
ULONG numberListElements = 0;
BOOLEAN srbListInitialized = FALSE; BOOLEAN srbListInitialized = FALSE;
@ -995,19 +1005,88 @@ Return Value:
deviceObject->Flags &= ~DO_VERIFY_VOLUME; deviceObject->Flags &= ~DO_VERIFY_VOLUME;
} }
status = CreatePartitionDeviceObjects(deviceObject, RegistryPath);
if (NT_SUCCESS(status))
return STATUS_SUCCESS;
CreateDiskDeviceObjectsExit:
// //
// Set up sector size fields. // Release the device since an error occurred.
//
// Stack variables will be used to update
// the partition device extensions.
//
// The device extension field SectorShift is
// used to calculate sectors in I/O transfers.
//
// The DiskGeometry structure is used to service
// IOCTls used by the format utility.
// //
ScsiClassClaimDevice(PortDeviceObject,
LunInfo,
TRUE,
NULL);
if (diskGeometry != NULL) {
ExFreePool(diskGeometry);
}
if (senseData != NULL) {
ExFreePool(senseData);
}
if (deviceObject != NULL) {
if (srbListInitialized) {
ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
}
IoDeleteDevice(deviceObject);
}
//
// Delete directory and return.
//
if (!NT_SUCCESS(status)) {
ZwMakeTemporaryObject(handle);
}
ZwClose(handle);
return(status);
} // end CreateDiskDeviceObjects()
NTSTATUS
STDCALL
CreatePartitionDeviceObjects(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PUNICODE_STRING RegistryPath
)
{
CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
ULONG partitionNumber = 0;
NTSTATUS status;
PDEVICE_OBJECT deviceObject = NULL;
PDISK_GEOMETRY diskGeometry = NULL;
PDRIVE_LAYOUT_INFORMATION partitionList = NULL;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_EXTENSION physicalDeviceExtension;
PCLASS_INIT_DATA initData = NULL;
PDISK_DATA diskData;
PDISK_DATA physicalDiskData;
ULONG bytesPerSector;
UCHAR sectorShift;
ULONG srbFlags;
ULONG dmByteSkew = 0;
PULONG dmSkew;
BOOLEAN dmActive = FALSE;
ULONG numberListElements = 0;
//
// Get physical device geometry information for partition table reads.
//
physicalDeviceExtension = PhysicalDeviceObject->DeviceExtension;
diskGeometry = physicalDeviceExtension->DiskGeometry;
bytesPerSector = diskGeometry->BytesPerSector; bytesPerSector = diskGeometry->BytesPerSector;
// //
@ -1023,13 +1102,14 @@ Return Value:
bytesPerSector = diskGeometry->BytesPerSector = 512; bytesPerSector = diskGeometry->BytesPerSector = 512;
} }
sectorShift = deviceExtension->SectorShift; sectorShift = physicalDeviceExtension->SectorShift;
// //
// Set pointer to disk data area that follows device extension. // Set pointer to disk data area that follows device extension.
// //
diskData = (PDISK_DATA)(deviceExtension + 1); diskData = (PDISK_DATA)(physicalDeviceExtension + 1);
diskData->PartitionListState = Initializing;
// //
// Determine is DM Driver is loaded on an IDE drive that is // Determine is DM Driver is loaded on an IDE drive that is
@ -1037,8 +1117,8 @@ Return Value:
// an Atapi device is sharing the controller with an IDE disk. // an Atapi device is sharing the controller with an IDE disk.
// //
HalExamineMBR(deviceExtension->DeviceObject, HalExamineMBR(PhysicalDeviceObject,
deviceExtension->DiskGeometry->BytesPerSector, physicalDeviceExtension->DiskGeometry->BytesPerSector,
(ULONG)0x54, (ULONG)0x54,
(PVOID)&dmSkew); (PVOID)&dmSkew);
@ -1050,9 +1130,9 @@ Return Value:
// to be skewed by *dmSkew sectors aka DMByteSkew. // to be skewed by *dmSkew sectors aka DMByteSkew.
// //
deviceExtension->DMSkew = *dmSkew; physicalDeviceExtension->DMSkew = *dmSkew;
deviceExtension->DMActive = TRUE; physicalDeviceExtension->DMActive = TRUE;
deviceExtension->DMByteSkew = deviceExtension->DMSkew * bytesPerSector; physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector;
// //
// Save away the infomation that we need, since this deviceExtension will soon be // Save away the infomation that we need, since this deviceExtension will soon be
@ -1060,7 +1140,7 @@ Return Value:
// //
dmActive = TRUE; dmActive = TRUE;
dmByteSkew = deviceExtension->DMByteSkew; dmByteSkew = physicalDeviceExtension->DMByteSkew;
} }
@ -1068,8 +1148,8 @@ Return Value:
// Create objects for all the partitions on the device. // Create objects for all the partitions on the device.
// //
status = IoReadPartitionTable(deviceObject, status = IoReadPartitionTable(PhysicalDeviceObject,
deviceExtension->DiskGeometry->BytesPerSector, physicalDeviceExtension->DiskGeometry->BytesPerSector,
TRUE, TRUE,
(PVOID)&partitionList); (PVOID)&partitionList);
@ -1078,9 +1158,9 @@ Return Value:
// then fix up the partition list to make it look like there is one // then fix up the partition list to make it look like there is one
// zero length partition. // zero length partition.
// //
DPRINT1("IoReadPartitionTable() status: 0x%08X\n", status);
if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) && if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) &&
deviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
@ -1136,28 +1216,53 @@ Return Value:
if (!diskData->Signature) { if (!diskData->Signature) {
if (!CalculateMbrCheckSum(deviceExtension, if (!CalculateMbrCheckSum(physicalDeviceExtension,
&diskData->MbrCheckSum)) { &diskData->MbrCheckSum)) {
DebugPrint((1, DebugPrint((1,
"SCSIDISK: Can't calculate MBR checksum for disk %x\n", "SCSIDISK: Can't calculate MBR checksum for disk %x\n",
deviceExtension->DeviceNumber)); physicalDeviceExtension->DeviceNumber));
} else { } else {
DebugPrint((2, DebugPrint((2,
"SCSIDISK: MBR checksum for disk %x is %x\n", "SCSIDISK: MBR checksum for disk %x is %x\n",
deviceExtension->DeviceNumber, physicalDeviceExtension->DeviceNumber,
diskData->MbrCheckSum)); diskData->MbrCheckSum));
} }
} }
// //
// Check the registry and determine if the BIOS knew about this drive. If // Check the registry and determine if the BIOS knew about this drive. If
// it did then update the geometry with the BIOS information. // it did then update the geometry with the BIOS information.
// //
UpdateGeometry(deviceExtension); UpdateGeometry(physicalDeviceExtension);
srbFlags = physicalDeviceExtension->SrbFlags;
initData = ExAllocatePool(NonPagedPool, sizeof(CLASS_INIT_DATA));
if (!initData)
{
DebugPrint((1,
"Disk.CreatePartionDeviceObjects - Allocation of initData failed\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreatePartitionDeviceObjectsExit;
}
RtlZeroMemory(initData, sizeof(CLASS_INIT_DATA));
initData->InitializationDataSize = sizeof(CLASS_INIT_DATA);
initData->DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
initData->DeviceType = FILE_DEVICE_DISK;
initData->DeviceCharacteristics = PhysicalDeviceObject->Characteristics;
initData->ClassError = physicalDeviceExtension->ClassError;
initData->ClassReadWriteVerification = physicalDeviceExtension->ClassReadWriteVerification;
initData->ClassFindDevices = physicalDeviceExtension->ClassFindDevices;
initData->ClassDeviceControl = physicalDeviceExtension->ClassDeviceControl;
initData->ClassShutdownFlush = physicalDeviceExtension->ClassShutdownFlush;
initData->ClassCreateClose = physicalDeviceExtension->ClassCreateClose;
initData->ClassStartIo = physicalDeviceExtension->ClassStartIo;
// //
// Create device objects for the device partitions (if any). // Create device objects for the device partitions (if any).
@ -1178,18 +1283,18 @@ Return Value:
sprintf(ntNameBuffer, sprintf(ntNameBuffer,
"\\Device\\Harddisk%lu\\Partition%lu", "\\Device\\Harddisk%lu\\Partition%lu",
*DeviceCount, physicalDeviceExtension->DeviceNumber,
partitionNumber + 1); partitionNumber + 1);
DebugPrint((2, DebugPrint((2,
"CreateDiskDeviceObjects: Create device object %s\n", "CreateDiskDeviceObjects: Create device object %s\n",
ntNameBuffer)); ntNameBuffer));
status = ScsiClassCreateDeviceObject(DriverObject, status = ScsiClassCreateDeviceObject(PhysicalDeviceObject->DriverObject,
ntNameBuffer, ntNameBuffer,
physicalDevice, PhysicalDeviceObject,
&deviceObject, &deviceObject,
InitData); initData);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
@ -1214,7 +1319,7 @@ Return Value:
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
} }
deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1; deviceObject->StackSize = (CCHAR)physicalDeviceExtension->PortDeviceObject->StackSize + 1;
// //
// Set up device extension fields. // Set up device extension fields.
@ -1264,16 +1369,15 @@ Return Value:
// Copy port device object pointer to device extension. // Copy port device object pointer to device extension.
// //
deviceExtension->PortDeviceObject = PortDeviceObject; deviceExtension->PortDeviceObject = physicalDeviceExtension->PortDeviceObject;
deviceExtension->PortNumber = (UCHAR)PortNumber;
// //
// Set the alignment requirements for the device based on the // Set the alignment requirements for the device based on the
// host adapter requirements // host adapter requirements
// //
if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) { if (physicalDeviceExtension->PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; deviceObject->AlignmentRequirement = physicalDeviceExtension->PortDeviceObject->AlignmentRequirement;
} }
@ -1297,8 +1401,8 @@ Return Value:
// Set the sense-data pointer in the device extension. // Set the sense-data pointer in the device extension.
// //
deviceExtension->SenseData = senseData; deviceExtension->SenseData = physicalDeviceExtension->SenseData;
deviceExtension->PortCapabilities = PortCapabilities; deviceExtension->PortCapabilities = physicalDeviceExtension->PortCapabilities;
deviceExtension->DiskGeometry = diskGeometry; deviceExtension->DiskGeometry = diskGeometry;
diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1; diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1;
diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType; diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType;
@ -1310,16 +1414,16 @@ Return Value:
deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset; deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset;
deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength; deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength;
diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors; diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors;
deviceExtension->PortNumber = (UCHAR)PortNumber; deviceExtension->PortNumber = physicalDeviceExtension->PortNumber;
deviceExtension->PathId = pathId; deviceExtension->PathId = physicalDeviceExtension->PathId;
deviceExtension->TargetId = targetId; deviceExtension->TargetId = physicalDeviceExtension->TargetId;
deviceExtension->Lun = lun; deviceExtension->Lun = physicalDeviceExtension->Lun;
// //
// Check for removable media support. // Check for removable media support.
// //
if (((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) { if (PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
} }
@ -1327,7 +1431,7 @@ Return Value:
// Set timeout value in seconds. // Set timeout value in seconds.
// //
deviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT; deviceExtension->TimeOutValue = physicalDeviceExtension->TimeOutValue;
deviceExtension->DiskGeometry->BytesPerSector = bytesPerSector; deviceExtension->DiskGeometry->BytesPerSector = bytesPerSector;
deviceExtension->SectorShift = sectorShift; deviceExtension->SectorShift = sectorShift;
deviceExtension->DeviceObject = deviceObject; deviceExtension->DeviceObject = deviceObject;
@ -1344,54 +1448,27 @@ Return Value:
} else { } else {
DebugPrint((1, CreatePartitionDeviceObjectsExit:
"CreateDiskDeviceObjects: IoReadPartitionTable failed\n"));
if (partitionList) {
ExFreePool(partitionList);
}
if (initData) {
ExFreePool(initData);
}
return status;
} // end if...else } // end if...else
physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
physicalDiskData->PartitionListState = Initialized;
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
CreateDiskDeviceObjectsExit:
// } // end CreatePartitionDeviceObjects()
// Release the device since an error occurred.
//
ScsiClassClaimDevice(PortDeviceObject,
LunInfo,
TRUE,
NULL);
if (diskGeometry != NULL) {
ExFreePool(diskGeometry);
}
if (senseData != NULL) {
ExFreePool(senseData);
}
if (deviceObject != NULL) {
if (srbListInitialized) {
ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
}
IoDeleteDevice(deviceObject);
}
//
// Delete directory and return.
//
if (!NT_SUCCESS(status)) {
ZwMakeTemporaryObject(handle);
}
ZwClose(handle);
return(status);
} // end CreateDiskDeviceObjects()
NTSTATUS NTSTATUS
@ -1937,6 +2014,12 @@ Return Value:
} }
case IOCTL_DISK_GET_DRIVE_GEOMETRY: case IOCTL_DISK_GET_DRIVE_GEOMETRY:
{
PDEVICE_EXTENSION physicalDeviceExtension;
PDISK_DATA physicalDiskData;
BOOLEAN removable = FALSE;
BOOLEAN listInitialized = FALSE;
if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof( DISK_GEOMETRY ) ) { sizeof( DISK_GEOMETRY ) ) {
@ -1945,8 +2028,16 @@ Return Value:
break; break;
} }
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { status = STATUS_SUCCESS;
physicalDeviceExtension = deviceExtension->PhysicalDevice->DeviceExtension;
physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
removable = (BOOLEAN)DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA;
listInitialized = (physicalDiskData->PartitionListState == Initialized);
if (removable || (!listInitialized))
{
// //
// Issue ReadCapacity to update device extension // Issue ReadCapacity to update device extension
// with information for current media. // with information for current media.
@ -1954,6 +2045,10 @@ Return Value:
status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice); status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
}
if (removable) {
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
// //
@ -1970,21 +2065,34 @@ Return Value:
// //
diskData->DriveNotReady = FALSE; diskData->DriveNotReady = FALSE;
} else if (NT_SUCCESS(status)) {
// ReadDriveCapacity was allright, create Partition Objects
if (physicalDiskData->PartitionListState == NotInitialized) {
status = CreatePartitionDeviceObjects(deviceExtension->PhysicalDevice, NULL);
}
} }
// if (NT_SUCCESS(status)) {
// Copy drive geometry information from device extension.
//
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, //
deviceExtension->DiskGeometry, // Copy drive geometry information from device extension.
sizeof(DISK_GEOMETRY)); //
status = STATUS_SUCCESS; RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); deviceExtension->DiskGeometry,
sizeof(DISK_GEOMETRY));
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
}
break; break;
}
case IOCTL_DISK_VERIFY: case IOCTL_DISK_VERIFY:
{ {