2
votes

Let's say an application is already running with elevated privileges. Is it possible for this application to show a UAC prompt and get its result (successfully confirmed or cancelled)?

Background story: I have an application that requires Administrator privileges but runs in a restricted user account, so an UAC prompt is shown at its start, the user enters Administrator credentials to confirm it and everything works fine. However, for some critical actions I'd like to verify that the current user is (still) allowed to do that.

For example, the original user left the workstation without locking his Windows account (yes, the world's not perfect...) and another user open that already running application and accesses some sensitive settings. You can compare this to an online-shop, where an already logged in user has to provide his credentials again if he wants to change his delivery address.

I understand that I could create a custom prompt, ask for admin account credentials and check if they're valid, but I don't want to touch those credentials at all. Neither do I want to introduce additional application-specific credentials. The UAC prompt would be a nice and native solution to re-verify the user has admin privileges.

Basically something like this:

if VerifyAdminWithUacPrompt then
begin
  //critical stuff
end;

A Delphi example would be perfect, but I'm also happy about general ideas how to accomplish this.

1
AFAIK you cannot force another UAC prompt for an already elevated process. I'm afraid you need to do what you suggest in the first part of the last paragraph of your question. But interesting question anyway. - Jabberwocky
However this SO post might be interesting: stackoverflow.com/a/31844696/898348, especially this link or also this - Jabberwocky
One way might be to put the implementation of your sensitive elements into a separate process called by your (non elevated) main process, and for that second process to exit when it is done. That way the UAC screen is delayed until the elevated status is required. - Dsm
You'd need to create a non elevated process, and then have it start the other process - David Heffernan
@CodeX in that case, you will have to make your main process run elevated as you want, but then have it spawn a non-elevated process when needed. That unelevated process can then spawn a new elevated process and exit. UAC will prompt the user before letting that final process run, and if successful then the process can do the actual admin work, or use an IPC mechanism to send a signal back to your main process so it can perform the admin work. - Remy Lebeau

1 Answers

2
votes

Your app does not need to invoke a new UAC prompt, since UAC is already running your app elevated. The app just needs to ask the user for credentials. Windows has APIs for that very purpose: CredUIPromptForCredentials() and CredUIPromptForWindowsCredentials():

The CredUIPromptForCredentials function creates and displays a configurable dialog box that accepts credentials information from a user.

The CredUIPromptForWindowsCredentials function creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer.

See Asking the User for Credentials on MSDN for more details:

Your application may need to prompt the user for user name and password information to avoid storing an administrator password or to verify that the token holds the appropriate privileges.

However, simply prompting for credentials may train users to supply those to any random, unidentified dialog box that appears on the screen. The following procedure is recommended to reduce that training effect.

To properly acquire user credentials

  • Inform the user, by using a message that is clearly part of your application, that they will see a dialog box that requests their user name and password. You can also use the CREDUI_INFO structure on the call to CredUIPromptForCredentials to convey identifying data or a message.

  • Call CredUIPromptForCredentials. Note that the maximum number of characters specified for user name and password information includes the terminating null character.

  • Call CredUIParseUserName and CredUIConfirmCredentials to verify that you obtained appropriate credentials.