Windows设备驱动判断

Posted fabric-summoner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows设备驱动判断相关的知识,希望对你有一定的参考价值。

Windows驱动

// type.h
#ifndef TYPE_H
#define TYPE_H

#include <setupapi.h>

struct wdi_device_info {
    struct wdi_device_info *next;
    unsigned short vid;
    unsigned short pid;
    BOOL is_composite;
    unsigned char mi;
    char* desc;
    char* driver;
    char* device_id;
    char* hardware_id;
    char* compatible_id;
    char* upper_filter;
    UINT64 driver_version;
};

struct wdi_options_create_list {
    BOOL list_all;
    BOOL list_hubs;
    BOOL trim_whitespaces;
};

#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define STR_BUFFER_SIZE             256
#define MAX_DESC_LENGTH             256
#define CR_SUCCESS                  0x00000000

#if defined(_MSC_VER)
#define safe_vsnprintf(buf, size, format, arg) _vsnprintf_s(buf, size, _TRUNCATE, format, arg)
#define safe_snprintf(buf, size, ...) _snprintf_s(buf, size, _TRUNCATE, __VA_ARGS__)
#else
#define safe_vsnprintf vsnprintf
#define safe_snprintf snprintf
#endif

#define MUTEX_START char mutex_name[10+sizeof(__FUNCTION__)]; HANDLE mutex;                    safe_snprintf(mutex_name, 10+sizeof(__FUNCTION__), "Global\%s", __FUNCTION__);            mutex = CreateMutexA(NULL, TRUE, mutex_name);                                              if (mutex == NULL) return WDI_ERROR_RESOURCE;                                              if (GetLastError() == ERROR_ALREADY_EXISTS) { CloseHandle(mutex); return WDI_ERROR_BUSY; }
#define PF_ERR          plog

#define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size)     WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)
#define PF_DECL_LIBRARY(name) HANDLE h##name = NULL
#define PF_LOAD_LIBRARY(name) h##name = LoadLibraryA(#name)
#define PF_DECL_LOAD_LIBRARY(name) HANDLE PF_LOAD_LIBRARY(name)
#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args
#define PF_DECL(proc) proc##_t pf##proc = NULL
#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc)
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_strdup _strdup
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))

typedef DWORD DEVNODE, DEVINST;
typedef DEVNODE *PDEVNODE, *PDEVINST;
typedef DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET;
typedef GUID  DEVPROPGUID, *PDEVPROPGUID;
typedef ULONG DEVPROPID,   *PDEVPROPID;

enum WindowsVersion {
    WINDOWS_UNDEFINED = -1,
    WINDOWS_UNSUPPORTED = 0,
    WINDOWS_7 = 0x61,
    WINDOWS_8 = 0x62,
    WINDOWS_8_1 = 0x63,
    WINDOWS_10_PREVIEW1 = 0x64,
    WINDOWS_10 = 0xA0,
    WINDOWS_MAX
};

enum wdi_error {
    WDI_SUCCESS = 0,
    WDI_ERROR_IO = -1,
    WDI_ERROR_INVALID_PARAM = -2,
    WDI_ERROR_ACCESS = -3,
    WDI_ERROR_NO_DEVICE = -4,
    WDI_ERROR_NOT_FOUND = -5,
    WDI_ERROR_BUSY = -6,
    WDI_ERROR_TIMEOUT = -7,
    WDI_ERROR_OVERFLOW = -8,
    WDI_ERROR_PENDING_INSTALLATION = -9,
    WDI_ERROR_INTERRUPTED = -10,
    WDI_ERROR_RESOURCE = -11,
    WDI_ERROR_NOT_SUPPORTED = -12,
    WDI_ERROR_EXISTS = -13,
    WDI_ERROR_USER_CANCEL = -14,
    WDI_ERROR_NEEDS_ADMIN = -15,
    WDI_ERROR_WOW64 = -16,
    WDI_ERROR_INF_SYNTAX = -17,
    WDI_ERROR_CAT_MISSING = -18,
    WDI_ERROR_UNSIGNED = -19,
    WDI_ERROR_OTHER = -99
};

int nWindowsVersion = WINDOWS_UNDEFINED;

static void free_di(struct wdi_device_info *di)
{
    if (di == NULL) {
        return;
    }
    safe_free(di->desc);
    safe_free(di->driver);
    safe_free(di->device_id);
    safe_free(di->hardware_id);
    safe_free(di->compatible_id);
    safe_free(di->upper_filter);
    safe_free(di);
}


int  wdi_destroy_list(struct wdi_device_info* list)
{
    struct wdi_device_info *tmp;

    MUTEX_START;

    while(list != NULL) {
        tmp = list;
        list = list->next;
        free_di(tmp);
    }
    CloseHandle(mutex);
    return WDI_SUCCESS;
}

struct wdi_device_info *device, *devlist = NULL;
struct wdi_options_create_list cl_options = { 0 };
HMENU hMenuOptions;
#define IDM_IGNOREHUBS                  40009
BOOL create_device = FALSE;

static __inline char* wchar_to_utf8(const wchar_t* wstr)
{
    int size = 0;
    char* str = NULL;

    // Find out the size we need to allocate for our converted string
    size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
    if (size <= 1)	// An empty string would be size 1
        return NULL;

    if ((str = (char*)calloc(size, 1)) == NULL)
        return NULL;

    if (wchar_to_utf8_no_alloc(wstr, str, size) != size) {
        sfree(str);
        return NULL;
    }

    return str;
}
static const DEVPROPKEY DEVPKEY_Device_BusReportedDeviceDesc = {
    { 0x540b947e, 0x8b40, 0x45bc, {0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2} }, 4 };

typedef ULONG DEVPROPTYPE, *PDEVPROPTYPE;

#define safe_swprintf _snwprintf
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)

#endif // TYPE_H

#include "type.h"

bool Widget::isDevConnected(wdi_device_info **list, wdi_options_create_list *options)
{
    bool b = false;  // true:usb设备连接正常   false:usb设备驱动未安装
    DWORD size, reg_type;
    HDEVINFO dev_info;
    SP_DEVINFO_DATA dev_info_data;
    HKEY key;
    char strbuf[STR_BUFFER_SIZE], drv_version[] = "xxxxx.xxxxx.xxxxx.xxxxx";
    struct wdi_device_info *start = NULL, *device_info = NULL;
    const char* usbhub_name[] = { "usbhub", "usbhub3", "usb3hub", "nusb3hub", "rusb3hub", "flxhcih", "tihub3",
                                  "etronhub3", "viahub3", "asmthub3", "iusb3hub", "vusb3hub", "amdhub30", "vhhub" };
    const char usbccgp_name[] = "usbccgp";
    BOOL is_hub;

    *list = NULL;

    // List all connected USB devices
    dev_info = SetupDiGetClassDevsA(NULL, "USB", NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);

    // Find the ones that are driverless
    for (int i = 0; ; i++)
    {
        // Free any invalid previously allocated struct 
        free_di(device_info);

        dev_info_data.cbSize = sizeof(dev_info_data);   // sizeof(dev_info_data)在不同电脑返回不同值(28,32)
        if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data))
        {
            b = true;
            break;
        }

        // Allocate a driver_info struct to store our data  
        device_info = (struct wdi_device_info*)calloc(1, sizeof(struct wdi_device_info));
        if (device_info == NULL)
        {
            wdi_destroy_list(start);
            SetupDiDestroyDeviceInfoList(dev_info);
        }

        // SPDRP_DRIVER seems to do a better job at detecting driverless devices than
        // SPDRP_INSTALL_STATE
        drv_version[0] = 0;
        if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER,
                                              &reg_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size))
        {
            if ((options == NULL) || (!options -> list_all))
            {
                continue;
            }

            // While we have the driver key, pick up the driver version
            key = SetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ);
            size = sizeof(drv_version);
            if (key != INVALID_HANDLE_VALUE)
            {
                RegQueryValueExA(key, "DriverVersion", NULL, &reg_type, (BYTE*)drv_version, &size);
            }
        }

        // Eliminate USB hubs by checking the driver string  
        strbuf[0] = 0;
        if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_SERVICE,
                                               &reg_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size))
        {
            device_info -> driver = NULL;
        }
        else
        {
            device_info -> driver = safe_strdup(strbuf);
        }
        is_hub = FALSE;
        for (int j = 0; j < ARRAYSIZE(usbhub_name); j++)
        {
            if (safe_stricmp(strbuf, usbhub_name[j]) == 0)
            {
                is_hub = TRUE;
                break;
            }
        }
        if (is_hub && ((options == NULL) || (!options -> list_hubs)))
        {
            continue;
        }
        // Also eliminate composite devices parent drivers, as replacing these drivers 
        if (safe_stricmp(strbuf, usbccgp_name) == 0)
        {
            if ((options == NULL) || (!options -> list_hubs))
            {
                continue;
            }
        }

        // Retrieve the first hardware ID 
        if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID,
                                              &reg_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size))
        {
            b = false;
            break;
        }
        else
        {
            strbuf[0] = 0;
        }
    }

    return b;
}
if (devlist != NULL)
{
    wdi_destroy_list(devlist);
}
cl_options.trim_whitespaces = TRUE;
bool ret;
ret = isDevConnected(&devlist, &cl_options);
if(ret)
{
    // 驱动正常
}
else
{
    // 设备连接但是驱动未安装
}

以上是关于Windows设备驱动判断的主要内容,如果未能解决你的问题,请参考以下文章

Windows 10连接到蓝牙经典设备而不进行配对

iOS判断判断设备类型信息

利用PHP判断iPhoneiPadAndroidPC设备

javascript常用代码片段

PHP判断iPhoneiPadAndroidPC设备的方法

UWP 区分设备类型