¿Cómo obtengo la versión de un controlador en Windows desde C ++?

Estoy buscando una forma programática de obtener el número de versión de un controlador. Quiero el mismo número que el administrador de dispositivos muestra en las propiedades del controlador para un dispositivo.

Antecedentes: Tengo una aplicación que habla con algún hardware personalizado. El controlador de dispositivo para el hardware personalizado tiene errores conocidos antes de un cierto número de versión. Quiero que la aplicación compruebe la versión del controlador y advierta al usuario si necesita actualizarla. La aplicación se ejecuta en Windows XP y 7 y está escrita en C ++.

Un truco anterior que utilicé fue leer el archivo .sys directamente desde system32 / drivers y buscar "FileVersion" directamente. Esto es malo por muchas razones. En particular, parece necesitar privilegios de administrador en Windows 7.

Conozco la clase GUID y el ID de hardware (es decir, "USB \ VID_1234 & PID_5678").

La aplicación actualmente utiliza SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces y luego SetupDiGetDeviceInterfaceDetail para obtener "DevicePath". Luego llama a CreateFile con esa ruta para hablar con el controlador.

Parece que necesito obtener una estructura SP_DRVINFO_DATA de algún lugar. He intentado varias funciones de setupapi.h, como SetupDiGetDeviceInterfaceDetail. Aquí hay un código que he probado que falla:

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

Editar - Mi código actualizado ahora se ve así:

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

Respuestas a la pregunta(1)

Su respuesta a la pregunta