⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diskwmi.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -