private Native.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string envBlock) { var startupInfo = new Native.STARTUPINFO(); var processInfo = new Native.PROCESS_INFORMATION(); startupInfo = new Native.STARTUPINFO(); if (CellEnabled(RuleType.WindowStation)) { startupInfo.lpDesktop = this.desktopName; } Native.ProcessCreationFlags creationFlags = Native.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~Native.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~Native.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= Native.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | Native.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | Native.ProcessCreationFlags.CREATE_SUSPENDED | Native.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT; // 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) { creationFlags |= Native.ProcessCreationFlags.CREATE_NEW_CONSOLE; startupInfo.lpDesktop = ""; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); } Native.SECURITY_ATTRIBUTES processAttributes = new Native.SECURITY_ATTRIBUTES(); Native.SECURITY_ATTRIBUTES threadAttributes = new Native.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); var createProcessSuc = Native.CreateProcessAsUser( hToken: logonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: false, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: this.prisonRules.PrisonHomePath, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo); if (createProcessSuc == false) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return processInfo; }
public Process Execute(string filename, string arguments, bool interactive, Dictionary <string, string> extraEnvironmentVariables) { // C with Win32 API example to start a process under a different user: http://msdn.microsoft.com/en-us/library/aa379608%28VS.85%29.aspx if (!this.isLocked) { throw new InvalidOperationException("This prison has to be locked before you can use it."); } var startupInfo = new Native.STARTUPINFO(); var processInfo = new Native.PROCESS_INFORMATION(); startupInfo = new Native.STARTUPINFO(); if (CellEnabled(RuleType.WindowStation)) { new WindowStation().Apply(this); startupInfo.lpDesktop = this.desktopName; } Native.ProcessCreationFlags creationFlags = Native.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~Native.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~Native.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= Native.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | Native.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | Native.ProcessCreationFlags.CREATE_SUSPENDED | Native.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT; // 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) { creationFlags |= Native.ProcessCreationFlags.CREATE_NEW_CONSOLE; startupInfo.lpDesktop = ""; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); } this.InitializeLogonToken(); this.LoadUserProfileIfNotLoaded(); var envs = GetDefaultEnvironmentVarialbes(); // environmentVariables from the method parameters have precedence over the default envs if (extraEnvironmentVariables != null) { foreach (var env in extraEnvironmentVariables) { envs[env.Key] = env.Value; } } string envBlock = extraEnvironmentVariables == null ? null : Prison.BuildEnvironmentVariable(envs); Native.SECURITY_ATTRIBUTES processAttributes = new Native.SECURITY_ATTRIBUTES(); Native.SECURITY_ATTRIBUTES threadAttributes = new Native.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); Logger.Debug("Starting process '{0}' with arguments '{1}' as user '{2}' in working dir '{3}'", filename, arguments, this.user.Username, this.prisonRules.PrisonHomePath); if (filename == string.Empty) { filename = null; } var createProcessSuc = Native.CreateProcessAsUser( hToken: logonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: false, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: this.prisonRules.PrisonHomePath, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo); if (createProcessSuc == false) { throw new Win32Exception(Marshal.GetLastWin32Error()); } var workerProcessPid = processInfo.dwProcessId; var workerProcess = Process.GetProcessById(workerProcessPid); // AccessTokenHandle // workerProcess.RemovePrivilege(ProcessPrivileges.Privilege.ChangeNotify); // ProcessExtensions.RemovePrivilege(new AccessTokenHandle() , Privilege.ChangeNotify); // Tag the process with the Job Object before resuming the process. this.jobObject.AddProcess(workerProcess); // Add process in the second job object this.AddProcessToGuardJobObject(workerProcess); // This would allow the process to query the ExitCode. ref: http://msdn.microsoft.com/en-us/magazine/cc163900.aspx workerProcess.EnableRaisingEvents = true; // Now that the process is tagged with the Job Object so we can resume the thread. IntPtr threadHandler = Native.OpenThread(Native.ThreadAccess.SUSPEND_RESUME, false, processInfo.dwThreadId); uint resumeResult = Native.ResumeThread(threadHandler); Native.CloseHandle(threadHandler); if (resumeResult != 1) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(workerProcess); }
private Native.PROCESS_INFORMATION NativeCreateProcessAsUser(bool interactive, string filename, string arguments, string envBlock) { var startupInfo = new Native.STARTUPINFO(); var processInfo = new Native.PROCESS_INFORMATION(); startupInfo = new Native.STARTUPINFO(); if (CellEnabled(RuleType.WindowStation)) { startupInfo.lpDesktop = this.desktopName; } Native.ProcessCreationFlags creationFlags = Native.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~Native.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~Native.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= Native.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | Native.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | Native.ProcessCreationFlags.CREATE_SUSPENDED | Native.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT; // 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) { creationFlags |= Native.ProcessCreationFlags.CREATE_NEW_CONSOLE; startupInfo.lpDesktop = ""; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); } Native.SECURITY_ATTRIBUTES processAttributes = new Native.SECURITY_ATTRIBUTES(); Native.SECURITY_ATTRIBUTES threadAttributes = new Native.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); var createProcessSuc = Native.CreateProcessAsUser( hToken: logonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: false, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: this.prisonRules.PrisonHomePath, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo); if (createProcessSuc == false) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(processInfo); }