VB.NET HID:SetupDiGetDeviceInterfaceDetail GetLastError()显示1784(ERROR_INVALID_USER_BUFFER)

时间:2012-05-01 22:19:03

标签: .net interop usb vb.net-2010 hid

我一直在努力解决这个问题,尝试各种各样的事情让它发挥作用。我的理解是SetupDiGetDeviceInterfaceDetail应该第一次给出1784错误,因为第一次调用它的唯一目的是将RequiredSize设置为正确的值。它第二次被调用,它应该实际工作并给我一个有效的DeviceInterfaceDetailData结构。我不确定是什么原因导致第二次通话失败。

结构定义:

<StructLayout(LayoutKind.Sequential)> _
Public Structure SP_DEVICE_INTERFACE_DETAIL_DATA
    Public cbSize As UInt32
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
    Public DevicePath As String
End Structure

Public Structure SP_DEVICE_INTERFACE_DATA
    Public cbSize As Integer
    Public InterfaceClassGuid As System.Guid
    Public Flags As Integer
    Public Reserved As UIntPtr
End Structure

Public Structure SP_DEVINFO_DATA
    Public cbSize As Integer
    Public ClassGuid As System.Guid
    Public DevInst As Integer
    Public Reserved As UIntPtr
End Structure

功能声明:

Public Declare Auto Function SetupDiGetClassDevs Lib "setupapi.dll" (ByRef ClassGuid As System.Guid, ByVal Enumerator As Integer, ByVal hwndParent As IntPtr, ByVal Flags As Integer) As IntPtr

Public Declare Auto Function SetupDiEnumDeviceInfo Lib "setupapi.dll" (ByVal DeviceInfoSet As Integer, ByVal MemberIndex As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA) As Boolean

Public Declare Auto Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" (ByVal DeviceInfoSet As IntPtr, ByRef DeviceInfoData As SP_DEVINFO_DATA, ByRef InterfaceClassGuid As System.Guid, ByVal MemberIndex As UInteger, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Boolean

//For the first call
Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" (ByVal DeviceInfoSet As IntPtr, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByVal DeviceInterfaceDetailData As IntPtr, ByVal DeviceInterfaceDetailDataSize As Integer, ByRef RequiredSize As Integer, ByRef DeviceInfoData As IntPtr) As Boolean

//For the second call
Public Declare Auto Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" (ByVal DeviceInfoSet As IntPtr, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByRef DeviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, ByVal DeviceInterfaceDetailDataSize As Integer, ByRef RequiredSize As Integer, ByRef DeviceInfoData As SP_DEVINFO_DATA) As Boolean

函数调用:

    Dim DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA
    Dim DeviceInterfaceDetailDataSize As Integer
    Dim DeviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA = Nothing
    Dim DeviceInfoSet As IntPtr
    Dim RequiredSize As Integer
    Dim HidGuid As System.Guid
    HidD_GetHidGuid(HidGuid)
    Dim LastError As Integer

    DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData)
    DeviceInterfaceDetailData.cbSize = Marshal.SizeOf(DeviceInterfaceDetailData
    DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData)


    DeviceInfoSet = SetupDiGetClassDevs(HidGuid, 0, IntPtr.Zero, DIGCF_PRESENT + DIGCF_DEVICEINTERFACE)

    success = SetupDiEnumDeviceInfo(DeviceInfoSet, 0, DeviceInfoData)
    LastError = GetLastError()

    success = SetupDiEnumDeviceInterfaces(DeviceInfoSet, DeviceInfoData, HidGuid, 0, DeviceInterfaceData)

    success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, IntPtr.Zero, 0, RequiredSize, IntPtr.Zero)
    //Success is false. GetLastError() shows 1784, but RequiredSize gets set to 166

    DeviceInterfaceDetailDataSize = RequiredSize + 16

    success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData)
    //Success is false. GetLastError() shows 1784, and DeviceInterfaceDetailData does not get set, so I can't get DeviceInterfaceDetailData.DevicePath

2 个答案:

答案 0 :(得分:1)

Private Structure SP_DEVICE_INTERFACE_DETAIL_DATA
    Dim cbSize As UInteger
    Dim DevicePath() As Char
End Structure

For target CPU x86: DetailedInterfaceDataStructure.cbSize = 6
For target CPU x64: DetailedInterfaceDataStructure.cbSize = 8

答案 1 :(得分:0)

你必须设置

DeviceInterfaceDetailData.cbSize = Marshal.SizeOf(UInt32) + Marshal.SizeOf(Char)

并忽略从SetupDiGetDeviceInterfaceDetail返回的第一个结果代码。

结构DeviceInterfaceDetailData声明为

typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {
  DWORD cbSize;
  TCHAR DevicePath[ANYSIZE_ARRAY];
} SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;

与ANYSIZE_ARRAY是一个!