📄 diskwmi.c
字号:
Enable
Return Value:
NT Status
--*/
{
NTSTATUS status;
PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
PAGED_CODE();
switch(diskData->FailurePredictionCapability)
{
case FailurePredictionSmart:
{
if (Enable)
{
status = DiskEnableSmart(FdoExtension);
} else {
status = DiskDisableSmart(FdoExtension);
}
break;
}
case FailurePredictionSense:
case FailurePredictionIoctl:
{
//
// We assume that the drive is already setup properly for
// failure prediction
//
status = STATUS_SUCCESS;
break;
}
default:
{
status = STATUS_INVALID_DEVICE_REQUEST;
}
}
return status;
}
NTSTATUS
DiskEnableDisableFailurePredictPolling(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
BOOLEAN Enable,
ULONG PollTimeInSeconds
)
/*++
Routine Description:
Enable or disable polling for hardware failure detection
Arguments:
FdoExtension
Enable
PollTimeInSeconds - if 0 then no change to current polling timer
Return Value:
NT Status
--*/
{
NTSTATUS status;
PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
PAGED_CODE();
if (Enable)
{
status = DiskEnableDisableFailurePrediction(FdoExtension,
Enable);
} else {
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status))
{
status = ClassSetFailurePredictionPoll(FdoExtension,
Enable ? diskData->FailurePredictionCapability :
FailurePredictionNone,
PollTimeInSeconds);
//
// Even if this failed we do not want to disable FP on the
// hardware. FP is only ever disabled on the hardware by
// specific command of the user.
//
}
return status;
}
NTSTATUS
DiskReadFailurePredictStatus(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
)
/*++
Routine Description:
Obtains current failure prediction status
Arguments:
FdoExtension
DiskSmartStatus
Return Value:
NT Status
--*/
{
PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
NTSTATUS status;
PAGED_CODE();
DiskSmartStatus->PredictFailure = FALSE;
switch(diskData->FailurePredictionCapability)
{
case FailurePredictionSmart:
{
UCHAR outBuffer[sizeof(SRB_IO_CONTROL) + (sizeof(SENDCMDINPARAMS) - 1 + sizeof(IDEREGS))];
ULONG outBufferSize = sizeof(outBuffer);
PSENDCMDOUTPARAMS cmdOutParameters;
status = DiskReadSmartStatus(FdoExtension,
(PSRB_IO_CONTROL)outBuffer,
&outBufferSize);
if (NT_SUCCESS(status))
{
cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
sizeof(SRB_IO_CONTROL));
DiskSmartStatus->Reason = 0; // Unknown;
DiskSmartStatus->PredictFailure = ((cmdOutParameters->bBuffer[3] == 0xf4) &&
(cmdOutParameters->bBuffer[4] == 0x2c));
}
break;
}
case FailurePredictionSense:
{
DiskSmartStatus->Reason = FdoExtension->FailureReason;
DiskSmartStatus->PredictFailure = FdoExtension->FailurePredicted;
status = STATUS_SUCCESS;
break;
}
case FailurePredictionIoctl:
case FailurePredictionNone:
default:
{
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
}
return status;
}
NTSTATUS
DiskReadFailurePredictData(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
)
/*++
Routine Description:
Obtains current failure prediction data. Not available for
FAILURE_PREDICT_SENSE types.
Arguments:
FdoExtension
DiskSmartData
Return Value:
NT Status
--*/
{
PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
NTSTATUS status;
PAGED_CODE();
switch(diskData->FailurePredictionCapability)
{
case FailurePredictionSmart:
{
PUCHAR outBuffer;
ULONG outBufferSize;
PSENDCMDOUTPARAMS cmdOutParameters;
outBufferSize = sizeof(SRB_IO_CONTROL) +
(sizeof(SENDCMDOUTPARAMS)-1) +
READ_ATTRIBUTE_BUFFER_SIZE;
outBuffer = ExAllocatePoolWithTag(NonPagedPool,
outBufferSize,
DISK_TAG_SMART);
if (outBuffer != NULL)
{
status = DiskReadSmartData(FdoExtension,
(PSRB_IO_CONTROL)outBuffer,
&outBufferSize);
if (NT_SUCCESS(status))
{
cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
sizeof(SRB_IO_CONTROL));
DiskSmartData->Length = READ_ATTRIBUTE_BUFFER_SIZE;
RtlCopyMemory(DiskSmartData->VendorSpecific,
cmdOutParameters->bBuffer,
READ_ATTRIBUTE_BUFFER_SIZE);
}
ExFreePool(outBuffer);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
}
case FailurePredictionSense:
{
DiskSmartData->Length = sizeof(ULONG);
*((PULONG)DiskSmartData->VendorSpecific) = FdoExtension->FailureReason;
status = STATUS_SUCCESS;
break;
}
case FailurePredictionIoctl:
case FailurePredictionNone:
default:
{
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
}
return status;
}
NTSTATUS
DiskReadFailurePredictThresholds(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
)
/*++
Routine Description:
Obtains current failure prediction thresholds. Not available for
FAILURE_PREDICT_SENSE types.
Arguments:
FdoExtension
DiskSmartData
Return Value:
NT Status
--*/
{
PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
NTSTATUS status;
PAGED_CODE();
switch(diskData->FailurePredictionCapability)
{
case FailurePredictionSmart:
{
PUCHAR outBuffer;
PSENDCMDOUTPARAMS cmdOutParameters;
ULONG outBufferSize;
outBufferSize = sizeof(SRB_IO_CONTROL) +
(sizeof(SENDCMDOUTPARAMS)-1) +
READ_THRESHOLD_BUFFER_SIZE;
outBuffer = ExAllocatePoolWithTag(NonPagedPool,
outBufferSize,
DISK_TAG_SMART);
if (outBuffer != NULL)
{
status = DiskReadSmartThresholds(FdoExtension,
(PSRB_IO_CONTROL)outBuffer,
&outBufferSize);
if (NT_SUCCESS(status))
{
cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
sizeof(SRB_IO_CONTROL));
RtlCopyMemory(DiskSmartThresholds->VendorSpecific,
cmdOutParameters->bBuffer,
READ_THRESHOLD_BUFFER_SIZE);
}
ExFreePool(outBuffer);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
}
case FailurePredictionSense:
case FailurePredictionIoctl:
case FailurePredictionNone:
default:
{
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
}
return status;
}
void DiskReregWorker(
IN PVOID Context
)
{
PDISKREREGREQUEST reregRequest;
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
PIRP irp;
PAGED_CODE();
do
{
reregRequest = (PDISKREREGREQUEST)ExInterlockedPopEntryList(
&DiskReregHead,
&DiskReregSpinlock);
deviceObject = reregRequest->DeviceObject;
irp = reregRequest->Irp;
status = IoWMIRegistrationControl(deviceObject,
WMIREG_ACTION_UPDATE_GUIDS);
if (! NT_SUCCESS(status))
{
DebugPrint((1, "DiskReregWorker: Reregistration failed %x\n",
status));
}
//
// Release remove lock and free irp, now that we are done
// processing this
//
ClassReleaseRemoveLock(deviceObject, irp);
IoFreeMdl(irp->MdlAddress);
IoFreeIrp(irp);
ExFreePool(reregRequest);
} while (InterlockedDecrement(&DiskReregWorkItems));
}
NTSTATUS DiskInitializeReregistration(
void
)
{
PAGED_CODE();
//
// Initialize the global work item and spinlock used to manage the
// list of disks reregistering their guids
//
ExInitializeWorkItem( &DiskReregWorkItem,
DiskReregWorker,
NULL );
KeInitializeSpinLock(&DiskReregSpinlock);
return(STATUS_SUCCESS);
}
NTSTATUS DiskPostReregisterRequest(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
{
PDISKREREGREQUEST reregRequest;
NTSTATUS status;
reregRequest = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DISKREREGREQUEST),
DISK_TAG_SMART);
if (reregRequest != NULL)
{
//
// add the disk that needs reregistration to the stack of disks
// to reregister. If the list is transitioning from empty to
// non empty then also kick off the work item so that the
// reregistration worker can do the reregister.
//
reregRequest->DeviceObject = DeviceObject;
reregRequest->Irp = Irp;
ExInterlockedPushEntryList(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -