__control_entrypoint(DeviceDriver)
NTSTATUS
DiskDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
I/O system entry for device controls to SCSI disks.
Arguments:
Fdo - Pointer to functional device object created by system.
Irp - IRP involved.
Return Value:
Status is returned.
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG ioctlCode;
ASSERT(DeviceObject != NULL);
Irp->IoStatus.Information = 0;
ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, "DiskDeviceControl: Received IOCTL 0x%X for device %p through IRP %p\n",
ioctlCode, DeviceObject, Irp));
switch (ioctlCode) {
case IOCTL_DISK_GET_CACHE_INFORMATION: {
status = DiskIoctlGetCacheInformation(DeviceObject, Irp);
break;
}
case IOCTL_DISK_SET_CACHE_INFORMATION: {
status = DiskIoctlSetCacheInformation(DeviceObject, Irp);
break;
}
case IOCTL_DISK_GET_CACHE_SETTING: {
status = DiskIoctlGetCacheSetting(DeviceObject, Irp);
break;
}
case IOCTL_DISK_SET_CACHE_SETTING: {
status = DiskIoctlSetCacheSetting(DeviceObject, Irp);
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
status = DiskIoctlGetDriveGeometry(DeviceObject, Irp);
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: {
status = DiskIoctlGetDriveGeometryEx( DeviceObject, Irp );
break;
}
case IOCTL_DISK_VERIFY: {
status = DiskIoctlVerify(DeviceObject, Irp);
break;
}
case IOCTL_DISK_GET_LENGTH_INFO: {
status = DiskIoctlGetLengthInfo(DeviceObject, Irp);
break;
}
case IOCTL_DISK_IS_WRITABLE: {
status = DiskIoctlIsWritable(DeviceObject, Irp);
break;
}
case IOCTL_DISK_UPDATE_DRIVE_SIZE: {
status = DiskIoctlUpdateDriveSize(DeviceObject, Irp);
break;
}
case IOCTL_DISK_REASSIGN_BLOCKS: {
status = DiskIoctlReassignBlocks(DeviceObject, Irp);
break;
}
case IOCTL_DISK_REASSIGN_BLOCKS_EX: {
status = DiskIoctlReassignBlocksEx(DeviceObject, Irp);
break;
}
case IOCTL_DISK_INTERNAL_SET_VERIFY: {
status = DiskIoctlSetVerify(DeviceObject, Irp);
break;
}
case IOCTL_DISK_INTERNAL_CLEAR_VERIFY: {
status = DiskIoctlClearVerify(DeviceObject, Irp);
break;
}
case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: {
status = DiskIoctlGetMediaTypesEx(DeviceObject, Irp);
break;
}
case IOCTL_STORAGE_PREDICT_FAILURE : {
status = DiskIoctlPredictFailure(DeviceObject, Irp);
break;
}
case SMART_GET_VERSION: {
status = DiskIoctlSmartGetVersion(DeviceObject, Irp);
break;
}
case SMART_RCV_DRIVE_DATA: {
status = DiskIoctlSmartReceiveDriveData(DeviceObject, Irp);
break;
}
case SMART_SEND_DRIVE_COMMAND: {
status = DiskIoctlSmartSendDriveCommand(DeviceObject, Irp);
break;
}
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS_ADMIN: {
status = DiskIoctlGetVolumeDiskExtents(DeviceObject, Irp);
break;
}
default: {
//
// Pass the request to the common device control routine.
//
return(ClassDeviceControl(DeviceObject, Irp));
break;
}
} // end switch
if (!NT_SUCCESS(status)) {
TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "DiskDeviceControl: IOCTL 0x%X to device %p failed with error 0x%X\n",
ioctlCode, DeviceObject, status));
if (IoIsErrorUserInduced(status) &&
(Irp->Tail.Overlay.Thread != NULL)) {
IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
}
}
//
// DiskIoctlVerify() (IOCTL_DISK_VERIFY) function returns STATUS_PENDING
// and completes the IRP in the work item. Do not touch or complete
// the IRP if STATUS_PENDING is returned.
//
if (status != STATUS_PENDING) {
Irp->IoStatus.Status = status;
ClassReleaseRemoveLock(DeviceObject, Irp);
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
}
return(status);
} // end DiskDeviceControl()