简体   繁体   English

如何从 C++ 获取 Windows 上的驱动程序版本

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

I'm looking for a programmatic way to get the version number of a driver.我正在寻找一种编程方式来获取驱动程序的版本号。 I want the same number that device manager shows in the driver properties for a device.我想要与设备管理器在设备的驱动程序属性中显示的数字相同的数字。

Background: I have an application that talks to some custom hardware.背景:我有一个与一些自定义硬件对话的应用程序。 The device driver for the custom hardware has known bugs before a certain version number.自定义硬件的设备驱动程序在某个版本号之前存在已知错误。 I want the application to check the driver version and warn the user if they need to update it.我希望应用程序检查驱动程序版本并警告用户是否需要更新它。 The application runs on Windows XP and 7 and is written in C++.该应用程序在 Windows XP 和 7 上运行,并用 C++ 编写。

A previous hack I used was to read the .sys file directly from system32/drivers and search for "FileVersion" directly.我以前使用的一个技巧是直接从 system32/drivers 读取 .sys 文件并直接搜索“FileVersion”。 This is bad for many reasons.这很糟糕,原因有很多。 In particular it seems to need admin privileges on Windows 7.特别是它似乎需要 Windows 7 的管理员权限。

I know the class GUID and the hardware ID (ie "USB\\VID_1234&PID_5678").我知道类 GUID 和硬件 ID(即“USB\\VID_1234&PID_5678”)。

The application currently uses SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces and then SetupDiGetDeviceInterfaceDetail to get the "DevicePath".该应用程序当前使用 SetupDiGetClassDevs、SetupDiEnumDeviceInterfaces 和 SetupDiGetDeviceInterfaceDetail 来获取“DevicePath”。 It then calls CreateFile with that path to talk to the driver.然后它使用该路径调用 CreateFile 与驱动程序对话。

It looks like I need to get a SP_DRVINFO_DATA structure from somewhere.看起来我需要从某个地方获取 SP_DRVINFO_DATA 结构。 I've tried various functions from setupapi.h, such as SetupDiGetDeviceInterfaceDetail.我尝试了 setupapi.h 中的各种功能,例如 SetupDiGetDeviceInterfaceDetail。 Here's some code I've tried that fails:这是我尝试过的一些失败的代码:

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;
}

Edit - My updated code now looks like this:编辑- 我更新的代码现在看起来像这样:

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);

You're incorrectly reusing i as index in SetupDiEnumDriverInfo .您错误地将i重用为SetupDiEnumDriverInfo索引。 That should be an inner loop for each driver info element per driver.这应该是每个驱动程序的每个驱动程序信息元素的内部循环。 As a result, you fail to retrieve driver info #0 for device #1.因此,您无法检索设备 #1 的驱动程序信息 #0。

Still, that doesn't explain why info #0 for device #0 fails.尽管如此,这并不能解释为什么设备 #0 的信息 #0 失败。 For that, you have to look at the second parameter of SetupDiEnumDriverInfo .为此,您必须查看SetupDiEnumDriverInfo的第二个参数。 That is a SP_DEVINFO_DATA structure for your device, but you leave it set to NULL .这是您设备的SP_DEVINFO_DATA结构,但您将其设置为NULL That gets you the list of drivers associated with the device class, not the device.这将为您提供与设备类关联的驱动程序列表,而不是设备。 Ie that works for mice and USB sticks, which have class drivers.即适用于具有类驱动程序的鼠标和 USB 记忆棒。 Your device probably has a vendor-specific driver, so you need the driver for that specific device.您的设备可能具有特定于供应商的驱动程序,因此您需要该特定设备的驱动程序。

As you asked a nearly identical question I post only the link to my answer here:当你问了一个几乎相同的问题时,我只在这里发布了我的答案的链接:

Why does SetupDiEnumDriverInfo give two version numbers for my driver 为什么 SetupDiEnumDriverInfo 为我的驱动程序提供两个版本号

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM