Page 1 of 1

Get Hardware by SetupDi

Posted: Mon Oct 19, 2009 1:00 am
by oryaaaaa
SetupDi.pbi

Code: Select all

Global SetupDiDestroyDeviceInfoList.l
Global SetupDiGetClassDevsA.l, SetupDiGetDeviceInstanceIdA.l
Global SetupDiGetDeviceInterfaceDetailA.l, SetupDiGetDeviceRegistryPropertyA.l
Global SetupDiOpenDeviceInfoA.l, SetupDiEnumDeviceInfo.l

Structure SP_INTERFACE_DEVICE_DETAIL_DATA ; from SETUPAPI.H
  cbSize.l
  DevicePath.c[#ANYSIZE_ARRAY]
EndStructure

Structure SP_DEVINFO_DATA 
  cbSize.l 
  ClassGuid.GUID 
  DevInst.l 
  reserved.l 
EndStructure 

#SPDRP_DRIVER = $9
#SPDRP_DEVICEDESC = 0
#DIGCF_ALLCLASSES = 4

ProcedureDLL setupapi_Init()
  Shared DLL.l
  DLL = LoadLibrary_("setupapi.dll")
  If DLL
    SetupDiDestroyDeviceInfoList = GetProcAddress_(DLL, "SetupDiDestroyDeviceInfoList")
    SetupDiEnumDeviceInfo = GetProcAddress_(DLL, "SetupDiEnumDeviceInfo")
    SetupDiGetClassDevsA = GetProcAddress_(DLL, "SetupDiGetClassDevsA")
    SetupDiGetDeviceInstanceIdA = GetProcAddress_(DLL, "SetupDiGetDeviceInstanceIdA")
    SetupDiGetDeviceInterfaceDetailA = GetProcAddress_(DLL, "SetupDiGetDeviceInterfaceDetailA")
    SetupDiGetDeviceRegistryPropertyA = GetProcAddress_(DLL, "SetupDiGetDeviceRegistryPropertyA")
    SetupDiOpenDeviceInfoA = GetProcAddress_(DLL, "SetupDiOpenDeviceInfoA")
  EndIf
EndProcedure

ProcedureDLL setupapi_End()
  Shared DLL.l
  FreeLibrary_(DLL)
EndProcedure

ProcedureDLL.l SetupDiDestroyDeviceInfoList(a.l)
  ProcedureReturn CallFunctionFast(SetupDiDestroyDeviceInfoList,a)
EndProcedure

ProcedureDLL.l SetupDiEnumDeviceInfo(a.l,b.l,c.l)
  ProcedureReturn CallFunctionFast(SetupDiEnumDeviceInfo,a,b,c)
EndProcedure

ProcedureDLL.l SetupDiGetClassDevsA(a.l,b.l,c.l,d.l)
  ProcedureReturn CallFunctionFast(SetupDiGetClassDevsA,a,b,c,d)
EndProcedure

ProcedureDLL.l SetupDiGetDeviceInstanceIdA(a.l,b.l,c.l,d.l,e.l)
  ProcedureReturn CallFunctionFast(SetupDiGetDeviceInstanceIdA,a,b,c,d,e)
EndProcedure

ProcedureDLL.l SetupDiGetDeviceInterfaceDetailA(a.l,b.l,c.l,d.l,e.l,f.l)
  ProcedureReturn CallFunctionFast(SetupDiGetDeviceInterfaceDetailA,a,b,c,d,e,f)
EndProcedure

ProcedureDLL.l SetupDiGetDeviceRegistryPropertyA(a.l,b.l,c.l,d.l,e.l,f.l,g.l)
  ProcedureReturn CallFunctionFast(SetupDiGetDeviceRegistryPropertyA,a,b,c,d,e,f,g)
EndProcedure

ProcedureDLL.l SetupDiOpenDeviceInfoA(a.l,b.l,c.l,d.l,e.l)
  ProcedureReturn CallFunctionFast(SetupDiOpenDeviceInfoA,a,b,c,d,e)
EndProcedure
I have one problem. Don't get USB AUDIO GUID :cry:

Example.pb

Code: Select all

XIncludeFile "SetupDi.pbi"

Procedure GetHardwareBySetupDI()
  setupapi_Init()
  Protected hDevInfo.l
  Protected DeviceInfoData.SP_DEVINFO_DATA
  Protected i.l
  
  ;/ Create a HDEVINFO with all present devices.
  hDevInfo = SetupDiGetClassDevsA(#Null, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
  
  If hDevInfo = #INVALID_HANDLE_VALUE
    ;/ Insert error handling here
    ProcedureReturn
  EndIf
  
  ;/ Enumerate through all devices in Set.
  
  DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)
  For i=0 To SetupDiEnumDeviceInfo(hDevInfo, i, @DeviceInfoData)
    Protected DataT.l
    Protected *buffer = AllocateMemory(128)
    Protected buffersize.l = 0
    
    ;/ Call function With null To begin With, 
    ;/ then use the returned Buffer size (doubled)
    ;/ To Alloc the Buffer. Keep calling Until
    ;/ success Or an unknown failure.
    ;/
    ;/  Double the returned buffersize To correct
    ;/  For underlying legacy CM functions that 
    ;/  Return an incorrect buffersize Value on 
    ;/  DBCS/MBCS systems.
    
    While (Not SetupDiGetDeviceRegistryPropertyA(hDevInfo, @DeviceInfoData, #SPDRP_DEVICEDESC, @DataT, *buffer, buffersize, @buffersize))
      If GetLastError_()=#ERROR_INSUFFICIENT_BUFFER
        ;/ Change the buffer size.
        If *buffer
          FreeMemory(*buffer)
          ;/ Double the Size To avoid problems on 
          ;/ W2k MBCS systems per KB 888609. 
          *buffer = AllocateMemory(buffersize * 2)
        EndIf
      Else
        ;/ Insert error handling here.
        Break
      EndIf
    Wend
    Debug "Result : ["+PeekS(*buffer)+"]"
    If *buffer
      FreeMemory(*buffer)
    EndIf
  Next
  
  If GetLastError_()<>#NO_ERROR And GetLastError_()<>#ERROR_NO_MORE_ITEMS
    ;/ Insert error handling here
    ProcedureReturn
  EndIf
  
  ;/ Cleanup
  SetupDiDestroyDeviceInfoList(hDevInfo)
  setupapi_End()
EndProcedure

GetHardwareBySetupDI()
End

Re: Get Hardware by SetupDi

Posted: Mon Oct 19, 2009 9:41 am
by Fred
Better use prototypes instead of procedure wrapper, it's much better. Also, better use OpenLibrary()/GetFunctionAddress() instead of API equivalent, because it won't work in unicode mode (GetProcAddress_() expects an ascii string even in unicode).


Warning, not tested, but you get the idea:

Code: Select all

; Prototypes
Prototype.l SetupDiDestroyDeviceInfoListPrototype(a.l)
Prototype.l SetupDiEnumDeviceInfoPrototype(a.l,b.l,c.l)
Prototype.l SetupDiGetClassDevsAPrototype(a.l,b.l,c.l,d.l)
Prototype.l SetupDiGetDeviceInstanceIdAPrototype(a.l,b.l,c.l,d.l,e.l)
Prototype.l SetupDiGetDeviceInterfaceDetailAPrototype(a.l,b.l,c.l,d.l,e.l,f.l)
Prototype.l SetupDiGetDeviceRegistryPropertyAPrototype(a.l,b.l,c.l,d.l,e.l,f.l,g.l)
Prototype.l SetupDiOpenDeviceInfoAPrototype(a.l,b.l,c.l,d.l,e.l)

Global SetupDiDestroyDeviceInfoList.SetupDiDestroyDeviceInfoListPrototype
Global SetupDiGetClassDevsA.SetupDiGetClassDevsAPrototype
Global SetupDiGetDeviceInstanceIdA.SetupDiGetDeviceInstanceIdAPrototype
Global SetupDiGetDeviceInterfaceDetailA.SetupDiGetDeviceInterfaceDetailAPrototype
Global SetupDiGetDeviceRegistryPropertyA.SetupDiGetDeviceRegistryPropertyAPrototype
Global SetupDiOpenDeviceInfoA.SetupDiOpenDeviceInfoAPrototype
Global SetupDiEnumDeviceInfo.SetupDiEnumDeviceInfoPrototype

Structure SP_INTERFACE_DEVICE_DETAIL_DATA ; from SETUPAPI.H
  cbSize.l
  DevicePath.c[#ANYSIZE_ARRAY]
EndStructure

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  reserved.l
EndStructure

#SPDRP_DRIVER = $9
#SPDRP_DEVICEDESC = 0
#DIGCF_ALLCLASSES = 4

Procedure setupapi_Init()
  Shared DLL.l
  DLL = OpendLibrary(#PB_Any, "setupapi.dll")
  If DLL
    SetupDiDestroyDeviceInfoList = GetFunction(DLL, "SetupDiDestroyDeviceInfoList")
    SetupDiEnumDeviceInfo = GetFunction(DLL, "SetupDiEnumDeviceInfo")
    SetupDiGetClassDevsA = GetFunction(DLL, "SetupDiGetClassDevsA")
    SetupDiGetDeviceInstanceIdA = GetFunction(DLL, "SetupDiGetDeviceInstanceIdA")
    SetupDiGetDeviceInterfaceDetailA = GetFunction(DLL, "SetupDiGetDeviceInterfaceDetailA")
    SetupDiGetDeviceRegistryPropertyA = GetFunction(DLL, "SetupDiGetDeviceRegistryPropertyA")
    SetupDiOpenDeviceInfoA = GetFunction(DLL, "SetupDiOpenDeviceInfoA")
  EndIf
EndProcedure

Procedure setupapi_End()
  Shared DLL.l
  CloseLibrary(DLL)
EndProcedure