Why does the VerQueryValue function give me the wrong file version number?


A customer was writing a test to verify that their patching system was working properly, but they found that even after the patch was installed, a call to VerQueryValue reported that the file was still the original version. Why was the VerQueryValue function reporting the wrong version?

Recall that the version resource is, well, a resource. And one of the things that happens with resources is that they can get redirected based on the language the user is running. When you ask for the resources of a language-neutral DLL, the loader redirects your request to the appropriate language-specific DLL. That way, if you're running on an English system, the resources come from the DLL with English resources, whereas if you're running on a German system, the resources come from the DLL with German resources.

The customer's patch updated only the language-neutral DLL (since it was a code fix that involved no resource changes). When the GetFileVersionInfo function loaded the DLL and asked for its resources, the loader redirected the request to the English satellite DLL.

To disable this redirection, you can use the GetFileVersionInfo function and don't pass the FILE_VER_GET_LOCALIZED flag or the FILE_VER_GET_NEUTRAL flag. Michael Kaplan covered this a few years ago. If you use the plain GetFileVersionInfo function, the version information that comes back is a blend of the language-neutral and the localized information: The binary version information comes from the language-neutral DLL, whereas the string version information comes from the localized DLL. The strings come from the localized DLL because you want the information like FileDescription to be something meaningful to the user.

It does mean, though, that if you are extracting version information for testing and verification purposes, you need to be mindful of where you are getting them from so that you get the values you expect.

Comments (9)
  1. John says:

    GetFileVersionInfo doesn't take any flags; you meant GetFileVersionInfoEx.

  2. Adam Rosenfield says:

    Is there any way that something similar could happen with executables instead of DLLs?  I recently filed a bug which I assumed was a bug in the Visual Studio Resource Compiler (connect.microsoft.com/…/resource-compiler-cannot-do-bit-shifting-multiplication-or-division) but apparently turned out to be a bug in Windows.

    I'm curious how Explorer is extracting the version information in that case and why it's getting it wrong, though I doubt I'll get an answer unless that bug just somehow gets assigned to Raymond.

    [The function doesn't care what the extension is. And the Resource Compiler arithmetic evaluator has always been limited to addition and subtraction. (It's not a bug; it's a design limitation.) This used to be documented somewhere but now I can't find it. -Raymond]
  3. Anonymous says:

    The Resource Compiler (rc.exe) is a part of Windows SDK, and according to rc.exe version info (6.1.7600.16385 – same as Windows 7 RTM), it is indeed a part of Windows :)

  4. Joshua says:

    Now that is interesting. The tools that build Windows are considered internally to be part of Windows.

  5. Adam Rosenfield says:

    [The function doesn't care what the extension is. -Raymond]

    So there's such a thing as a language-neutral EXE and language-specific EXEs for a specific localized executable? (Honest question, not trying to give you a hard time)

    [And the Resource Compiler arithmetic evaluator has always been limited to addition and subtraction. (It's not a bug; it's a design limitation.) This used to be documented somewhere but now I can't find it. -Raymond]

    Ok, well even if it's a design limitation, it should give a reasonable error instead of computing x*y ==> x.

    [The Resource Compiler (rc.exe) is a part of Windows SDK, and according to rc.exe version info (6.1.7600.16385 – same as Windows 7 RTM), it is indeed a part of Windows :) -Anonymous]

    I didn't realize that at the time I filed the bug, though I realize that now.  I can't seem to find any place to file bugs/feedback against Windows — Microsoft Connect only accepts feedback against certain products.

  6. chentiangemalc says:

    There's probably a good reason that feedback is only on paid support calls or selected products. I'm sorry but I deal with all the time people raising issues that are "bugs" in Windows / Office / IE when the real bug is they haven't read MSDN / TechNet documentation. That is not to say there are valid cases out there; I'm pretty sure there would be overwhelming amount of crap feedback from lazy people who don't take the time to understand how the product is documented to work. I see it all the time. But I can see it would be prohibitively expensive. That being said there are many people from MS on Twitter or through their blogs will provide excellent "free" support if you've done real research and provide something new

    & interesting to them, and they'll raise genuine bugs through their team. I've done this many times with great success. The blogs I talk about though are not Old New Thing, but rather the product area specific blogs.

  7. [Ok, well even if it's a design limitation, it should give a reasonable error instead of computing x*y ==> x.]

    Totally agree here.  The described behavior sounds like it acts really broken.  For example, the compiler's lexer accepted the syntax without complaining, when the lexical analyzer shouldn't have even accepted the "*" and "/" symbols in the first place if they weren't allowed.  OK, so you decide to reuse the lexer from the C compiler, which allows those symbols.  Fine, but the parser should have thrown it out with an error then.  The only reason I can see for not fixing it now is compatibility – if changing would break some existing RC files that depended on this buggy behavior…  But it could at least emit a warning!

    [I can't seem to find any place to file bugs/feedback against Windows — Microsoft Connect only accepts feedback against certain products.]

    I have had the same problem – both with Windows and Office.  I have found only two choices: (1) pay Microsoft and talk to technical support (heck no I'm not doing that to report YOUR bug!!!), or (2) the only thing I have found after much digging is an anonymous web form that doesn't even ask for contact information.  For all I know, the web form has been silently broken for the past 3 years, or goes into some Microsoft employee's mailbox who doesn't work here any more, etc.  There's no real sign of life with it.

    Connect is a much better system, in that it provides an organized way for the customer to be sure that (1) Microsoft received the message and a real person reviewed it, (2) Microsoft has a means to respond to the customer in case there are further questions.  It also provides a way for many customers to report the same issue and avoid duplicates, via the "upvote" system and comment system.

    That tells me that Microsoft isn't very interested in hearing feedback from customers who would like to see Microsoft products improved (bug fixes and maybe new features) unless those customers pay additional money to Microsoft just for the privilege of giving feedback in a back-and-forth manner.  I would like to think that Microsoft cares about their customers who want to see the products improved, but not even showing a willingness to listen to feedback in a constructive manner without the customer ponying up more money doesn't really inspire confidence.

    I'm not asking for free technical support.  All I'd like to see is a little respect shown if I spend 30 minutes or an hour of my time putting together a real bug report.  And it gives me a way to know if other customers commonly have the same issue, and provide further feedback on it.  A simple response message like "thanks for your report, we will look into it" and "we have confirmed this is a bug" or "can't reproduce" or whatever (like I already see on Connect) would be sufficient, and shows that Microsoft has become aware of the issue.  A simple anonymous web form "mailer" does NOT do the job!  I think it would provide a direct improvement in the quality of Microsoft's flagship products if they would just do this simple thing.

    Contrast this with the open source world, where a well thought out and written bug report is usually welcomed by the development community.  In comparison, the opaqueness/lack of transparency with Microsoft (though it has gotten much better in recent years) drives me nuts sometimes.

    OK I apologize and realize this is a bit of a rant not directly related to this blog post because of another commenter who pushed my buttons, but maybe I can hope that some of the employees who work at Microsoft who read this can pass it up the chain…

    [It didn't compute x*y=x. It computed x*y="x*y". Take a closer look at the output. -Raymond]
  8. @chentiangemalc:  It's certainly a valid concern and one I had thought of.  But:

    1.  How is using an anonymous web form a better solution to this problem than a more engaged site like Connect?  I don't see how it is, unless Microsoft really truly does ignore the entire lot of feedback sent via an anonymous web form like I suspect they might be doing.  Sending a short hand-written acknowledgement after reviewing the submission doesn't cost much.  Either they should kill the web form, or kill it and add the products to Connect.

    2.  With a site like Connect, others can upvote issues that are a real problem.  Microsoft can then pay more attention to the most upvoted issues.  This would be an actual improvement over the anonymous web form, which provides no such facilities (as far as I know) for handling duplicate issues.  These issues are either real bugs, or arguably documentation bugs if such a large mass of people fail to understand something that is by design.  Issues that don't get more attention are more likely to be user error (which the community can point out).  But I would caution against completely ignoring submissions that don't get much attention: I've submitted a bug for the .NET StreamReader class, which was acknowledged as a bug.  It never received any attention from anyone other than me.  But thank goodness it was a bug in the framework and not Win32, or they'd probably never acknowledge the issue and fix it eventually.

    3.  Incorrectly raising issues that are "bugs" in Windows, etc. would be an issue with Connect for Visual Studio as well.  I've certainly seen many developers who are too eager to blame someone else and not look inward at their own faults.  Yet somehow Visual Studio manages.  Why not Windows & Office?

    4.  Another thing I suspect someone might say is that the support cost would be refunded if it really is a bug.  How does this work?  It sounds like going to fight something in court where the judge is heavily biased in favor of the police.  Even clear proof might not be enough to convince a judge to rule completely in my favor.  And I'd imagine with Microsoft support that there is also heavy pressure in favor of NOT granting refunds for bug reporters, for the obvious financial reasons.  Why wouldn't there be?  I'm sure there are bean counters to make it so.  ("It wasn't a bug.  We think all 'buggy' behavior is by design!!")

    5.  Again, even mass market open source products like FireFox welcome bug fixes.  That said, they make you look for it – it took 6 clicks to get there from firefox.com: (1) About, (2) Participate, (3) See all the ways you can get involved, (4) Area of Interest, (5) hunt down bugs, (6) learn how to file bugs here.  I had to skip numerous pages offering me support, help from the community, ways to help the community, etc.  Finally, I arrive at a long page that describes how to write good bug reports with a big bold note at the top to use support options if you need support.  Then I have to register.  I would imagine this significantly cuts down on the garbage: most users I know who don't know computers well or are idiots and think everything is a "bug" are not going to find this system.  One could argue that Microsoft Connect is similarly buried so that only those with more experience who know to look for such a system will find it.

  9. Adam Rosenfield says:

    [It didn't compute x*y=x. It computed x*y="x*y". Take a closer look at the output. -Raymond]

    Ok, I did.  Using this resource script:

    #define MULT_TEST (3*4)

    #define DIV_TEST (20/4)

    #define LEFT_SHIFT_TEST (16<<1)

    #define RIGHT_SHIFT_TEST (16>>1)

    VS_VERSION_INFO VERSIONINFO

    FILEVERSION MULT_TEST,DIV_TEST,LEFT_SHIFT_TEST,RIGHT_SHIFT_TEST

    PRODUCTVERSION 1,0,0,1

    FILEFLAGSMASK 0x3fL

    #ifdef _DEBUG

    FILEFLAGS 0x1L

    #else

    FILEFLAGS 0x0L

    #endif

    FILEOS 0x40004L

    FILETYPE 0x1L

    FILESUBTYPE 0x0L

    […]

    The VS_FIXEDFILEINFO in the compiled .res file looks like this:

          dwSignature: 0xfeef04bd

       dwStrucVersion: 0x00010000

      dwFileVersionMS: 0x00030014

      dwFileVersionLS: 0x00100010

    dwProductVersionMS: 0x00010000

    dwProductVersionLS: 0x00000001

      dwFileFlagsMask: 0x0000003f

          dwFileFlags: 0x00000000

             dwFileOS: 0x00040004

           dwFileType: 0x00000001

        dwFileSubtype: 0x00000000

         dwFileDateMS: 0x00000000

         dwFileDateLS: 0x00000000

    So it seems to me that the resource compiler is translating 3*4 into 0x0003.

    [Oh, I thought you were using it as a resource identifier, not a version number. -Raymond]

Comments are closed.