Reputation: 4406
My app runs as Standard User. Occasionally I need to create a Registry Key that requires Admin access. I would like to prompt the user for Admin permission.
If I do something along these lines:
GetNamedSecurityInfo
AllocateAndInitializeSid
SetEntriesInAcl
SetNamedSecurityInfo (or RegSetKeySecurity)
should this cause Windows to automatically pop up a dialog prompting the user for authorization?
Do I instead have to launch a process just to get access to the Registry? In which case, how do I prompt the user to obtain Admin rights for the process?
I prefer not to use CredUIPromptForCredentials
because I don't want to see the user's password.
I've read through the Access Control documentation, can't seem to see the forest for the trees.
Upvotes: 0
Views: 144
Reputation: 4406
Here's what I have come up with, thanks to @Anders' excellent advice:
// launch separate process for elevation to Admin
void launchAsAdmin(void)
{ SHELLEXECUTEINFO shelinfo;
char *err = NULL;
DWORD exitCode;
memset(&shelinfo, 0, sizeof(shelinfo));
shelinfo.cbSize = sizeof(shelinfo);
shelinfo.hwnd = NULL;
shelinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shelinfo.lpVerb = "RunAs";
shelinfo.lpFile = "notepad.exe";
shelinfo.lpParameters = "C:\\Windows\\System32\\drivers\\etc\\hosts";
shelinfo.nShow = SW_SHOW;
ShellExecuteEx(&shelinfo);
switch((int)shelinfo.hInstApp)
{ case SE_ERR_FNF:
err = "File not found"; break;
case SE_ERR_PNF:
err = "Path not found"; break;
case SE_ERR_ACCESSDENIED:
err = "Access denied"; break;
case SE_ERR_OOM:
err = "Out of memory"; break;
case SE_ERR_DLLNOTFOUND:
err = "Dynamic-link library not found"; break;
case SE_ERR_SHARE:
err = "Cannot share an open file"; break;
case SE_ERR_ASSOCINCOMPLETE:
err = "File association information not complete"; break;
case SE_ERR_DDETIMEOUT:
err = "DDE operation timed out"; break;
case SE_ERR_DDEFAIL:
err = "DDE operation failed"; break;
case SE_ERR_DDEBUSY:
err = "DDE operation is busy"; break;
case SE_ERR_NOASSOC:
err = "File association not available"; break;
}
if((int)shelinfo.hInstApp <= 32)
return; // failed
if(shelinfo.hProcess == 0)
return; // nothing to monitor
// wait until the process has finished
time_t st = clock();
do
{ if(!GetExitCodeProcess(shelinfo.hProcess, &exitCode))
break;
if(clock() - st > CLOCKS_PER_SEC * 5) // max 5 seconds - give up
break;
} while(exitCode != STATUS_WAIT_0); // STILL_ACTIVE
CloseHandle(shelinfo.hProcess);
}
This works. If I am Standard User and I run a program that calls this function, I am prompted for Admin login ID & password, and allowed to change and save the "HOSTS" system file. (Normally this file is off-limits to a Standard User).
Upvotes: 0
Reputation: 101746
Windows will not display the UAC dialog just because you called some API that requires elevation to perform its task, the API will simply fail with ERROR_ACCESS_DENIED.
You basically have three options:
ShellExecute
yourself with the RunAs
verb and a command line parameter so you can detect that you are in this mode.Upvotes: 2