Как мне получить версию драйвера для Windows от C++?
Я ищу программный способ получить номер версии драйвера. Я хочу тот же номер, который диспетчер устройств показывает в свойствах драйвера для устройства.
Предыстория: у меня есть приложение, которое общается с некоторым пользовательским оборудованием. Драйвер устройства для нестандартного оборудования имеет известные ошибки до определенного номера версии. Я хочу, чтобы приложение проверило версию драйвера и предупредило пользователя, если ему нужно его обновить. Приложение работает на Windows XP и 7 и написано на C++.
Предыдущий хак, который я использовал, - это чтение файла.sys напрямую из system32/drivers и прямой поиск "FileVersion". Это плохо по многим причинам. В частности, кажется, что для Windows 7 необходимы права администратора.
Я знаю GUID класса и идентификатор оборудования (т. Е. "USB\VID_1234&PID_5678").
В настоящее время приложение использует SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces, а затем SetupDiGetDeviceInterfaceDetail для получения "DevicePath". Затем он вызывает CreateFile с этим путем для связи с драйвером.
Похоже, мне нужно откуда-то получить структуру SP_DRVINFO_DATA. Я пробовал различные функции из setupapi.h, такие как SetupDiGetDeviceInterfaceDetail. Вот некоторый код, который я пробовал, который терпит неудачу:
int main(void)
{
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_INTERFACE_DEVICE_DATA InterfaceDeviceData;
InterfaceDeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
// Cycle through all devices.
for (int i = 0; i < 32; i++)
{
if (!SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, (LPGUID)&GUID_DEVINTERFACE_USBSPI, i, &InterfaceDeviceData))
break;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
DWORD RequiredSize;
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, NULL, 0, &RequiredSize, NULL);
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, RequiredSize);
try
{
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL);
// Try to get the driver info. This part always fails with code
// 259 (ERROR_NO_MORE_ITEMS).
SP_DRVINFO_DATA drvInfo;
drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
if (!SetupDiEnumDriverInfo(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER, i, &drvInfo))
printf("error = %d\n", GetLastError());
printf("Driver version is %08x %08x\n", drvInfo.DriverVersion >> 32, drvInfo.DriverVersion & 0xffffffff);
}
catch(...)
{
HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
throw;
}
HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return 0;
}
Редактировать - мой обновленный код теперь выглядит так:
HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
// Cycle through all devices.
for (int i = 0; ; i++)
{
// Get the device info for this device
SP_DEVINFO_DATA devInfo;
devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiEnumDeviceInfo(devInfoSet, i, &devInfo))
break;
// Get the first info item for this driver
SP_DRVINFO_DATA drvInfo;
drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
if (!SetupDiEnumDriverInfo(devInfoSet, &devInfo, SPDIT_COMPATDRIVER, 0, &drvInfo))
printf("err - %d\n", GetLastError()); // Still fails with "no more items"
}
SetupDiDestroyDeviceInfoList(devInfoSet);
1 ответ
Вы неправильно используете i
в качестве индекса в SetupDiEnumDriverInfo
, Это должен быть внутренний цикл для каждого элемента информации о драйвере для каждого драйвера. В результате вам не удалось получить информацию о драйвере № 0 для устройства № 1.
Тем не менее, это не объясняет, почему информация № 0 для устройства № 0 дает сбой. Для этого вам нужно взглянуть на второй параметр SetupDiEnumDriverInfo
, Это SP_DEVINFO_DATA
структура для вашего устройства, но вы оставляете его установленным на NULL
, Это дает вам список драйверов, связанных с классом устройства, а не устройства. Т.е. это работает для мышей и флешек, у которых есть класс драйверов. Ваше устройство, вероятно, имеет драйвер, зависящий от поставщика, поэтому вам нужен драйвер для этого конкретного устройства.
Поскольку вы задали почти идентичный вопрос, я публикую здесь только ссылку на свой ответ:
Почему SetupDiEnumDriverInfo дает два номера версии для моего драйвера