disk.c
来自「一个类似windows」· C语言 代码 · 共 2,090 行 · 第 1/5 页
C
2,090 行
DPRINT("Unhandled control code: %lx\n", ControlCode);
Status = STATUS_INVALID_DEVICE_REQUEST;
Information = 0;
break;
case SMART_GET_VERSION:
{
PGETVERSIONINPARAMS Version;
DPRINT("SMART_GET_VERSION\n");
if (OutputLength < sizeof(GETVERSIONINPARAMS))
{
Status = STATUS_BUFFER_TOO_SMALL;
Information = sizeof(GETVERSIONINPARAMS);
break;
}
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
if (SrbIoControl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Version = (PGETVERSIONINPARAMS)(SrbIoControl + 1);
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
memcpy(SrbIoControl->Signature, "ScsiDisk", 8);
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
SrbIoControl->Length = sizeof(GETVERSIONINPARAMS);
SrbIoControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
DeviceExtension->PortDeviceObject,
SrbIoControl,
sizeof(SRB_IO_CONTROL),
SrbIoControl,
sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
FALSE,
&Event,
&IoSB);
if (LocalIrp == NULL)
{
ExFreePool(SrbIoControl);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoSB.Status;
}
if (NT_SUCCESS(Status))
{
memcpy(Irp->AssociatedIrp.SystemBuffer, Version, sizeof(GETVERSIONINPARAMS));
Information = sizeof(GETVERSIONINPARAMS);
}
ExFreePool(SrbIoControl);
break;
}
case SMART_SEND_DRIVE_COMMAND:
{
DPRINT("SMART_SEND_DRIVE_COMMAND\n");
if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
if (InParams->irDriveRegs.bCommandReg == SMART_CMD)
{
if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE)
{
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");
ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES)
{
DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");
ControlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS)
{
DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == SMART_WRITE_LOG)
{
DPRINT("IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG\n");
ControlCode = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG;
if (InputLength < sizeof(SENDCMDINPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_SMART)
{
DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");
ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == DISABLE_SMART)
{
DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");
ControlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS)
{
DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");
ControlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
Information = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
}
else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTO_OFFLINE)
{
DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
else
{
DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
Status = STATUS_INVALID_PARAMETER;
break;
}
}
else
{
Status = STATUS_INVALID_PARAMETER;
break;
}
if (OutputLength < Information)
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));
if (SrbIoControl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Information = 0;
break;
}
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
SrbIoControl->Length = Information;
SrbIoControl->ControlCode = ControlCode;
InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);
memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
InParams->bDriveNumber = DeviceExtension->TargetId;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
DeviceExtension->PortDeviceObject,
SrbIoControl,
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
SrbIoControl,
sizeof(SRB_IO_CONTROL) + Information,
FALSE,
&Event,
&IoSB);
if (LocalIrp == NULL)
{
ExFreePool(SrbIoControl);
Information = 0;
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoSB.Status;
}
if (NT_SUCCESS(Status))
{
Information = SrbIoControl->Length;
}
else
{
Information = sizeof(SENDCMDOUTPARAMS) - 1;
}
memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
ExFreePool(SrbIoControl);
break;
}
case SMART_RCV_DRIVE_DATA:
{
DPRINT("SMART_RCV_DRIVE_DATA\n");
if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
if (InParams->irDriveRegs.bCommandReg == ID_CMD)
{
DPRINT("IOCTL_SCSI_MINIPORT_IDENTIFY\n");
ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
Information = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bCommandReg == SMART_CMD)
{
if (InParams->irDriveRegs.bFeaturesReg == READ_ATTRIBUTES)
{
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
Information = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == READ_THRESHOLDS)
{
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
Information = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
}
else if (InParams->irDriveRegs.bFeaturesReg == SMART_READ_LOG)
{
DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");
ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_LOG;
Information = sizeof(SENDCMDOUTPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg);
}
else
{
DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
Status = STATUS_INVALID_PARAMETER;
break;
}
}
else
{
DPRINT("%x\n", InParams->irDriveRegs.bCommandReg);
Status = STATUS_INVALID_PARAMETER;
break;
}
if (OutputLength < Information)
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + Information);
if (SrbIoControl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Information = 0;
break;
}
memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + Information);
SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
SrbIoControl->Length = Information;
SrbIoControl->ControlCode = ControlCode;
InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);
memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
InParams->bDriveNumber = DeviceExtension->TargetId;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
DeviceExtension->PortDeviceObject,
SrbIoControl,
sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
SrbIoControl,
sizeof(SRB_IO_CONTROL) + Information,
FALSE,
&Event,
&IoSB);
if (LocalIrp == NULL)
{
ExFreePool(SrbIoControl);
Information = 0;
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoSB.Status;
}
if (NT_SUCCESS(Status))
{
#if 0
CHAR Buffer[256];
ULONG i, j;
UCHAR sum = 0;
memset(Buffer, 0, sizeof(Buffer));
for (i = 0; i < 512; i += 16)
{
for (j = 0; j < 16 && i + j < 512; j++)
{
sprintf(&Buffer[3*j], "%02x ", ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]);
sum += ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j];
}
for (j = 0; j < 16 && i + j < 512; j++)
{
sprintf(&Buffer[3*16 + j], "%c", isprint(((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]) ? ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j] : '.');
}
DPRINT1("%04x %s\n", i, Buffer);
}
DPRINT1("Sum %02x\n", sum);
#endif
Information = SrbIoControl->Length;
}
else
{
Information = sizeof(SENDCMDOUTPARAMS) -1;
}
memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
ExFreePool(SrbIoControl);
break;
}
default:
/* Call the common device control function */
return(ScsiClassDeviceControl(DeviceObject, Irp));
}
/* Verify the device if the user caused the error */
if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
{
IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(Status);
}
/**********************************************************************
* NAME EXPORTED
* DiskClassShutdownFlush
*
* DESCRIPTION
* Answer requests for shutdown and flush calls.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DeviceObject
* Pointer to the device.
*
* Irp
* Pointer to the IRP
*
* RETURN VALUE
* Status
*/
NTSTATUS STDCALL
DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
DPRINT("DiskClassShutdownFlush() called!\n");
DeviceExtension = DeviceObject->DeviceExtension;
/* Allocate SRB */
Srb = ExAllocatePool(NonPagedPool,
sizeof(SCSI_REQUEST_BLOCK));
if (Srb == NULL)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
/* Set timeout */
Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;
/* Flush write cache */
Srb->CdbLength = 10;
Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
ScsiClassSendSrbSynchronous(DeviceObject,
Srb,
NULL,
0,
TRUE);
/* Get current stack location */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?