我有一个代码,在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
将会失败(并且你将会在那里管理错误),但是你经常能够读取值并且你的代码将会顺利运行。