【问题标题】:Stack Corruption With SetupDiXxx structures使用 SetupDiXxx 结构的堆栈损坏
【发布时间】:2015-02-20 00:54:27
【问题描述】:

我在用于获取设备信息的结构方面遇到了一些问题。据我了解,正确设置 cbSize 有点棘手,因此 API 正在将数据写入超出预期的位置(导致堆栈损坏)。到目前为止,我有以下代码:

GUID guid;
HidD_GetHidGuid(&guid);

HDEVINFO info;
info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

SP_DEVINFO_DATA DeviceInfoData;

memset(&DeviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);


int deviceIndex = 0;
while (SetupDiEnumDeviceInfo(info, deviceIndex++, &DeviceInfoData))
{
    SP_INTERFACE_DEVICE_DATA data;
    data.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    int interfaceIndex = 0;


    while (SetupDiEnumDeviceInterfaces(info, &DeviceInfoData, &guid, interfaceIndex++, &data))
    {

        //https://msdn.microsoft.com/en-us/library/windows/hardware/ff551120%28v=vs.85%29.aspx
        //Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a NULLDeviceInterfaceDetailData pointer, 
        //a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize variable. In response to such a call, this function
        //returns the required buffer size at RequiredSize and fails with GetLastError returning ERROR_INSUFFICIENT_BUFFER.

        SP_DEVICE_INTERFACE_DETAIL_DATA interfaceData;
        interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        DWORD bufferSize = 0;
        SetupDiGetDeviceInterfaceDetail(info, &data, NULL, 0, &bufferSize, nullptr);

        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            //Call the function again
            SetupDiGetDeviceInterfaceDetail(info, &data, &interfaceData, bufferSize, NULL, &DeviceInfoData);

            DWORD error = GetLastError();
            if (error != ERROR_SUCCESS)
            {
                printf("Could not obtain device interface details. Error: %d \n", error);
            }
        }
    }

我得到的错误是:

    Run-Time Check Failure #2 - Stack around the variable 'DeviceInfoData' was corrupted.

虽然我已经看到 SP_INTERFACE_DEVICE_DATASP_DEVICE_INTERFACE_DETAIL_DATA 导致同样的错误

非常感谢任何帮助!

【问题讨论】:

  • 这不是错误,但是如果您要进行 memset 操作,我建议您直接使用 sizeof (DeviceInfoData) 即变量,因此如果它的类型发生变化,它仍然可以工作。你也可以试试SP_DEVINFO_DATA DeviceInfoData = {};
  • 好收获。是的,非常真实。谢谢!
  • 您在第一次调用时检索必要的缓冲区大小,但将其传递给第二次调用实际上并未分配该空间。你在向 API 撒谎说有多少可用空间,所以它覆盖堆栈真的不是 API 的错。

标签: c++ windows-8 device-driver hid


【解决方案1】:

您的interfaceData 缓冲区似乎太小了。

再次检查 the documentationDeviceInterfaceDetailData 参数到 SetupDiGetDeviceInterfaceDetail

【讨论】:

    【解决方案2】:

    如果你想获得更多关于驱动程序开发的信息,我推荐这本书USB Complete。我根据他们的解释解决了这个问题。问题如下:

    首先,获取缓冲区大小:

    SetupDiGetDeviceInterfaceDetail(info, &data, NULL, 0, &bufferSize, nullptr);
    

    然后,根据返回的大小使用 malloc 手动分配 PSP_DEVICE_INTERFACE_DETAIL_DATA 结构:

    PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceData;
    interfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    

    注意PSP_DEVICE_INTERFACE_DETAIL_DATA 前面的P。这是此 API 的 Microsoft 语义。它代表指针;查看文档时很容易错过的东西(如果你也错过了->

    SetupDiGetDeviceInterfaceDetail 函数返回整个结构的大小,因此您需要将其分配给该大小。我已经看到尝试增加大小直到错误消失的示例。这种方法是错误的……有很多原因。从SetupDiGetDeviceInterfaceDetail 获取大小,然后根据该大小分配整个PSP_DEVICE_INTERFACE_DETAIL_DATA 内存块。不要忘记将 cbSize 设置为结构体的大小SP_DEVICE_INTERFACE_DETAIL_DATA

    再次注意命名约定中的P,因为很容易误认sizeof(PSP_DEVICE_INTERFACE_DETAIL_DATA)

    【讨论】:

    • 严格来说,由于您查询的数据可能会在您检索大小之后和获取数据之前发生变化,因此您应该在第二次调用时检查 ERROR_INSUFFICIENT_BUFFER,并在必要时重新分配和循环。但是发生这种情况的风险非常低,以至于很多人都不会打扰。
    • 更重要的是,您显示的代码写入尚未分配的缓冲区!
    猜你喜欢
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多