It’s bad enough for a guest to demolish the host’s house; demolishing an unrelated person’s house is taking it to a whole new level


"How do I destroy a window that belongs to another process?"

The Destroy­Window function will not destroy windows that belong to another thread, much less another process. The best you can do is post a WM_CLOSE message to the window to ask it nicely. The Def­Window­Proc function response to the WM_CLOSE message by destroying the window, but the window is free to add a custom handler for the WM_CLOSE message which rejects the request.

(If you are thinking of posting the WM_DESTROY message, then you're the sort of person who prank-calls somebody pretending to be the police.)

If you want to distinguish between user-initiated requests to close the window (say, by clicking the X button in the corner), and your special, "No, really, just destroy the window" demand to close the window, you can invent a private message for this purpose.

#define WM_FORCECLOSE (WM_APP + 3141)

LRESULT CALLBACK VictimWndProc(HWND hwnd, UINT uMsg,
    WPARAM wParam, LPARAM lParam)
{
 switch (uMsg) {
 ...
 case WM_FORCECLOSE: DestroyWindow(hwnd); return 0;
 ...
 }
 return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void ForceCloseWindow(HWND hwnd)
{
 PostMessage(hwnd, WM_FORCECLOSE, 0, 0);
}

Of course, this WM_FORCE­CLOSE message works only with windows specially designed to understand it.

"I can't do that because the window I want to force closed belongs to some application I did not write, so I cannot modify its window procedure."

This is another case of If it's not yours, then don't mess with it without permission from the owner. One of the rules of thumb for real life is that if something doesn't belong to you, then you shouldn't mess with it unless you have permission from the owner.

You need to work with the application vendor to come to some sort of agreement on how you can tell the application to close the window unconditionally. Otherwise, you're even worse than the guest who visits a house and calls the demolition company to have the house destroyed. You're the guy who calls the demolition company to order the destruction of some completely unrelated house.

How would you like it if a random person called the demolition company to destroy your house?

Comments (35)
  1. WndSks says:

    The really stupid don't do this version:

    PostMessage(hwndApp, WM_CLOSE, 0, 0);

    Sleep(1337);

    PostMessage(hwndApp, WM_DESTROY, 0, 0);

    Sleep(1337);

    PostMessage(hwndApp, WM_QUIT, 0, 0); // If you are lucky this makes WinMain return without any cleanup nor saving important data

  2. Joshua says:

    Hijack the thread of the owning window's message loop to inject the DestroyWindow call. The difficulty of doing this correctly should reduce it's use to the only reasonable case: correcting sourceless and effectively unsupported programs (think VB6 business apps until proven otherwise).

  3. Mordachai says:

    I'm always flabbergasted that programmers tend to think that they know better, that they can just blow away other apps, force their software to the front, add extra icons to the desktop and the root of the start menu and the notification area and add pop-ups over the tops of everything else, hide messages globally, and any of a hundred other things because their software is clearly the most important thing ever and everyone must pay attention only to it.  Such folks should be publicly executed on national (and international) TV.  Perhaps a few heads would get the message across.

  4. Yuri Khan says:

    There is one legitimate use for the requested functionality, and that is writing a task/process manager. When you’re a task manager, you send WM_CLOSE, wait for a timeout, and if the victim window still exists, then find out its process and terminate that.

  5. MNGoldenEagle says:

    @Yuri Khan: That's not what the customer was trying to do according to Raymond, though.  They were trying to destroy the window programmatically instead of posting a CLOSE message and letting the window close itself in a more graceful, sane manner.  A task manager shouldn't force-close windows; if you're at that point, you may as well tear down the entire process.

  6. Brian_EE says:

    I immediately thought of this real life example that was in the news last year:

    http://www.wxyz.com/…/oops-crews-demolish-the-wrong-house-in-pontiac

  7. Chris Crowther says:

    @Steve Wolf, you're assuming we do it because we want to.  We usually do those thing because someone with a more expensive hat than us says "can't you just…" or "why doesn't it…".

  8. Dan Bugglin says:

    "How would you like it if a random person called the demolition company to destroy your house?"

    Probably the same as if a random alien race called the demolition company to destroy my planet to make way for a hyperspace bypass.

  9. bob says:

    What about someone trying to write an accessibility service?

    [Then use accessibility to invoke the Close button, the same way a user would with a mouse. -Raymond]
  10. AC says:

    My first response (apart from "don't do that") would have been CreateRemoteThread. But then you're still only in the right process, not thread. And as Joshua already noted, hijacking the thread is even worse.

    What happens when the associated thread gets destroyed btw? Does the kernel do the some kind of cleanup like it does when the process terminates?

  11. JAHA says:

    Shouldn't you use RegisterWindowMessage?

    [If you are in cahoots with the victim window, then you can use a private message. RegisterWindowMessage is not needed here, since you control the window procedure of the recipient. -Raymond]
  12. Ken Hagan says:

    So, umm, whilst we're on the subject, how can I distinguish between WM_CLOSE messages that were initiated by the end-user and ones that were initiated by a program pushing fake mouse movements and clicks onto my input queue?

    Oh wait…

  13. Joshua says:

    @Ken Hagan: If you do, I uninstall your program as you are incompatible with my accessibility tools.

  14. MNGoldenEagle says:

    @AC: Unless I'm very much mistaken, killing the thread will just leak all the resources that thread was holding.  The kernel won't clean up anything until the process is taken down; after all, how is the kernel supposed to know if another thread is going to use those resources?

  15. Alegr1 says:

    @MNGoldenEagle:

    The only favor Vista+ does to the untimely deceased thread is to deallocate its stack (and cancel its I/O).

  16. Dominic says:

    That house was in the way of my bonus.

  17. Dominic says:

    I tried to send the house a WM_FORECLOSE method, but the court procedure ignored it.

  18. Erwin says:

    @Dominic:

    That's how I initially read it as well: WM_FORECLOSE. The intent looks the same!

  19. Anon says:

    @Steve Wolf

    UX designers are even worse!

    They do things like forcing colour themes and font styles, and even removing entire menus and toolbars from the operating system because they just happen to not use them as often as others.

    *cough*

  20. Alegr1 says:

    @Ken Hagan:

    WM_CLOSE *is* the right way to close the top level window (and quit the application).

    This is what SC_CLOSE gets translated to by DefWindowProc.

  21. Ken Hagan says:

    @Alegr1: I know, but Raymond has just alerted us all to the existence of programs that impersonate the end-user for malicious ends, so the next step is for the rest of us to distinguish between genuine input from an honest, decent upstanding end-user and fake input from a horrid, deceitful "app".

    Coz programming is just a holy war against other (infidel) vendors, right? At least, that's the message I'm getting from Raymond's inbox. as reported on this blog. So it stands to reason that we need defensive techniques as well as offensive ones. We shouldn't just rely on the merciful AppCompat team to protect us.

    (* To pick up on Joshua's reply, I'm not sure that the need to support accessibility tools actually makes the problem any harder than it already is.)

  22. Fleet Command says:

    ROFL! God, it was long time since laughed while reading a post so hard!

  23. jas88 says:

    @Ken Hagan: Clearly, we need to implement a CAPTCHA inside the window message pump to authenticate genuine user input! (Sadly, I can see someone trying just about that, as a "security" measure…)

  24. jas88 says:

    @Ken Hagan: Clearly, we need to implement a CAPTCHA inside the window message pump to authenticate genuine user input! (Sadly, I can see someone trying just about that, as a "security" measure…)

  25. smf says:

    This is the type of thing you end up doing a lot of if you're providing kiosk mode solutions. Especially when the software doesn't work properly and needs closing down and reopening regularly (and can't rely on the user to do it).

  26. Gabe says:

    smf: For kiosk solutions, you probably want TerminateProcess or TerminateJobObject. Just trying to destroy a window is not a reliable solution. Of course you could tell the window to close, give it a few seconds, and then terminate the process.

  27. Steven Stewart-Gallus says:

    @Ken Hagan:

    Actually this is a real problem although definitely not one which should be solved at the application level. It is really bad that malicious applications can forge user input and snoop on other windows. See http://qubes-os.org/trac for an attempt at solving the problem of GUI isolation.

    [But it's not a problem that can be solved at the application level. After all, the malicious application can just patch your malicious application detector. -Raymond]
  28. Fleet Command says:

    What I want to know is: How does uiAccess attribute of requestedExecutionLevel token in the application manifest would factor in. I never studied it, knowing that my apps would never need it and I needed a special digital signature anyway. But now I am curious.

    However, the main documentation page of requestedExecutionLevel has mysteriously disappeared from MSDN.

  29. Maurits says:

    ExitWindowsEx, obviously.

  30. dbacher says:

    WM_DESTROY is awesome.

    HWND is a pointer (conceptually).  WM_DELETE is delete (again conceptually).  And so you're going to release someone else's pointer, without worrying about who else might have a copy.  That's just an awesome attitude in an app. And then on top of it, you're going to post the message instead of calling the function — and so whatever base class cleanup Microsoft would do isn't going to happen.

    That just strikes me as not understanding the platform on which you're operating, at a fundamental level.

  31. Nico says:

    @Steven Stewart-Gallus

    There may be some argument for specific targeted application isolation (sandboxing), but trying to apply it across the board isn't worth the cost.  The flexibility and capabilities provided by the even playing field of a desktop are some of the primary things that set it apart (and make it superior to) more restricted platforms (such as mobile, console, etc).

  32. Cheong says:

    [However, the main documentation page of requestedExecutionLevel has mysteriously disappeared from MSDN.]

    You mean this one? msdn.microsoft.com/…/6ad1fshk.aspx

  33. Fleet Command says:

    @cheong00: Oh, I see the ClickOnce version is intact, but no, it doesn't contain anything beyond a short description.

  34. Cheong says:

    I can't see it from the Manifest schema here: msdn.microsoft.com/…/aa375632(v=vs.85).aspx

    Possibly the page is removed because it's no longer used.

  35. Fleet Command says:

    That's like saying Microsoft is discontinuing User Account Control. (Maybe they are. Maybe they've decided to make Metro-style apps the only type of apps and forever preventing developers from developing anything without their consent.)

Comments are closed.