首次调用SetupDiGetDeviceInterfaceDetail将始终失败,并显示ERROR_INVALID_USER_BUFFER

时间:2012-12-20 14:14:03

标签: vb.net

我对此有点疯狂,我已经花了几个小时才找到问题所以我想我需要一些WinAPI大师:)我使用VB .NET所以请善待:)

尝试与某些USB设备进行通信,并且在SetupDiGetDeviceInterfaceDetail()步骤中,(第一个)函数调用将失败,并显示ERROR_INVALID_USER_BUFFER。第二次调用现在没有意义了:)问题是为什么? DeviceInfoTable句柄是正确的,因为我在成功使用了更少的函数,并在每次调用后测试了Err.LastDllError。

我假设的InterfaceDataStructure也是正确的,因为其他SetupDiEnumDeviceInterfaces()将失败。我怀疑dll导入或结构的声明不正确。

    If Not SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, Nothing, 0, StructureSize, Nothing) Then

        ErrorStatus = Err.LastDllError ' <-- always 0x6F8, ERROR_INVALID_USER_BUFFER

    End If

以下是声明

       Dim DeviceInfoTable As IntPtr = INVALID_HANDLE_VALUE
        Dim InterfaceDataStructure As SP_DEVICE_INTERFACE_DATA = New SP_DEVICE_INTERFACE_DATA
        Dim InterfaceIndex As Integer = 0
        Dim ErrorStatus As Integer = 0

        Dim DevInfoData As SP_DEVINFO_DATA = New SP_DEVINFO_DATA

        Dim dwRegType As Integer
        Dim dwRegSize As Integer

        Dim DetailedInterfaceDataStructure As SP_DEVICE_INTERFACE_DETAIL_DATA = New SP_DEVICE_INTERFACE_DETAIL_DATA
        Dim StructureSize As Integer = 0


    'Structures declarations
    <StructLayout(LayoutKind.Sequential, Pack:=1)> _
   Public Structure SP_DEVINFO_DATA
        Public cbSize As UInteger
        Public InterfaceClassGUID As Guid
        Public DevInst As UInteger
        Public Reserved As IntPtr
    End Structure

    <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    Public Structure SP_DEVICE_INTERFACE_DATA
        Public cbSize As UInteger
        Public InterfaceClassGuid As Guid
        Public Flags As UInteger
        Public Reserved As IntPtr
    End Structure

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

    <DllImport("setupapi.dll",
    CharSet:=CharSet.Auto,
    SetLastError:=True)> _
    Public Shared Function SetupDiGetDeviceInterfaceDetail(ByVal hDevInfo As IntPtr,
                                                           ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA,
                                                           ByRef deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA,
                                                           ByVal deviceInterfaceDetailDataSize As Int32,
                                                           ByRef RequiredSize As Int32,
                                                           ByRef deviceInfo As SP_DEVINFO_DATA) As Boolean

非常感谢,

3 个答案:

答案 0 :(得分:1)

If Not SetupDiGetDeviceInterfaceDetail(..., Nothing, 0, StructureSize, Nothing)

您在使用基本的VB.NET时遇到困难,关键字 Nothing 并不意味着您希望它做什么。 api函数要求你做的是传递一个空指针。 IntPtr.Zero。那个可以什么都不是,但在这种情况下不是。您将参数类型声明为结构。它们是值类型。在值类型的情况下,没有什么意味着什么,它意味着“默认值”。所以你实际上是在这里传递一个指向结构的指针,这是一个零初始化的结构。该功能对此不满意并告诉您。

使用这些pinvoke声明时,无法传递IntPtr.Zero。您可以欺骗并声明函数的重载,它使用不同的参数类型。像这样:

<DllImport("setupapi.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function SetupDiGetDeviceInterfaceDetail(
   ByVal hDevInfo As IntPtr,
   ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA,
   ByVal mustPassIntPtrZero As IntPtr,
   ByVal mustPassZero As Int32,
   ByRef RequiredSize As Int32,
   ByVal mustPassIntPtrZero2 As IntPtr) As Boolean

现在您可以第一次调用该函数:

If Not SetupDiGetDeviceInterfaceDetail(..., IntPtr.Zero, 0, StructureSize, IntPtr.Zero)

您应该使用返回的RequiredSize通过Marshal.AllocHGlobal()分配内存。将返回的指针作为deviceInterfaceDetailData参数传递。现在必须将其声明为ByVal IntPtr。并在调用后使用Marshal.PtrToStructure()将其转换为结构。是的,Pack是64位操作系统上的一个问题。

通过使用CharSet:= CharSet.Auto声明结构来修复字符串问题,这样您就可以获得Unicode转换而不是Ansi转换。

答案 1 :(得分:0)

现在我想通了,实际上是半工作:)也许有人可以点亮我。

至少在VB .NET 2010上,SetupDiGetDeviceInterfaceDetail()不会将NULL(也就是没有)作为参数排成行,所以我不得不首先传递虚拟的东西:

    DetailedInterfaceDataStructure.cbSize = 6

    SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, 1000, StructureSize, DevInfoData)  

cbSize必须是&lt;&gt; 0和32位系统必须为6(DWORD为4,空终止宽字符串为2)。 1000它只是一个大数字,所以SetupDiGetDeviceInterfaceDetail()甚至不会返回ERROR_INSUFFICIENT_BUFFER

现在第二遍应该得到真实的东西:

    SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, StructureSize, Nothing)

哪个不会返回任何系统错误,但路径只是一个反斜杠字符“\”,这不好....它应该是一个有效的USB路径

“\\?\ USB#vid_01E5&安培; pid_00A2#5和; 1d4952dc&安培; 0和2#{18d0A210-85D2 -........”

任何人都可以帮助我吗?...

答案 2 :(得分:0)

是的,我正在努力使用VB,因为我来自纯C99和MCU的汇编程序:)事实上,经过几个小时的错误后,我在C#中得到了一些片段,它像魅力一样,但我必须知道为什么不是'在VB工作:)我终于解决了,部分喜欢你的建议

我用另一个重载了SetupDiGetDeviceInterfaceDetail(),只是为了接受某个非托管缓冲区的ptr:

<DllImport("setupapi.dll",
 CharSet:=CharSet.Auto,
 SetLastError:=True)> _
Public Shared Function SetupDiGetDeviceInterfaceDetail(ByVal hDevInfo As IntPtr,
                                                       ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA,
                                                       ByVal deviceInterfaceDetailData As IntPtr,
                                                       ByVal deviceInterfaceDetailDataSize As Int32,
                                                       ByRef RequiredSize As Int32,
                                                       ByRef deviceInfo As SP_DEVINFO_DATA) As Boolean
End Function

Now the problem was I used ByRef deviceInterfaceDetailData As IntPtr instead of ByVal deviceInterfaceDetailData As IntPtr, was my mistake from VB's quite simple perspective.

Indeed, now I can pass some unmanaged buffer at 2'nd call of SetupDiGetDeviceInterfaceDetail()




    Dim PUnmanagedDetailedInterfaceDataStructure As IntPtr = IntPtr.Zero

    PUnmanagedDetailedInterfaceDataStructure = Marshal.AllocHGlobal(StructureSize) 
    DetailedInterfaceDataStructure.cbSize = 6 ' cbSize = 4 bytes for DWORD + 2 bytes for Unicode null terminator
    Marshal.StructureToPtr(DetailedInterfaceDataStructure, PUnmanagedDetailedInterfaceDataStructure, False) ' Copy the contents of the structure, to an unmanaged memory space


    SetupDiGetDeviceInterfaceDetail(DeviceInfoTable, InterfaceDataStructure, PUnmanagedDetailedInterfaceDataStructure, StructureSize, StructureSize, DevInfoData)

这终于有效了。我希望有些积分可以挣扎:) 我在互联网上看到了很多类似的线程,但没有一个完全解决。

祝大家圣诞快乐

相关问题