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

📄 diskwmi.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 5 页
字号:
    check for IDE SMART capability. This is done by sending the drive an
    IDENTIFY command and checking if the SMART command set bit is set.

    Next we check if SCSI SMART (aka Information Exception Control Page,
    X3T10/94-190 Rev 4). This is done by querying for the Information
    Exception mode page.

    Lastly we check if the device has IOCTL failure prediction. This mechanism
    a filter driver implements IOCTL_STORAGE_PREDICT_FAILURE and will respond
    with the information in the IOCTL. We do this by sending the ioctl and
    if the status returned is STATUS_SUCCESS we assume that it is supported.

Arguments:

    FdoExtension

    *FailurePredictCapability

Return Value:

    NT Status

--*/
{
    PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
    PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
    BOOLEAN supportFP;
    NTSTATUS status;
    STORAGE_PREDICT_FAILURE checkFailure;
    STORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
    BOOLEAN logErr;

    PAGED_CODE();

    //
    // Assume no failure predict mechanisms
    //
    *FailurePredictCapability = FailurePredictionNone;

    //
    // See if this is an IDE drive that supports SMART. If so enable SMART
    // and then ensure that it suports the SMART READ STATUS command
    //
    status = DiskGetIdentifyInfo(FdoExtension,
                                 &supportFP);

    if (supportFP)
    {
        status = DiskEnableSmart(FdoExtension);
        if (NT_SUCCESS(status))
        {
            *FailurePredictCapability = FailurePredictionSmart;

            status = DiskReadFailurePredictStatus(FdoExtension,
                                                  &diskSmartStatus);

            DebugPrint((1, "Disk: Device %p %s IDE SMART\n",
                       FdoExtension->DeviceObject,
                       NT_SUCCESS(status) ? "does" : "does not"));

            if (! NT_SUCCESS(status))
            {
                *FailurePredictCapability = FailurePredictionNone;
            }
        }
        return(status);
    }

    //
    // See if there is a a filter driver to intercept
    // IOCTL_STORAGE_PREDICT_FAILURE
    //
    status = DiskSendFailurePredictIoctl(FdoExtension,
                                         &checkFailure);

    DebugPrint((1, "Disk: Device %p %s IOCTL_STORAGE_FAILURE_PREDICT\n",
                       FdoExtension->DeviceObject,
                       NT_SUCCESS(status) ? "does" : "does not"));

    if (NT_SUCCESS(status))
    {
        *FailurePredictCapability = FailurePredictionIoctl;
        if (checkFailure.PredictFailure)
        {
            checkFailure.PredictFailure = 512;
            ClassNotifyFailurePredicted(FdoExtension,
                                            (PUCHAR)&checkFailure,
                                            sizeof(checkFailure),
                                            (BOOLEAN)(FdoExtension->FailurePredicted == FALSE),
                                            0x11,
                                            diskData->ScsiAddress.PathId,
                                            diskData->ScsiAddress.TargetId,
                                            diskData->ScsiAddress.Lun);

            FdoExtension->FailurePredicted = TRUE;
        }
        return(status);
    }
    
    //
    // Finally we assume it will not be a scsi smart drive. but
    // we'll also send off an asynchronous mode sense so that if
    // it is SMART we'll reregister the device object
    //

    DiskInfoExceptionCheck(FdoExtension);
    
    *FailurePredictCapability = FailurePredictionNone;

    return(STATUS_SUCCESS);
}


NTSTATUS
DiskWmiFunctionControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN ULONG GuidIndex,
    IN CLASSENABLEDISABLEFUNCTION Function,
    IN BOOLEAN Enable
    )
/*++

Routine Description:

    This routine is a callback into the driver to enabled or disable event
    generation or data block collection. A device should only expect a
    single enable when the first event or data consumer enables events or
    data collection and a single disable when the last event or data
    consumer disables events or data collection. Data blocks will only
    receive collection enable/disable if they were registered as requiring
    it.


    When NT boots, failure prediction is not automatically enabled, although
    it may have been persistantly enabled on a previous boot. Polling is also
    not automatically enabled. When the first data block that accesses SMART
    such as SmartStatusGuid, SmartDataGuid, SmartPerformFunction, or
    SmartEventGuid is accessed then SMART is automatically enabled in the
    hardware. Polling is enabled when SmartEventGuid is enabled and disabled
    when it is disabled. Hardware SMART is only disabled when the DisableSmart
    method is called. Polling is also disabled when this is called regardless
    of the status of the other guids or events.

Arguments:

    DeviceObject is the device whose data block is being queried

    GuidIndex is the index into the list of guids provided when the
        device registered

    Function specifies which functionality is being enabled or disabled

    Enable is TRUE then the function is being enabled else disabled

Return Value:

    status

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
    ULONG enableCount;

    PAGED_CODE();

    if ((Function == DataBlockCollection) && Enable)
    {
        if ((GuidIndex == SmartStatusGuid) ||
            (GuidIndex == SmartDataGuid) ||
            (GuidIndex == SmartThresholdsGuid) ||
            (GuidIndex == SmartPerformFunction))
        {
            status = DiskEnableDisableFailurePrediction(fdoExtension,
                                                        TRUE);
            DebugPrint((3, "Disk: DeviceObject %p, Irp %p Enable -> %lx\n",
                       DeviceObject,
                       Irp,
                       status));

        } else {
            DebugPrint((3, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Collection\n",
                      DeviceObject, Irp,
                      GuidIndex,
                      Enable ? "Enabled" : "Disabled"));        }
    } else if (Function == EventGeneration) {
        DebugPrint((3, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Event Generation\n",
                  DeviceObject, Irp,
                  GuidIndex,
                  Enable ? "Enabled" : "Disabled"));


        if ((GuidIndex == SmartEventGuid) && Enable)
        {
            status = DiskEnableDisableFailurePredictPolling(fdoExtension,
                                                   Enable,
                                                   0);
            DebugPrint((3, "Disk: DeviceObject %p, Irp %p %s -> %lx\n",
                       DeviceObject,
                       Irp,
                       Enable ? "DiskEnableSmartPolling" : "DiskDisableSmartPolling",
                       status));
        }

#if DBG
    } else {
        DebugPrint((3, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for function %d\n",
                  DeviceObject, Irp,
                  GuidIndex,
                  Enable ? "Enabled" : "Disabled",
                  Function));
#endif
    }

    status = ClassWmiCompleteRequest(DeviceObject,
                                     Irp,
                                     status,
                                     0,
                                     IO_NO_INCREMENT);
    return status;
}



NTSTATUS
DiskFdoQueryWmiRegInfo(
    IN PDEVICE_OBJECT DeviceObject,
    OUT ULONG *RegFlags,
    OUT PUNICODE_STRING InstanceName
    )
/*++

Routine Description:

    This routine is a callback into the driver to retrieve the list of
    guids or data blocks that the driver wants to register with WMI. This
    routine may not pend or block. Driver should NOT call
    ClassWmiCompleteRequest.

Arguments:

    DeviceObject is the device whose data block is being queried

    *RegFlags returns with a set of flags that describe the guids being
        registered for this device. If the device wants enable and disable
        collection callbacks before receiving queries for the registered
        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
        the instance name is determined from the PDO associated with the
        device object. Note that the PDO must have an associated devnode. If
        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
        name for the device.

    InstanceName returns with the instance name for the guids if
        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
        caller will call ExFreePool with the buffer returned.


Return Value:

    status

--*/
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
    NTSTATUS status;

    PAGED_CODE();

    SET_FLAG(DiskWmiFdoGuidList[SmartThresholdsGuid].Flags,  WMIREG_FLAG_REMOVE_GUID);
    SET_FLAG(DiskWmiFdoGuidList[ScsiInfoExceptionsGuid].Flags,  WMIREG_FLAG_REMOVE_GUID);
    
    switch (diskData->FailurePredictionCapability)
    {
        case FailurePredictionSmart:
        {
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartThresholdsGuid].Flags,  WMIREG_FLAG_REMOVE_GUID);
            //
            // Fall Through
            //
        }
        case FailurePredictionIoctl:
        {
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartStatusGuid].Flags,      WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartDataGuid].Flags,        WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartEventGuid].Flags,       WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
                  
            break;
        }

        case FailurePredictionSense:
        {
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartStatusGuid].Flags,      WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartEventGuid].Flags,       WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
            CLEAR_FLAG(DiskWmiFdoGuidList[ScsiInfoExceptionsGuid].Flags,  WMIREG_FLAG_REMOVE_GUID);
            SET_FLAG  (DiskWmiFdoGuidList[SmartDataGuid].Flags,        WMIREG_FLAG_REMOVE_GUID);
            break;
        }


        default:
        {
            SET_FLAG  (DiskWmiFdoGuidList[SmartStatusGuid].Flags,      WMIREG_FLAG_REMOVE_GUID);
            SET_FLAG  (DiskWmiFdoGuidList[SmartDataGuid].Flags,        WMIREG_FLAG_REMOVE_GUID);
            SET_FLAG  (DiskWmiFdoGuidList[SmartEventGuid].Flags,       WMIREG_FLAG_REMOVE_GUID);
            SET_FLAG  (DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
            break;
        }
    }

    //
    // Use devnode for FDOs
    *RegFlags = WMIREG_FLAG_INSTANCE_PDO;

    return STATUS_SUCCESS;
}

NTSTATUS
DiskFdoQueryWmiRegInfoEx(
    IN PDEVICE_OBJECT DeviceObject,
    OUT ULONG *RegFlags,
    OUT PUNICODE_STRING InstanceName,
    OUT PUNICODE_STRING MofName                      
    )
/*++

Routine Description:

    This routine is a callback into the driver to retrieve the list of
    guids or data blocks that the driver wants to register with WMI. This
    routine may not pend or block. Driver should NOT call
    ClassWmiCompleteRequest.

Arguments:

    DeviceObject is the device whose data block is being queried

    *RegFlags returns with a set of flags that describe the guids being
        registered for this device. If the device wants enable and disable
        collection callbacks before receiving queries for the registered
        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
        the instance name is determined from the PDO associated with the
        device object. Note that the PDO must have an associated devnode. If
        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
        name for the device.

    InstanceName returns with the instance name for the guids if
        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
        caller will call ExFreePool with the buffer returned.

    MofName returns initialized with the mof resource name for the
        binary mof resource attached to the driver's image file. If the
        driver does not have a mof resource then it should leave this
        parameter untouched.

Return Value:

    status

--*/
{
    NTSTATUS status;
    
    status = DiskFdoQueryWmiRegInfo(DeviceObject,
                                    RegFlags,
                                    InstanceName);

    //
    // Leave MofName alone since disk doesn't have one
    //
    return(status);
}


NTSTATUS
DiskFdoQueryWmiDataBlock(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN ULONG GuidIndex,
    IN ULONG BufferAvail,
    OUT PUCHAR Buffer
    )
/*++

Routine Description:

    This routine is a callback into the driver to query for the contents of
    a data block. When the driver has finished filling the data block it
    must call ClassWmiCompleteRequest to complete the irp. The driver can
    return STATUS_PENDING if the irp cannot be completed immediately.

Arguments:

    DeviceObject is the device whose data block is being queried

    Irp is the Irp that makes this request

    GuidIndex is the index into the list of guids provided when the
        device registered

    BufferAvail on has the maximum size available to write the data
        block.

    Buffer on return is filled with the returned data block


Return Value:

    status

--*/
{
    NTSTATUS status;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
    ULONG sizeNeeded;

    PAGED_CODE();

    DebugPrint((3, "Disk: DiskQueryWmiDataBlock, Device %p, Irp %p, GuiIndex %d\n"
             "      BufferAvail %lx Buffer %lx\n",
             DeviceObject, Irp,
             GuidIndex, BufferAvail, Buffer));

    switch (GuidIndex)
    {
        case DiskGeometryGuid:
        {
            sizeNeeded = sizeof(DISK_GEOMETRY);
            if (BufferAvail >= sizeNeeded)
            {
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -