簡體   English   中英

如何從 C++ 獲取 Windows 上的驅動程序版本

[英]How do I get the version of a driver on Windows from C++

我正在尋找一種編程方式來獲取驅動程序的版本號。 我想要與設備管理器在設備的驅動程序屬性中顯示的數字相同的數字。

背景:我有一個與一些自定義硬件對話的應用程序。 自定義硬件的設備驅動程序在某個版本號之前存在已知錯誤。 我希望應用程序檢查驅動程序版本並警告用戶是否需要更新它。 該應用程序在 Windows XP 和 7 上運行,並用 C++ 編寫。

我以前使用的一個技巧是直接從 system32/drivers 讀取 .sys 文件並直接搜索“FileVersion”。 這很糟糕,原因有很多。 特別是它似乎需要 Windows 7 的管理員權限。

我知道類 GUID 和硬件 ID(即“USB\\VID_1234&PID_5678”)。

該應用程序當前使用 SetupDiGetClassDevs、SetupDiEnumDeviceInterfaces 和 SetupDiGetDeviceInterfaceDetail 來獲取“DevicePath”。 然后它使用該路徑調用 CreateFile 與驅動程序對話。

看起來我需要從某個地方獲取 SP_DRVINFO_DATA 結構。 我嘗試了 setupapi.h 中的各種功能,例如 SetupDiGetDeviceInterfaceDetail。 這是我嘗試過的一些失敗的代碼:

int main(void)
{
    HDEVINFO DeviceInfoSet = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    SP_INTERFACE_DEVICE_DATA InterfaceDeviceData;
    InterfaceDeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    // Cycle through all devices.
    for (int i = 0; i < 32; i++)
    {
        if (!SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, (LPGUID)&GUID_DEVINTERFACE_USBSPI, i, &InterfaceDeviceData))
            break;

        PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
        DWORD RequiredSize;

        SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, NULL, 0, &RequiredSize, NULL);
        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, RequiredSize); 
        try
        {
            DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &InterfaceDeviceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL);

            // Try to get the driver info. This part always fails with code 
            // 259 (ERROR_NO_MORE_ITEMS).
            SP_DRVINFO_DATA drvInfo;
            drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
            if (!SetupDiEnumDriverInfo(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER, i, &drvInfo))
                printf("error = %d\n", GetLastError());

            printf("Driver version is %08x %08x\n", drvInfo.DriverVersion >> 32, drvInfo.DriverVersion & 0xffffffff);
        }
        catch(...)
        {
            HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
            throw;
        }
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
    }

    SetupDiDestroyDeviceInfoList(DeviceInfoSet);

    return 0;
}

編輯- 我更新的代碼現在看起來像這樣:

HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBSPI, NULL, NULL,
                                          DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

// Cycle through all devices.
for (int i = 0; ; i++)
{
    // Get the device info for this device
    SP_DEVINFO_DATA devInfo;
    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    if (!SetupDiEnumDeviceInfo(devInfoSet, i, &devInfo))
        break;

    // Get the first info item for this driver
    SP_DRVINFO_DATA drvInfo;
    drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
    if (!SetupDiEnumDriverInfo(devInfoSet, &devInfo, SPDIT_COMPATDRIVER, 0, &drvInfo))
        printf("err - %d\n", GetLastError()); // Still fails with "no more items"
}

SetupDiDestroyDeviceInfoList(devInfoSet);

您錯誤地將i重用為SetupDiEnumDriverInfo索引。 這應該是每個驅動程序的每個驅動程序信息元素的內部循環。 因此,您無法檢索設備 #1 的驅動程序信息 #0。

盡管如此,這並不能解釋為什么設備 #0 的信息 #0 失敗。 為此,您必須查看SetupDiEnumDriverInfo的第二個參數。 這是您設備的SP_DEVINFO_DATA結構,但您將其設置為NULL 這將為您提供與設備類關聯的驅動程序列表,而不是設備。 即適用於具有類驅動程序的鼠標和 USB 記憶棒。 您的設備可能具有特定於供應商的驅動程序,因此您需要該特定設備的驅動程序。

當你問了一個幾乎相同的問題時,我只在這里發布了我的答案的鏈接:

為什么 SetupDiEnumDriverInfo 為我的驅動程序提供兩個版本號

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM