I warned you: The dangers of attaching input queues


Some people didn't take to heart my cautions on the subject of attached input queues, item number five on the list of five things every Win32 programmer should know. And then they find that their application stops responding.

// Code in italics is wrong
void TryToStealFocus(HWND hwnd)
{
  // First try plain SetForegroundWindow
  SetForegroundWindow(hwnd);
  HWND hwndFG = GetForegroundWindow();
  if (hwndFG == hwnd) return;

  // That didn't work - if the foreground window belongs
  // to another thread, attach to that thread and try again
  DWORD dwCurrentThread = GetCurrentThreadId();
  DWORD dwFGThread = GetWindowThreadProcessId(hwndFG, NULL);
  if (dwFGThread == dwCurrentThread) return;

  AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);
  SetForegroundWindow(hwnd); // hangs here
  AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);
}

Their customer feedback data shows that this function often hangs at the second call to SetForegroundWindow. My exercise for you is to explain why. (Here's someone else with the same problem.)

(Note that both of these customers are trying to circumvent the foreground lock timeout so that they can steal focus and shove a dialog box in the user's face.)

Comments (53)
  1. Anonymous says:

    I don’t know if it’s just me or not (strangely…) but the embedded video on the linked page doesn’t work. I guess it did in prehistoric ’05!

    Iain.

  2. Anonymous says:

    "// Code in italics is wrong"

    Eh heh… ALL the code is it italics… :)

  3. Anonymous says:

    You should call the exit() function in the foreground program.

    Just kidding.

  4. Anonymous says:

    Though it’s been a while since I’ve done any real Windows programming, it seems problematic to me that a thread from one application has it’s input queue attached to the thread of another application (I assume we’re dealing with different applications here or the programmer could have simply brought a dialog up in front of their own). Since the memory spaces of the two applications are separate, it seems like the messages in the thread that was attached to will be giberish (i.e. the HWND will not be the HWND that’s expected).

  5. Anonymous says:

    let us know who these silly programmers are, so I/we can boycott such rude behaviour.

    mmm … now if only windows would stop doing this (I get windows jumping to the front when just using apps such as winexplorer, iexplorer, and winmail).

  6. Anonymous says:

    Could someone find a better link to that video? It cuts off after 5mins and the audio is terrible.

    A transcript would be even better.

    [The audio is terrible because it’s a bootleg. A better quality video is part of the PDC DVD set that all PDC attendees received, and it was also available for free live streaming for several months after the PDC. -Raymond]
  7. Anonymous says:

    Iain: Embedded video doesn’t work for me, either, I had to download the WMV.

    That’s some really good animatronics though… :-P

    (http://blogs.msdn.com/oldnewthing/archive/2007/12/06/6648392.aspx)

  8. Anonymous says:

    And that is why I always use SwitchToThisWindow when I want to shove something in the user’s face.

    Just kidding :) I have legitimate reasons to use it (activating the window "as if" the user activated it, such as bringing a background window to the foreground instead of creating a new one, for single-instance apps, etc)

  9. Anonymous says:

    So, what if I actually need to bring my window in foreground? For example if we should display a dialog/window etc in response to a user’s hotkey (registered with RegisterHotKey).

    [Response. -Raymond]
  10. Anonymous says:

    "So, what if I actually need to bring my window in foreground? For example if we should display a dialog/window etc in response to a user’s hotkey

    (registered with RegisterHotKey)."

    Use SetForegroundWindow()

    http://msdn.microsoft.com/en-us/library/ms633539(VS.85).aspx

  11. Anonymous says:

    Ian: SetForegroundWindow() won’t work if our app is not active one.

  12. alex_l says:

    I think it’s deadlock. I suppose that SetForegroundWindow sends something like WM_WINDOWPOSCHANGING to destination thread, which cannot be processed (who know what is destination thread doing?) and SetForegroundWindow does not returns.

  13. Anonymous says:

    “And that is why I always use SwitchToThisWindow when I want to shove something in the user’s face.”

    Again it is because of that legal settlement that Raymond do not want to discuss. It is off topic, so do not post any comments about it.

    [Wow, that’s a neat trick. Let me try that. “It is because of the indictment that Yuhong Bao does not want to discuss, so do not post any comments about it.” -Raymond]
  14. Anonymous says:

    "Ian: SetForegroundWindow() won’t work if our app is not active one."

    That is correct.  Your app is not the active one, so you have no business making it the foreground window.  Let the user decide that he wants to stop typing an email to satisfy your app, not you.  At least you can annoy them by blinking it on the task bar.  Take solace in that.

  15. Anonymous says:

    A very basic (but honest) question:

    WHY do these developers want to bring something to front? What’s the motivation in stealing the focus?

    It would be great if someone could provide a patch for this undocumented Swtich…-function to disable it forever. Are there ANY reasons the function exists?

  16. Anonymous says:

    This is an off topic comment. It is off topic, so do not post any comments about it.

  17. Anonymous says:

    Christian: Virus and malware scanners are the most obvious programs to have a somewhat valid reason to do it. The only other things I can think of simply do it to be obnoxious, so they feel the wrath of my delete key quite quickly.

  18. Anonymous says:

    "It would be great if someone could provide a patch for this undocumented Swtich…-function to disable it forever."

    Not undocumented anymore, thanks to the settlement, which as I said is off topic.

  19. Anonymous says:

    BTW, if you didn’t believe me when I said that it is not undocumented anymore, here it is:

    http://msdn.microsoft.com/en-us/library/ms633553

    Notice this note:

    “Although you can access this function by using LoadLibrary and GetProcAddress combined in Microsoft Windows versions prior to Windows XP, the function is not accessible using the standard Include file and library linkage. The header files included in Windows XP Service Pack 1 (SP1) and Windows Server 2003 document this function and make it accessible using the appropriate Include file and library linkage. However, this function is deprecated and not intended for general use. It is recommended that you do not use it in new programs because it might be altered or unavailable in subsequent versions of Windows. “

    [Wow “It is off topic, so do not post any comments about it” lasted less than an hour. -Raymond]
  20. Anonymous says:

    [Wow “It is off topic, so do not post any comments about it” lasted less than an hour. -Raymond]

    Well, notice that I never discussed the legal issues. And that is what I meant by it being off topic.

    [You wrote “Do not post any comments about it” and then you posted a comment about it. Just saying. -Raymond]
  21. Anonymous says:

    @Christian: I would guess that the taskbar needs it whenever you click on a task tab. From my understanding, SetForegroundWindow should be enough even here, but I may be missing something… it’s the only scenario I can come up with anyway. It’s the "as if the user did it" thing.

  22. Anonymous says:

    [You wrote "Do not post any comments about it" and then you posted a comment about it. Just saying. -Raymond]

    What I meant by "it" was the legal issues, the technical issues I considered as OK.

  23. Anonymous says:

    BTW, the same thing happened back in the days of DOS with SETVER. From http://groups.google.com/group/comp.os.msdos.misc/msg/24a0896d233e67d2:

    "And the MSDOS team also published the 3306h "real version call" function,

    somewhat under protest (we didn’t want vendors to use it, and told them

    so in the beta, but we knew some had already found it because they

    were telling other vendors on the beta forum about it, so….) "

  24. Anonymous says:

    "(Note that both of these customers are trying to circumvent the foreground lock timeout so that they can steal focus and shove a dialog box in the user’s face.)" – so if anyone *does* know how to bypass the timeout, please keep it to yourself!

  25. Anonymous says:

    Another "legit" to force the foreground window is showing a window from a shell notification area icon. As it is not explorer that’s doing the showing, it gets put on hold by Windows until the user clicks on it.

    The "trick" above, gets around this issue.

    Further more, when I last tried to NOT take the focus, I failed horribly and gave up.

  26. Anonymous says:

    I show a window from a notification area click using SetForegroundWindow() in one application of mine. That call has never failed.

  27. Anonymous says:

    Everything about developers who feel that their app is so important that they MUST STEAL THE FOCUS is incredibly annoying. The worst ones can’t even be moved until they’re dealt with. *Sigh*

  28. Anonymous says:

    "Virus and malware scanners are the most obvious programs to have a somewhat valid reason to do it. The only other things I can think of simply do it to be obnoxious"

    Sigh. Just because you can’t come up with a valid reason (or because others have abused it in the past) doesn’t mean the function has no valid uses. :-)

    For instance, one of the components of Winstep Xtreme optionally replaces the Windows taskbar in order to provide several task management enhancements – in order to work properly, it obviously needs to bring to the foreground the window associated to the task button the *user* just clicked on.

    Another example I can think of are ALT-TAB replacements (e.g. programs that bring Mac OSX’s Exposé-like functionality to Windows).

  29. Anonymous says:

    I gave a bad example above, sorry. As long as your application *is* the foreground window, you should have no trouble bringing other windows to the foreground (regardless of them belonging to your process or not).

    SetForegroundWindow only fails when your application does NOT have the focus (in the task manager example I gave, the user already brought my application to the foreground when he clicked on the task button).

    A better example can be given with NextSTART, which can be configured to pop up a menu when the user bumps a screen edge/corner with the mouse pointer. It’s anybody’s guess which application has the focus at the time, so SetForegroundWindow alone does not cut it when it comes to bring the menu to the foreground. Note that this is a *legit* action, initiated by the *user*.

  30. Anonymous says:

    The code doesn’t work if IE has the focus. IE has special hacks which prevents other apps from stealing it’s focus. Nasty, because IE steals focus from other apps. Why shouldn’t any app be allowed to steal focus when IE does it?

  31. Anonymous says:

    You also has to disable the flash-behavior (stored in registry) by calling SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, …), as stated in msdn library.

  32. Anonymous says:

    We cannot say: "When I speak of all propositions, I mean all except those in which ‘all propositions’ are mentioned"; for in this explanation we have mentioned the propositions in which all propositions are mentioned, which we cannot do significantly.  It is impossible to avoid mentioning a thing by mentioning that we won’t mention it.  One might as well, in talking to a man with a long nose, say: "When I speak of noses, I except such as are inordinately long", which would not be a very successful effort to avoid a painful topic.

    (Bertrand Russell, Mathematical Logic as based on the Theory of Types, American Journal of Mathematics, Vol. 30, No. 3 (July, 1908), pp. 222-262)

  33. Anonymous says:

    Yeah.  Usually program shouldn’t throw windows in front of the user’s face.  Even if they must tell the user something, they should still use FlashWindow().

  34. Anonymous says:

    Umm, can’t you just move the z-order of the window using SetWindowPos, if it’s just to show information?  Or is this action blocked as well?

    Being the window showing on top and being the focused foreground window are two different things.

  35. Anonymous says:

    Jack Mathews: “That is correct.  Your app is not the active one, so you have no business making it the foreground window. “

    There is only one reason: if user ask us to do it. What to do if a core function of the application is to register a system-wide keyboard shortcut and then once user press it, display a dialog that should interact with the user, i.e. should have a focus?

    [Pressing a registered hotkey gives you the foreground activation love. -Raymond]
  36. Anonymous says:

    If the user isn’t prepared to a window stealing focus/coming on top, he/she might enter input accidentally. That’s why SetForegroundWindow nowdays prevents program from surprising the user.

  37. Anonymous says:

    SwitchToThisWindow, at least on 2000/XP, is roughly equivalent to calling both SetActiveWindow and SetForegroundWindow, and suffers the same limitations.

    If you set a key in the properties of a shortcut then pressing that key a second time activates the running application. Trying to display a dialog on a hotkey may be one of those things you’re not supposed to do.

  38. Anonymous says:

    Wait…when does IE steal focus from other apps?  I’ve never seen this as far as I can recall, unless you’re getting a popup, and even then it only happens when another IE window already had focus.  I often leave an instance of all four major browsers running while I do other things, and I’ve never had a problem with them stealing focus (except in that pages like Google steal focus from the browser and stick it in the search box when I was typing in the address bar…grrrr…that lead me to change my homepage away from Google since I have a search box in all four browsers pointed to the same search anyway).

    On Vista it shouldn’t be able to steal focus from user/admin processes, unless you run everything as Admin to avoid UAC, because it’s a low process.

  39. Anonymous says:

    Stuff that handles DDE are able to steal focus, Opera does it to me all the time

  40. Anonymous says:

    I don’t think I’ve seen IE7 steal focus (I could be wrong), but IE6 stole the focus all the time.  Specifically on page-loading.  I remember opening an IE6 window, navigating to some URL, then going back to another application.  I would be typing something into the other application when all of a sudden IE6 steals the focus after the page fully loads.  Also, don’t forget the annoying Windows Update reboot notification dialog that keeps popping up.

  41. Igor Levicki says:

    Christian said: “It would be great if someone could provide a patch for this undocumented Swtich…-function to disable it forever. Are there ANY reasons the function exists?”

    Lets kill SetForegroundWindow() first.

    For XP Professional x64 SP2 you need to patch 2 files:

    1. 32-bit user32.dll (in SysWOW64 folder) version 5.2.3790.4033 (srv03_sp2_gdr.070228-0030) starting at 0x16FB8 put 0x33 0xC0 0xC2 0x04 0x00.

    2. 64-bit user32.dll (in System32 folder) version 5.2.3790.4033 (srv03_sp2_gdr.070228-0030) starting at 0x143D0 put 0x48 0x33 0xC0 0xC3 0x90.

    Note that I haven’t tested it so you are doing it at your own risk — make a backup copy of both files and keep them around along with a method to put them back in place in case your system fails to boot. You may need to fix the DLL checksum, you can find a command line tool for that in my website Downloads section.

    Disabling SwitchToThisWindow() would be much harder though — you would have to check if fAltTab is true and let it pass or you could break Alt+Tab behavior. That would require more space to code so you would have to expand both DLLs or find some unused space in there. I leave that to you as an exercise.

    [Of course, once you patch the file, you risk not receiving any security updates for it. -Raymond]
  42. Anonymous says:

    I have a case where a third-party application contains information that would be useful for our users to look up in our system.

    I.e. when they use this third-party app, they press a hotkey, and up pops our app containing additional and highly relevant information. The user definitively want this lookup functionality, and the action is very much initiated by the user. (no, we did not trap the Enter key, and yes, the hotkey is selectable)

    I wasn’t responsible for that add-on, so I don’t know the details. The window in question is now always on top, and I suspect part of the reason could be this lock Raymond is discussing?

    But anyway, I think there are exceptions and that stealing focus can sometimes be a valid (and expected) action.

    [Pressing a registered hotkey gives you the foreground activation love. -Raymond]
  43. Anonymous says:

    Could it be that the process this code attaches to (could be any process running on the system) is in some kind of input modal state?  If the input queues are synchronized then if the target process is, for instance, processing a mouse click by popping up a modal dialog then this process will hang waiting for that modal processing to complete??

  44. Anonymous says:

    Wow, how do you handle the noise in here?

    You’ve got:

    • several people saying "stealing focus is rude" (true, but not exactly on point)
    • a couple more saying "wait, if I have a legitimate need to steal focus, how do I do it?" (obviously cognizant that SetForegroundWindow doesn’t)

    • then several more saying "use SetForegroundWindow" (obviously not cognizant of that fact, or that it’s the whole reason people would abuse AttachThreadInput in the first place)

    Anyway, it’s true that there are legitimate needs to "steal" focus (aka, trick or force SetForegroundWindow to succeed when it doesn’t want to).

    This whole foreground window lock thing wouldn’t be such a bad idea if Windows always knew which is really the user’s idea of foreground process, but it doesn’t.

    http://blogs.msdn.com/oldnewthing/archive/2008/08/01/8795860.aspx#8800782 and http://blogs.msdn.com/oldnewthing/archive/2008/08/01/8795860.aspx#8803036 and http://blogs.msdn.com/oldnewthing/archive/2008/08/01/8795860.aspx#8807912 are all examples of this.

    So, like, you warned us, but it’s not like Windows didn’t create the problem in the first place.

  45. Anonymous says:

    Although most applications have no need to steal focus, there are some valid reason:

    1) Visual Studio. You are interacting with the target application when you hit a break point in the code. You probably want Visual Studio to bring itelf to the front with the focus.

    2) Test Automation (my field). You are playing back a script over the target application and a problem arises so the test automation application needs to take the focus back to provide the user with options.

  46. orsino says:

    Adrian,

    VS 2005 does not always come to the forground when it hits a breakpoint. I am doing something in WPF now and if the "Enable the Visual Studio hosting process" option is not enabled the task bar window of VS will just blink and I have to bring it to the foreground. But if the option is enabled VS becomes the forground window automatically. Perhaps the hosting process calls AllowSetForegroundWindow so that VS can successfully call SetForgroundWindow, something you could also try in your test automation.

  47. Igor Levicki says:

    Raymond said: “Of course, once you patch the file, you risk not receiving any security updates for it.”

    I am sorry Raymond but I believe your info is wrong this time.

    I didn’t have such a problem here — every system update I apply which contains NTOSKRNL.EXE happily updates my patched NTOSKRNL.EXE.

    For the record, I make a new patch for NTOSKRNL.EXE each time I get new version to prevent creation of “System Volume Information” folder since I don’t use any of its associated features (System Restore, mountpoints, tracking).

    [I guess the update behavior changed since the last time I investigated it. Still, I wouldn’t chance it. -Raymond]
  48. Anonymous says:

    For all the guys who do not understand why on Earth you need to "steal the focus", consider this scenario: your application (A) communicates with another application (B). B has an API, so you can build an interface to A. B sends a message, A takes it and activates, you have the source code of A, it’s yours. A needs to send a message to B and the API of B does not allow to set the focus. It’s annoying, for the user, to switch the windows in this case….

  49. Anonymous says:

    I wonder where that code came from in the first place. Oh wait…

    http://groups.google.com.ar/group/microsoft.public.win32.programmer.ui/msg/b4cd62ba65b81525?hl=en

  50. Anonymous says:

    I don’t think I’ve seen IE7 steal focus (I could be wrong),

    IE7 does that on page loading. Very annoying. Somebody, please, beat IE guys with a stick, until they promise to stop doing that.

  51. Anonymous says:

    Get the owner to share it with you.

Comments are closed.