SetupDiGetDeviceRegistryProperty:“传递给系统调用的数据区域太小”错误

时间:2014-01-15 09:04:17

标签: c windows winapi windows-xp setupapi

我有一个使用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;
        }
    }

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

任何想法有什么不对?

1 个答案:

答案 0 :(得分:3)

原始代码出现问题: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将失败(并且您将在那里管理错误),但通常您可以读取值并且代码将顺利运行。