Billy ONeal
Billy ONeal

Reputation: 106609

Getting File Version Information fails -- But not for me

I am trying to get version information from a file. My code works perfectly for me, but fails on several others' machines. Because I can't reproduce the bug, I'm having quite a time finding the issue.

Does anyone see anything majorly wrong with this?

LPBYTE versionInformationBlock;
struct LANGANDCODEPAGE {
    WORD wLanguage;
    WORD wCodePage;
} *langBlockPointer;
UINT translationsCount;

void fileData::enumVersionInformationBlock()
{
    bits.set(VERSIONINFOCHECKED);
    disable64.disableFS(); //Shut down WOW64
    DWORD zero = 0;
    DWORD lengthOfVersionData =
    GetFileVersionInfoSize(getFileName().c_str(),&zero);
    if (!lengthOfVersionData)
    {
        disable64.enableFS();
        return;
    }
    versionInformationBlock = new BYTE[lengthOfVersionData];
    GetFileVersionInfo(getFileName().c_str(),zero,lengthOfVersionData,versionInformationBlock);
    VerQueryValue(versionInformationBlock,L"\\VarFileInfo\\Translation",(LPVOID*)&langBlockPointer,&translationsCount);
    translationsCount /= sizeof(struct LANGANDCODEPAGE);
    disable64.enableFS();
}
std::wstring fileData::getVersionInformationString(const std::wstring& str)
{
    if (!bits[VERSIONINFOCHECKED])
        enumVersionInformationBlock();
    if (!versionInformationBlock)
        return L"!VERINFO: NOT PE FILE!";
    LPCTSTR retString;
    UINT retStringLength;
    std::wstring result;
    static const wchar_t hexChars[] = L"0123456789ABCDEF";
    wchar_t hexLanguage[26] = L"\\StringFileInfo\\        \\";
    for( size_t idx = 0; idx < translationsCount; idx++ )
    {
        hexLanguage[16] = *(hexChars + ((langBlockPointer[idx].wLanguage >> 12) & 0x0F));
        hexLanguage[17] = *(hexChars + ((langBlockPointer[idx].wLanguage >> 8 ) & 0x0F));
        hexLanguage[18] = *(hexChars + ((langBlockPointer[idx].wLanguage >> 4 ) & 0x0F));
        hexLanguage[19] = *(hexChars + ( langBlockPointer[idx].wLanguage        & 0x0F));
        hexLanguage[20] = *(hexChars + ((langBlockPointer[idx].wCodePage >> 12) & 0x0F));
        hexLanguage[21] = *(hexChars + ((langBlockPointer[idx].wCodePage >> 8 ) & 0x0F));
        hexLanguage[22] = *(hexChars + ((langBlockPointer[idx].wCodePage >> 4 ) & 0x0F));
        hexLanguage[23] = *(hexChars + ( langBlockPointer[idx].wCodePage        & 0x0F));
        std::wstring targetResource(hexLanguage,25);
        targetResource.append(str);
        if (!VerQueryValue(versionInformationBlock,targetResource.c_str(),(LPVOID *)&retString,&retStringLength))
        {
            return std::wstring(L"!DOESN'T APPER TO EXIST IN FILE! ERROR: ").append(boost::lexical_cast<std::wstring>(GetLastError()));
        }
        retStringLength--;
        if (!result.empty())
            result.append(L" / ");
        std::wstring toAppend;
        toAppend.assign(retString,retStringLength);
        boost::algorithm::trim(toAppend);
        result.append(toAppend);
    }
    return result;
}
std::wstring fileData::getVerCompany()
{
    return getVersionInformationString(L"CompanyName");
}
~fileData()
{
    if (versionInformationBlock)
        delete [] versionInformationBlock;
};

What's really bugging me is that it isn't throwing any of my error messages... it keeps returning garbage.

Any ideas?

Billy3

Upvotes: 0

Views: 889

Answers (3)

Billy ONeal
Billy ONeal

Reputation: 106609

nvm. Seems Stackoverflow beats the heck out of me if it isn't answered.....

Billy3

Upvotes: 0

dirkgently
dirkgently

Reputation: 111316

Try the following:

  • Retrieve the reason for GetFileVersion's failure by using GetLastError
  • Tell us what OS it works on and what OS it doesn't
  • Check if GetFileVersionInfo succeeds or not (again GetLastError)
  • Read the Remarks section of the MSDN documentation of the abovementioned functions repeatedly and check if you are not missing something.

Upvotes: 4

Eric Melski
Eric Melski

Reputation: 16840

It looks like you are not checking for errors from many of the system calls you are using. For example, GetFileVersionInfo will return zero if there is an error getting the data, at which point you can call GetLastError to find out what the specific failure was. Likewise, GetFileVersionInfoSize will return zero if there is an error. It looks like you check for that failure but don't bother to log the system error code (again, use GetLastError to retrieve that value).

I suggest you add the error handling code for the system calls you are using. Most likely one of those is failing, and probably leaving a very meaningful error code for you to inspect with GetLastError.

Upvotes: 3

Related Questions