private void WaitForConnectionCallBack(IAsyncResult iar) { try { // Get the pipe var pipeServer = (NamedPipeServerStream)iar.AsyncState; // End waiting for the connection pipeServer.EndWaitForConnection(iar); var bRequest = new byte[1024]; do { int cbRequest = bRequest.Length; pipeServer.Read(bRequest, 0, cbRequest); } while (!pipeServer.IsMessageComplete); var serializer = new XmlSerializer(typeof(StartInfo)); var startInfo = (StartInfo)serializer.Deserialize(new MemoryStream(bRequest)); NativeMethods.EnableSecurityRights("SeTcbPrivilege", true); NativeMethods.EnableSecurityRights("SeAssignPrimaryTokenPrivilege", true); NativeMethods.EnableSecurityRights("SeIncreaseQuotaPrivilege", true); pipeServer.RunAsClient(() => { PROCESS_INFORMATION procInfo; var startupInfo = new STARTUPINFO(); int size = Marshal.SizeOf(startupInfo); startupInfo.cb = size; if (startInfo.Interact) { //TODO: Find right session ID and call SetTokenInformation to set it to the user token startupInfo.dwFlags = 0x00000001; //#define STARTF_USESHOWWINDOW startupInfo.wShowWindow = 5; //#define SW_SHOW startupInfo.lpDesktop = "WinSta0\\Default"; } if (!CreateProcessAsUser(WindowsIdentity.GetCurrent().Token, null, startInfo.CommandLine, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startupInfo, out procInfo)) { Debug.WriteLine(String.Format("{0}", Marshal.GetLastWin32Error())); } }); // Kill original sever and create new wait server pipeServer.Close(); pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 1024, 1024, _security); // Recursively wait for the connection again and again.... pipeServer.BeginWaitForConnection( WaitForConnectionCallBack, pipeServer); } catch (Exception ex) { Debug.WriteLine(ex.Message); } }
static extern bool CreateProcessAsUser( IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);