【问题标题】:SetupDiGetDeviceRegistryProperty: "The data area passed to a system call is too small" errorSetupDiGetDeviceRegistryProperty:“传递给系统调用的数据区域太小”错误
【发布时间】:2026-01-11 09:55:02
【问题描述】:

我有一个使用 SetupAPI 在 Windows XP 上枚举 USB 设备的代码:

    HDEVINFO hDevInfo = SetupDiGetClassDevs( &_DEVINTERFACE_USB_DEVICE, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

    for (DWORD i = 0; ; ++i)
    {
        SP_DEVINFO_DATA devInfo;
        devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
        BOOL succ = SetupDiEnumDeviceInfo(hDevInfo, i, &devInfo);
        if (GetLastError() == ERROR_NO_MORE_ITEMS)
            break;
        if (!succ) continue;

        DWORD devClassPropRequiredSize = 0;
        succ = SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfo, SPDRP_COMPATIBLEIDS, NULL, NULL, 0, &devClassPropRequiredSize);
        if (!succ)
        {
           // This shouldn't happen!
           continue;
        }
    }

它曾经工作多年,但现在我从SetupDiGetDeviceRegistryProperty 得到FALSE,最后一个错误是“传递给系统调用的数据区域太小”。 看来我的调用参数对应这个函数的文档:http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967(v=vs.85).aspx

有什么想法吗?

【问题讨论】:

    标签: c windows winapi windows-xp setupapi


    【解决方案1】:

    问题出在您的原始代码中:SetupDiGetDeviceRegistryProperty 函数可能返回 FALSE(并将最后一个错误设置为 ERROR_INSUFFICIENT_BUFFER)当所需的属性不存在时(或者当它的数据无效时,是的,他们一直很懒惰选择一个正确的错误代码)所以你应该总是检查ERROR_INSUFFICIENT_BUFFER作为一个(不是这样的)特殊情况:

    DWORD devClassPropRequiredSize = 0;
    succ = SetupDiGetDeviceRegistryProperty(
        hDevInfo,
        &devInfo,
        SPDRP_COMPATIBLEIDS,
        NULL, 
        NULL, 
        0,
        &devClassPropRequiredSize);
    
    if (!succ) {
        if (ERROR_INSUFFICIENT_BUFFER == GetLastError() {
            // I may ignore this property or I may simply
            // go on, required size has been set in devClassPropRequiredSize
            // so next call should work as expected (or fail in a managed way).
        } else {
            continue; // Cannot read property size
        }
    }
    

    通常您在读取属性大小时可能会忽略此错误(如果devClassPropRequiredSize 仍然为零,您可以将其默认为适当的常量以获得最大允许长度)。如果无法读取属性,则下一次调用 SetupDiGetDeviceRegistryProperty 将失败(您将在那里管理错误)但通常您能够读取值并且您的代码将顺利运行。

    【讨论】:

      最近更新 更多