disk.c
来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
PartitionList,
BufferSize);
Status = STATUS_SUCCESS;
Information = BufferSize;
}
ExFreePool(PartitionList);
}
}
break;
case IOCTL_DISK_SET_DRIVE_LAYOUT:
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(DRIVE_LAYOUT_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
PDRIVE_LAYOUT_INFORMATION PartitionList;
ULONG TableSize;
PartitionList = Irp->AssociatedIrp.SystemBuffer;
TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Update partition device objects */
DiskClassUpdatePartitionDeviceObjects (DeviceObject,
Irp);
/* Write partition table */
Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
DeviceExtension->DiskGeometry->BytesPerSector,
DeviceExtension->DiskGeometry->SectorsPerTrack,
DeviceExtension->DiskGeometry->TracksPerCylinder,
PartitionList);
}
}
break;
case IOCTL_DISK_IS_WRITABLE:
{
PMODE_PARAMETER_HEADER ModeData;
ULONG Length;
ModeData = ExAllocatePool (NonPagedPool,
MODE_DATA_SIZE);
if (ModeData == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory (ModeData,
MODE_DATA_SIZE);
Length = ScsiClassModeSense (DeviceObject,
(PVOID)ModeData,
MODE_DATA_SIZE,
MODE_SENSE_RETURN_ALL);
if (Length < sizeof(MODE_PARAMETER_HEADER))
{
/* FIXME: Retry */
Status = STATUS_IO_DEVICE_ERROR;
ExFreePool (ModeData);
break;
}
if (ModeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT)
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
}
else
{
Status = STATUS_SUCCESS;
}
ExFreePool (ModeData);
}
break;
case IOCTL_DISK_VERIFY:
case IOCTL_DISK_FORMAT_TRACKS:
case IOCTL_DISK_PERFORMANCE:
case IOCTL_DISK_LOGGING:
case IOCTL_DISK_FORMAT_TRACKS_EX:
case IOCTL_DISK_HISTOGRAM_STRUCTURE:
case IOCTL_DISK_HISTOGRAM_DATA:
case IOCTL_DISK_HISTOGRAM_RESET:
case IOCTL_DISK_REQUEST_STRUCTURE:
case IOCTL_DISK_REQUEST_DATA:
/* If we get here, something went wrong. Inform the requestor */
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))
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?