0

I have searched high and low for it, could not find any documentation, I am able to get the DriverVersion as described Here. Creating and enumerating the device drives is working so there is no need to look there. The DriverVersion is a type of "DWORDLONG". I need to convert this to Human readable format like 20.xx.xx.xx. There ain't any documentation on MSDN, or anywhere I have searched.

Any help will be appreciated.

Example value of "DriverVersion" : 1688863374327808

Code snippet, if at all its required,

SP_DEVINFO_DATA devInfo;
                devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
                if (SetupDiEnumDeviceInfo(handle, 0, &devInfo))
                {   
                    if(SetupDiBuildDriverInfoList(handle,&devInfo,SPDIT_COMPATDRIVER))
                     {
                         SP_DRVINFO_DATA drvInfo;
                        drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
                            int i=0;
                        while(1)
                        {
                            try
                            {
                                if (SetupDiEnumDriverInfo(handle, &devInfo, SPDIT_COMPATDRIVER, i++, &drvInfo))
                                {
                                    cout<<"Version :"<<drvInfo.DriverVersion<<endl; // Need Human Readable version here.
                                }
                                else
                                    break;
                            }
                            catch(std::exception ex)
                            {
                                break;
                            }
                        }
                     }
                } 
Suraj S
  • 1,019
  • 7
  • 18

2 Answers2

2

You could use a ULARGE_INTEGER union, the HIWORD/LOWORD macros and string formatting utils like boost::format to do the following (untested code):

SP_DRVINFO_DATA driverInfoData;
ULARGE_INTEGER version;

version.QuadPart = driverInfoData.DriverVersion;

std::string versionStr = (boost::format("%s.%s.%s.%s")
    % HIWORD(version.HighPart)
    % LOWORD(version.HighPart)
    % HIWORD(version.LowPart)
    % LOWORD(version.LowPart)).str();

Following your code and to get rid of boost simply do:

std::cout << "Version: "
          << std::to_string(HIWORD(version.HighPart)) << "."
          << std::to_string(LOWORD(version.HighPart)) << "."
          << std::to_string(HIWORD(version.LowPart)) << "."
          << std::to_string(LOWORD(version.LowPart)) << std::endl;
Wum
  • 306
  • 1
  • 10
  • Still didn't test it but can it not be done natively without using any other libraries like boost? – Suraj S Feb 13 '18 at 15:10
  • Yes, of course. There are many ways to convert the numbers into strings, e.g. `std::stringstream` or `std::to_string`: http://www.cplusplus.com/articles/D9j2Nwbp/ – Wum Feb 13 '18 at 15:19
  • Awesome! Works as expected, Can you explain the logic of how those version strings are encoded to the DWORDLONG ? @Wum – Suraj S Feb 14 '18 at 03:00
  • `ULARGE_INTEGER` is a union that represents a 64-bit unsigned integer value. You assign `SP_DRVINFO_DATA.DriverVersion` to it which is a 64-bit unsigned integer as well. Using the macros `HIWORD`/`LOWORD` you retrieve the high-order/low-order word of the 32-bit data members `ULARGE_INTEGER.HighPart` and `ULARGE_INTEGER.LowPart` of your `ULARGE_INTEGER`. – Wum Feb 14 '18 at 09:54
  • Thanks a lot!, That helped – Suraj S Feb 14 '18 at 12:34
0

If anyone's interested in the Golang implementation, here you go.

highPart := uint32(drvInfo.DriverVersion >> 32)
lowPart := uint32(drvInfo.DriverVersion & 0xffffffff)
versionStr := fmt.Sprintf("%d.%d.%d.%d",
    uint16(highPart>>16),
    uint16(highPart),
    uint16(lowPart>>16),
    uint16(lowPart))
fmt.Printf("Version: %s\n", versionStr)
fortytwo
  • 491
  • 1
  • 5
  • 16