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

我有一个代码,在Windows XP上使用SetupAPI枚举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

任何想法有什么不对?

问题在于你的原始代码:当需要的属性不存在(或者当它的数据无效时,是的,他们已经懒惰地选择一个适当的错误代码), 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将会失败(并且你将会在那里管理错误),但是你经常能够读取值并且你的代码将会顺利运行。