public static System.Diagnostics.Process StartProcessInSession(int sessionId, string cmdLine)
{
IntPtr processToken = IntPtr.Zero;
IntPtr duplicateToken = IntPtr.Zero;
try
{
// Get our current process token
using (System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess())
{
if (!SafeNativeMethods.OpenProcessToken(me.Handle, (uint)TokenAccessLevels.AllAccess, out processToken))
{
LibraryLogging.Error("StartProcessInSession({1}, {2}) OpenProcessToken Error:{0}", LastError(), sessionId, cmdLine);
}
}
// Duplicate it, so we can change it's session id
if (!SafeNativeMethods.DuplicateTokenEx(processToken, (uint)SafeNativeMethods.ACCESS_MASK.MAXIMUM_ALLOWED, IntPtr.Zero, SafeNativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, SafeNativeMethods.TOKEN_TYPE.TokenPrimary, out duplicateToken))
{
LibraryLogging.Error("StartProcessInSession({1}, {2}) DuplicateTokenEx Error:{0}", LastError(), sessionId, cmdLine);
}
// Poke the session id we want into our new token
if (!SafeNativeMethods.SetTokenInformation(duplicateToken, SafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenSessionId, ref sessionId, Marshal.SizeOf(sessionId)))
{
LibraryLogging.Error("StartProcessInSession({1}, {2}) SetTokenInformation Error:{0}", LastError(), sessionId, cmdLine);
}
return StartProcessWithToken(duplicateToken, cmdLine);
}
finally
{
SafeNativeMethods.CloseHandle(processToken);
SafeNativeMethods.CloseHandle(duplicateToken);
}
}