CreateProcessAsUser fails with ERROR_ELEVATION_REQUIRED for a process with UIAccess="true"
c, c++, service, uac, winapi
Solution
I found the answer. Here it is for whoever runs into it as well:
Add this after `DuplicateTokenEx` call:
HANDLE hToken2;
DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken2);
//ONLY if requiring UIAccess!
DWORD dwUIAccess = 1;
::SetTokenInformation(hToken2, TokenUIAccess, &dwUIAccess, sizeof(dwUIAccess));
Problem
I'm trying to use the following code to run a user-mode process from my service application (running as a `local system`.) The requirement for the user-mode process is to run without elevatation, but to have `UIAccess="true"` in its manifest to be able to display `top-most` windows correctly under Windows 8. So I do this (from my service) to run my user-mode process: ``` //NOTE: Error checking is omitted for readability //'dwSessionID' = user session ID to run user-mode process in //'pUserProcPath' = L"C:\\Program Files (x86)\\Company\\Software\\user_process.exe" HANDLE hToken = NULL; WTSQueryUserToken(dwSessionID, &hToken); HANDLE hToken2; DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken2); LPVOID pEnvBlock = NULL; CreateEnvironmentBlock(&pEnvBlock, hToken2, FALSE); STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.lpDesktop = L"winsta0\\default"; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); //ImpersonateLoggedOnUser(hToken2); //Not necessary as suggested below PVOID OldRedir; Wow64DisableWow64FsRedirection(&OldRedir); BOOL bSuccess = CreateProcessAsUser( hToken2, // client's access token pUserProcPath, // file to execute NULL, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, // creation flags pEnvBlock, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ); int nOSError = ::GetLastError(); Wow64RevertWow64FsRedirection(OldRedir); //RevertToSelf(); //Not necessary as suggested below CloseHandle(pi.hProcess); CloseHandle(pi.hThread); DestroyEnvironmentBlock(pEnvBlock); CloseHandle(hToken2); CloseHandle(hToken); ``` This runs fine, if `UIAccess="false"` in the manifest for the `user_process.exe`. But if I do the following: - Enable `UIAccess="true"` for the `user_process.exe`: Sign it with my code-signing certificate and Place it in the `"C:\Program Files (x86)\Company\Software"` folder. What I get is that `CreateProcessAsUser` fails with the error `ERROR_ELEVATION_REQUIRED`. Can someone suggest how to make it work? PS. I tried adjusting my service's privileges to enable `SE_DEBUG_NAME` and `SE_TCB_NAME`, but neither helped. PS2. If I simply double-click my `user_process.exe` process compiled with `UIAccess="true"`, code-signed, and placed in the `C:\Program Files (x86)\Company\Software` folder, it starts & runs just fine (not elevated.).