diff --git a/reactos/drivers/storage/class/disk/disk.c b/reactos/drivers/storage/class/disk/disk.c index 6d6daa645ac..4b01c32d14b 100644 --- a/reactos/drivers/storage/class/disk/disk.c +++ b/reactos/drivers/storage/class/disk/disk.c @@ -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: {