Проверьте, существует ли драйвер Windows для данного идентификатора устройства

Я пишу библиотеку Windows, используя C ++. Эта библиотека должна быть в состоянии проверить, установлен ли в системе драйвер устройства определенного устройства. Поэтому я ищу способ проверить, установлен ли драйвер для известного Идентификатор устройства.

До сих пор я нашел эту информацию:

SetupDiBuildDriverInfoList перечисляет доступные драйверы для данных устройств. Тем не менее, я должен предоставить больше, чем просто идентификатор устройства.

SetupDiGetClassDevs кажется, возвращает именно то, что мне нужно для вызова SetupDiBuildDriverInfoList, но он по-прежнему не принимает идентификатор устройства в качестве ввода. Может потребоваться GUID класса настройки / интерфейса устройства, но если я правильно понимаю, драйвер конкретного производителя не имеет такого GUID. Он также может использовать перечислитель PnP, о котором я не знаю достаточно, чтобы сказать, могу ли я каким-то образом его использовать. Или, наконец, это может занять Идентификатор экземпляра устройства — но не идентификатор устройства.

Очевидно, я хочу проверить наличие любого устройства такого же типа, поэтому запрос по идентификатору экземпляра устройства невозможен. Итак, вопрос заключается в следующем: как проверить, установлен ли драйвер для данного идентификатора устройства (или любой другой информации, которая может идентифицировать устройство; я предполагаю, что идентификатор устройства здесь подходит), используя функции API, которые я перечислил ( или любым другим способом)?

3

Решение

Вы можете преобразовать идентификатор устройства в список идентификаторов экземпляров устройства следующим образом:

#include <Windows.h>
#include <Cfgmgr32.h>
#include <SetupAPI.h>
#include <stdio.h>

#pragma comment(lib, "setupapi.lib")

int main(int argc, char ** argv)
{
static wchar_t buffer[1024 * 1024];
wchar_t * ptr;
CONFIGRET result;

result = CM_Get_Device_ID_ListW(L"usb\\vid_0461&pid_4d15", buffer,
_countof(buffer), CM_GETIDLIST_FILTER_ENUMERATOR);

if (result != CR_SUCCESS)
{
printf("CM_Get_Device_ID_ListW: %u\n", result);
return 1;
}

ptr = buffer;

while (*ptr)
{
printf("%ws\n", ptr);
ptr += wcslen(ptr) + 1;
}

printf("Done\n");
return 0;
}

Или вот так:

int main(int argc, char ** argv)
{
HDEVINFO hdevinfo;

SP_DEVINFO_DATA devinfo;
wchar_t instance_id[4096];
DWORD n;

hdevinfo = SetupDiGetClassDevs(NULL, L"usb\\vid_0461&pid_4d15",
NULL, DIGCF_ALLCLASSES);

if (hdevinfo == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
printf("SetupDiGetClassDevs: %u\n", err);
return 1;
}

for (n = 0;; n++)
{
devinfo.cbSize = sizeof(devinfo);
if (!SetupDiEnumDeviceInfo(hdevinfo, n, &devinfo))
{
DWORD err = GetLastError();
printf("SetupDiEnumDeviceInfo: %u\n", err);
break;
}

if (!SetupDiGetDeviceInstanceId(hdevinfo, &devinfo,
instance_id, _countof(instance_id), NULL))
{
DWORD err = GetLastError();
printf("SetupDiGetDeviceInstanceId: %u\n", err);
}
else
{
printf("DevicePath: %ws\n", instance_id);
}
}

return 0;
}

Первый пример кода использует более старый API, CM_Get_Device_ID_List.

Второй пример кода использует более новый API, SetupDiGetClassDevs, но обратите внимание, что возможность использовать идентификатор устройства вместо просто перечислителя не задокументирована. Это работает, но это не задокументировано.

В любом случае устройство не обязательно должно присутствовать в настоящее время, но оно должно быть установлено в определенный момент в прошлом.

Если вы не уверены в правильном формате идентификатора устройства, который вы хотите, вы можете перечислить все экземпляры устройства. (Идентификатор устройства — это просто идентификатор экземпляра устройства с удаленным идентификатором экземпляра, то есть, все, кроме последнего обратного слеша, кроме

В первом примере кода используйте CM_GETIDLIST_FILTER_NONE чтобы получить список всех экземпляров устройства.

Во втором примере кода передайте NULL вместо строки идентификатора устройства, чтобы получить список всех экземпляров устройства.

3

Другие решения

Ответ Гарри Джонстона приблизил меня, но мне пришлось добавить немного больше, чтобы это сработало. Магия, которой не хватало, заключалась в том, что мне пришлось позвонить обоим SetupDiEnumDeviceInfo а также SetupDiBuildDriverInfoList до SetupDiEnumDriverInfoW на самом деле сделал что-то полезное.

Вот полный пример (по модулю очистки), замените строку, переданную SetupDiGetClassDevsW соответствовать вашему собственному устройству. Для моего конкретного устройства это печатает

Driver found: description: USBXpress Device, MfgName: Silicon Labs, ProviderName: Silicon Laboratories Inc.

на ПК с установленным драйвером и

No driver found

на ПК (фактически на виртуальной машине) без установленного драйвера.

#include <Windows.h>
#include <SetupAPI.h>
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib, "setupapi.lib")

int main(int argc, char ** argv)
{
HDEVINFO hdevinfo = SetupDiGetClassDevsW(NULL, LR"(USB\VID_10C4&PID_EA61)",
NULL, DIGCF_ALLCLASSES);
if (hdevinfo == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
printf("SetupDiGetClassDevs: %u\n", err);
return 1;
}

SP_DEVINFO_DATA devinfo;
devinfo.cbSize = sizeof(devinfo);
if (!SetupDiEnumDeviceInfo(hdevinfo, 0, &devinfo))
{
DWORD err = GetLastError();
printf("SetupDiEnumDeviceInfo: %u %d\n", err, 0);
return 1;
}

if (!SetupDiBuildDriverInfoList(hdevinfo, &devinfo, SPDIT_COMPATDRIVER)) {
printf("error %d\n", GetLastError());
return 1;
}

SP_DRVINFO_DATA_W drvdata;
drvdata.cbSize = sizeof(SP_DRVINFO_DATA_W);
BOOL worked = SetupDiEnumDriverInfoW(hdevinfo, &devinfo, SPDIT_COMPATDRIVER,
0, &drvdata);
if (worked) {
printf("Driver found: description: %ws, MfgName: %ws, ProviderName: %ws\n",
drvdata.Description, drvdata.MfgName, drvdata.ProviderName);
}
else {
DWORD err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS)
printf("No driver found\n");
else {
printf("SetupDiEnumDriverInfoW: %d", err);
return 1;
}
}
return 0;
}
1

По вопросам рекламы [email protected]