Reputation: 18171
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
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