Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an API call to prompt user for UAC elevation?

Tags:

uac

winapi

My app needs to write to a file in \ProgramData that could be protected. This only happens once after installation.

Is there an API function that would take ACL info and prompt the user to authorize the app to access the file? In other words the app would ask Windows to prompt the user for confirmation and authorization. This should happen interactively, and allow the app to resume execution after access to the file has been authorized. The app runs as Standard User, does not require Admin privilege.

The file gets opened with CreateFile().

Edit: There is a subtle difference between my query and the others said to be duplicates. I am asking for permission to access one specific object, a file. The others are asking to elevate the privileges of the whole process. Anyway, I am grateful for all responses which include a solution.

like image 771
Pierre Avatar asked Aug 05 '15 23:08

Pierre


People also ask

What are UAC prompts?

The UAC elevation prompts are color-coded to be app-specific, enabling for immediate identification of an application's potential security risk. When an app attempts to run with an administrator's full access token, Windows 10 or Windows 11 first analyzes the executable file to determine its publisher.

What triggers UAC?

There are many types of activities that may trigger a UAC prompt: Running a desktop application as an administrator. Making changes to settings and files in the Windows and Program Files folders. Installing or removing drivers and desktop applications.

How do you raise permissions in Python?

You can make a shortcut somewhere and as the target use: python yourscript.py then under properties and advanced select run as administrator. When the user executes the shortcut it will ask them to elevate the application.


3 Answers

If you don't want to elevate your entire app, you have a few options:

  1. spawn a separate elevated process just to access the file. Use ShellExecute/Ex() with the runas verb, or CreateProcessElevated(), to run a second copy of your app, or another helper app, with command-line parameters to tell it what to do. The main process can wait for the second process to exit, if needed.

  2. create a COM object to access the file, and then use the COM Elevation Moniker to run the COM object in an elevated state.

  3. prompt the user for credentials using CredUIPromptForCredentials() or CredUIPromptForWindowsCredentials() (see Asking the User for Credentials for more details), then logon to the specified account using LogonUser() to get a token, impersonate that token using ImpersonateLoggedOnUser(), access the file as needed, and then stop impersonating using RevertToSelf() and close the token with CloseHandle().

like image 131
Remy Lebeau Avatar answered Oct 11 '22 03:10

Remy Lebeau


Thanks to @Remy for the ShellExecuteEx suggestion, here are the sordid details. Note the use of 'cmd' and the double-command, so the user only has to reply once. Also, [1] must wait for process completion otherwise you could find yourself creating the file before it was deleted, and [2] don't wait for the process if it failed.

// delete file with Admin privilege
// 'file_name' is path of file to be deleted
SHELLEXECUTEINFO shex;
char param[512];
char *cmd = "/C \"attrib -H \"%s\" && del /F /Q \"%s\"\""; // double command

_snprintf(param, sizeof(param), cmd, file_name, file_name);
ZeroMemory(&shex, sizeof(shex));
shex.cbSize = sizeof(shex);
shex.lpVerb = "runas";  // runas, open
shex.lpFile = "cmd";    // not 'del'
shex.lpParameters = param;
shex.nShow = SW_HIDE;
shex.fMask = SEE_MASK_NOCLOSEPROCESS;
BOOL retshx = ShellExecuteEx(&shex);
// wait otherwise could return before completed
if(retshx)
{   time_t st = clock();
    DWORD exitCode;
    do
    {   if(!GetExitCodeProcess(shex.hProcess, &exitCode))
            break;
        if(clock() - st > CLOCKS_PER_SEC * 5)       // max 5 seconds
            break;
    } while(exitCode != STATUS_WAIT_0); // STILL_ACTIVE
    CloseHandle(shex.hProcess);
}
like image 26
Pierre Avatar answered Oct 11 '22 04:10

Pierre


Processes can only be launched with an elevated token, they can't gain it after the fact. So you can either re-launch your app elevated with a command line argument telling it what to do (simple solution), or implement an out-of-proc COM server that you can create elevated and pass instructions to it (harder).

A third solution is to leverage the built-in UAC support of the IFileOperation interface, but this doesn't let you read/write, only copy. So you could make a copy of the file you need to modify, modify the copy and then use IFileOperation to copy the temporary over the original.

like image 23
Jonathan Potter Avatar answered Oct 11 '22 03:10

Jonathan Potter