Windows設備驅動判斷

来源:https://www.cnblogs.com/fabric-summoner/archive/2020/07/15/13304534.html
-Advertisement-
Play Games

###Windows驅動 // type.h #ifndef TYPE_H #define TYPE_H #include <setupapi.h> struct wdi_device_info { struct wdi_device_info *next; unsigned short vid; ...


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
{
    // 設備連接但是驅動未安裝
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通常我們在項目開髮結束後向伺服器部署站點後,站點的動態頁面未能按照預期進行訪問,這很有可能是IIS沒有註冊動態頁面相應的“可執行文件”導致。這裡所說的動態頁面例如:訪問MVC視圖、WebAPI、aspx、ashx等,也就是頁面會對應有dll文件的情況。 動態頁面訪問失敗的幾種場景 ashx(一般處理 ...
  • 上次課程我們完成了項目基本的UI風格配置。 現在就開始進入我們的需求開發,我們先捋一下需求。 一、總體需求說明 項目背景第一篇文章已有介紹,我們回顧一下。 這是一個數據管理"工具類"的系統,計劃有三個核心功能: 1、數據查詢 通過界面配置相關連接字元串,查詢資料庫的表數據。 2、數據採集 配置相關模 ...
  • 大家好,我是良許。 有使用過 Linux 系統的小伙伴,肯定會使用過 cat 這個命令。當然,在 Linux 下,此貓非彼貓,這裡的 cat 並不代表貓,而是單詞 concatenate 的縮寫。 cat 命令是一個 Unix 或類 Unix 下文本的查看命令,同時也可以配合重定向實現合併與複製功能 ...
  • linux系統管理工具 shell腳本代碼 > #!/bin/bash#2020-07-14#system managemenu() {cat <<-EOF 系統管理工具 | 2020-7-14 | 網路 w 網卡信息收集 | ************************************ ...
  • 這個文章nice,https://www.cnblogs.com/ftl1012/p/ssh.htmlssh,secure shell縮寫,加密傳輸,比telnet明文傳輸更安全,旨在替代ftp和telnet連接linux伺服器預設埠22,伺服器端包含ssh服務和sftp服務,客戶端包含ssh連接... ...
  • centos7安裝配置tomcat9 第一步:下載tomcat9 鏈接:https://pan.baidu.com/s/1HC9YEU_bvm7D2s4gMo3q-Q 提取碼:uzv7 第二步:上傳到linux伺服器中 第三步:解壓 1.解壓到/usr/local/tomcat 2.查看 3.重命名 ...
  • centos7安裝配置jdk1.8 第一步:下載JDK 鏈接:https://pan.baidu.com/s/1sXWzvL9Tv7HIDxDPIw70SQ 提取碼:vpbi 第二步:將JDK8上傳到linux 在/home目錄下新建一個文件夾soft,以後壓縮包都放到這裡 第三步:解壓jdk-8u ...
  • 存儲器的主要功能是存儲程式和各種數據,並能在電腦運行過程中高速、自動地完成程式或數據的存取。存儲器單元實際上是時序邏輯電路的一種。按存儲器的使用類型可分為只讀存儲器(ROM)和隨機存取存儲器(RAM),兩者的功能有較大的區別,因此在描述上也有所不同。存儲的基礎部分分為ROM和RAM。 常見存儲器分 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...