I have the Version Info in resources declared:
100 VERSIONINFO
FILEVERSION 1,0,0,2
PRODUCTVERSION 1,0,0,2
FILEOS VOS_NT
FILETYPE VFT_APP
{
BLOCK \"String
VerQueryValue()
cannot access version info from the original resource directly. You must make a copy of the resource in memory, then pass that memory to VerQueryValue()
instead. The reason is because VerQueryValue()
is designed to work with GetFileVersionInfo()
, which requires a user-allocated block of writable memory and performs certain fixups within that memory. Accessing the VS_FIXEDFILEINFO
struct does not require the fixups, but the memory block must still be writable. You cannot pass the original resource directly to VerQueryValue()
because it is read-only memory.
Try this instead:
HRSRC hResInfo;
DWORD dwSize;
HGLOBAL hResData;
LPVOID pRes, pResCopy;
UINT uLen;
VS_FIXEDFILEINFO *lpFfi;
hResInfo = FindResource(hInst, MAKEINTRESOURCE(100), RT_VERSION);
dwSize = SizeofResource(hInst, hResInfo);
hResData = LoadResource(hInst, hResInfo);
pRes = LockResource(hResData);
pResCopy = LocalAlloc(LMEM_FIXED, dwSize);
CopyMemory(pResCopy, pRes, dwSize);
FreeResource(hResData);
VerQueryValue(pResCopy, TEXT("\\"), (LPVOID*)&lpFfi, &uLen);
DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
DWORD dwLeftMost = HIWORD(dwFileVersionMS);
DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
DWORD dwSecondRight = HIWORD(dwFileVersionLS);
DWORD dwRightMost = LOWORD(dwFileVersionLS);
LocalFree(pResCopy);
UPDATE: this only works if you access the VS_FIXEDFILEINFO
struct only. If you need to access any other values, you must use GetFileVersionInfo()
. Per Raymond Chen's 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.
The above would create a heap corruption error message in debug mode, such as "Free Heap block b753e70 modified at b753ed4 after it was freed". Someone has posted this problem many years ago at http://microsoft.public.win32.programmer.kernel.narkive.com/mqoHgVwM/verqueryvalue-bug. It is still hapenning today. One can make the message disappear by making dwSize sufficiently large, such as multiplying it by 4.