简体   繁体   中英

How to get FileDescription with VerQueryValue (getting the example to work)?

I am trying to get the various attributes of a file as seen in its "Details" tab with the WinAPI function VerQueryValue . I have successfully used this function to get the non-string version info with VS_FIXEDFILEINFO , but have not been able to get the example shown at the bottom of the functions documentation working.

The example isn't actually complete as it leaves out the use of the other related functions and the constructions of some buffers needed to use the function, so I've filled in the blanks the best I can and changed some of the in-between steps to use C++ SL since that's ultimately the language I need to use this in:

#include <iostream>
#include <iomanip>
#include "sstream"
#include "Windows.h"
#pragma comment(lib, "Version.lib")

int ReadOutFileDescriptions(std::wstring filename)
{
    LPBYTE lpBuffer = NULL;
    DWORD  verHandle, verSize = GetFileVersionInfoSize(filename.c_str(), &verHandle);

    if (verSize != NULL)
    {
        LPSTR verData = new char[verSize];

        if (GetFileVersionInfo(filename.c_str(), verHandle, verSize, verData))
        {
            UINT cbTranslate;

            // Structure used to store enumerated languages and code pages.
            struct LANGANDCODEPAGE {
                WORD wLanguage;
                WORD wCodePage;
            } *lpTranslate;

            // Read the list of languages and code pages.
            VerQueryValue(verData, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate);

            // Read the file description for each language and code page.
            for (ULONGLONG i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
            {
                std::wostringstream ss; ss << std::setfill(L'0') << std::hex;
                ss << std::setw(4) << lpTranslate[i].wLanguage;
                std::wstring langS = ss.str();
                ss.str(std::wstring());
                ss << std::setw(4) << lpTranslate[i].wCodePage;
                std::wstring codeS = ss.str();
                std::wstring subBlock = L"\\StringFileInfo\\" + langS + codeS + L"\\FileDescription";

                // Retrieve file description for language and code page "i".
                WCHAR descBuffer[50];
                LPVOID lpBuffer = &descBuffer;
                UINT bufferSize;
                VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);
                
                std::cout << bufferSize << '\n' << descBuffer; 
            }
        }

        delete[] verData;
    }

    return 0;
}

int main(int argc, char* argv[])
{
    ReadOutFileDescriptions(L"MyFile.exe");
    return 0;
}

I only have a little experience with WinAPI and its typedefs and my C is a bit rusty so I'm sure I'm just setting-up/using a buffer incorrectly or the like.

The printed buffer size is correct (the length of MyFile.exe 's description + 1 for the null character) so I know the function is getting the right value, but the actually value that gets printed is just a series of hexadecimal character, most likely an address.

What am I doing wrong?

EDIT (Answer): Thanks to @dxiv I was made aware that I did not fully understand how the "result" argument (lplpBuffer) of VerQueryValue was to be used, both internally and after the function returns.

Changing the end of the loop to the following achieves my desired result:

//WCHAR descBuffer[50] Not required, the function doesn't utilize a user made buffer
LPVOID lpBuffer;
UINT bufferSize;

VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize); // lpBuffer is reassigned here
std::wstring fileDescription((const TCHAR*)lpBuffer); // Create std::string from C style string (char*) that lpBuffer now points to
std::wcout << bufferSize << '\n' << fileDescription;
VerQueryValue(verData, subBlock.c_str(), &lpBuffer, &bufferSize);

std::cout << bufferSize << '\n' << descBuffer; 

Once VerQueryValue returns, lpBuffer no longer points to descBuffer , but to a different buffer assigned inside the call. The returned string is at (const TCHAR *)lpBuffer at that point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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