How likely is it that a window will receive a WM_NULL message out of the blue?


A customer discovered a bug in their control that resulted in a crash:

LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg) {
  ...
  default:
    if (uMsg == g_customRegisteredMessage) {
      // For this message, the lParam is a pointer
      return HandleCustomMessage((SOMETHING*)lParam);
    }
    break;
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

The problem is that under certain conditions, the control doesn't initialize the g_custom­Registered­Message variable. If a WM_NULL message arrives, the test

    if (uMsg == g_customRegisteredMessage) {

is true, and we take the lParam of the WM_NULL message and treat it as a pointer. Since the lParam of the WM_NULL message is usually zero, this causes the program to crash with a null pointer.

The customer fully acknowledged the bug. But their question was one of risk management. How likely is a window going to receive the WM_NULL mesasge? Knowing the likelihood of the scenario would help them decide how critical the fix is. (And they weren't able to reproduce the problem in-house, so as far as they could determine, the likelihood was effectively zero. And yet it was happening.)

The WM_NULL message is not a common one, but it's not uncommon either. Posting a WM_NULL is usually done by a window to itself in order to wake up its message loop. This is typically done when the program has a custom message loop, and it needs some of the non-message code to run. We saw an example of this some time ago where we posted a WM_NULL to let our message loop know that the pseudo-dialog has exited.

Posted WM_NULL messages are usually done from a program to itself, and they are usually posted as thread messages, not window messages, so they don't normally come through the window procedure.

Sending a WM_NULL is a different story, though. It is a relative common technique to send a WM_NULL message to a window for the purpose of checking whether the window is responding to messages. We used it to wait for a window to finish processing a foreground change. Some system monitoring tools will periodically call Send­Message­Timeout to send a WM_NULL to all windows, just to see if they are responding. Windows UI Automation uses WM_NULL messages help determine the window interaction state.

The customer could try running system monitoring tools or accessibility tools to increase the likelihood of receiving a WM_NULL message under normal use. (I mean, sure, they could write a program that explicitly sends a WM_NULL message to their window, but that wouldn't be anything a normal end-user would have.)

I suspect the customer will bump up the priority of this issue due to the accessibility angle. People who use accessibility tools tend to really need them. It's not like you can tell a person with poor visual acuity, "Oh, just suck it up for a while."

Bonus chatter: The customer wrote back. After further investigation, they found that the problem was traced to a third party tool that their client was using, specifically this line of code that sends a WM_NULL message to the foreground window to determine whether it is responding.

Comments (16)
  1. GPF says:

    “sometimes it hungs…” – Remarks above this line of code
    Yes, sometimes it does.

  2. Roger says:

    Oooh fun! TONT has transitioned into a future where “old” customer problems are now new enough for the, related-but-not-at-fault (this time), code to be publicly found on something like GitHub!

    1. smf says:

      I’m disappointed that we don’t get many 1980/1990’s era windows stories anymore. 16 bit stories are the best.

    2. Yes. The ‘New’ Old Thing.

  3. I’m afraid I’m guilty of that. I now of course correctly only use WM_USER and WM_APP ranges. I guess the fact that it says WM_NULL says ‘sentinel’ to me before it says WM. Which is of course fantastically bogus…

      1. Written in reverse… Then I’d have noticed it.

  4. Azarien says:

    Speaking of accessibility, why is Windows still buggy when it comes to remembering user-selected mouse pointer theme? Whenever I set one of the “large” themes, it’s back to normal after system restart.

    1. I also use a large mouse pointer theme. I am not experiencing the problem you describe. Perhaps there is some “mouse enhancement” software that is resetting it.

      1. GL says:

        Speaking of themes, I noticed that Windows randomly thinks the theme has been edited (and shows as an unsaved theme Custom.theme) while it’s not. I am wondering if some software is misbehaving…

        1. Joshua says:

          If some software changes it and changes it back it shows modified. We have some software that must get rid of the background image temporarily. :(

      2. ender9 says:

        Since upgrading to 1703, Windows keeps using the standard mouse pointer instead of my chosen one (even though it does show it in the Mouse applet). I never had these problems with older builds (and I also never had problems with my monitors not going to sleep/Windows not locking the screen before 1703).

        1. GregM says:

          “I also never had problems with my monitors not going to sleep/Windows not locking the screen before 1703”

          I have that problem, and I’m still on 7. :)

  5. xcomcmdr says:

    Huh, I never would have expected that a program I use all the the time (ConEmu) would be linked to on this blog.

    BTW, ConEmu is awesome. Use it. ;-)

  6. manuell says:

    WM_NULL may also be sent/posted just after SetWindowsHookEx, in the context of Dll injection.

Comments are closed.

Skip to main content