📄 disk.c
字号:
Irp->IoStatus.Information = sizeof(DISK_WRITE_CACHE_STATE);
status = STATUS_SUCCESS;
break;
}
case SMART_GET_VERSION: {
PUCHAR buffer;
PSRB_IO_CONTROL srbControl;
PGETVERSIONINPARAMS versionParams;
if(!commonExtension->IsFdo) {
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GETVERSIONINPARAMS)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
break;
}
//
// Create notification event object to be used to signal the
// request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
srbControl = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SRB_IO_CONTROL) +
sizeof(GETVERSIONINPARAMS),
DISK_TAG_SMART);
if (!srbControl) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS)
);
//
// fill in srbControl fields
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
srbControl->Timeout = fdoExtension->TimeOutValue;
srbControl->Length = sizeof(GETVERSIONINPARAMS);
srbControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
//
// 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.
//
versionParams = (PGETVERSIONINPARAMS)buffer;
versionParams->bIDEDeviceMap = diskData->ScsiAddress.TargetId;
//
// Copy the IOCTL parameters to the srb control buffer area.
//
RtlMoveMemory(buffer,
Irp->AssociatedIrp.SystemBuffer,
sizeof(GETVERSIONINPARAMS));
ClassSendDeviceIoControlSynchronous(
IOCTL_SCSI_MINIPORT,
commonExtension->LowerDeviceObject,
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
FALSE,
&ioStatus);
status = ioStatus.Status;
//
// If successful, copy the data received into the output buffer.
// This should only fail in the event that the IDE driver is older
// than this driver.
//
if (NT_SUCCESS(status)) {
buffer = (PUCHAR)srbControl;
(ULONG_PTR)buffer += srbControl->HeaderLength;
RtlMoveMemory (Irp->AssociatedIrp.SystemBuffer, buffer,
sizeof(GETVERSIONINPARAMS));
Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
}
ExFreePool(srbControl);
break;
}
case SMART_RCV_DRIVE_DATA: {
PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
ULONG controlCode = 0;
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;
Irp->IoStatus.Information = 0;
break;
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) + 512 - 1)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) + 512 - 1;
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
//
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;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
} else {
status = STATUS_INVALID_PARAMETER;
}
if (controlCode == 0) {
status = STATUS_INVALID_PARAMETER;
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;
Irp->IoStatus.Information = 0;
break;
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) - 1)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
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 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))) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information =
sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
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) {
status = STATUS_INVALID_PARAMETER;
break;
}
length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? 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;
//
// 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);
srbControl->ControlCode = controlCode;
irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
commonExtension->LowerDeviceObject,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -