8

I have an application that I wrote in .NET. It needs to remain running and have access the desktop that the UAC dialog windows open on and interact with that desktop using keyboard and mouse events.

It's sort of like a VNC program. Imagine you are running a VNC program and a UAC window pops up, you want your VNC program to still be able to control the desktop with the UAC window in it so that the user can move the mouse and click the OK button on the UAC dialog. Can anyone tell me how I would go about doing that?

Thanks

Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
Ray
  • 187
  • 1
  • 7
  • No, the mouse and keyboard don't work because my application is still running on the original desktop and the UAC window is on a secure desktop, which my program doesn't have access to. I need to be able to find that secure desktop then run my program on it. – Ray May 12 '10 at 18:38
  • 1
    If you could do that, it wouldn't make it a secure desktop, would it...;) – siride Aug 09 '10 at 04:38

5 Answers5

7

I would suggest you start by reading the documentation. I would guess that maybe you could open the window station and attach your process to it, but I am not very familiar with this area of Windows.

Edit 1:

In Windows XP I was able to access the secure desktop ("winlogon") via OpenDesktop when running as SYSTEM; the ACL on the secure desktop allows access only to the SYSTEM account. After opening it I could enumerate the windows on it, though there were only a handful. Perhaps you could set a window hook and listen for creation of the specific dialog. I'm not sure if Vista changed this model, so maybe it won't work; I don't have a Vista machine in front of me to test against.

Edit 2:

Ok, I got something that mostly works (tested on Windows 7). First you have to have a service running as SYSTEM. From that service, you need to launch a separate application in the user's session. To do this, enumerate all the processes looking for winlogon.exe, open its token, and CreateProcessAsUser. Specify "WinSta0\Winlogon" for the lpDesktop parameter of STARTUPINFO. Now you have a process running as SYSTEM in the user's session on the "Winlogon" desktop. In the new process you can do whatever you want; I did a quick test with EnumDesktopWindows and I was able to get the window class and text for various UAC related windows ("$$$Secure UAP Background Window", "$$$Secure UAP Background Fake Client Window", etc). I'm not sure how to determine when a UAC prompt is being displayed, though; as a quick hack you could just run a loop every 100 ms looking for UAC windows or something. I could paste some code if it would help.

Edit 3:

Ok. I have written a Win32 service that takes the following parameters:

/install - installs the service
/uninstall - uninstalls the service
/service - runs as a service; invoked via SCM
/client - runs as a client; invoked via CreateProcessAsUser

The only interesting code is in the /service and /client modes.

In /service mode it enumerates the running processes via EnumProcesses and GetModuleFileNameEx looking for "winlogon.exe". When it finds one it opens its token and launches itself in /client mode via CreateProcessAsUser:

HANDLE hProcess = ...;
// winlogon.exe runs as SYSTEM in user's session; we need to run the same way
HANDLE hToken = NULL;
if(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &hToken))
{
    TCHAR szCommandLine[MAX_PATH];
    GetModuleFileName(NULL, szCommandLine, MAX_PATH);
    PathQuoteSpaces(szCommandLine);
    // run in /client mode
    _tcscat_s(szCommandLine, MAX_PATH, _T(" /client"));
    STARTUPINFO StartupInfo;
    ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
    StartupInfo.cb = sizeof(STARTUPINFO);
    // run on the Winlogon desktop
    StartupInfo.lpDesktop = _T("WinSta0\\Winlogon");
    PROCESS_INFORMATION ProcessInformation;
    ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    if(CreateProcessAsUser(hToken, NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
    {
        CloseHandle(ProcessInformation.hThread);
        ProcessInformation.hThread = NULL;
        CloseHandle(ProcessInformation.hProcess);
        ProcessInformation.hProcess = NULL;
    }
    CloseHandle(hToken);
    hToken = NULL;
}

In /client mode it clicks the "Yes" button on the UAC prompt via a bunch of FindWindow and FindWindowEx calls. You can use Spy++ to figure out the window hierarchy.

HWND hWnd = ...;
HWND hWndButton = FindWindowEx(hWnd, NULL, _T("Button"), NULL);
if(hWndButton != NULL)
{
    // see if this is the "Yes" button
    TCHAR szText[32];
    if(GetWindowText(hWndButton, szText, 32) && _tcsicmp(szText, _T("&Yes")) == 0)
    {
        // click it
        SendMessage(hWndButton, BM_CLICK, 0, 0);
    }
}

The way I test this is to stick a Sleep(5000); in the /client code. Then I start the service and immediately do something that triggers a UAC prompt (i.e. run regedit). After 5 seconds the /client code will wake up and find and click the "Yes" button. You can run other processes on the Winlogon desktop; cmd.exe and spyxx.exe (Spy++) are most useful. Unfortunately, explorer.exe exhibits a lot of problems when running on the Winlogon desktop and isn't very useful. To get to the Winlogon desktop you can run regedit and then Alt+Tab to switch to the other application. If you want to get fancy you can write your own desktop switching utility (using the SwitchDesktop function) so you don't have to trigger a UAC prompt to get to the Winlogon desktop. If you want to get really fancy you can set a global window hook to monitor window creation; when the UAC dialog is about to be displayed you can prepare to click its "Yes" button. I didn't take it quite that far, though.

Luke
  • 11,211
  • 2
  • 27
  • 38
  • Thanks for the code. Any interest in working on this for me on a contract basis? – Ray May 25 '10 at 20:45
  • I got this compiled and running in vb.net. Every step returns true, but I'm getting a process ID of zero back in "ProcessInformation", even though the function returns true, so it doesn't appear to be creating the process. When this works, will I literally see the window to my application showing on my windows login screen? Do I have to be on the login screen when I run this? Is running it on the winlogon desktop the same as running it on the desktop that the UAC window shows up on? Any tips you can provide would be appreciated. Thanks! – Ray Aug 09 '10 at 04:31
  • It's been so long that I don't really remember the specifics. If I recall correctly I believe it was showing up on the same desktop that the UAC prompt appears on. I think I tested it by running regedit, which is manifested so it always shows the UAC prompt. Once on the UAC desktop you can ALT+TAB to the other app. – Luke Aug 09 '10 at 19:42
  • @Luke : Your post is very helpful! Would you mind providing the complete code for this service? – divB Apr 20 '15 at 03:41
  • I'm sure I don't have it anymore, sorry. – Luke Apr 23 '15 at 11:08
5

The problem is that the UAC prompt doesn't open on the current desktop, but rather in a completely new Secure Desktop, which suspends any currently open desktops.

This is intentional, as programs are not allowed to interact with this dialog.

There is one exception: "trusted SYSTEM processes can run on the Secure Desktop," according to this blog entry.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • Yes, that is correct but it still is possible to get your program to run on the secure desktop when a UAC window opens. VNC programs do it, otherwise they'd be pretty useless. – Ray May 12 '10 at 18:40
  • Well, they wouldn't be totally useless. You can always turn off UAC, if it's your machine. GotoMyPC has apparently solved this problem, but I don't know how. – Robert Harvey May 12 '10 at 18:41
  • Turning off the UAC actually isn't a great option because it disables some other functionality of the OS when you do that. – Ray May 12 '10 at 18:44
  • 2
    There is one exception: Trusted processes running as the SYSTEM user can still interact with the Secure Desktop. – Powerlord May 12 '10 at 18:44
  • @Ray: It isn't possible for a "user mode" application to interact with the WinStation (Secure Desktop) displaying the UAC prompt. Otherwise, such user mode applications could interact with the UAC prompt and "Click" the button for you automagically, which would completely defeat the purpose of displaying the prompt in the first place. – Scott Dorman May 12 '10 at 18:47
  • As a service it should be able to. My application is signed with a certificate too – Ray May 12 '10 at 19:52
0

I would imagine that you probably need to be running as a Windows Service to be allowed to execute while UAC is active.

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
0

I believe everything you see on your screen during UAC prompt is a screenshot(except the dialog itself)

John Grey
  • 356
  • 1
  • 3
  • 5
  • It creates a new desktop and uses a screenshot of your desktop as the background, but it's still a fully functional desktop and other programs can run on it. – Ray May 12 '10 at 18:42
  • @Ray: It's not a "fully functional desktop" (in fact it's not even a desktop, it's a WinStation) and other programs can't run on it as it's isolated. – Scott Dorman May 12 '10 at 18:45
-1

You can't do this. By default, when a UAC prompt appears, it is actually running in an isolated WinStation that is different from the one that runs "normal" applications. This WinStation is isolated specifically to prevent user applications from interacting with the UAC prompt. It looks like your desktop because the background of that WinStation is actually a static bitmap image of your desktop as it was just before the UAC prompt was displayed.

I suspect this might be a problem in the version of VNC you are running as I'm fairly certain the Remote Desktop provides the correct behavior and allows you the user to still interact with the UAC prompt through the remote desktop client. Keep in mind, when running any kind of remote client (remote desktop, VNC, etc.) the idea is taht the client should allow you to do anything you would normally be able to do if you were physically sitting at the keyboard.

Scott Dorman
  • 42,236
  • 12
  • 79
  • 110
  • 2
    It's possible. A lot of VNC programs are able to do it, including logmein.com. – Ray May 12 '10 at 18:56