📄 disk.c
字号:
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;
BOOLEAN writable = FALSE;
BOOLEAN mediaPresent = FALSE;
DebugPrint((3,
"Disk.DiskDeviceControl: GetMediaTypes\n"));
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GET_MEDIA_TYPES)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(GET_MEDIA_TYPES);
break;
}
if(!commonExtension->IsFdo) {
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
//
// Send a TUR to determine if media is present.
//
srb->CdbLength = 6;
cdb = (PCDB)srb->Cdb;
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
//
// Set timeout value.
//
srb->TimeOutValue = fdoExtension->TimeOutValue;
status = ClassSendSrbSynchronous(DeviceObject,
srb,
NULL,
0,
FALSE);
if (NT_SUCCESS(status)) {
mediaPresent = TRUE;
}
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
//
// Allocate memory for mode header and block descriptor.
//
modeLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
modeData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
modeLength,
DISK_TAG_MODE_DATA);
if (modeData == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(modeData, modeLength);
//
// Build the MODE SENSE CDB.
//
srb->CdbLength = 6;
cdb = (PCDB)srb->Cdb;
//
// Set timeout value from device extension.
//
srb->TimeOutValue = fdoExtension->TimeOutValue;
//
// Page code of 0 will return header and block descriptor only.
//
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
cdb->MODE_SENSE.PageCode = 0;
cdb->MODE_SENSE.AllocationLength = (UCHAR)modeLength;
Retry:
status = ClassSendSrbSynchronous(DeviceObject,
srb,
modeData,
modeLength,
FALSE);
if (status == STATUS_VERIFY_REQUIRED) {
if (retries--) {
//
// Retry request.
//
goto Retry;
}
} else if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status) || (status == STATUS_NO_MEDIA_IN_DEVICE)) {
//
// Get the block descriptor.
//
blockDescriptor = (PMODE_PARAMETER_BLOCK)modeData;
(ULONG_PTR)blockDescriptor += sizeof(MODE_PARAMETER_HEADER);
//
// Do some validation.
//
if (modeData->BlockDescriptorLength != sizeof(MODE_PARAMETER_BLOCK)) {
DebugPrint((1,
"DiskDeviceControl: BlockDescriptor length - "
"Expected %x, actual %x\n",
modeData->BlockDescriptorLength,
sizeof(MODE_PARAMETER_BLOCK)));
}
DebugPrint((1,
"DiskDeviceControl: DensityCode %x, MediumType %x\n",
blockDescriptor->DensityCode,
modeData->MediumType));
if (TEST_FLAG(modeData->DeviceSpecificParameter,
MODE_DSP_WRITE_PROTECT)) {
writable = FALSE;
} else {
writable = TRUE;
}
status = DiskDetermineMediaTypes(DeviceObject,
Irp,
modeData->MediumType,
blockDescriptor->DensityCode,
mediaPresent,
writable);
//
// If the buffer was too small, DetermineMediaTypes updated the status and information and the request will fail.
//
} else {
DebugPrint((1,
"DiskDeviceControl: Mode sense for header/bd failed. %lx\n",
status));
}
ExFreePool(modeData);
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
DebugPrint((2, "IOCTL_DISK_GET_DRIVE_GEOMETRY to device %p through irp %p\n",
DeviceObject, Irp));
DebugPrint((2, "Device is a%s.\n",
commonExtension->IsFdo ? "n fdo" : " pdo"));
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_GEOMETRY)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
break;
}
if(!commonExtension->IsFdo) {
//
// Pdo should issue this request to the lower device object
//
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
// DiskAcquirePartitioningLock(fdoExtension);
if (TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
//
// Issue ReadCapacity to update device extension
// with information for current media.
//
status = DiskReadDriveCapacity(
commonExtension->PartitionZeroExtension->DeviceObject);
//
// Note whether the drive is ready.
//
diskData->ReadyStatus = status;
if (!NT_SUCCESS(status)) {
// DiskReleasePartitioningLock(fdoExtension);
break;
}
}
//
// Copy drive geometry information from device extension.
//
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
&(fdoExtension->DiskGeometry),
sizeof(DISK_GEOMETRY));
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
// DiskReleasePartitioningLock(fdoExtension);
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: {
DebugPrint((1, "IOCTL_DISK_GET_DRIVE_GEOMETRY_EX to device %p through irp %p\n",
DeviceObject, Irp));
DebugPrint((1, "Device Is a%s.\n",
commonExtension->IsFdo ? "n fdo" : " pdo"));
if (!commonExtension->IsFdo) {
//
// Pdo should issue this request to the lower device object
//
ClassReleaseRemoveLock (DeviceObject, Irp);
ExFreePool (srb);
SendToFdo (DeviceObject, Irp, status);
return status;
} else {
status = DiskIoctlGetDriveGeometryEx( DeviceObject, Irp );
}
break;
}
case IOCTL_STORAGE_PREDICT_FAILURE : {
PSTORAGE_PREDICT_FAILURE checkFailure;
STORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
DebugPrint((2, "IOCTL_STORAGE_PREDICT_FAILURE to device %p through irp %p\n",
DeviceObject, Irp));
DebugPrint((2, "Device is a%s.\n",
commonExtension->IsFdo ? "n fdo" : " pdo"));
checkFailure = (PSTORAGE_PREDICT_FAILURE)Irp->AssociatedIrp.SystemBuffer;
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(STORAGE_PREDICT_FAILURE)) {
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);
break;
}
if(!commonExtension->IsFdo) {
//
// Pdo should issue this request to the lower device object
//
ClassReleaseRemoveLock(DeviceObject, Irp);
ExFreePool(srb);
SendToFdo(DeviceObject, Irp, status);
return status;
}
//
// See if the disk is predicting failure
//
if (diskData->FailurePredictionCapability == FailurePredictionSense) {
ULONG readBufferSize;
PUCHAR readBuffer;
PIRP readIrp;
IO_STATUS_BLOCK ioStatus;
PDEVICE_OBJECT topOfStack;
checkFailure->PredictFailure = 0;
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
topOfStack = IoGetAttachedDeviceReference(DeviceObject);
//
// SCSI disks need to have a read sent down to provoke any
// failures to be reported.
//
// Issue a normal read operation. The error-handling code in
// classpnp will take care of a failure prediction by logging the
// correct event.
//
readBufferSize = fdoExtension->DiskGeometry.BytesPerSector;
readBuffer = ExAllocatePoolWithTag(NonPagedPool,
readBufferSize,
DISK_TAG_SMART);
if (readBuffer != NULL) {
LARGE_INTEGER offset;
offset.QuadPart = 0;
readIrp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
topOfStack,
readBuffer,
readBufferSize,
&offset,
&event,
&ioStatus);
if (readIrp != NULL) {
status = IoCallDriver(topOfStack, readIrp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
}
ExFreePool(readBuffer);
}
ObDereferenceObject(topOfStack);
}
if ((diskData->FailurePredictionCapability == FailurePredictionSmart) ||
(diskData->FailurePredictionCapability == FailurePredictionSense))
{
status = DiskReadFailurePredictStatus(fdoExtension,
&diskSmartStatus);
if (NT_SUCCESS(status))
{
status = DiskReadFailurePredictData(fdoExtension,
Irp->AssociatedIrp.SystemBuffer);
if (diskSmartStatus.PredictFailure)
{
checkFailure->PredictFailure = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -