The program “G” is preventing you from shutting down

Raymond Chen

Raymond

So you’re trying to sign off or shut down, but you get a message saying that some program named “G” is preventing you. What’s going on? Who is this mysterious “G” program?

We noted some time ago that treating a UTF16-LE Unicode string as if it were an 8-bit string generally results in only the first character surviving, because the high-order byte of the UTF16-LE code unit is zero for most Western European characters, and the zero byte is interpreted as the end of the 8-bit string.

This mismatch can go undetected by the compiler if the data came in as an untyped blob (like, say, a byte stream), or if got smuggled through some other channel that erased the original type.

One case where you can see this is if you call the Register­ClassW function to register a window class. The W at the end of Register­ClassW indicates that you want the Unicode version, and one of the things you provide is a window procedure, which will therefore be treated as a Unicode window procedure.

Your window procedure consequently needs to cast its WPARAM and LPARAM parameters into the Unicode versions of whatever message you are receiving.

And if it chooses to continue with default message handling, it needs to call the Unicode version of Def­Window­Proc: Def­Window­ProcW. That tells the system that the WPARAM and LPARAM parameters that you’re passing along should be treated as Unicode parameters, not ANSI parameters.

If you pass your Unicode messages to Def­Window­ProcA, then you’ll find that a lot of strings get truncated at their first character.

And that brings us back to today’s topic. What is this mysterious “G” program?

At the time the GDI+ library was written, it needed to support Windows 98, which had very limited support for Unicode. Therefore, it was compiled as ANSI and consequently used the ANSI versions of functions like Register­Class, like Create­Window, and Def­WindowProc to create and manage its helper window. The lack of Unicode support in the helper window didn’t really cause a problem because the window never displayed any UI and never processed any text. The window was there to do things like listen for WM_SETTINGS­CHANGE messages so it knew when to invalidate its caches.

A few years ago, the GDI+ team did a little cleanup, and one of the things they did was get rid of support for Windows 98 and Windows Me. Because c’mon, Windows 98 and Windows Me went out of support over a decade ago.

For the most part, this meant simply recompiling GDI+ as a Unicode component rather than an ANSI component.

Except that the notification window procedure contained an explicit call to Def­Window­ProcA. Most character set mismatches would be caught by the compiler due to a type mismatch. But the character set dependency in Def­Window­Proc is not encoded in the parameter types. It’s implicit in how you received the message. This mismatch went undetected by the compiler.

This mismatch also went undetected by testing because the notification window doesn’t do any text processing. The title of the window got truncated from "GDI+ Hook Window" to simply "G", but that title isn’t used for anything, so the error was of no consequence. The window title is never shown to the user.

Except when it is.

As we saw last time, one mistake that programs make is taking responsibility for the GDI+ helper window but failing to pump messages. When the user tries to sign out or shut down, every window is sent a WM_QUERY­END­SESSION message to let it know that the user is signing out, and this is your last chance to save your work and clean up.

If the application is not pumping messages, then the window will be flagged as not responding to the WM_QUERY­END­SESSION message and consequently is blamed for preventing you from signing out (or shutting down).

When a program prevents you from signing out or shutting down, Windows looks for a visible window belonging to that program and uses that to represent it in the Blocked Shutdown Resolver (BSDR) screen. But if the program has no visible windows, then the BSDR will take any window belonging to the program, visible or not. And sometimes the invisible window that gets chosen is the one named “G”.

That’s why you end up with a message that implicates some mysterious program named “G” as the one that is preventing you from shutting down.

Once the problem was identified, the fix was simple: Change Def­Window­ProcA to plain old Def­Window­Proc, so that it follows the character set preference of the rest of the component, namely Unicode. This restores the full name of the window: "GDI+ Hook Window".

But we took the fix one step further. Since it was clear that this window was a source of problems, we put the name of the underlying process in the window title, so that when it gets blamed for preventing you from signing out or shutting down, you have a better idea of what program is responsible.

The title of the window is now "GDI+ Window (contoso.exe)". The fix is available in Windows 10 Insider Preview Build 19013.

 

Raymond Chen
Raymond Chen

Follow Raymond   

13 comments

Comments are closed.

  • Avatar
    Alex Martin

    I don’t know if this is a good idea, but what if the BSDR showed the file description from the image of the window’s owning process? Isn’t that what Task Manager does?

  • Avatar
    Wim Bonner

    Does this mean that it will likely be included in the Fall 2019 update, or is it already pushed out towards future updates?

  • Henke37
    Henke37

    So that’s the story behind the bug I’ve been seeing. And nice to see more information on who to blame. Is this just this specific case, or for all situations?

    • Raymond Chen
      Raymond Chen

      Not sure what you mean “all situations”. This certainly doesn’t cover all situations of an app preventing shutdown. This is just fixing the mystery “G”.

        • Raymond Chen
          Raymond Chen

          This fixes the title of the window formerly known as “G”. Other windows are unaffected. If you want to change the Blocked Shutdown Resolver screen itself, then I encourage you file a Feedback Hub item, or find Alex’s and upvote it.

  • Avatar
    Danstur

    This seems like a situation where a quick grep over the codebase for A[^\W] would’ve worked reasonably well to find problematic code.

    It’s always obvious in hindsight.

  • Avatar
    Iman Kalyan

    Uninstall NVIDIA PhysX software…and nvidia hd audio driver or uninstall all nvidia driver and program..and install new nvidia driver…my problem solved

  • Alexandre Grigoriev
    Alexandre Grigoriev

    The whole shutdown screen is a bad misfeature. Has been for 10 years already.
    How about allowing to go back to the desktop to the offending app (which if most likely on a “save this file?” dialog, and to respond to the app, to allow the shutdown proceed?

  • Avatar
    Ray

    I was recently creating a P/Invoke signature for DefWindowProc in C#, failing to correctly decorate it with the DllImportAttribute and CharSet.Auto parameter (remember C# defaults to ANSI unlike the rest of NET for another reason), as I did not see any LP*STR parameters on MSDN. And yes, my window was titled “K” afterwards and I didn’t find the bug for at least 40 minutes. Duh.