📄 disk.c
字号:
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
ScsiDiskReadWriteVerification(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
I/O System entry for read and write requests to SCSI disks.
Arguments:
DeviceObject - Pointer to driver object created by system.
Irp - IRP involved.
Return Value:
NT Status
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
LARGE_INTEGER startingOffset;
//
// Verify parameters of this request.
// Check that ending sector is within partition and
// that number of bytes to transfer is a multiple of
// the sector size.
//
startingOffset.QuadPart = (currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
transferByteCount);
if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) ||
(transferByteCount & (deviceExtension->DiskGeometry->BytesPerSector - 1))) {
//
// This error maybe caused by the fact that the drive is not ready.
//
if (((PDISK_DATA)(deviceExtension + 1))->DriveNotReady) {
//
// Flag this as a user errror so that a popup is generated.
//
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
} else {
//
// Note fastfat depends on this parameter to determine when to
// remount do to a sector size change.
//
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
} // end ScsiDiskReadWrite()
NTSTATUS
STDCALL
ScsiDiskDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
I/O system entry for device controls to SCSI disks.
Arguments:
DeviceObject - Pointer to driver object created by system.
Irp - IRP involved.
Return Value:
Status is returned.
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PDISK_DATA diskData = (PDISK_DATA)(deviceExtension + 1);
PSCSI_REQUEST_BLOCK srb;
PCDB cdb;
PMODE_PARAMETER_HEADER modeData;
PIRP irp2;
ULONG length;
NTSTATUS status;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PAGED_CODE();
srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
if (srb == NULL) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Write zeros to Srb.
//
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
cdb = (PCDB)srb->Cdb;
switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
case SMART_GET_VERSION: {
ULONG_PTR buffer;
PSRB_IO_CONTROL srbControl;
PGETVERSIONINPARAMS versionParams;
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GETVERSIONINPARAMS)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// Create notification event object to be used to signal the
// request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
srbControl = ExAllocatePool(NonPagedPool,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
if (!srbControl) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// fill in srbControl fields
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
srbControl->Timeout = deviceExtension->TimeOutValue;
srbControl->Length = sizeof(GETVERSIONINPARAMS);
srbControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
//
// Point to the 'buffer' portion of the SRB_CONTROL
//
buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
//
// Ensure correct target is set in the cmd parameters.
//
versionParams = (PGETVERSIONINPARAMS)buffer;
versionParams->bIDEDeviceMap = deviceExtension->TargetId;
//
// Copy the IOCTL parameters to the srb control buffer area.
//
RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(GETVERSIONINPARAMS));
irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
deviceExtension->PortDeviceObject,
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
FALSE,
&event,
&ioStatus);
if (irp2 == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// Call the port driver with the request and wait for it to complete.
//
status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
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 = (ULONG_PTR)srbControl + srbControl->HeaderLength;
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)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;
ULONG_PTR buffer;
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_INVALID_PARAMETER;
break;
}
//
// Create notification event object to be used to signal the
// request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
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 = ExAllocatePool(NonPagedPool,
sizeof(SRB_IO_CONTROL) + length);
if (!srbControl) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// fill in srbControl fields
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
srbControl->Timeout = deviceExtension->TimeOutValue;
srbControl->Length = length;
srbControl->ControlCode = controlCode;
//
// Point to the 'buffer' portion of the SRB_CONTROL
//
buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
//
// Ensure correct target is set in the cmd parameters.
//
cmdInParameters->bDriveNumber = deviceExtension->TargetId;
//
// Copy the IOCTL parameters to the srb control buffer area.
//
RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
deviceExtension->PortDeviceObject,
srbControl,
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
srbControl,
sizeof(SRB_IO_CONTROL) + length,
FALSE,
&event,
&ioStatus);
if (irp2 == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// Call the port driver with the request and wait for it to complete.
//
status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
//
// If successful, copy the data received into the output buffer
//
buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
if (NT_SUCCESS(status)) {
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length - 1);
Irp->IoStatus.Information = length - 1;
} else {
RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)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;
ULONG_PTR buffer;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
(sizeof(SENDCMDINPARAMS) - 1)) {
status = STATUS_INVALID_PARAMETER;
break;
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
(sizeof(SENDCMDOUTPARAMS) - 1)) {
status = STATUS_INVALID_PARAMETER;
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_INVALID_PARAMETER;
break;
}
controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
length = sizeof(IDEREGS);
break;
case ENABLE_DISABLE_AUTOSAVE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -