📄 disk.c
字号:
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);
modeLength = MODE_DATA_SIZE;
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 0x3F will return all pages.
//
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
cdb->MODE_SENSE.PageCode = MODE_SENSE_RETURN_ALL;
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.
//
if (modeData->BlockDescriptorLength != 0)
{
blockDescriptor = (PMODE_PARAMETER_BLOCK)modeData;
(ULONG_PTR)blockDescriptor += sizeof(MODE_PARAMETER_HEADER);
densityCode = blockDescriptor->DensityCode;
}
if (TEST_FLAG(modeData->DeviceSpecificParameter,
MODE_DSP_WRITE_PROTECT)) {
writable = FALSE;
}
status = DiskDetermineMediaTypes(DeviceObject,
Irp,
modeData->MediumType,
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;
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;
}
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)) {
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);
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;
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;
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;
}
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
ExFreePool(readBuffer);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
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;
} else {
checkFailure->PredictFailure = 0;
}
Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);
}
} else {
status = STATUS_INVALID_DEVICE_REQUEST;
}
break;
}
case IOCTL_DISK_VERIFY: {
PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
LARGE_INTEGER byteOffset;
DebugPrint((2, "IOCTL_DISK_VERIFY to device %p through irp %p\n",
DeviceObject, Irp));
DebugPrint((2, "Device is a%s.\n",
commonExtension->IsFdo ? "n fdo" : " pdo"));
//
// Validate buffer length.
//
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(VERIFY_INFORMATION)) {
status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
//
// Add disk offset to starting sector.
//
byteOffset.QuadPart = commonExtension->StartingOffset.QuadPart +
verifyInfo->StartingOffset.QuadPart;
if(!commonExtension->IsFdo) {
//
// Adjust the request and forward it down
//
verifyInfo->StartingOffset.QuadPart = byteOffset.QuadPart;
ClassReleaseRemoveLock(DeviceObject, Irp);
SendToFdo(DeviceObject, Irp, status);
ExFreePool(srb);
return status;
}
//
// Perform a bounds check on the sector range
//
if ((verifyInfo->StartingOffset.QuadPart > commonExtension->PartitionLength.QuadPart) ||
(verifyInfo->StartingOffset.QuadPart < 0))
{
status = STATUS_NONEXISTENT_SECTOR;
break;
}
else
{
ULONGLONG bytesRemaining = commonExtension->PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart;
if ((ULONGLONG)verifyInfo->Length > bytesRemaining)
{
status = STATUS_NONEXISTENT_SECTOR;
break;
}
}
{
PDISK_VERIFY_WORKITEM_CONTEXT Context = NULL;
Context = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DISK_VERIFY_WORKITEM_CONTEXT),
DISK_TAG_WI_CONTEXT);
if (Context)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -