Check if a Windows driver exists for a given Device ID

浪子不回头ぞ 提交于 2019-11-30 15:28:10

You can convert a device ID to a list of device instance IDs like this:

#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;
}

Or like this:

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;
}

The first code sample uses the older API, CM_Get_Device_ID_List.

The second code sample uses the newer API, SetupDiGetClassDevs, but note that the ability to use a device ID instead of just an enumerator isn't documented. It works, but it isn't documented.

In either case, the device does not have to be currently present, but it must have been installed at some point in the past.

If you aren't sure of the correct format for the device ID you want, you can list all device instances. (The device ID is just the device instance ID with the instance-specific ID removed, i.e., everything up to but excluding the last backslash.)

In the first code sample, use CM_GETIDLIST_FILTER_NONE to get a list of all device instances.

In the second code sample, pass NULL instead of the device ID string to get a list of all device instances.

Harry Johnston's answer brought me close, but I had to add a bit more to make it work. The magic bit that was missing was that I had to call both SetupDiEnumDeviceInfo and SetupDiBuildDriverInfoList before SetupDiEnumDriverInfoW actually did something useful.

Here is a complete (modulo cleanup) example, replace the string passed to SetupDiGetClassDevsW to match your own device. For my specific device it prints

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

on a PC with the driver installed and

No driver found

on a PC (actually VM) with no driver installed.

#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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!