【问题标题】:PInvoke with SetupDiGetDriverInfoDetail使用 SetupDiGetDriverInfoDetail 调用 PInvoke
【发布时间】:2011-07-04 11:18:20
【问题描述】:

我正在尝试从 C# 应用程序调用 SetupDiGetDriverInfoDetail。调用失败,我得到的 win32 错误是 0x6F8(“提供的用户缓冲区对于请求的操作无效。”)。到目前为止,我已经能够成功调用其他 setupdi 函数,所以我认为问题在于我编组函数或 SP_DRVINFO_DETAIL_DATA 结构的方式。

我不确定,但我认为问题可能出在 SP_DRVINFO_DETAIL_DATA 结构的 HardwareID 成员上。我尝试将 HardwareID 指定为不同的类型(例如,字节数组并在设置大小和调用函数之前分配缓冲区),但总是出现相同的错误。如果有人对此电话有任何经验或有任何指示,我将不胜感激。

下面是我的结构定义、函数导入和代码sn-p。在这个版本中,我使用固定大小的 HardwareID 缓冲区。我还尝试将缓冲区大小指定为 1,期望出现“缓冲区太小”错误,但我总是收到“无效缓冲区”错误。

    [DllImport("setupapi.dll", SetLastError = true)]
    internal static extern Int32 SetupDiGetDriverInfoDetail(
        IntPtr DeviceInfoSet,
        SP_DEVINFO_DATA DeviceInfoData,
        SP_DRVINFO_DATA DriverInfoData,
        ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
        Int32 DriverInfoDetailDataSize,
        ref Int32 RequiredSize);


    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct SP_DRVINFO_DETAIL_DATA
    {
        public Int32 cbSize;
        public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
        public Int32 CompatIDsOffset;
        public Int32 CompatIDsLength;
        public IntPtr Reserved;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String SectionName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String InfFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String DrvDescription;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String HardwareID;
    };

SetupApiWrapper.SP_DRVINFO_DETAIL_DATA DriverInfoDetailData = new SetupApiWrapper.SP_DRVINFO_DETAIL_DATA();
DriverInfoDetailData.cbSize = Marshal.SizeOf(DriverInfoDetailData);

result = SetupApiWrapper.SetupDiGetDriverInfoDetail(
                            DevInfo,
                            DeviceInfoData,
                            DriverInfoData,
                            ref DriverInfoDetailData,
                            DriverInfoDetailData.cbSize,
                            ref reqSize);

【问题讨论】:

    标签: c# pinvoke


    【解决方案1】:

    o虽然我同意错误代码似乎出乎意料,但我认为问题在于 cbSize 应设置为 sizeof(SP_DRVINFO_DETAIL_DATA)(这是正确的 C sizeof,而不是您的 p/invoke 结构中的 Marshal.SizeOf。)

    一个两行 C 程序的快速测试给出:

    ANSI 797
    UNICODE 1570
    

    对于两个适当的 sizeof 值(您需要自己确定需要哪一个...)

    相比之下,Marshal.SizeOf(typeof(SP_DRVINFO_DETAIL_DATA)) 为您的结构提供 1048 作为长度。

    我认为你需要先把它排好,然后再继续。

    我怀疑可能是DriverInfoDetailDataSize太小返回buffer-too-small错误,但是cbSize错误返回invalid-buffer错误。

    SetupDiGetDriverInfoDetail 的帮助也明确指出 cbSize 和 DriverInfoDetailDataSize 不应该是相同的值(因为 ANYSIZE_ARRAY 只是定义为 1 作为占位符),因此您不应期望 Marshal.SizeOf 与您的故意超大结构。

    补充修正:

    您的 InfFilename 成员也是错误的长度 - 与 SETUPAPI.H 中的结构完全匹配的结构是:

        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Unicode)]
        internal struct SP_DRVINFO_DETAIL_DATA
        {
            public Int32 cbSize;
            public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
            public Int32 CompatIDsOffset;
            public Int32 CompatIDsLength;
            public IntPtr Reserved;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public String SectionName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public String InfFileName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public String DrvDescription;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
            public String HardwareID;
        };
    

    这在 ANSI 和 UNICODE 版本中都给出了正确的长度。但是,您不想按原样使用它,因为您需要更长的 HardwareID,因此您必须调整它的长度,然后使用 Marshal.SizeOf 为直接插入 cbSize 提供错误的值。

    【讨论】:

      【解决方案2】:

      函数声明错误,第二个和第三个参数由ref传递。解释“无效缓冲区”,API 需要一个指针。小心 Pack,它在 32 位操作系统上只有 1 个。确保将平台目标设置为 x86。您应该首先测量所需的结构尺寸。做起来很棘手,把 HardwareID 做得又好又大,不要节俭并扔掉 16K。

      【讨论】:

      • SetupAPI 的结构在 32 位版本上是 1 字节压缩的,在 64 位版本上是 8 字节压缩的。这个结构的 ANSI 版本的标准大小是奇数字节,这是一个很好的想法,可以知道有多少“默认打包”正在发生。但你是对的,其他两个 args 应该是 ref。
      • Win32 32/64 位版本的这种对齐变化是否适用于 API 的整个表面区域?
      • @David - 不,这很不寻常。在 SDK 包含目录中搜索 pshpack1 和 pshpack4 的异常情况。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      相关资源
      最近更新 更多