CASorter
asked on
Help calling SetupDiEnumDeviceInterfaces from VB.NET
I've been pounding on this pretty hard, and have yet to find a solution.
I need to call the SetupDiEnumDeviceInterface s API function from VB.NET (Not C#). I get a PInvoke error which usually results from not having declared something properly. Any help would be greatly appreciated!!!
Public Structure SP_DEVINFO_DATA
Public cbSize As Long
Public ClassGuid As Guid
Public DevInst As Long
Public Reserved As Long
End Structure
Public Structure SP_DEVICE_INTERFACE_DATA
Dim cbSize As Int64
Dim InterfaceClassGuid As Guid
Dim Flags As Integer
Dim Reserved As UInt32
End Structure
Public Enum DEVICEFLAGS
DIGCF_ALLCLASSES = &H4&
DIGCF_DEVICEINTERFACE = &H10
DIGCF_PRESENT = &H2
DIGCF_PROFILE = &H8
End Enum
Public Declare Function SetupDiGetDeviceInterfaceD etail lib "setupapi.dll" Alias "SetupDiGetDeviceInterface DetailA" (ByVal DeviceInfoSet As Integer, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByVal DeviceInterfaceDetailData As Integer, ByVal DeviceInterfaceDetailDataS ize As Integer, ByRef RequiredSize As Integer, ByVal DeviceInfoData As Integer) As Integer
Public Declare Auto Function SetupDiEnumDeviceInterface s Lib "setupapi.dll" (ByVal Handle As Long, ByVal InfoPtr As IntPtr, ByRef GuidPtr As IntPtr, ByVal MemberIndex As Integer, ByRef InterfaceDataPtr As IntPtr) As Boolean
Public Declare Function SetupDiGetClassDevs Lib "setupapi.dll" Alias "SetupDiGetClassDevsA" (ByRef ClassGuid As IntPtr, ByVal Enumerator As String, ByVal hwndParent As Int32, ByVal flags As DEVICEFLAGS) As Int64
Private Sub Initialize()
Try
IOCTL_ASYNC_IN = CTL_CODE(FILE_DEVICE_UNKNO WN, 850, METHOD_BUFFERED, FILE_ANY_ACCESS)
1010: IOCTL_USB_PACKET_SIZE = CTL_CODE(FILE_DEVICE_UNKNO WN, 851, METHOD_BUFFERED, FILE_ANY_ACCESS)
'// Make all the necessary Windows calls to get a handle to our USB device
1015: Dim szOfPacket_T As Integer
Dim theBytesReturned As Long = 0
Dim theDevInfoData As Int64
Dim theDevInfo As Int64
Dim theInterfaceData As SP_DEVICE_INTERFACE_DATA
Dim holderForSizeCalc As SP_DEVINFO_DATA
Dim hldForSP_DEVINFO_DATA As New SP_DEVINFO_DATA
Dim holderForPacket_t As Packet_T
Dim devDetailData As SP_DEVICE_INTERFACE_DETAIL _DATA
Dim ptrToDevDetailData As IntPtr
1025: theDevInfoData = Marshal.SizeOf(hldForSP_DE VINFO_DATA )
hldForSP_DEVINFO_DATA.cbSi ze = Marshal.SizeOf(hldForSP_DE VINFO_DATA )
Dim theStartSessionPacket As Packet_T
theStartSessionPacket.mPac ketId = 0
theStartSessionPacket.mRes erved3 = 5
theStartSessionPacket.mDat aSize = 0
theStartSessionPacket.mDat a = 0
1040:
szOfPacket_T = Marshal.SizeOf(holderForPa cket_t)
1045: Dim thePacket As IntPtr
thePacket = Marshal.AllocHGlobal(szOfP acket_T)
1050: Dim gd As Guid
Dim devcFlags As DEVICEFLAGS
1060: devcFlags = DEVICEFLAGS.DIGCF_PRESENT Or DEVICEFLAGS.DIGCF_DEVICEIN TERFACE
Dim GUID_DEVINTERFACE_GRMNUSB As New Guid(&H2C9C45C2L, &H8E7D, &H4C08, &HA1, &H2D, &H81, &H6B, &HBA, &HE7, &H22, &HC0)
gd = GUID_DEVINTERFACE_GRMNUSB
Dim s1 As String = DEVICE_CLASS_USB_DEVICE
Dim ptr As IntPtr = Marshal.StringToHGlobalAut o(s1)
Dim guidPtr As IntPtr = Marshal.AllocHGlobal(Marsh al.SizeOf( gd))
'The SetupDiGetClassDevs function retrieves a device information set
'that contains all the devices of a specified class
1080: theDevInfo = SetupDiGetClassDevs(guidPt r, 0&, callersHandle, devcFlags)
1090: Dim ptrToTheIntfData As IntPtr = Marshal.AllocHGlobal(Marsh al.SizeOf( theInterfa ceData))
theInterfaceData.cbSize = Marshal.SizeOf(theInterfac eData)
1095: Marshal.StructureToPtr(the InterfaceD ata, ptrToTheIntfData, False)
1100: Dim result As Boolean
'The SetupDiEnumDeviceInterface s function retrieves a context structure for a device
'interface of a device information set. Each call returns information about one device
'interface. The function can be called repeatedly to get information about several
'interfaces exposed by one or more devices.
result = SetupDiEnumDeviceInterface s(theDevIn fo, 0&, guidPtr, 0, ptrToTheIntfData)
"ABOVE GIVES THE PINVOKE ERROR
If Not result Then
If GetLastError() = ERROR_NO_MORE_ITEMS Then
gHandle = 0
GoTo CommonExit
End If
End If
CommonExit:
Catch ex As Exception
Dim sNum As Long
sNum = GetLastError()
Dim errText As String
errText = FormatError("Error initializing USB Device.")
MsgBox(errText, MsgBoxStyle.Critical, "Error Initializing USB Device")
LogError(errText, "USBComm::Initialize")
End Try
End Sub
I need to call the SetupDiEnumDeviceInterface
Public Structure SP_DEVINFO_DATA
Public cbSize As Long
Public ClassGuid As Guid
Public DevInst As Long
Public Reserved As Long
End Structure
Public Structure SP_DEVICE_INTERFACE_DATA
Dim cbSize As Int64
Dim InterfaceClassGuid As Guid
Dim Flags As Integer
Dim Reserved As UInt32
End Structure
Public Enum DEVICEFLAGS
DIGCF_ALLCLASSES = &H4&
DIGCF_DEVICEINTERFACE = &H10
DIGCF_PRESENT = &H2
DIGCF_PROFILE = &H8
End Enum
Public Declare Function SetupDiGetDeviceInterfaceD
Public Declare Auto Function SetupDiEnumDeviceInterface
Public Declare Function SetupDiGetClassDevs Lib "setupapi.dll" Alias "SetupDiGetClassDevsA" (ByRef ClassGuid As IntPtr, ByVal Enumerator As String, ByVal hwndParent As Int32, ByVal flags As DEVICEFLAGS) As Int64
Private Sub Initialize()
Try
IOCTL_ASYNC_IN = CTL_CODE(FILE_DEVICE_UNKNO
1010: IOCTL_USB_PACKET_SIZE = CTL_CODE(FILE_DEVICE_UNKNO
'// Make all the necessary Windows calls to get a handle to our USB device
1015: Dim szOfPacket_T As Integer
Dim theBytesReturned As Long = 0
Dim theDevInfoData As Int64
Dim theDevInfo As Int64
Dim theInterfaceData As SP_DEVICE_INTERFACE_DATA
Dim holderForSizeCalc As SP_DEVINFO_DATA
Dim hldForSP_DEVINFO_DATA As New SP_DEVINFO_DATA
Dim holderForPacket_t As Packet_T
Dim devDetailData As SP_DEVICE_INTERFACE_DETAIL
Dim ptrToDevDetailData As IntPtr
1025: theDevInfoData = Marshal.SizeOf(hldForSP_DE
hldForSP_DEVINFO_DATA.cbSi
Dim theStartSessionPacket As Packet_T
theStartSessionPacket.mPac
theStartSessionPacket.mRes
theStartSessionPacket.mDat
theStartSessionPacket.mDat
1040:
szOfPacket_T = Marshal.SizeOf(holderForPa
1045: Dim thePacket As IntPtr
thePacket = Marshal.AllocHGlobal(szOfP
1050: Dim gd As Guid
Dim devcFlags As DEVICEFLAGS
1060: devcFlags = DEVICEFLAGS.DIGCF_PRESENT Or DEVICEFLAGS.DIGCF_DEVICEIN
Dim GUID_DEVINTERFACE_GRMNUSB As New Guid(&H2C9C45C2L, &H8E7D, &H4C08, &HA1, &H2D, &H81, &H6B, &HBA, &HE7, &H22, &HC0)
gd = GUID_DEVINTERFACE_GRMNUSB
Dim s1 As String = DEVICE_CLASS_USB_DEVICE
Dim ptr As IntPtr = Marshal.StringToHGlobalAut
Dim guidPtr As IntPtr = Marshal.AllocHGlobal(Marsh
'The SetupDiGetClassDevs function retrieves a device information set
'that contains all the devices of a specified class
1080: theDevInfo = SetupDiGetClassDevs(guidPt
1090: Dim ptrToTheIntfData As IntPtr = Marshal.AllocHGlobal(Marsh
theInterfaceData.cbSize = Marshal.SizeOf(theInterfac
1095: Marshal.StructureToPtr(the
1100: Dim result As Boolean
'The SetupDiEnumDeviceInterface
'interface of a device information set. Each call returns information about one device
'interface. The function can be called repeatedly to get information about several
'interfaces exposed by one or more devices.
result = SetupDiEnumDeviceInterface
"ABOVE GIVES THE PINVOKE ERROR
If Not result Then
If GetLastError() = ERROR_NO_MORE_ITEMS Then
gHandle = 0
GoTo CommonExit
End If
End If
CommonExit:
Catch ex As Exception
Dim sNum As Long
sNum = GetLastError()
Dim errText As String
errText = FormatError("Error initializing USB Device.")
MsgBox(errText, MsgBoxStyle.Critical, "Error Initializing USB Device")
LogError(errText, "USBComm::Initialize")
End Try
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
'WINSETUPAPI BOOL WINAPI
'SetupDiEnumDeviceInterfac
' IN HDEVINFO DeviceInfoSet, <- "H" means handle (a pointer to a handle obtained by SetupDiGetClassDevs)
' IN SP_DEVINFO_DATA DeviceInfoData, OPTIONAL <- "P" means pointer to a SP_DEVINFO_DATA structure
' IN LPGUID InterfaceClassGuid, <- "LP" means a long pointer (in this case a GUID)
' IN DWORD MemberIndex, <- Integer
' OUT SP_DEVICE_INTERFACE_DATA DeviceInterfaceData <- "P" means pointer to a SP_DEVICE_INTERFACE_DATA structure
');
Declare Auto Function SetupDiEnumDeviceInterface
ByVal DeviceInfoSet As IntPtr, _ <- this might seem strange, but ByVal is correct for an IntPtr that is a pointer to a handle
ByRef DeviceInfoData As SP_DEVINFO_DATA, _ <- structures are value types, so a ByRef make is this a pointer
ByRef InterfaceClassGuid As Guid, _ <- likewise, a ByRef makes this a pointer
ByVal MemberIndex As Integer, _ <- plain ole integer
ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA _ <- ByRef makes this a pointer to a structure
)
Optionally, you could substitute
ByVal DeviceInfoSet As IntPtr <- the preferred method
with
ByRef DeviceInfoSet as Integer
As for the structures, all API-style structures are "packed", so we need to decorate the structures with the LayoutKind.Sequential attribute
'typedef struct _SP_DEVINFO_DATA {
' DWORD cbSize; <- Integer
' GUID ClassGuid; <- GUID
' DWORD DevInst; <- Integer
' ULONG_PTR Reserved; <- pointer to an usigned long
'} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
<StructLayout(LayoutKind.S
Structure SP_DEVINFO_DATA
Dim cbSize As Integer
Dim ClassGuid As Guid
Dim DevInst As Integer
Dim Reserved As IntPtr
End Structure
I only did one API declare and one structure, but I bet you can take it from here.
... if not, let us know and we'll continue