April 29th, 2020

How can I detect that the system is no longer showing a UAC prompt?

A customer wanted to know how to detect when the system is no longer showing a UAC prompt.

They explained that their program uses Direct3D9. When the UAC dialog is shown, a desktop switch occurs, and their application loses the graphics device. The attempt to reacquire the graphics device fails for as long as the UAC dialog is on screen. They want to know when the UAC dialog is dismissed so they know when they can attempt to reacquire the graphics device. Otherwise, they are forced to poll.

Before checking with the product team, the customer liaison suggested that the customer look for a process called consent.exe and wait for it to exit.

Okay, first of all, that’s a bad idea. The consent.exe program is an implementation detail. Nothing in the platform requires that the UAC feature be implemented by a program called consent.exe, nor does anything bind that the disappearance of such a program to the ability to create a Direct3D9 device.

The customer is too focused on the UAC dialog and missing the big picture. Their application can lose access to graphics hardware for reasons other than the UAC dialog. The user might lock the workstation. The user might hit Ctrl+Alt+Del. The screen saver could start.

If you are specifically interested in when the user has switched to your desktop, you can get the desktop associated with the current thread and see if it is the one that is receiving input.

BOOL IsCurrentThreadOnInputDesktop()
{
  BOOL result;
  HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
  return desktop &&
         GetUserObjectInformation(desktop, UOI_IO, &result,
                                  sizeof(result), nullptr) &&
         result;
}

To know when the input desktop has changed, you can register an accessibility event hook and listen for the EVENT_SYSTEM_DESKTOP­SWITCH event. When you receive that event, check again.

But really, you don’t care about whether you’re the input desktop. You want to know whether you can try to acquire graphics resources.

So do that.

Wait for a WM_PAINT message and attempt your acquisition then. When your window isn’t visible, the system stops sending WM_PAINT messages, so the fact that they have returned is an indicator that now might be a good time to try to acquire your graphics resources.

This does have a thundering herd problem: When the user switches desktops, all the programs on the new desktop will try to grab graphics resources all at once. The user may find themselves with a momentarily unresponsive system as all the programs wake up and try to do stuff all at the same time. Better would be to wait until the user activates your application’s window, if possible.

A member of the graphics team suggested that the customer could switch to Direct3D 9Ex, which has improvements to the way it deals with desktop switching.

Bonus chatter: The UAC dialog can be configured to show on the same desktop, rather than a custom desktop. But the customer doesn’t care about that case. If we had answered the customer’s question as original stated, they would have been handling that case incorrectly.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

6 comments

Discussion is closed. Login to edit/delete existing comments.

  • word merchant

    “… the customer liaison suggested that the customer look for a process called consent.exe and wait for it to exit…”

    You should name and shame that person here, right now. Maybe supply a home address.

  • Georg Rottensteiner

    Isn’t that exactly what you’re supposed to check with TestCooperativeLevel?

    It returns D3DERR_DEVICELOST when your device was lost, you keep checking (in a relaxed loop), and once you get D3DERR_DEVICENOTRESET, you reset your device and off you go.

    • Mystery Man

      It appears that’s exactly what the customer didn’t want to do… or was calling “Plan B”. Here is the relevant excerpt:

      They want to know when the UAC dialog is dismissed so they know when they can attempt to reacquire the graphics device. Otherwise, they are forced to poll.

  • Yuhong Bao

    One thing to keep in mind is that not all Windows Vista and Windows 7 systems have the WDDM drivers needed for Direct3D 9Ex.

    • Daniel Sturm

      Good thing then that neither of those two OSes are still supported. Windows 95 also wouldn’t work.

      • Mark Tolley

        Still have a PC running Windows 98 – links my MIDI keyboards and controllers. Boots faster than my Windows 10 laptop…