如何从C++中获取Windows上的驱动版本?

问题描述 投票:4回答:2

我正在寻找一种程序化的方法来获取驱动程序的版本号。我想要一个和设备管理器在设备的驱动程序属性中显示的一样的版本号。

背景:我有一个应用程序,它与一些自定义硬件对话。我有一个应用程序可以和一些定制的硬件对话 自定义硬件的设备驱动程序在某个版本号之前有已知的错误。我想让应用程序检查驱动程序的版本,并警告用户是否需要更新它。该应用程序运行在Windows XP和7上,用C++编写。

我之前使用的一个黑客是直接从system32drivers中读取.sys文件,并直接搜索 "FileVersion"。这是很糟糕的,原因很多。尤其是在Windows7上似乎需要管理员权限。

我知道类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);
c++ windows driver
2个回答
3
投票

你错误地重用了 i 作为指数 SetupDiEnumDriverInfo. 这应该是每个驱动的每个驱动信息元素的内部循环。结果,你没有检索到设备#1的驱动信息#0。

不过,这还是不能解释为什么设备#0的信息#0会失败。对于这个问题,你必须看一看 SetupDiEnumDriverInfo. 这是一个 SP_DEVINFO_DATA 结构的设备,但你把它设置为 NULL. 这可以得到与设备类别相关的驱动程序列表,而不是设备。例如,这适用于鼠标和U盘,它们有类驱动程序。您的设备可能有一个供应商特定的驱动程序,所以您需要该特定设备的驱动程序。


0
投票

由于您问了一个几乎相同的问题,我在这里只贴出了我的答案的链接。

为什么SetupDiEnumDriverInfo给我的驱动程序提供了两个版本号?

© www.soinside.com 2019 - 2024. All rights reserved.