📄 disk.c
字号:
PSRB_IO_CONTROL srbControl;
PUCHAR buffer;
if(!commonExtension->IsFdo) {
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
(sizeof(SENDCMDINPARAMS) - 1)) {
status = STATUS_INVALID_PARAMETER;
break;
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) + 512 - 1)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Create notification event object to be used to signal the
// request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// use controlCode as a sort of 'STATUS_SUCCESS' to see if it's
// a valid request type
//
status = STATUS_INVALID_PARAMETER;
if (cmdInParameters->irDriveRegs.bCommandReg == ID_CMD) {
length = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
} else if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
case READ_ATTRIBUTES:
controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
length = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
break;
case READ_THRESHOLDS:
controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
length = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS);
break;
case SMART_READ_LOG:
{
if (diskData->FailurePredictionCapability != FailurePredictionSmart)
{
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
//
// Calculate additional length based on number of sectors to be read.
// Then verify the output buffer is large enough.
//
length = cmdInParameters->irDriveRegs.bSectorCountReg * SMART_LOG_SECTOR_SIZE;
length += max(sizeof(SENDCMDOUTPARAMS), sizeof(SENDCMDINPARAMS));
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < length - 1)
{
status = STATUS_BUFFER_TOO_SMALL;
break;
}
controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_LOG;
break;
}
}
}
if (controlCode == 0) {
break;
}
srbControl = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SRB_IO_CONTROL) + length,
DISK_TAG_SMART);
if (!srbControl) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// fill in srbControl fields
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
srbControl->Timeout = fdoExtension->TimeOutValue;
srbControl->Length = length;
srbControl->ControlCode = controlCode;
//
// Point to the 'buffer' portion of the SRB_CONTROL
//
buffer = (PUCHAR)srbControl;
(ULONG_PTR)buffer += srbControl->HeaderLength;
//
// Ensure correct target is set in the cmd parameters.
//
cmdInParameters->bDriveNumber = diskData->ScsiAddress.TargetId;
//
// Copy the IOCTL parameters to the srb control buffer area.
//
RtlMoveMemory(buffer,
Irp->AssociatedIrp.SystemBuffer,
sizeof(SENDCMDINPARAMS) - 1);
irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
commonExtension->LowerDeviceObject,
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
srbControl,
sizeof(SRB_IO_CONTROL) + length,
FALSE,
&event,
&ioStatus);
if (irp2 == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(srbControl);
break;
}
//
// Call the port driver with the request and wait for it to complete.
//
status = IoCallDriver(commonExtension->LowerDeviceObject, irp2);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
//
// Copy the data received into the output buffer. Since the status buffer
// contains error information also, always perform this copy. IO will will
// either pass this back to the app, or zero it, in case of error.
//
buffer = (PUCHAR)srbControl;
(ULONG_PTR)buffer += srbControl->HeaderLength;
if (NT_SUCCESS(status)) {
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, length - 1);
Irp->IoStatus.Information = length - 1;
} else {
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, (sizeof(SENDCMDOUTPARAMS) - 1));
Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
ExFreePool(srbControl);
break;
}
case SMART_SEND_DRIVE_COMMAND: {
PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
PSRB_IO_CONTROL srbControl;
ULONG controlCode = 0;
PUCHAR buffer;
if(!commonExtension->IsFdo) {
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
(sizeof(SENDCMDINPARAMS) - 1)) {
status = STATUS_INVALID_PARAMETER;
break;
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) - 1)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Create notification event object to be used to signal the
// request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
length = 0;
if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
case SMART_WRITE_LOG:
{
if (diskData->FailurePredictionCapability != FailurePredictionSmart)
{
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
//
// Calculate additional length based on number of sectors to be written.
// Then verify the input buffer is large enough.
//
length = cmdInParameters->irDriveRegs.bSectorCountReg * SMART_LOG_SECTOR_SIZE;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
(sizeof(SENDCMDINPARAMS) - 1) + length)
{
status = STATUS_BUFFER_TOO_SMALL;
break;
}
controlCode = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG;
break;
}
case ENABLE_SMART:
controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
break;
case DISABLE_SMART:
controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
break;
case RETURN_SMART_STATUS:
//
// Ensure bBuffer is at least 2 bytes (to hold the values of
// cylinderLow and cylinderHigh).
//
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS))) {
/*
* Don't set controlCode; that'll cause us to break out below.
*/
status = STATUS_BUFFER_TOO_SMALL;
break;
}
controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
length = sizeof(IDEREGS);
break;
case ENABLE_DISABLE_AUTOSAVE:
controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
break;
case SAVE_ATTRIBUTE_VALUES:
controlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
break;
case EXECUTE_OFFLINE_DIAGS:
//
// Validate that this is an ok self test command
//
if (DiskIsValidSmartSelfTest(cmdInParameters->irDriveRegs.bSectorNumberReg))
{
controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
}
break;
case ENABLE_DISABLE_AUTO_OFFLINE:
controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE;
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
}
else {
status = STATUS_INVALID_PARAMETER;
}
if (controlCode == 0) {
break;
}
length += max(sizeof(SENDCMDOUTPARAMS), sizeof(SENDCMDINPARAMS));
srbControl = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SRB_IO_CONTROL) + length,
DISK_TAG_SMART);
if (!srbControl) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// fill in srbControl fields
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
srbControl->Timeout = fdoExtension->TimeOutValue;
srbControl->Length = length;
srbControl->ControlCode = controlCode;
//
// Point to the 'buffer' portion of the SRB_CONTROL
//
buffer = (PUCHAR)srbControl;
(ULONG_PTR)buffer += srbControl->HeaderLength;
//
// Ensure correct target is set in the cmd parameters.
//
cmdInParameters->bDriveNumber = diskData->ScsiAddress.TargetId;
//
// Copy the IOCTL parameters to the srb control buffer area.
//
RtlMoveMemory(buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
commonExtension->LowerDeviceObject,
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
srbControl,
sizeof(SRB_IO_CONTROL) + length,
FALSE,
&event,
&ioStatus);
if (irp2 == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(srbControl);
break;
}
//
// Call the port driver with the request and wait for it to complete.
//
status = IoCallDriver(commonExtension->LowerDeviceObject, irp2);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
//
// Copy the data received into the output buffer. Since the status buffer
// contains error information also, always perform this copy. IO will will
// either pass this back to the app, or zero it, in case of error.
//
buffer = (PUCHAR)srbControl;
(ULONG_PTR)buffer += srbControl->HeaderLength;
//
// Update the return buffer size based on the sub-command.
//
if (cmdInParameters->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) {
length = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
} else {
length = sizeof(SENDCMDOUTPARAMS) - 1;
}
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, length);
Irp->IoStatus.Information = length;
ExFreePool(srbControl);
break;
}
case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: {
PMODE_PARAMETER_BLOCK blockDescriptor;
ULONG modeLength;
ULONG retries = 4;
UCHAR densityCode = 0;
BOOLEAN writable = TRUE;
BOOLEAN mediaPresent = FALSE;
DebugPrint((3,
"Disk.DiskDeviceControl: GetMediaTypes\n"));
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GET_MEDIA_TYPES)) {
status = STATUS_BUFFER_TOO_SMALL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -