Check if a Windows driver exists for the given device ID

I am writing a Windows library using C ++. This library should be able to check if the device driver for a specific device is installed on the system. So I'm looking for a way to check if a driver is installed for a known Device ID .

So far I have found this information:

SetupDiBuildDriverInfoList contains a list of available drivers for these devices. However, I have to provide more than just the device ID.

SetupDiGetClassDevs seems to return exactly what I need to call SetupDiBuildDriverInfoList, but still doesn't take the device ID as input. It can accept the GUID of the device / interface installation class, but if I understand it correctly, the manufacturer-specific driver does not have such a GUID. It can also accept a PnP enumerator, which I don't know enough to tell if I can somehow use it. Or finally, the device instance ID may be required - but not the device ID.

Obviously I want to test any device of the same type, so a query on the device instance id is not possible. So this begs the question: how to check if a driver is installed for a given device id (or any other information that can identify a device, I assume the device id is the right thing here) using the API functions I listed (or any other way) ?

+3


source to share


1 answer


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

#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 example uses the older API, CM_Get_Device_ID_List .



The second code example uses a new API, SetupDiGetClassDevs , but note that the ability to use a device ID instead of just enumerating isnโ€™t documented. It works, but it is not documented.

In any case, the device should not be present now, but it should have been installed at some point in the past.

If you are unsure of the correct format for the device ID you want, you can list all the device instances. ( The device ID is only the device instance ID with the instance ID removed , i.e. everything before and without the last backslash.)

In your first code example, use CM_GETIDLIST_FILTER_NONE

to get a list of all device instances.

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

+2


source







All Articles