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,
®_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, ®_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,
®_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,
®_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;
}