What is the default version of the shell common controls?

Date:April 12, 2007 / year-entry #129
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20070412-00/?p=27263
Comments:    14
Summary:It depends on what you mean by default. As we saw earlier, the convention for Windows header files is that if you don't specify a particular version, then you get the most recent version. The shell common controls header file follows this convention, so if you include the Windows XP version of commctrl.h, you get functions,...

It depends on what you mean by default.

As we saw earlier, the convention for Windows header files is that if you don't specify a particular version, then you get the most recent version. The shell common controls header file follows this convention, so if you include the Windows XP version of commctrl.h, you get functions, messages, and structures designed for use with version 6 of the common controls. (And functions, messages, and structures may not work with version 5 of the shell common controls due to changes in structure sizes, for example.) So from the Windows XP Platform SDK header file's point of view, the default version of the shell common controls is version 6.

On the other hand, there's the question of what version of the shell common controls you actually get at run time. Prior to Windows XP, the answer was simple: You got the most recent version installed on the machine.

With Windows XP, however, the rules changed. The visuals team wanted to do something more ambitious with the common controls, but the compatibility constraints also created significant risk. The solution was to use side-by-side assemblies.

For compatibility, if a program didn't specify what version of the shell common controls it wanted, it got version 5.82, which was carefully designed for extremely high compatibility with the previous version, 5.81, which came with Windows 2000 and Windows Me. Now, version 5.82 is not completely identical to 5.81, because it also needs to interoperate with version 6. More on this later.

If a program wanted to use version 6 of the common controls, it had to say so explicitly in a manifest. (What we on the shell team informally call a "v6 manifest".) That way, only programs that asked for the new behavior got it. The theory being that if you asked for the new behavior, you presumably tested your program against version 6 of the common controls to verify that it behaves as you expected. This freed up the visuals team to make more substantial changes to the common controls without having to worry about some old program that relied on some strange undocumented behavior of the common controls. That old program would get version 5.82, which was designed for high compatibility.

Now, on that interoperability thing. There are places where the common controls library creates an object which you can then use with other common controls. For example, you can create an image list with ImageList_Create and then use that image list in a list view or tree view. Care had to be taken so that an image list created by version 5 of the common controls (a "v5 image list") could be used by a list view created by version 6 (a "v6 list view"), or conversely that a v6 image list could be used in a v5 list view. This sort of cross-version image list usage is actually quite common: Any application that calls Shell_GetImageLists (or its old-fashioned equivalent, SHGetFileInfo with the SHGFI_SYSICONINDEX flag) will get a v6 image list. If that application uses version 5 of the common controls (because it doesn't have a v6 manifest), then it will find itself using a v6 image list inside a v5 list view. Since each DLL has its own manifest, you can quickly find yourself in a case where there is a hodgepodge of v5 and v6 components all inside a single process, and they all have to work with each other.

Another example of this cross-version interoperability is the HPROPSHEETPAGE. Property sheet pages created with CreatePropSheetPage from one version of the shell common controls had to work with the PropertySheet function of the other version. This happens a lot with shell property sheet extensions. The shell namespace will ask the shell extensions to provide their custom property sheets, and all the ones written for Windows 2000 will hand back a v5 HPROPSHEETPAGE. But Explorer is going to display that property sheet with the v6 PropertySheet function. That v5 property sheet page had better work even when hosted inside a v6 property sheet.

Okay, but back to the original problem. If you don't specify what version of the header file you want, then you get the latest version (version 6 if you got the header file from the Windows XP Platform SDK). On the other hand, if you don't specify what version of the DLL you want, you get version 5.82, the compatible version of the DLL. Yes, this is a mismatch. Be on the lookout. This is what happens when a header file convention is at odds with a compatibility decision.


Comments (14)
  1. star me says:

    Meow.

  2. Ivo says:

    Is 6 supposed to be backwards-compatible with 5.82? I’ve had problems with using 5.82 structures with 6. It is understandable if it isn’t, since I need a manifest to get 6.

    Also, what’s the common controls version in Vista? Is it still 6?

  3. Jack Mathews says:

    By the way, I have to applaud the plunge you guys took regarding using SxS dlls for v5 vs. v6.  I especially respect the “isolation aware” stuff, as it allowed DLL’s in our tools to use v6 features, while letting us take our time on transitioning everything else to v6.

    I have to wonder, management-wise, how hard of a problem was the v5/v6 interop?  Was it something that really manifested as an issue late in development, or was the full scope pretty much known at the beginning?

    [v5/v6 interop was a huge undertaking. Your last question presents a false dichotomy. We knew up front that it would be a lot of work, but that doesn’t mean we understood the full scope up front. Do you ever know the full scope of a large undertaking before you begin? There are always unexpected problems that arise. -Raymond]
  4. Jack Mathews says:

    [v5/v6 interop was a huge undertaking. Your last question presents a false dichotomy. We knew up front that it would be a lot of work, but that doesn’t mean we understood the full scope up front. Do you ever know the full scope of a large undertaking before you begin? There are always unexpected problems that arise. -Raymond]

    Oh, I get that, I was just curious the level of planning that goes into an undertaking like this.  Like was it “well, we’ll need some interop” or was it down to the nitty gritty of “property pages will need to be cross compatible” ?  Also, was the dll-isolation-support planned from the get-go, so something that came of incompatibilities after implementation began?

    To me, it could just be an interesting case-study into planning-and-consequences of things at Microsoft.  And since this is relatively recent, it seems a bit more relevant given the maturity of the platform as compared to design decisions on Win16 or Win32.  I’m not trying to grill you, but it seems to be one of the more impressive and risky gambits given the huge size of windows, and a peephole as to how it was pulled off so well could be a decent learning experience.

    [I can’t tell whether you’re asking me to write up the case study or you’re just speculating out loud. -Raymond]
  5. Dom says:

    [I can’t tell whether you’re asking me to write up the case study or you’re just speculating out loud. -Raymond]

    If there is a case study in the offing that would be worth the price of addmission.

  6. Ross Bemrose says:

    If there is a case study in the offing that would be worth the price of addmission.

    Of course, when the price of admission is nothing, anything at all (including nothing itself) is worth the price of admission… usually considerably more.

  7. Victor says:

    I use SysInternal/Microsoft ‘s listdll to check which dll is actually loaded at runtime.

  8. Jack Mathews says:

    [I can’t tell whether you’re asking me to write up the case study or you’re just speculating out loud. -Raymond]

    Haha, I was asking _you_. :)

    [And people think I’m silly for thinking that comments are directed at me. It seems rather presumptuous, don’t you think, to expect somebody to write a white paper in their spare time just because you asked them to? -Raymond]
  9. Daniel says:

    Raymond I’m sure he wasn’t asking you to write a white paper, he is,
    like myself, just curious about how things like this work.
     Unfortunatly there arn’t many people out there with this kind of
    knowledge!  Anyway just an idea for a future blog post if you feel
    so inclined :)

    [I don’t have the knowledge you’re talking about.
    I’d have to interview people. It’s not like I attend every meeting and
    read every spec. A white paper is a lot more work than a blog post.
    White papers take weeks to write, review, and approve. A blog post doesn’t even have to be true! -Raymond
    ]
  10. Norman Diamond says:

    I have enough spare time to write a white paper for free.  Of
    course the paper has to be white to start with.  Guess what colour
    it will be when I’m done.

    Anyway Jack Mathews was teasing you.  He even wrote “haha” when teasing.  I can’t believe I had to write this.

    [I read that haha as a taunt. Shows how much I know. -Raymond]
  11. Norman Diamond says:

    Speak of the devil.

    > The solution was to use side-by-side assemblies.

    "Some people, faced with a problem, say ‘I know what, I’ll use regular expressions.  Then they have two problems."

    s/regular expressions/side-by-side/g

    > you can quickly find yourself in a case where

    > there is a hodgepodge of v5 and v6 components

    > all inside a single process, and they all have

    > to work with each other

    Then maybe that’s the only case where they really work.  I do have to congratulate you on getting it working.

    DLL Hell .Net is worse than DLL Hell Classic.[*]

    [* Yeah this is the fourth time I’ve posted this in two days, but it’s still true.]

  12. Jack Mathews says:

    [And people think I’m silly for thinking that comments are directed at me. It seems rather presumptuous, don’t you think, to expect somebody to write a white paper in their spare time just because you asked them to? -Raymond]

    Well I’m not holding my breath, but I at least wanted the request out there.  At the very least, it may be something to expand on in further blog posts if you have the time.  I would hope I’m speaking for a decent amount of people that finds this sort of talk interesting.  Most of us don’t have the opportunity to work on projects with an impact on literally tens of millions of people.

    That’s actually one of the more interesting threads on this blog for me, is seeing the butterfly effect of a lot of seemingly small changes/change requests.  Most of the posts, though, are more in the vein of “we didn’t do this because,” so it’s a nice insight to see “we knew this would hurt, but we did it anyway.”

    [Plenty of people already write about stuff that happened. Not enough people write about stuff that didn’t happen. -Raymond]
  13. Jack Mathews says:

    > Anyway Jack Mathews was teasing you.  He even wrote "haha" when teasing.  I can’t believe I had to write this.

    I’m not teasing anyone.  I thought the reply was funny, because yeah, re-reading it did make it just seem like pointless out-loud speculation.

  14. cdecl says:

    What are the implications of using run-time linking with LoadLibrary (with and without manifest) to get comctl32? Because there’s no version number in LoadLibrary(TEXT(“COMCTL32.DLL”)).

    [You already answered your question. The manifest decides. This is a fusion question; you’ll have better luck asking the fusion folks. -Raymond]

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index