vico
vico

Reputation: 18171

VerQueryValue in Windows10

I have moved from Win8 to Win10 with my VS2012 C++ project. I had no problem while using VerQueryValue function in Win8, but now I have error during debug:

Unhandled exception at 0x77C88F11 (ntdll.dll) in MyApp.exe: 0xC0000005: Access violation writing location 0x00AAC2DC.

I use sample code from MSDN:

CString GetVersionInfo(HMODULE hLib, CString csEntry)
{
    CString csRet;

    if (hLib == NULL)
        hLib = AfxGetResourceHandle();

    HRSRC hVersion = FindResource( hLib, 
        MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION );
    if (hVersion != NULL)
    {
        HGLOBAL hGlobal = LoadResource( hLib, hVersion ); 
        if ( hGlobal != NULL)  
        {  

            LPVOID versionInfo  = LockResource(hGlobal);  
            if (versionInfo != NULL)
            {
                DWORD vLen,langD;
                BOOL retVal;    

                LPVOID retbuf=NULL;

                static char fileEntry[256];

                sprintf(fileEntry,"\\VarFileInfo\\Translation");
                retVal = VerQueryValue(versionInfo,fileEntry,&retbuf,(UINT *)&vLen);
                if (retVal && vLen==4) 
                {
                    memcpy(&langD,retbuf,4);            
                    sprintf(fileEntry, "\\StringFileInfo\\%02X%02X%02X%02X\\%s",
                        (langD & 0xff00)>>8,langD & 0xff,(langD & 0xff000000)>>24, 
                        (langD & 0xff0000)>>16, csEntry);            
                }
                else 
                    sprintf(fileEntry, "\\StringFileInfo\\%04X04B0\\%s", 
                    GetUserDefaultLangID(), csEntry);

                if (VerQueryValue(versionInfo,fileEntry,&retbuf,(UINT *)&vLen)) 
                    csRet = (char*)retbuf;
            }
        }

        UnlockResource( hGlobal );  
        FreeResource( hGlobal );  
    }

    return csRet;
}

What might be problem?

Upvotes: 0

Views: 1232

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596277

You are directly accessing the version resource data instead of using GetFileVersionInfo(). As such, you cannot use VerQueryValue() to query localized values, you can query only the VS_FIXEDFILEINFO structure and nothing else. And even then, you cannot use the return value of LockResource() for that access, either. You must copy the resource data into your own read/write memory buffer before then accessing the structure.

The reason for this is because GetFileVersionInfo() performs data lookups and memory block allocations that VerQueryValue() uses internally. Raymond Chen explains this on his blog:

The first parameter to VerQueryValue really must be a buffer you obtained from GetFileVersionInfo

The documentation says that the first parameter to VerQueryValue must be a buffer returned by the GetFileVersionInfo function for a reason. The buffer returned by GetFileVersionInfo is an opaque data block specifically formatted so that VerQueryValue will work. You're not supposed to look inside that buffer, and you certainly can't try to "obtain the data some other way". Because if you do, VerQueryValue will look for something in a buffer that is not formatted in the manner the function expects.

That is why you are getting a crash - VerQueryValue() is trying to access memory that has not been setup properly.

If you are going to access the version resource directly, then you need to parse its data manually, do not use VerQueryValue() at all. You were lucky that your code never crashed before. You were operating in undefined behavior territory! Your luck has run out. You need to re-write the code to do the right thing.

Upvotes: 4

Related Questions