Why doesn’t my program receive the WM_DWMSENDICONICTHUMBNAIL message when I ask for an iconic representation?


A customer was having trouble adding Windows 7 taskbar integration features to their application:

I'm trying to use the new Windows 7 taskbar integration features, but am running into a problem. I've made certain that my program has the DWMWA_FORCE_ICONIC_REPRESENTATION and DWMWA_HAS_ICONIC_BUTMAP DWMWA_HAS_ICONIC_BITMAP [corrected 8am] attributes set, yet I never receive a WM_DWMSENDICONICTHUMBNAIL message in my window procedure.

A member of the taskbar team invoked psychic powers:

Is your program running elevated by any chance? If so, then you need to add the WM_DWMSENDICONICTHUMBNAIL message to your UIPI message filter:

ChangeWindowMessageFilter(WM_DWMSENDICONICTHUMBNAIL, MSGFLT_ADD);

Psychic powers once again save the day.

That was it. Thanks!

Note that forcing someone to invoke psychic powers is a bad thing. It means that you withheld crucial information that somebody had to guess at. Here are some crucial pieces of information people tend to forget to mention:

  • "Oh, did I mention that my process is running elevated?"
  • "Oh, did I mention that my process is a service?"
  • "Oh, did I mention that my process is 32-bit, running on a 64-bit machine?"
  • "Oh, did I mention that I initialized COM as MTA?"
  • "Oh, did I mention that my process is impersonating another user?"
  • "Oh, did I mention that I'm running a version of the operating system different from Windows 7?" (or whatever the most current client operating system is)

Added: The reason those items above are crucial pieces of information is that all of them (except the last one) are "game-changers": If you do any of the things in the list, a whole bunch of rules change. It's like asking a question about traffic regulations and neglecting to mention that the other vehicle is a fire truck with its siren on. (And presumably when you chose to invoke any of those game-changing conditions, you were aware of the rules which applied to the new situation. Those rules are documented with the game-changing condition, not with the general description of a normally-functioning universe. Imagine if every physics book had the sentence "This rule does not apply to Superman" at the end of every paragraph.)

Comments (37)
  1. John says:

    Jennifer Lopez has an iconic butmap.

  2. Km says:

    Problem is, that requires the asking one to KNOW that a piece of information is relevant.

    I hope if you go to the doctor because you are coughing they are asking if you have tremors and fever and so on, before giving you a cure, and not simply saying “you should have mentioned”.

    So no. It’s your job to be psychic when helping others.. of course this is correct if helping clients is your job.

    [Basically, if there’s some way your program’s execution environment is different from “Running as normal user from the Start menu” then it’s relevant. -Raymond]
  3. Vilx- says:

    Nitpickers. Gotta love them. :P

    Though I have to say one thing – Windows has become SO complicated that it’s sometimes pretty difficult to figure out what the relevant information. For example, I have but a vague idea of what half of the list you gave is, let alone what implications it has. COM alone is such a hairy beast that it is no wonder people sometimes forget to tell something. Not because they wanted to withhold important information, or because they are lazy, but simply because they had no idea that some-seemingly-completely-unrelated-thing makes all the difference.

    This is especially true with copy-paste code from the Internet. Of course, one should always study the code and try to understand it as much as possible – but sometimes trying to understand it brings one to such deep waters that it’s much more efficient to just copy the line, check that it works, and forget about it – instead of spending two weeks studying the internals of COM interop marshalling or something.

    I’m not saying this is good. It’s a bad thing, no doubt about it. But it is understandable and forgivable.

  4. peterchen says:

    I agree that it’s hard to know what is relevant – but then, asking in a different way

    "Can you think of any reasons why I don’t receive message X"?

    at least seems more polite – and might help you think of some reasons for yourself.

  5. Magnus says:

    You should not need psychic powers to fill in what’s missing from the documentation either.

    In this case the documentation should say.

    Oh, if your process is elavated you must also do this to let the message trough.

    ( At least it’s not documented on this page: http://msdn.microsoft.com/en-us/library/aa969530(VS.85).aspx )

    [Except that the message filter isn’t specific to that message. It’s a general property of all messages. Should every window message have the Remark: “By default, UIPI blocks this message from being sent across processes of different integrity levels”? Should every class-defined message include the remark “Since class-defined messages are not marshalled, care must be taken when sending this message across processes”? Should it also mention other properties of messages, like “If this message is posted, then it is retrieved by the GetMessage or PeekMessage function. If it is sent, then the message is delivered directly to the window procedure and bypasses the message queue.”? (Or maybe there should just be a generic “Things you need to know about messages” page that every window message links to?) -Raymond]
  6. Magnus says:

    If the user is supposed to know all the details that are relevant for every question then yes, this info should be on every page in the documentation to.

  7. James Schend says:

    Vilx: that’s why I’d recommend starting new development in C#/.net. It’s just sooo much easier.

    (I had the same kind of culture shock coming from the Mac Classic API– which is very small and simple– to the Win32 API– which is large and complicated. I never really felt comfortable with it, just because I wasn’t "raised" on it. But .net turns that all around.)

  8. Henke37 says:

    I am all for a page just about windows messages. With my psychic powers, I estimate that there is in fact one, but it does not cover every single listed generic issue.

    The link on the other hand is overkill.

  9. waleri says:

    I guess it would be helpful if documentation for WM_DWMSENDICONICTHUMBNAIL mentioned the fact, that message may be filtered.

  10. Kyle S says:

    @waleri et al., I guess the documentation for WM_DWMSENDICONICTHUMBNAIL should also contain a copy of the C language reference, in case you encounter a syntax error when compiling code that sends that message.

    I don’t understand this "the documentation must contain everything" mindset.

  11. @everhaveabadday:

    When Windows unzips an archive, it creates all of the expanded files with the "Read & Execute" security attribute set.  Other programs may not.

    I’ve run into a similar problem before fairly often — when I unzip an archive with Cygwin’s ‘unzip’ executable, it does NOT create the expanded files as executable (they don’t have chmod +x as Cygwin sees it), so any .exes or .dlls in the archive will to load.

    The workaround for this is either to unzip the archive outside of Cygwin, or use the CYGWIN environment variable to tell Cygwin "Yes, I really want the files to be executable", e.g.

    CYGWIN=nontsec unzip foo.zip

    See also http://www.cygwin.com/ml/cygwin/2003-02/msg02181.html

  12. mikeb says:

    > There may be plenty of idiot programmers out there, but let’s not forget that programming and debugging can be a complex endeavor, and sometimes even the best of us can have a bad day. <<

    Hear, hear!

  13. Anonymous Coward says:

    Actually, if someone is using Windows 7, he should probably mention it (except in obvious cases such as this, where we’re talking about a new feature) since almost everyone is still using Windows XP.

  14. Billy O'Neal says:

    @Anonymous Coward:

    The new taskbar APIs are a Windows 7 specific feature, so talking about them sort of implies that the user is running 7.

  15. TKW says:

    DWMWA_HAS_ICONIC_B*I*TMAP

    [Thanks, fixed (sort-of). -Raymond]
  16. Zan Lynx says:

    I say the real problem here is running elevated at all.

    I’ve got MMO clients that launch as elevated so they can download updates. A better way would be to add game users to some kind of permissions group.

    There are ridiculous bits of software that think they need full Administrator privileges and from this question above, I see that the authors of such programs don’t even know what they’re doing!

    From a Unix background, you don’t write setuid code unless you understand the dynamic loader, environment variables, and check every return code from every system function and handle it properly!

  17. KenW says:

    @Km: Not quite right.

    What Raymond is discussing is like a *doctor* going to his own personal physician and saying "This hurts." As a professional in the same line of work, he should know that more information would be helpful, and provide it without having to be asked.

    In the same way, the person asking the question of tech support is *supposed to be* a programmer (otherwise, why ask technical questions about programming), and as a fellow professional they should know that running elevated makes a difference on current versions of Windows. If they don’t, they should not be worrying about Win7 taskbar integration; they should be concentrating on recording what they’re doing as VBA macros in Office instead.

  18. Matt says:

    Sure, you should provide all the relevant information you can, when asking for help or reporting a problem.

    But within reason — if you include tons of stuff that the recipient doesn’t think is relevant, you may fall victim to TLDR syndrome.

    Meanwhile, while forcing people to use psychic powers is bad, I submit that if you design a piece of software or component that is fragile in a certain way such that (a) people often get confused about it and (b) they often ask you for help and (c) they often omit key details and (d) you can often psychically guess what’s wrong… um, maybe you share some of the blame too.

    [The thing that most of the “psychic details” have in common is that they radically change the rules of Win32. -Raymond]
  19. me says:

    I must be honest.  I am pretty good at this sort of thing.  I would have made the EXACT same mistake.  The docs do not speak to it at all.  This would have been a set my glasses down on my desk with a ‘how would I know it did that?’

    The documentation is deficient here in some way.

  20. everhaveabadday says:

    >> In the same way, the person asking the question of tech support is *supposed to be* a programmer (otherwise, why ask technical questions about programming), and as a fellow professional they should know that running elevated makes a difference on current versions of Windows. If they don’t, they should not be worrying about Win7 taskbar integration; they should be concentrating on recording what they’re doing as VBA macros in Office instead.

    ————

    That last part is a little harsh.  Clearly in this case if the person had thought of elevation and UIPI he would’ve probably been able to fix the problem himself.  Even the best of us sometimes don’t remember or realize all the relevant details to an issue, which is why Raymond helpfully provided that checklist at the end of his blog entry as a good starting point.

    It’s especially clear in this case that the person was not familiar with the Win7 Taskbar integration APIs, so naturally his assumption was that he’s made some stupid mistake in his usage of those specific APIs/Windows messages.  It’s understandable that he would be focusing on that instead of something more general like UIPI.

    As a counterpoint, here’s a recent example I encountered where the more obvious information didn’t help. An end user was complaining that a certain part of a certain program is working on XP but not on Vista.  To simplify the story:

    1) The user (as well as I) already tried all the various compatibility settings as well as elevation, to no avail.

    2) I then naturally started by trying to repro the problem on my Vista machine, but couldn’t.

    3) I noticed the program uses a DLL residing in the program’s directory, so as a hunch, I asked the user to see if he has another copy of the DLL, perhaps a different version, residing in places like %windir%system32.  Nope.

    4) Later after some more talking, it turned out user was actually running this 32-bit program on Vista 64-bit. I found a machine with that installed and try reproing issue.  Still no repro on my end.  Baffled since the symptoms suggest a problem accessing files in a directory, which isn’t something that comes to mind as being affected by Wow64. (And no, we’re not talking about directories that gets redirected under Wow64 like system32.)

    [Of course I also asked the user to redo step #3 with SysWow64.  We ruled that out too.]

    5) Eventually, as another hunch based on my inability to repro, I asked the user whether he unzipped the zip file containing all the program’s files using windows, or using some third-party unzipper.

    Lo and behold, the user found that if he unzipped using windows instead of the third-party unzip program he was using, the problem went away.

    ——————-

    So we started with the kinds of things on Raymond’s checklist, but in this case, they all ended up being a detour to the actual problem.  (And no, I still have no idea how exactly the third-party unzip program causes the problem, not that I need to know in this case since it’s not my program, and the end user is merely a user not the author of the program.)

    ————-

    There may be plenty of idiot programmers out there, but let’s not forget that programming and debugging can be a complex endeavor, and sometimes even the best of us can have a bad day.

  21. Gabe says:

    Another reason that a 3rd-party unzip program might cause different results is that it might put all files into a single directory by default, while Windows’s unzipper always puts them in the directories specifed in the zip file.

    I agree that the problem is knowing what information would be relevant, in particular because knowing that a piece of information is relevant would probably lead you to the answer in the first place.

  22. Skywing says:

    For code that is written to work against Win7 or later, I’d use ChangeWindowMessageFilterEx (http://msdn.microsoft.com/en-us/library/dd388202.aspx ) instead.  ChangeWindowMessageFilterEx only opens the message ‘firewall’ for the window you specify, instead of all windows, which is the behavior of ChangeWindowMessageFilter.

    Using ChangeWindowMessageFilter without extreme care can be dangerous ( http://www.nynaeve.net/?p=151 ), especially for messages outside of the system-marshaled range (WM_USER+).  In this case, the DWM message is within the system marshaled range, but it is still good practice to get into the habit of using ChangeWindowMessageFilterEx everywhere for new code.

  23. Teo says:

    Raymond, can you please make an experiment? Ask your user’s question to an Office team member and measure how much time does it need to get the answer correctly.

    Why do I have the gut feeling that at least 50% of MS programmers won’t have a clue what the problem is?

  24. Yuhong Bao says:
    [deleted for violation of ground rules. Looking forward to the creation of yuhong3. -Raymond]
    [(that was sarcasm) -Raymond]
  25. Matt says:

    > [Except that the message filter isn’t specific to that message. It’s a general property of all messages. Should every window message have the Remark: “By default, UIPI blocks this message from being sent across processes of different integrity levels”? Should every class-defined message include the remark “Since class-defined messages are not marshalled, care must be taken when sending this message across processes”? Should it also mention other properties of messages, like “If this message is posted, then it is retrieved by the GetMessage or PeekMessage function. If it is sent, then the message is delivered directly to the window procedure and bypasses the message queue.”? (Or maybe there should just be a generic “Things you need to know about messages” page that every window message links to?) -Raymond]

    I think that this is exactly what should appear in MSDN. I’ve been doing win32 programming off-and-on for more than a decade and it’s such an immense platform that I have to look things like this up over and over. It would be *very* helpful for each message’s page in MSDN to have a number of notes with all of the special cases.

    It’s not dumbing down the documentation – it’s just providing all of the information you need in one place for those of us that aren’t win32 programming day-in-day-out (or in my case, haven’t done any win32 development since just before the release of vista).

    [Except that it’s not “all the information in one place”; it’s “all the information repeated in 2000 places.” The deal here is that there is an interaction between messages and elevation. It is documented in the docs on elevation and is repeated in the docs for SendMessage. If you want it repeated everywhere messages are mentioned, every page is going to have so much boilerplate people wouldn’t read it. -Raymond]
  26. dave says:

    I would LOVE to have a list of "Stupid things to check when you’re not getting a window message you expect to" (or, more generally, "Stupid things to check when X doesn’t seem to be working"), even if it’s nothing more than one-sentence summaries (e.g. "If the program is running with elevated privileges, messages may get filtered") with links to the documentation that addresses that problem.

    Assuming that such a list existed, I don’t think a link to it in the "See Also" section of every message’s documentation would be excessive.

  27. yuhong2.71828 says:

    I think it’s safe to say that a guy whose job it is to write UI code would never look at the docs for SendMessage (because he has been using it regularly for decades), nor the docs for elevation (because that’s somebody else’s job). However even after reading the docs it’s not clear that the problem is caused by running elevated. For one thing, one doesn’t think of the window manager as a process, per se, so why would one think of the DWM as a process? Even if one did know that it’s a process, it’s not mentioned anywhere that it’s a medium integrity process. Afterall, it’s a system service, so shouldn’t it be running a system integrity level? Another problem with the docs is that they tell you the problem of running at low integrity, so it’s not obvious that being elevated would cause problems.

    Missing from the documentation is that DWM only has medium integrity level (and therefore it’s necessary to change the window filter) and that there is such a thing as a window filter that can be changed to allow in other messages. Furthermore, the ChangeWindowMessageFilter[Ex] docs only say that messages above WM_USER get blocked by default and some message below WM_USER are not blockable. Since WM_DWMSENDICONICTHUMBNAIL is below WM_USER, why would it be blocked?

    I agree with other posters in believing that the docs for WM_DWMSENDICONICTHUMBNAIL should say "The window that receives this message should either be running with low or medium integrity, or it should change its message filter with ChangeWindowMessageFilter[Ex]."

  28. Matt G says:

    I just had another experience in psychic debugging that’s obvious after the fact but points at the difficulty of knowing what’s relevant up front.

    I was trying to use Netflix Watch Instantly on my Win7-x64 laptop. It always failed with an error code (8156-4001) which, if you believe every story you can find on the net about people running into this problem and fixing it somehow, has either to do with corrupt Silverlight installs, corrupt SIlverlight local appdata stores, IE’s Trusted Sites settings, your network speed, or a few other things. I called Netflix support and they said it has either to do with audio driver compatibility with Silverlight or my Internet connection speed, but they couldn’t tell which. (Really?)

    Eventually I talked to a support agent with psychic powers and he asked me if I installed any debugging software on that machine. Well yes, it has windbg, which probably isn’t relevant, but I also had set the kernel to boot in debug mode — months ago and had forgotten doing so. I used bcdedit to disable that, and now Netflix/Silverlight works fine.

    In retrospect it’s kind of obvious (though still lame) that Netflix/Silverlight DRM would be afraid of debuggers. But normally, just enabling the debug support in the kernel doesn’t change app behavior, and for apps that specifically intentionally change their behavior because of it, you’d think they’d have the decency to complain about it specifically (not using an opaque error code that’s shared with 3 or more unrelated causes!).

    So, I put to you: was this supposed to be obvious? Is activating the kernel debug mode another one of these game-changers?

  29. bdcrazy says:

    I’d say most users have never heard of kernel debug mode and most windows programmers I have asked didn’t know it existed either so they didn’t test in that mode.

  30. CGomez says:

    Having to resort to psychic debugging is always tough, but one issue I have is sometimes the customer may not even realize they withheld a crucial bit of information.

    Certainly there are plenty of developers who just throw basic information at MSFT and expect them to start pinpointing the problem.  However, there have been times that I have included everything I can think of that is relevant only to forget or not realize that there was a little tidbit that would have made it obvious.

  31. 640k says:

    This is a flaw in windows. How is anyone expected to develop software for this os when the conditions can vary this much when executing the software.

  32. Bulletmagnet says:

    @640k

    How is anyone expected to develop software for this os when the conditions can vary this much when executing the software.

    Step 1: RTFM

    Step 2: ???

    Step 3: Profit!

  33. Peter says:

    Hmmm….I’m with all the people who say it’s a doc issue.

    Let’s see: there are two general ways to send a message: SendMessage and PostMessage.  I don’t know if there are hidden "extra" ways that Microsoft uses internally.  Special Microsoft mechanism is reasonably common.

    Beyond that, I assume that the message was sent via SendMessage or PostMessage.  The UIPI documentation is actually in the hWnd parameter docs (which personally I often skip on the grounds that they generally have no content).  I find out that what UIPI stands for, and that there’s an "integrity level" associated with a process.

    But I don’t know that DWP is a process (the docs are unclear about that), and they don’t say what the DWP integrity level is normally set up.

    Then I do a search and discover that integrity level is determined by the SID with the form S-1-16-xxxx.  At this point my eyes glaze over, and I haven’t even gotten to where the introduction says that the Windows integrity model resembles the Biba model, but isn’t like the Clark-Wilson model.

    Exactly what percent of developers will understand this?  I happen to be a decent developer, and I happen to have done a pretty good job of updating an app to Vista level — and I’ve never heard of any of this.

  34. Billy O'Neal says:

    I think the point of the blog post has nothing to do about the specific case of ChangeWindowsMessageFilter — Asking the question is completely normal. The point is, if you are running under one of the kinds of conditions mentioned above, the rules change for you. These "special things" (such as the fact that your app is running elevated) are information you need to provide to those helping you fix a bug, so that the person helping you debug takes those changed rules into account.

    You’re all reading too much into the specific question that was asked and completely missing the point of Raymond’s post.

  35. 640k says:

    > “Oh, did I mention that…”

    All those reasons explain why it’s hard to program Windows. It explains why programs are buggy, developers can’t usually remember all those “taxes”.

    [These aren’t taxes though. Taxes are things you have to do even though you didn’t ask for them. But in this case, you opted into the situation. It’s more like getting a puppy without realizing that you’re going to have to take care of it even when it’s no longer cute. -Raymond]
  36. Matt says:

    [deleted for violation of ground rules. Looking forward to the creation of yuhong3. -Raymond]

    [(that was sarcasm) -Raymond]

    Raymond, I often wish I could give you stars back on your comments to comments.

  37. Dan says:

    Wouldn’t supplying enough information to avoid psychic debugging require that the asker of the question himself be psychic? And if he is psychic, would he even have to ask the question in the first place?

Comments are closed.

Skip to main content