Sign in to follow this  
Followers 0
weaponx

[Resolved] Device listing via setupapi.dll

7 posts in this topic

#1 ·  Posted (edited)

The purpose of this code is to enumerate the names of all devices. Visual Basic code is here:

http://www.codeproject.com/KB/system/SimpleSetup.aspx

The very first DllCall in this script is returning error code 13 "The data is invalid". Any help is appreciated.

MSDN info for SetupDiGetClassDevs:

http://msdn.microsoft.com/en-us/library/ms792959.aspx

#include <StructureConstants.au3>
#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)

;Create a struct to hold a GUID and its pointer
;$tGUID = DllStructCreate($tagGUID)
;$pGUID = DllStructGetPtr($tGUID)

;$tStr = DllStructCreate("chr")
;$pStr = DllStructGetPtr($tStr)

;Returns a handle to a device information set that contains requested device information elements for a local machine
#cs
HDEVINFO
  SetupDiGetClassDevs(
    IN LPGUID  ClassGuid,  OPTIONAL
    IN PCTSTR  Enumerator,  OPTIONAL
    IN HWND  hwndParent,  OPTIONAL
    IN DWORD  Flags
    );
#ce
$result = Dllcall($dll,"hwnd", "SetupDiGetClassDevs", "ptr", "", "str", "", "hwnd*", "","dword", BitOr($DIGCF_PRESENT, $DIGCF_ALLCLASSES, $DIGCF_PROFILE))

If @ERROR Then 
    MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
    MsgBox(0,"",_WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
    ;MsgBox(0,"",_WinAPI_GetLastError()) ;Error 13: The data is invalid.
    
    Debug($result)
    $hDevInfo = $result[0]
EndIf

;Create a struct to hold a GUID and its pointer
$tGUID = DllStructCreate($tagGUID)
$pGUID = DllStructGetPtr($tGUID)

;Defines a device instance that is a member of a device information set.
$tSP_DEVINFO_DATA = DllStructCreate("DWORD cbSize; DWORD ClassGuid; DWORD DevInst; ULONG_PTR Reserved")
If @ERROR Then MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)

;Store pointer to GUID
DllStructSetData($tSP_DEVINFO_DATA,"ClassGuid",$pGUID)
DllStructSetData($tSP_DEVINFO_DATA,"cbSize",DllStructGetSize($tSP_DEVINFO_DATA))
$pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)

;Loop until error is set
$wIndex = 0;

;Returns a SP_DEVINFO_DATA structure that specifies a device information element in a device information set.
$result = Dllcall($dll,"int", "SetupDiEnumDeviceInfo", "dword", $hDevInfo, "long", $wIndex, "ptr", $pSP_DEVINFO_DATA)
If @ERROR Then 
    MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
    ;MsgBox(0,"",_WinAPI_GetLastError()) ;Error 6: The handle is invalid.
    Debug($result)
EndIf

ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "cbsize") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "ClassGuid") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "DevInst") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "Reserved") & @CRLF)

$tByte = DllStructCreate("byte")
$pByte = DllStructGetPtr($tByte)

;Retrieves a specified Plug and Play device property.
$result = Dllcall($dll,"int", "SetupDiGetDeviceRegistryProperty", "dword", $hDevInfo, "ptr", $pSP_DEVINFO_DATA, "dword", $SPDRP_FRIENDLYNAME, "dword*", 0, "str", $pByte, "dword", 2048, "dword*", 0)
;MsgBox(0,"",_WinAPI_GetLastError()) ;Error 6: The handle is invalid.
If @ERROR Then 
    MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
    Debug($result)
EndIf

;Display friendly name of device
ConsoleWrite(DllStructGetData($tByte, 0) & @CRLF)

;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
Edited by weaponx

Share this post


Link to post
Share on other sites



This is so weird.

The exact same function call works flawless in vc++ (except it returns a void*, not HWND (not sure if that means anything)).

Not in any way a final solution, but I compiled my working c++ code into a dll so you can at least continue debugging the rest of the code :P

http://monoceres.se/Uploads/wrapper.dll

Call it like:

$res=DllCall("wrapper.dll","ptr:cdecl","SetupDiGetClassDevsWrapper","dword",$flag)
MsgBox(0,"",$res[0])

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

This is so weird.

The exact same function call works flawless in vc++ (except it returns a void*, not HWND (not sure if that means anything)).

Not in any way a final solution, but I compiled my working c++ code into a dll so you can at least continue debugging the rest of the code :P

http://monoceres.se/Uploads/wrapper.dll

Call it like:

$res=DllCall("wrapper.dll","ptr:cdecl","SetupDiGetClassDevsWrapper","dword",$flag)
 MsgBox(0,"",$res[0])
Thanks but I just don't understand why it isn't working. Here is a simpler reproducer:

#include <StructureConstants.au3>
#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

;Retrieve handle to Setup API dll
$dll = DllOpen("setupapi.dll")
If @ERROR Then MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)

;Create a struct to hold a GUID and its pointer
;$tGUID = DllStructCreate($tagGUID)
;$pGUID = DllStructGetPtr($tGUID)

;$tStr = DllStructCreate("chr")
;$pStr = DllStructGetPtr($tStr)

;Returns a handle to a device information set that contains requested device information elements for a local machine
#cs
HDEVINFO
  SetupDiGetClassDevs(
    IN LPGUID  ClassGuid,  OPTIONAL
    IN PCTSTR  Enumerator,  OPTIONAL
    IN HWND  hwndParent,  OPTIONAL
    IN DWORD  Flags
    );
#ce
$result = Dllcall($dll,"hwnd", "SetupDiGetClassDevs", "ptr", 0, "wstr*", "", "long", 0,"hwnd", BitOr($DIGCF_PRESENT, $DIGCF_ALLCLASSES, $DIGCF_PROFILE))

DllClose($dll)

If @ERROR Then
    MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)
Else
    MsgBox(0,"",_WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
    ;MsgBox(0,"",_WinAPI_GetLastError()) ;Error 13: The data is invalid.
   
    Debug($result)
    $hDevInfo = $result[0]
EndIf

;Dump array to console
Func Debug($aArray)
    For $X = 0 to Ubound($aArray)-1
        ConsoleWrite("["&$X&"]: " & $aArray[$X] & @CRLF)
    Next
    ConsoleWrite(@CRLF)
EndFunc

Share this post


Link to post
Share on other sites

Your arguments are all wrong.

Are you trying to call this with a NULL second parameter? If yes, then you would use "ptr", 0, not "wstr*", "". Also, using "wstr*" is wrong for several reasons. First, you don't want to use "wstr*" at all, you would want to use "wstr" if you do actually want to pass a string. Second, the ANSI version of the function is being called and you are passing it a wide string. Lastly, remember that an empty string is not the same thing as NULL.

Finally you have the wrong types for the 3rd and 4th parameters.

Something like this is more likely to work:

Dllcall($dll,"hwnd", "SetupDiGetClassDevs", "ptr", 0, "ptr", 0, "hwnd", 0,"dword", BitOr($DIGCF_PRESENT, $DIGCF_ALLCLASSES, $DIGCF_PROFILE))

If I had to guess, I would say that "wstr*" is the reason the code is failing entirely.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Damn you are right. That completed okay. Unfortunately the following DllCall's fail as well. Error message from dll call to SetupDiEnumDeviceInfo:

Error 1784: The supplied user buffer is not valid for the requested operation.

Doesn't seem to like the nested struct.

#include <StructureConstants.au3>
#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

;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; ptr ClassGuid; DWORD DevInst; ULONG_PTR Reserved")
;$tSP_DEVINFO_DATA = DllStructCreate("DWORD cbSize; " & $tagGUID & " DWORD DevInst; ULONG_PTR Reserved")
If @ERROR Then MsgBox(0,"","@ERROR: " & @ERROR & @CRLF & "@EXTENDED: " & @EXTENDED)

;Create a struct to hold a GUID and its pointer
$tGUID = DllStructCreate($tagGUID)
$pGUID = DllStructGetPtr($tGUID)

;Store pointer to GUID
DllStructSetData($tSP_DEVINFO_DATA,"ClassGuid",$pGUID)
DllStructSetData($tSP_DEVINFO_DATA,"cbSize",DllStructGetSize($tSP_DEVINFO_DATA))
$pSP_DEVINFO_DATA = DllStructGetPtr($tSP_DEVINFO_DATA)

;Loop until error is set
$wIndex = 0;

;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)
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()) ;Error 1784: The supplied user buffer is not valid for the requested operation.
        Exit
    EndIf
EndIf

ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "cbsize") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "DevInst") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "Reserved") & @CRLF)
Edited by weaponx

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I have made some progress. There are no longer any errors. I am just having a problem translating a PBYTE to AutoIt (for dllcall to SetupDiGetDeviceRegistryProperty):

Nevermind, I got it! Seems to only retrieve devices when $wIndex is between 1 and 5...hmm.

#include <StructureConstants.au3>
#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 = 1

;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)
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

;Dump structure contents
ConsoleWrite("SP_DEVINFO_DATA: " & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "cbsize") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "DevInst") & @CRLF)
ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "Reserved") & @CRLF)
ConsoleWrite(@CRLF)

ConsoleWrite("GUID:" & @CRLF)
ConsoleWrite("Data1: " & DllStructGetData($tSP_DEVINFO_DATA, "Data1") & @CRLF)
ConsoleWrite("Data2: " & DllStructGetData($tSP_DEVINFO_DATA, "Data2") & @CRLF)
ConsoleWrite("Data3: " & DllStructGetData($tSP_DEVINFO_DATA, "Data3") & @CRLF)
ConsoleWrite(@CRLF)

;Retrieves a specified Plug and Play device property.
$result = 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,"",_WinAPI_GetLastErrorMessage()) ;Error 87: The parameter is incorrect.
        MsgBox(0,"SetupDiGetDeviceRegistryProperty","Error " & _WinAPI_GetLastError() & @CRLF & _WinAPI_GetLastErrorMessage()) ;Error 13: The data is invalid.
    EndIf
    Debug($result)
EndIf

;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
Edited by weaponx

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Well for anyone interested, here is a big step towards device management via AutoIt. This will enumerate all of the devices on your system and show a few of the properties available. I hope to have a complete device management UDF in the future.

#include <StructureConstants.au3>
#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)
    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
    EndIf

#cs
    ;Dump structure contents
    ConsoleWrite("SP_DEVINFO_DATA: " & @CRLF)
    ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "cbsize") & @CRLF)
    ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "DevInst") & @CRLF)
    ConsoleWrite(DllStructGetData($tSP_DEVINFO_DATA, "Reserved") & @CRLF)
    ConsoleWrite(@CRLF)

    ConsoleWrite("GUID:" & @CRLF)
    ConsoleWrite("Data1: " & DllStructGetData($tSP_DEVINFO_DATA, "Data1") & @CRLF)
    ConsoleWrite("Data2: " & DllStructGetData($tSP_DEVINFO_DATA, "Data2") & @CRLF)
    ConsoleWrite("Data3: " & DllStructGetData($tSP_DEVINFO_DATA, "Data3") & @CRLF)
    ConsoleWrite(@CRLF)
#ce

    ;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($result2)
    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($result2)
    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
Edited by weaponx

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0