This code works as expected on Windows XP, but SetupDiGetDeviceRegistryProperty returns Error: Invalid Handle on Windows 10. Any idea why?
#Include <WinAPI.au3>
Global Const $DIGCF_DEFAULT = 0x00000001 ;// only valid with DIGCF_DEVICEINTERFACE
Global Const $DIGCF_PRESENT = 0x00000002
Global Const $DIGCF_ALLCLASSES = 0x00000004
Global Const $DIGCF_PROFILE = 0x00000008
Global Const $DIGCF_DEVICEINTERFACE = 0x00000010
Global Const $SPDRP_DEVICEDESC = (0x00000000) ;// DeviceDesc (R/W)
Global Const $SPDRP_HARDWAREID = (0x00000001) ;// HardwareID (R/W)
Global Const $SPDRP_COMPATIBLEIDS = (0x00000002) ;// CompatibleIDs (R/W)
Global Const $SPDRP_UNUSED0 = (0x00000003) ;// unused
Global Const $SPDRP_SERVICE = (0x00000004) ;// Service (R/W)
Global Const $SPDRP_UNUSED1 = (0x00000005) ;// unused
Global Const $SPDRP_UNUSED2 = (0x00000006) ;// unused
Global Const $SPDRP_CLASS = (0x00000007) ;// Class (R--tied to ClassGUID)
Global Const $SPDRP_CLASSGUID = (0x00000008) ;// ClassGUID (R/W)
Global Const $SPDRP_DRIVER = (0x00000009) ;// Driver (R/W)
Global Const $SPDRP_CONFIGFLAGS = (0x0000000A) ;// ConfigFlags (R/W)
Global Const $SPDRP_MFG = (0x0000000B) ;// Mfg (R/W)
Global Const $SPDRP_FRIENDLYNAME = (0x0000000C) ;// FriendlyName (R/W)
Global Const $SPDRP_LOCATION_INFORMATION = (0x0000000D) ;// LocationInformation (R/W)
Global Const $SPDRP_PHYSICAL_DEVICE_OBJECT_NAME= (0x0000000E) ;// PhysicalDeviceObjectName ®
Global Const $SPDRP_CAPABILITIES = (0x0000000F) ;// Capabilities ®
Global Const $SPDRP_UI_NUMBER = (0x00000010) ;// UiNumber ®
Global Const $SPDRP_UPPERFILTERS = (0x00000011) ;// UpperFilters (R/W)
Global Const $SPDRP_LOWERFILTERS = (0x00000012) ;// LowerFilters (R/W)
Global Const $SPDRP_BUSTYPEGUID = (0x00000013) ;// BusTypeGUID ®
Global Const $SPDRP_LEGACYBUSTYPE = (0x00000014) ;// LegacyBusType ®
Global Const $SPDRP_BUSNUMBER = (0x00000015) ;// BusNumber ®
Global Const $SPDRP_ENUMERATOR_NAME = (0x00000016) ;// Enumerator Name ®
Global Const $SPDRP_SECURITY = (0x00000017) ;// Security (R/W, binary form)
Global Const $SPDRP_SECURITY_SDS = (0x00000018) ;// Security (W, SDS form)
Global Const $SPDRP_DEVTYPE = (0x00000019) ;// Device Type (R/W)
Global Const $SPDRP_EXCLUSIVE = (0x0000001A) ;// Device is exclusive-access (R/W)
Global Const $SPDRP_CHARACTERISTICS = (0x0000001B) ;// Device Characteristics (R/W)
Global Const $SPDRP_ADDRESS = (0x0000001C) ;// Device Address ®
Global Const $SPDRP_UI_NUMBER_DESC_FORMAT = (0X0000001D) ;// UiNumberDescFormat (R/W)
Global Const $SPDRP_DEVICE_POWER_DATA = (0x0000001E) ;// Device Power Data ®
Global Const $SPDRP_REMOVAL_POLICY = (0x0000001F) ;// Removal Policy ®
Global Const $SPDRP_REMOVAL_POLICY_HW_DEFAULT = (0x00000020) ;// Hardware Removal Policy ®
Global Const $SPDRP_REMOVAL_POLICY_OVERRIDE = (0x00000021) ;// Removal Policy Override (RW)
Global Const $SPDRP_INSTALL_STATE = (0x00000022) ;// Device Install State ®
Global Const $SPDRP_LOCATION_PATHS = (0x00000023) ;// Device Location Paths ®
Global Const $SPDRP_MAXIMUM_PROPERTY = (0x00000024) ;// Upper bound on ordinals
; Retrieve handle to Setup API dll
$dll = DllOpen("setupapi.dll")
If @ERROR Then MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
; Returns a handle to a device information set that contains requested device information elements for a local machine
$result = Dllcall($dll,"hwnd", "SetupDiGetClassDevs", "ptr", 0, "ptr", 0, "hwnd", 0,"dword", BitOr($DIGCF_PRESENT, $DIGCF_ALLCLASSES, $DIGCF_PROFILE))
If @ERROR Then
MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
; Check for WinAPI error
$WinAPI_Error = _WinAPI_GetLastError()
If $WinAPI_Error <> 0 Then
MsgBox(0,"SetupDiGetClassDevs","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
Else
;~ Debug($result)
$hDevInfo = $result[0]
EndIf
EndIf
; Defines a device instance that is a member of a device information set.
$tSP_DEVINFO_DATA = DllStructCreate("DWORD cbSize;int Data1;ushort Data2;ushort Data3;byte Data4[8];DWORD DevInst;INT_PTR Reserved")
If @ERROR Then MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
$pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)
$tSP_DEVINFO_DATA_Size = DllStructGetSize($tSP_DEVINFO_DATA)
;~ ConsoleWrite("$tSP_DEVINFO_DATA_Size: " & $tSP_DEVINFO_DATA_Size & @CRLF) ;16 bytes
; Store pointer to GUID
DllStructSetData($tSP_DEVINFO_DATA,"cbSize",$tSP_DEVINFO_DATA_Size)
; Loop until error is set
$wIndex = 0
While 1
ConsoleWrite("Index: " & $wIndex & @CRLF)
; Returns a SP_DEVINFO_DATA structure that specifies a device information element in a device information set.
$result = DllCall($dll,"int", "SetupDiEnumDeviceInfo", "hwnd", $hDevInfo, "long", $wIndex, "ptr", $pSP_DEVINFO_DATA)
If @ERROR Then
MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Exit
Else
;~ Debug($result)
; Check for WinAPI error
$WinAPI_Error = _WinAPI_GetLastError()
If $WinAPI_Error <> 0 Then
MsgBox(0,"SetupDiEnumDeviceInfo","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage())
Exit
EndIf
EndIf
If $result[0] = 0 Then ContinueLoop
; SPDRP_CLASS - Retrieves a specified Plug and Play device property.
$result2 = Dllcall($dll,"int", "SetupDiGetDeviceRegistryProperty", "dword", $hDevInfo, "ptr", $pSP_DEVINFO_DATA, "dword", $SPDRP_CLASS, "dword*", 0, "str", "", "dword", 2048, "dword*", 0)
If @ERROR Then
MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
;Check for WinAPI error
$WinAPI_Error = _WinAPI_GetLastError()
If $WinAPI_Error <> 0 Then
;~ MsgBox(0,"SetupDiGetDeviceRegistryProperty","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
EndIf
;~ Debug($result2)
EndIf
; SPDRP_FRIENDLYNAME - Retrieves a specified Plug and Play device property.
$result3 = Dllcall($dll,"int", "SetupDiGetDeviceRegistryProperty", "dword", $hDevInfo, "ptr", $pSP_DEVINFO_DATA, "dword", $SPDRP_FRIENDLYNAME, "dword*", 0, "str", "", "dword", 2048, "dword*", 0)
If @ERROR Then
MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
; Check for WinAPI error
$WinAPI_Error = _WinAPI_GetLastError()
If $WinAPI_Error <> 0 Then
;~ MsgBox(0,"SetupDiGetDeviceRegistryProperty","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
EndIf
;~ Debug($result3)
EndIf
; SPDRP_DEVICEDESC - Retrieves a specified Plug and Play device property.
$result4 = Dllcall($dll,"int", "SetupDiGetDeviceRegistryProperty", "dword", $hDevInfo, "ptr", $pSP_DEVINFO_DATA, "dword", $SPDRP_DEVICEDESC, "dword*", 0, "str", "", "dword", 2048, "dword*", 0)
If @ERROR Then
MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
; Check for WinAPI error
$WinAPI_Error = _WinAPI_GetLastError()
If $WinAPI_Error <> 0 Then
;~ MsgBox(0,"SetupDiGetDeviceRegistryProperty","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
EndIf
;~ Debug($result4)
EndIf
ConsoleWrite("Class name: " & $result2[5] & @CRLF)
ConsoleWrite("Friendly name: " & $result3[5] & @CRLF)
ConsoleWrite("Device description: " & $result4[5] & @CRLF)
ConsoleWrite(@CRLF)
$wIndex += 1
WEnd
; Close handle to Setup API dll
DllClose($dll)
; Dump array to console
Func Debug($aArray)
For $X = 0 to Ubound($aArray)-1
ConsoleWrite("["&$X&"]: " & $aArray[$X] & @CRLF)
Next
ConsoleWrite(@CRLF)
EndFunc
This code was originally posted by weaponx [url=https://www.autoitscript.com/forum/topic/77375-resolved-device-listing-via-setupapidll/?do=findComment&comment=561887]here.