zoukankan      html  css  js  c++  java
  • C语言判断windows USB设备驱动是否正常

    USB设备驱动在不同电脑有不同表现:正常;驱动显示感叹号,不能使用,我用如下代码判断

    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
    

    main.cpp

    bool bDevConnect(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) return different value(28, 32) in different computer
            dev_info_data.cbSize = 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;
    }
    
    int main()
    {
        if (devlist != NULL)
        {
            wdi_destroy_list(devlist);
        }
        cl_options.trim_whitespaces = TRUE;
        bool r;
        r = bDevConnect(&devlist, &cl_options);
        if(r)
        {
            // usb设备正常
        }
        else
        {
            // usb设备驱动未安装
        }
    
        return 0;
    }
    
  • 相关阅读:
    固态硬盘和机械硬盘的比较和SQLSERVER在两种硬盘上的性能差异
    带您理解SQLSERVER是如何执行一个查询的
    SQL Server 2000中的并行处理和执行计划中的位图运算符
    SQL2005解密已经被加密的存储过程
    使用SQLServer 2008的CDC功能实现数据变更捕获
    like语句百分号前置会使用到索引吗?
    再说一下表分区
    SQLSERVER中的元数据锁
    验证非法电话号码
    OpenCV 2.2版本号以上显示图片到 MFC 的 Picture Control 控件中
  • 原文地址:https://www.cnblogs.com/tjhd/p/13927450.html
Copyright © 2011-2022 走看看