This time we will look at checking if a device is enabled, disabled, or has a problem.  From last time we received a device structure that contained a SP_DEVINFO_DATA structure.  Within that structure we find a DevInst integer.  With that and the use of the CM_Get_DevNode_Status function we can get status information on a device.
Private Declare Auto Function CM_Get_DevNode_Status Lib "cfgmgr32.dll" (ByRef pulStatus As IntPtr, ByRef pulProblemNumber As IntPtr, ByVal dnDevInst As Integer, ByVal ulFlags As Long) As Integer
This function will return the status and any problem with the device given.  The last variable must be set to 0.  The Status and Problem flags can have numerous meanings, so we have two enumerations to describe all the possible values.  I've only encountered a handful of status and problem codes through normal use.
   'Status Flags.  Devices can have one or more of these.  ANDing is used to determine which apply
    Public Enum DN_Flags
        DN_ROOT_ENUMERATED = &H1                        ' Was enumerated by ROOT
        DN_DRIVER_LOADED = &H2                          ' Has Register_Device_Driver
        DN_ENUM_LOADED = &H4                            ' Has Register_Enumerator
        DN_STARTED = &H8                                ' Is currently configured
        DN_MANUAL = &H10                                ' Manually installed
        DN_NEED_TO_ENUM = &H20                          ' May need reenumeration
        DN_NOT_FIRST_TIME = &H40                        ' Has received a config
        DN_HARDWARE_ENUM = &H80                         ' Enum generates hardware ID
        DN_LIAR = &H100                                 ' Lied about can reconfig once
        DN_HAS_MARK = &H200                             ' Not CM_Create_DevInst lately
        DN_HAS_PROBLEM = &H400                          ' Need device installer
        DN_FILTERED = &H800                             ' Is filtered
        DN_MOVED = &H1000                               ' Has been moved
        DN_DISABLEABLE = &H2000                         ' Can be disabled
        DN_REMOVABLE = &H4000                           ' Can be removed
        DN_PRIVATE_PROBLEM = &H8000                     ' Has a private problem
        DN_MF_PARENT = &H10000                          ' Multi function parent
        DN_MF_CHILD = &H20000                           ' Multi function child
        DN_WILL_BE_REMOVED = &H40000                    ' DevInst is being removed
        DN_NOT_FIRST_TIMEE = &H80000                    ' Has received a config enumerate
        DN_STOP_FREE_RES = &H100000                     ' When child is stopped, free resources
        DN_REBAL_CANDIDATE = &H200000                   ' Don't skip during rebalance
        DN_BAD_PARTIAL = &H400000                       ' This devnode's log_confs do not have same resources
        DN_NT_ENUMERATOR = &H800000                     ' This devnode's is an NT enumerator
        DN_NT_DRIVER = &H1000000                        ' This devnode's is an NT driver
        DN_NEEDS_LOCKING = &H2000000                    ' Devnode need lock resume processing
        DN_ARM_WAKEUP = &H4000000                       ' Devnode can be the wakeup device
        DN_APM_ENUMERATOR = &H8000000                   ' APM aware enumerator
        DN_APM_DRIVER = &H10000000                      ' APM aware driver
        DN_SILENT_INSTALL = &H20000000                  ' Silent install
        DN_NO_SHOW_IN_DM = &H40000000                   ' No show in device manager
        DN_BOOT_LOG_PROB = &H80000000                   ' Had a problem during preassignment of boot log conf
    End Enum
    'Problem associated with device.  A device has 0 or 1 problem associated with it.
    Public Enum CM_PROB
        CM_PROB_NOT_CONFIGURED = &H1                    ' no config for device
        CM_PROB_DEVLOADER_FAILED = &H2                  ' service load failed
        CM_PROB_OUT_OF_MEMORY = &H3                     ' out of memory
        CM_PROB_ENTRY_IS_WRONG_TYPE = &H4               '
        CM_PROB_LACKED_ARBITRATOR = &H5                 '
        CM_PROB_BOOT_CONFIG_CONFLICT = &H6              ' boot config conflict
        CM_PROB_FAILED_FILTER = &H7                     '
        CM_PROB_DEVLOADER_NOT_FOUND = &H8               ' Devloader not found
        CM_PROB_INVALID_DATA = &H9                      ' Invalid ID
        CM_PROB_FAILED_START = &HA                      '
        CM_PROB_LIAR = &HB                              '
        CM_PROB_NORMAL_CONFLICT = &HC                   ' config conflict
        CM_PROB_NOT_VERIFIED = &HD                      '
        CM_PROB_NEED_RESTART = &HE                      ' requires restart
        CM_PROB_REENUMERATION = &HF                     '
        CM_PROB_PARTIAL_LOG_CONF = &H10                 '
        CM_PROB_UNKNOWN_RESOURCE = &H11                 ' unknown res type
        CM_PROB_REINSTALL = &H12                        '
        CM_PROB_REGISTRY = &H13                         '
        CM_PROB_VXDLDR = &H14                           ' WINDOWS 95 ONLY
        CM_PROB_WILL_BE_REMOVED = &H15                  ' devinst will remove
        CM_PROB_DISABLED = &H16                         ' devinst is disabled
        CM_PROB_DEVLOADER_NOT_READY = &H17              ' Devloader not ready
        CM_PROB_DEVICE_NOT_THERE = &H18                 ' device doesn't exist
        CM_PROB_MOVED = &H19                            '
        CM_PROB_TOO_EARLY = &H1A                        '
        CM_PROB_NO_VALID_LOG_CONF = &H1B                ' no valid log config
        CM_PROB_FAILED_INSTALL = &H1C                   ' install failed
        CM_PROB_HARDWARE_DISABLED = &H1D                ' device disabled
        CM_PROB_CANT_SHARE_IRQ = &H1E                   ' can't share IRQ
        CM_PROB_FAILED_ADD = &H1F                       ' driver failed add
        CM_PROB_DISABLED_SERVICE = &H20                 ' service's Start = 4
        CM_PROB_TRANSLATION_FAILED = &H21               ' resource translation failed
        CM_PROB_NO_SOFTCONFIG = &H22                    ' no soft config
        CM_PROB_BIOS_TABLE = &H23                       ' device missing in BIOS table
        CM_PROB_IRQ_TRANSLATION_FAILED = &H24           ' IRQ translator failed
        CM_PROB_FAILED_DRIVER_ENTRY = &H25              ' DriverEntry() failed.
        CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD = &H26       ' Driver should have unloaded.
        CM_PROB_DRIVER_FAILED_LOAD = &H27               ' Driver load unsuccessful.
        CM_PROB_DRIVER_SERVICE_KEY_INVALID = &H28       ' Error accessing driver's service key
        CM_PROB_LEGACY_SERVICE_NO_DEVICES = &H29        ' Loaded legacy service created no devices
        CM_PROB_DUPLICATE_DEVICE = &H2A                 ' Two devices were discovered with the same name
        CM_PROB_FAILED_POST_START = &H2B                ' The drivers set the device state to failed
        CM_PROB_HALTED = &H2C                           ' This device was failed post start via usermode
        CM_PROB_PHANTOM = &H2D                          ' The devinst currently exists only in the registry
        CM_PROB_SYSTEM_SHUTDOWN = &H2E                  ' The system is shutting down
        CM_PROB_HELD_FOR_EJECT = &H2F                   ' The device is offline awaiting removal
        CM_PROB_DRIVER_BLOCKED = &H30                   ' One or more drivers is blocked from loading
        CM_PROB_REGISTRY_TOO_LARGE = &H31               ' System hive has grown too large
        CM_PROB_SETPROPERTIES_FAILED = &H32             ' Failed to apply one or more registry properties  
        NUM_CM_PROB = &H33                              '
    End Enum
    'Returns true if the device is enabled
    Public Function IsDeviceEnabled(ByVal DevInst As Integer) As Boolean
        Dim Result As Integer
        Dim Problem, Status As IntPtr
        Result = CM_Get_DevNode_Status(Status, Problem, DevInst, 0)
        If Result = 13 Then Return Nothing
        If Result <> 0 Then Throw New ApplicationException("Return Code From CM_Get_DevNode_Status was not 0")
        Return Not Problem.ToInt32 = CM_PROB.CM_PROB_DISABLED
    End Function
    'Returns true if the Status Flag to hide the device is set.
    Public Function IsDeviceHidden(ByVal DevInst As Integer) As Boolean
        Dim Result As Integer
        Dim Problem, Status As IntPtr
        Result = CM_Get_DevNode_Status(Status, Problem, DevInst, 0)
        If Result <> 0 Then Throw New ApplicationException("Return Code From CM_Get_DevNode_Status was not 0")
        Return (Status.ToInt32 And DN_Flags.DN_NO_SHOW_IN_DM) = DN_Flags.DN_NO_SHOW_IN_DM
    End Function
    'Gets all the Device Status Flags for a device
    Public Function GetDeviceStatus(ByVal DevInst As Integer) As String()
        Dim Result As Integer
        Dim Problem, Status As IntPtr
        Result = CM_Get_DevNode_Status(Status, Problem, DevInst, 0)
        If Result = 13 Then Return Nothing
        If Result <> 0 Then Throw New ApplicationException("Return Code From CM_Get_DevNode_Status was not 0")
        Return GetBitFlags(Status, GetType(DN_Flags))
    End Function
    'Gets a Device Problem
    Public Function GetDeviceProblem(ByVal DevInst As Integer) As String
        Dim Result As Integer
        Dim Problem, Status As IntPtr
        Result = CM_Get_DevNode_Status(Status, Problem, DevInst, 0)
        If Result = 13 Then Return Nothing
        If Result <> 0 Then Throw New ApplicationException("Return Code From CM_Get_DevNode_Status was not 0")
        If Problem.ToInt32 = 0 Then
            Return "No Problem"
        Else
            Return CType(Problem.ToInt32, CM_PROB).ToString
        End If
    End Function
    'Returns an array of strings representing the Status Flags set for a device.
    Private Function GetBitFlags(ByVal Bits As IntPtr, ByVal EnumType As Type) As String()
        Dim arrData As New ArrayList
        For Each TypeName As String In [Enum].GetNames(EnumType)
            Dim Number As Int32 = [Enum].Parse(EnumType, TypeName)
            If (Bits.ToInt32 And Number) = Number Then
                arrData.Add(TypeName)
            End If
        Next
        Dim StrData(arrData.Count) As String
        arrData.CopyTo(StrData)
        Return StrData
    End Function
Here is how you could call this. after you retrieve a device in variable objDevice.
If IsDeviceEnabled(objDevice.DevInfo.DevInst) Then
   'Device Enabled
   ...
Else
   'Device Disabled
   ...
End If
I think that the code should be fairly straightforward to follow.
Subscribe to:
Post Comments (Atom)
 
 




No comments:
Post a Comment