The documentation for the VerQueryValue
function states that the first parameter is a “pointer to the buffer containing the version-information resource returned by the GetFileVersionInfo
function.” Some people, however, decide to bypass this step and pass a pointer to data that was obtained some other way, and then wonder why VerQueryValue
doesn’t work.
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.
(And it can’t even detect that the buffer is improperly formatted because there is no cbSize
parameter to the VerQueryValue
function that tells it how big the buffer is. Without that information, VerQueryValue
can’t check that, say, all the internal values are in range, since it doesn’t know what “out-of-range” is! Is a value of 4000 out of range? It would be if the buffer were only 3000 bytes long. But it would be okay if the buffer were 5000 bytes long. Since there is no size parameter, the the VerQueryValue
function is forced to assume that everything is okay.)
If it wasn’t obvious enough from the documentation that you can’t just pass a pointer to a version resource obtained “some other way”, it’s even more obvious once you see the format of 32-bit version resources. Notice that all strings are stored in Unicode. But if you call the ANSI version VerQueryValueA
to request a string, the function has to give you a pointer to an ANSI string. There is no ANSI version of the string in the raw version resource, so what can it possibly return? You can’t return a pointer to something that doesn’t exist. VerQueryValueA
needs to produce an ANSI string, and it does so from memory that GetFileVersionInfo
prepared when the resources were extracted.
That there is no cbSize
parameter to VerQueryValue
was a failure of the original design of the function, but a slightly more understandable one when you look at the original design of 16-bit version resources: Since 16-bit Windows didn’t have Unicode support, there was only one version of VerQueryValue
, and it operated on ANSI strings. The 16-bit version resource format used ANSI strings, so VerQueryValue
could just return a pointer into the raw version resource. No character set conversion was necessary, and therefore no need to reserve additional space as a string conversion buffer, no need for GetFileVersionInfo
to “prepare” a buffer so that VerQueryValue
could convert from one character set to another.
0 comments