Hi Team,
I am using the advapi32.dll to consume CreateProcessAsUser to launch the ui exe(UIAccess=true) in user context.
But i am getting elevated permission required exception..
I googled it and found that we need to use SetTokenInformation to make it work for uiaccesss=true exe's.
Could you please guide me how to do it..?
Below is my current code..
public Process StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)
{
// APIs below will fail if it is not running in session 0
//if (Process.GetCurrentProcess().SessionId != 0)
// return null;
var userToken = IntPtr.Zero;
var startInfo = new NativeStructsNew.STARTUPINFO();
var procInfo = new NativeStructsNew.PROCESS_INFORMATION();
var environmentHandler = IntPtr.Zero;
Process result = null;
startInfo.cb = Marshal.SizeOf(typeof(NativeStructsNew.STARTUPINFO));
try
{
if (!GetActiveSessionUserToken(out userToken))
{
throw new Exception($"{nameof(StartProcessAsCurrentUser)} - {nameof(GetActiveSessionUserToken)} failed.");
}
int dwCreationFlags = NativeConsts.CREATE_UNICODE_ENVIRONMENT | (visible ? NativeConsts.CREATE_NEW_CONSOLE : NativeConsts.CREATE_NO_WINDOW);
startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
startInfo.lpDesktop = "winsta0\\default";
if (!NativeMethodsNew.CreateEnvironmentBlock(ref environmentHandler, userToken, false))
{
int errorCode = Marshal.GetLastWin32Error();
throw new Exception($"{nameof(StartProcessAsCurrentUser)} - {nameof(NativeMethodsNew.CreateEnvironmentBlock)} failed. GetLastError = {errorCode}");
}
var sa = new NativeStructsNew.SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
var ta = new NativeStructsNew.SECURITY_ATTRIBUTES();
ta.Length = Marshal.SizeOf(ta);
if (!NativeMethodsNew.CreateProcessAsUser(userToken, appPath, cmdLine, ref sa, ref ta, false,
dwCreationFlags, environmentHandler, workDir, ref startInfo, out procInfo))
{
int errorCode = Marshal.GetLastWin32Error();
throw new Exception($"{nameof(StartProcessAsCurrentUser)} - CreateProcessAsUser failed. GetLastError = {errorCode}");
}
uint pid = procInfo.dwProcessId;
result = Process.GetProcessById((int)pid);
}
catch (Exception)
{
// The process does not exist
result = null;
}
finally
{
if (userToken != IntPtr.Zero)
{
NativeMethodsNew.CloseHandle(userToken);
}
if (environmentHandler != IntPtr.Zero)
{
NativeMethodsNew.DestroyEnvironmentBlock(environmentHandler);
}
if (procInfo.hThread != IntPtr.Zero)
{
NativeMethodsNew.CloseHandle(procInfo.hThread);
}
if (procInfo.hProcess != IntPtr.Zero)
{
NativeMethodsNew.CloseHandle(procInfo.hProcess);
}
}
return result;
}
---------
private static UInt32 GetActiveConsoleSessionId()
{
try
{
IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
uint activeSessionId = Platform.NoUserSession;
IntPtr infoSessionsHandler = IntPtr.Zero;
int sessionsCount = 0;
if (NativeMethodsNew.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref infoSessionsHandler, ref sessionsCount))
{
Int32 dataSize = Marshal.SizeOf(typeof(NativeStructsNew.WTS_SESSION_INFO));
IntPtr current = infoSessionsHandler;
for (int i = 0; i < sessionsCount; i++)
{
var si = (NativeStructsNew.WTS_SESSION_INFO)Marshal.PtrToStructure(current, typeof(NativeStructsNew.WTS_SESSION_INFO));
if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State)
{
activeSessionId = si.SessionID;
break;
}
current += dataSize;
}
if (infoSessionsHandler != IntPtr.Zero)
NativeMethodsNew.WTSFreeMemory(infoSessionsHandler);
}
return activeSessionId;
}
catch (Exception ex)
{
Debug.WriteLine("exception in GetActiveConsoleSessionId - {0}", ex);
}
return Platform.NoUserSession;
}
public uint GetActiveUserSessionId()
{
return GetActiveConsoleSessionId();
}
public bool GetActiveSessionUserToken(out IntPtr userToken)
{
userToken = IntPtr.Zero;
bool result = false;
IntPtr userTokenHandle = IntPtr.Zero;
try
{
// Get active user session id by enumerating through the sessions
uint activeSessionId = GetActiveUserSessionId();
// If enumerating did not work, fall back to the old method
if (activeSessionId == NativeConsts.INVALID_SESSION_ID)
{
activeSessionId = NativeMethodsNew.WTSGetActiveConsoleSessionId();
}
// Get the primary access token of the logged-on user specified by the session ID
if (activeSessionId != NativeConsts.INVALID_SESSION_ID
&& NativeMethodsNew.WTSQueryUserToken(activeSessionId, out userTokenHandle) != 0)
{
var ta = new NativeStructsNew.SECURITY_ATTRIBUTES();
ta.Length = Marshal.SizeOf(ta);
// Convert the impersonation token to a primary token
result = NativeMethodsNew.DuplicateTokenEx(userTokenHandle, 0, ref ta,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary,
out userToken);
NativeMethodsNew.SetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenUIAccess, 0, (UInt32)IntPtr.Size);
}
}
finally
{
if (userTokenHandle != IntPtr.Zero)
{
NativeMethodsNew.CloseHandle(userTokenHandle);
}
}
return result;
}