Reputation: 4775
I am trying to make a running process of mine which is elevated to restart explorer using the standard user token.
What I'm doing is first I run the main process as an administrator, then I take a snapshot of the running:
if (Process32First(hSnapshot,&pe32))
{
do
{
if (!wcsicmp(pe32.szExeFile, L"explorer.exe"))
{
DWORD dwExplorerSessId = 0;
if (ProcessIdToSessionId(pe32.th32ProcessID, &dwExplorerSessId) && dwExplorerSessId == dwSessionId)
{
dwExplorerLogonPid = pe32.th32ProcessID;
break;
}
}
} while (Process32Next(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
then once I get the PID of explorer which is running under the standard user account, I call:
OpenProcessToken(hProcess,TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_IMPERSONATE
,&hPToken))
then I call:
ImpersonateLoggedOnUser(hPToken);
and finally I taskkill explorer.exe and shell execute it again but its running under the administrators privileges.
Its as if the impersonateLoggedonUser is not working. Although its returning true and GetLastError() returns 0;
I have also tried using CreateProcessAsUser() but this always gives an ERROR_FILE_NOT_FOUND:
STARTUPINFO si;
GetStartupInfo(&si);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
TCHAR tchcmd[MAX_PATH];
_tcscpy(tchcmd, _T("explorer.exe"));
PVOID penv;
CreateEnvironmentBlock(&penv, hToken, FALSE);
HANDLE hNewToken;
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenImpersonation, &hNewToken);
CreateProcessAsUser(, NULL, tchcmd, 0, 0, 0, CREATE_DEFAULT_ERROR_MODE, penv, 0, &si, &pi );
Any Ideas or suggestions.
Upvotes: 4
Views: 4517
Reputation: 4153
I have encountered a similar problem when trying to run a program as a standard user from an installer started with elevated admin privileges. After trying ( and failing miserably ) to do this using CreateProcessAsUser function I have stumbled upon a solution that uses ShellExecute from IShellDispatch2 interface.
It can be used to start a process as current interactive user. For complete implementation look here: https://code.google.com/p/mulder/source/browse/trunk/Utils/nsis_stdutils/Contrib/StdUtils/ShellExecAsUser.cpp?r=327
Hope this helps!
Upvotes: 0
Reputation: 347276
Are you calling DuplicateTokenEx on the token before using it? You should.
Instead of ImpersonateLoggedOnUser, you could more easily just call CreateProcessAsUser.
Edit to match yours:
Your CreateProcessAsUser by the way should be passing: CREATE_DEFAULT_ERROR_MODE | CREATE_UNICODE_ENVIRONMENT
for the dwCreationFlags
.
You should also be error checking your CreateEnvironmentBlock
.
You should also be adjusting the Ace of the desktop
and window station
.
Instead of specifying the path directly in CreateProcessByUser you should first expand any environment variables in the string by using ExpandEnvironmentStringsForUser. This will for example convert: %windir%\explorer.exe
to C:\windows\explorer.exe
.
wchar_t szNewCommandLine[MAX_PATH];
if(!::ExpandEnvironmentStringsForUser(hNewToken, tchcmd, szNewCommandLine, MAX_PATH - 1))
{
DWORD dwExpandEnvLastError = GetLastError();
//error handling
}
For further reading please see this post on Session, Window Station, and Desktop management.
Upvotes: 3