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