public static System.Diagnostics.Process StartProcessWithToken(IntPtr token, string cmdLine)
{
IntPtr environmentBlock = IntPtr.Zero;
try
{
// Default nil security attribute
SafeNativeMethods.SECURITY_ATTRIBUTES defSec = new SafeNativeMethods.SECURITY_ATTRIBUTES();
defSec.nLength = Marshal.SizeOf(defSec);
defSec.lpSecurityDescriptor = IntPtr.Zero;
defSec.bInheritHandle = 0;
// Create an environment block
if (!SafeNativeMethods.CreateEnvironmentBlock(ref environmentBlock, token, false))
{
LibraryLogging.Error("StartProcessWithToken(IntPtr, {1}) CreateEnvironmentBlock Error:{0}", LastError(), cmdLine);
}
// Now we can finally get into the business at hand and setup our process info
SafeNativeMethods.STARTUPINFO startInfo = new SafeNativeMethods.STARTUPINFO();
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.wShowWindow = 0;
startInfo.lpDesktop = "Winsta0\\Default"; // TBD: Support other desktops?
SafeNativeMethods.PROCESS_INFORMATION procInfo = new SafeNativeMethods.PROCESS_INFORMATION();
if (!SafeNativeMethods.CreateProcessAsUser(token, null, cmdLine, ref defSec, ref defSec, false, SafeNativeMethods.CREATE_UNICODE_ENVIRONMENT, environmentBlock, null, ref startInfo, out procInfo))
{
LibraryLogging.Error("StartProcessWithToken(IntPtr, {1}) CreateProcessAsUser Error:{0}", LastError(), cmdLine);
}
// We made it, process is running! Closing our handles to it ensures it doesn't orphan,
// then we just use its pid to return a process object
SafeNativeMethods.CloseHandle(procInfo.hProcess);
SafeNativeMethods.CloseHandle(procInfo.hThread);
return System.Diagnostics.Process.GetProcessById((int)procInfo.dwProcessId);
}
finally
{
SafeNativeMethods.CloseHandle(environmentBlock);
}
}