Sometimes a function returns NULL because NULL really is the answer

A customer reported that sometimes the Get­GUI­Thread­Info function returned a valid window handle, but sometimes it returned all NULLs.

  DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
  GUITHREADINFO guiThreadInfo;
  guiThreadInfo.cbSize = sizeof(GUITHREADINFO);
  if (GetGUIThreadInfo(dwThreadId, &guiThreadInfo)) {
   HWND hwndActive = guiThreadInfo.hwndActive;

Most of the time, the call to Get­GUI­Thread­Info succeeds and obtains hwndActive successfully. But sometimes, Get­GUI­Thread­Info succeeds, but guiThreadInfo.hwndActive is NULL. In fact, aside from the cbSize, all the members of the guiThreadInfo are NULL or zero. "Under what circumstances will Get­GUI­Thread­Info succeed but return no data?"

I suggested that they start with the obvious: Is it possible that the function is correct and the thread has no active window?

The customer confessed that they were too quick to assume that there was a problem with the Get­GUI­Thread­Info function just because it reported no data. It turns out that, in fact, there was no data to report.

The root cause was that another thread in their program called Set­Window­Pos and didn't pass the SWP_NO­ACTIVATE flag. As a result, that thread stole activation from the first thread, so when they got around to asking the first thread, "Tell me about your active window, your focus window, your caret window, and your caret location," it replied, "I don't have any of those things!"

Comments (11)
  1. Mark says:

    Sometimes, zero handle is a valid handle returned most of the times, which confuses people:…/getphysicalmonitorsfromhmonitor-returned-handle-is-always-null

  2. 12BitSlab says:

    Is this similar to when my wife gets home and asks me how many chores I have completed on a particular Saturday?  At times, my response is "Absolutely nuttin'."  I consider that to be a perfectly valid answer while she clearly does not.

    I'll send her a link to this article and see if that helps.

  3. Bill says:

    @12BitSlab: See…/10652235.aspx for the difference between valid and correct.

  4. 12BitSlab says:

    @ Bill — Please don't give my wife any more ammunition!     :)

  5. Kirby FC says:

    And sometimes null is a person's last name…/null

  6. Dave says:

    @12BitSlab: I fell into that trap while chatting with my dentist, he asked me what I was going to do for the rest of the day and I said "nothing", meaning "catch up on tech support mail, run backups and rotate media, check access logs, clean out temp files, update software packages, and in my copious extra time, do the end-of-months taxes", i.e. nothing useful or interesting.  I then compounded the sin by replying "yes" when he asked "absolutely nothing?".

  7. Dave says:

    @Kirby FC: That's a not-uncommon surname in Germany, a quick search of the German phone directory ( returns 88 people called Null.

  8. Jan Ringoš says:

    @Mark: That particular example you linked is very peculiar one because I never managed to get it fully working either, abd I can easily live with NULL handles, even NULL as a placeholder that means "that one you asked for just before" and being returned for all monitors (in my case).

  9. D-Coder says:

    "@Dave: That's a not-uncommon surname in Germany, a quick search of the German phone directory ( returns 88 people called Null."

    You're assuming the search is returning valid information. Maybe people have left out their names for anonymity, or the search has an error. :-)

  10. Fabian Schmied says:

    It gets funny, though, when NULL – or any value – is both a valid answer and an indicator that an error occurred. I once had this problem with GetWindowText, which returns 0 both for windows with no text and to report errors. In the error case, you can ask GetLastError for more information, but not in the "no text" case. Now, how do you know which case you got?…/how-do-i-differentiate-between-an-empty-window-text-and-an-error-with-the-getwin

  11. poizan42 says:

    @Fabian, GetAncestor has the same problem:…/ms633502(v=vs.85).aspx

    It is not even documented that it can fail at all, but obviously it fails if you supply an invalid handle, or information in blocked due to UIPI. The rules for the latter has been changed several times by windows update patches, without any documentation whatsoever.

    GetWindowThreadProcessId has the same problem with lack of documentation that it can even fail at all:…/ms633522(v=vs.85).aspx

Comments are closed.

Skip to main content