private Native.NativeMethods.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string curDir, string envBlock, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName) { var startupInfo = new Native.NativeMethods.STARTUPINFO(); var processInfo = new Native.NativeMethods.PROCESS_INFORMATION(); startupInfo = new Native.NativeMethods.STARTUPINFO(); if (this.prison.RuleEnabled(RuleTypes.WindowStation)) { startupInfo.lpDesktop = this.prison.desktopName; } NativeMethods.ProcessCreationFlags creationFlags = NativeMethods.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~NativeMethods.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~NativeMethods.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= NativeMethods.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | NativeMethods.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | NativeMethods.ProcessCreationFlags.CREATE_SUSPENDED | NativeMethods.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT | NativeMethods.ProcessCreationFlags.CREATE_NEW_CONSOLE; // TODO: extra steps for interactive to work: // http://blogs.msdn.com/b/winsdk/archive/2013/05/01/how-to-launch-a-process-interactively-from-a-windows-service.aspx if (interactive) { startupInfo.lpDesktop = string.Empty; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES // Dangerous and maybe insecure to give a handle like that an untrusted processes // startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); // startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); // startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); if (stdinPipeName != null || stdoutPipeName != null || stderrPipeName != null) { startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES } if (stdinPipeName != null) { startupInfo.hStdInput = GetHandleFromPipe(stdinPipeName); } if (stdoutPipeName != null) { startupInfo.hStdOutput = GetHandleFromPipe(stdoutPipeName); } if (stderrPipeName != null) { startupInfo.hStdError = GetHandleFromPipe(stderrPipeName); } } if (string.IsNullOrWhiteSpace(curDir)) { curDir = this.prison.PrisonHomePath; } NativeMethods.SECURITY_ATTRIBUTES processAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES threadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); if (!NativeMethods.CreateProcessAsUser( hToken: this.prison.User.LogonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: true, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: curDir, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return processInfo; }
private Native.NativeMethods.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string curDir, string envBlock, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName) { var startupInfo = new Native.NativeMethods.STARTUPINFO(); var processInfo = new Native.NativeMethods.PROCESS_INFORMATION(); startupInfo = new Native.NativeMethods.STARTUPINFO(); if (this.prison.RuleEnabled(RuleTypes.WindowStation)) { startupInfo.lpDesktop = this.prison.desktopName; } NativeMethods.ProcessCreationFlags creationFlags = NativeMethods.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~NativeMethods.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~NativeMethods.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= NativeMethods.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | NativeMethods.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | NativeMethods.ProcessCreationFlags.CREATE_SUSPENDED | NativeMethods.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT | NativeMethods.ProcessCreationFlags.CREATE_NEW_CONSOLE; // TODO: extra steps for interactive to work: // http://blogs.msdn.com/b/winsdk/archive/2013/05/01/how-to-launch-a-process-interactively-from-a-windows-service.aspx if (interactive) { startupInfo.lpDesktop = string.Empty; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES // Dangerous and maybe insecure to give a handle like that an untrusted processes // startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); // startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); // startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); if (stdinPipeName != null || stdoutPipeName != null || stderrPipeName != null) { startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES } if (stdinPipeName != null) { startupInfo.hStdInput = GetHandleFromPipe(stdinPipeName); } if (stdoutPipeName != null) { startupInfo.hStdOutput = GetHandleFromPipe(stdoutPipeName); } if (stderrPipeName != null) { startupInfo.hStdError = GetHandleFromPipe(stderrPipeName); } } if (string.IsNullOrWhiteSpace(curDir)) { curDir = this.prison.PrisonHomePath; } NativeMethods.SECURITY_ATTRIBUTES processAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES threadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); if (!NativeMethods.CreateProcessAsUser( hToken: this.prison.User.LogonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: true, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: curDir, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(processInfo); }