Exemple #1
0
        public void Run()
        {
            IntPtr primaryToken = GetCurrentUserToken();

            if (primaryToken == IntPtr.Zero)
            {
                return;
            }
            NativeMethods.STARTUPINFO StartupInfo = new NativeMethods.STARTUPINFO();
            processInfo_   = new NativeMethods.PROCESS_INFORMATION();
            StartupInfo.cb = Marshal.SizeOf(StartupInfo);

            NativeMethods.SECURITY_ATTRIBUTES Security1 = new NativeMethods.SECURITY_ATTRIBUTES();
            NativeMethods.SECURITY_ATTRIBUTES Security2 = new NativeMethods.SECURITY_ATTRIBUTES();

            string command = "\"" + processPath_ + "\"";

            if ((arguments_ != null) && (arguments_.Length != 0))
            {
                command += " " + arguments_;
            }

            IntPtr lpEnvironment = IntPtr.Zero;
            bool   resultEnv     = NativeMethods.CreateEnvironmentBlock(out lpEnvironment, primaryToken, false);

            if (resultEnv != true)
            {
                int nError = NativeMethods.GetLastError();
            }

            NativeMethods.CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, NativeMethods.CREATE_NO_WINDOW | NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_);

            NativeMethods.DestroyEnvironmentBlock(lpEnvironment);
            NativeMethods.CloseHandle(primaryToken);
        }
Exemple #2
0
        private Win32Process(NativeMethods.PROCESS_INFORMATION pi, StreamWriter stdin, StreamReader stdout, StreamReader stderror)
        {
            StandardInput  = stdin;
            StandardOutput = stdout;
            StandardError  = stderror;
            _hasExited     = false;
            _exitCodeLock  = new object();
            Id             = pi.dwProcessId;
            MainThreadId   = pi.dwThreadId;
            _processHandle = new SafeProcessHandle(pi.hProcess, true);

            var threadHandle = new SafeThreadHandle(pi.hThread);
            var wait         = new ProcessWaitHandle(_processHandle);

            _registeredWait = ThreadPool.RegisterWaitForSingleObject(wait, (o, t) => {
                _registeredWait.Unregister(wait);
                SetExitState();
                Exited?.Invoke(this, EventArgs.Empty);
                _processHandle.Close();
                threadHandle.Close();
                wait.Close();
            }, null, -1, true);

            _disposable
            .Add(() => _registeredWait.Unregister(wait))
            .Add(_processHandle)
            .Add(threadHandle)
            .Add(wait);
        }
Exemple #3
0
        public Process Execute(string fileName, string arguments, string currentDirectory, bool interactive, Dictionary <string, string> extraEnvironmentVariables, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName)
        {
            // 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.prison.IsLocked)
            {
                throw new PrisonException("The prison has to be locked before you can use it.");
            }

            this.prison.User.Profile.LoadUserProfileIfNotLoaded();

            var envs = this.prison.User.RetrieveDefaultEnvironmentVariables();

            // 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 = BuildEnvironmentVariable(envs);

            Logger.Debug("Starting process '{0}' with arguments '{1}' as user '{2}' in working directory '{3}'", fileName, arguments, this.prison.User.UserName, this.prison.PrisonHomePath);

            if (string.IsNullOrWhiteSpace(fileName))
            {
                fileName = null;
            }

            if (this.prison.RuleEnabled(RuleTypes.WindowStation))
            {
                var winStationCell = this.prison.prisonCells.First((a) => { return(a.RuleType == RuleTypes.WindowStation); });
                winStationCell.Apply(this.prison);
            }

            NativeMethods.PROCESS_INFORMATION processInfo = this.NativeCreateProcessAsUser(interactive, fileName, arguments, currentDirectory, envBlock, stdinPipeName, stdoutPipeName, stderrPipeName);

            NativeMethods.CloseHandle(processInfo.hProcess);
            NativeMethods.CloseHandle(processInfo.hThread);

            var workerProcessPid = processInfo.dwProcessId;
            var workerProcess    = Process.GetProcessById(workerProcessPid);

            // Tag the process with the Job Object before resuming the process.
            this.prison.jobObject.AddProcess(workerProcess);

            // Add process in the second job object
            this.prison.PrisonGuard.AddProcessToGuardJobObject(workerProcess);

            // This would allow the process to query the ExitCode. ref: http://msdn.microsoft.com/en-us/magazine/cc163900.aspx
            workerProcess.EnableRaisingEvents = true;

            ResumeProcess(workerProcess);

            return(workerProcess);
        }
Exemple #4
0
        private static int CreateProcessAsUser(string executablePath, string commandLine, string workingDirectory, IntPtr userToken)
        {
            using (AutoDisposeHandle environmentVariables = CreateEnvironmentBlock(userToken))
            {
                if (environmentVariables == null)
                {
                    return(-1);
                }

                NativeMethods.STARTUPINFO startupInformation = new NativeMethods.STARTUPINFO();
                startupInformation.length     = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO));
                startupInformation.desktop    = "Winsta0\\Default";
                startupInformation.showWindow = (short)NativeMethods.WindowShowStyle.ShowNoActivate;
                NativeMethods.PROCESS_INFORMATION processInformation = new NativeMethods.PROCESS_INFORMATION();
                try
                {
                    bool result = NativeMethods.CreateProcessAsUser
                                  (
                        userToken,
                        executablePath,
                        commandLine,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        false,
                        (uint)(NativeMethods.CreateProcessFlags.DETACHED_PROCESS | NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT),
                        environmentVariables,
                        workingDirectory,
                        ref startupInformation,
                        ref processInformation
                                  );
                    if (!result)
                    {
                        Win32Helper.ThrowLastWin32Error("Unable to start process \"" + executablePath + "\"");
                    }
                    return(processInformation.processID);
                }
                finally
                {
                    if (processInformation.processHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.CloseHandle(processInformation.processHandle);
                        }
                        catch { }
                    }
                    if (processInformation.threadHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.CloseHandle(processInformation.threadHandle);
                        }
                        catch { }
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Initializes a new instance of the BrokerProcess class
        /// </summary>
        /// <param name="brokerFileName">indicating the broker file name</param>
        /// <param name="environments">indicating the environments</param>
        public BrokerProcess(string brokerFileName, NameValueConfigurationCollection environments)
        {
            this.startupInfo    = new NativeMethods.STARTUPINFO();
            this.startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO));
            this.processInfo    = new NativeMethods.PROCESS_INFORMATION();

            string        path        = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string        fileName    = Path.Combine(path, brokerFileName);
            StringBuilder commandLine = null;

            TraceHelper.TraceEvent(TraceEventType.Information, "[BrokerProcess] Start broker process, FileName = {0}", fileName);

            IntPtr environmentPtr;

            if (environments != null)
            {
                this.environmentHandle = GCHandle.Alloc(ToByteArray(environments), GCHandleType.Pinned);
                environmentPtr         = this.environmentHandle.AddrOfPinnedObject();
            }
            else
            {
                environmentPtr = IntPtr.Zero;
            }

            if (!NativeMethods.CreateProcess(fileName, commandLine, IntPtr.Zero, IntPtr.Zero, true, creationFlags, environmentPtr, path, ref this.startupInfo, out this.processInfo))
            {
                int errorCode = Marshal.GetLastWin32Error();
                TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed: {0}", errorCode);
                ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, errorCode.ToString());
            }

            SafeWaitHandle handle = new SafeWaitHandle(this.processInfo.hProcess, false);

            if (handle.IsClosed || handle.IsInvalid)
            {
                TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed because the process handle is invalid or closed.");
                ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, "Handle is invalid or closed");
            }

            string uniqueWaitHandleName = BuildUniqueWaitHandle(this.Id, out this.readyWaitHandle);

            WaitOrTimerCallback brokerProcessReadyCallback = new ThreadHelper <object>(new WaitOrTimerCallback(this.BrokerProcessReadyCallback)).WaitOrTimerCallbackRoot;
            WaitOrTimerCallback processExitCallback        = new ThreadHelper <object>(new WaitOrTimerCallback(this.ProcessExitCallback)).WaitOrTimerCallbackRoot;

            this.exitWaitHandle = new ManualResetEvent(false);
            this.exitWaitHandle.SafeWaitHandle = handle;

            // Register broker process exit callback
            ThreadPool.RegisterWaitForSingleObject(this.exitWaitHandle, processExitCallback, null, -1, true);

            // Register callback to be raised when broker process opened service host and is ready to initialize.
            ThreadPool.RegisterWaitForSingleObject(this.readyWaitHandle, brokerProcessReadyCallback, null, readyTimeout, true);
        }
Exemple #6
0
        /// <summary>
        /// ユーザーセッションでコマンドを実行する
        /// </summary>
        /// <param name="commandline">実行したいコマンド</param>
        /// <exception cref="InvalidOperationException"></exception>
        public static void CreateProcessAsUser(string commandline)
        {
            var sessionId = NativeMethods.WTSGetActiveConsoleSessionId();

            IntPtr hPToken       = IntPtr.Zero;
            var    hUserTokenDup = IntPtr.Zero;

            var ret = NativeMethods.WTSQueryUserToken(sessionId, out hPToken);

            var sa = new NativeMethods.SECURITY_ATTRIBUTES();

            sa.nLength = Marshal.SizeOf(sa);

            if (!NativeMethods.DuplicateTokenEx(hPToken, NativeMethods.TOKEN_ALL_ACCESS, ref sa, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, NativeMethods.TOKEN_TYPE.TokenPrimary, out hUserTokenDup))
            {
                NativeMethods.CloseHandle(hPToken);
                throw new InvalidOperationException();
            }

            var si = new NativeMethods.STARTUPINFO()
            {
                cb          = Marshal.SizeOf(sa),
                lpDesktop   = @"winsta0\default",
                wShowWindow = 0,//SW_HIDE
                dwFlags     = NativeMethods.STARTF_USESHOWWINDOW,
            };

            var creationFlags = NativeMethods.CREATE_UNICODE_ENVIRONMENT;
            var env           = IntPtr.Zero;

            // アクティブユーザのセッションを設定します
            var ret2 = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenSessionId, ref sessionId, sizeof(NativeMethods.TOKEN_INFORMATION_CLASS));

            // 環境変数を設定
            if (!NativeMethods.CreateEnvironmentBlock(out env, hUserTokenDup, true))
            {
                env = IntPtr.Zero;
            }

            NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION();

            NativeMethods.CreateProcessAsUser(hUserTokenDup, IntPtr.Zero, commandline, IntPtr.Zero, IntPtr.Zero, false, creationFlags, env, IntPtr.Zero, ref si, out pi);

            NativeMethods.DestroyEnvironmentBlock(env);
        }
Exemple #7
0
 private Win32Process(NativeMethods.PROCESS_INFORMATION pi)
 {
     _hasExited      = false;
     _exitCodeLock   = new object();
     ProcessId       = pi.dwProcessId;
     MainThreadId    = pi.dwThreadId;
     _processHandle  = new SafeProcessHandle(pi.hProcess, true);
     _threadHandle   = new SafeThreadHandle(pi.hThread);
     _wait           = new ProcessWaitHandle(_processHandle);
     _registeredWait = ThreadPool.RegisterWaitForSingleObject(_wait, (o, t) => {
         _registeredWait.Unregister(_wait);
         SetExitState();
         Exited?.Invoke(this, new Win32ProcessExitEventArgs(_exitCode));
         _processHandle.Close();
         _threadHandle.Close();
         _wait.Close();
     }, null, -1, true);
 }
Exemple #8
0
        /// <summary>
        /// If HpcServiceHost is launched to run a pre/post task, launch the pre/post task
        /// </summary>
        private static bool RunPrePostTask(ref uint exitCode)
        {
            bool   prePostTaskExists      = false;
            string prePostTaskCommandLine = Environment.GetEnvironmentVariable(Constant.PrePostTaskCommandLineEnvVar);

            // Check if pre/post task exists
            prePostTaskExists = !string.IsNullOrEmpty(prePostTaskCommandLine);

            // if so run it
            if (prePostTaskExists)
            {
                string serviceWorkingDirectory = null;

                // Working directory is the service assembly's directory. If we are on Azure, change to the service package's dir. If
                //  not on azure use service assemblies directory from service config which is passed to svchost via env var so we dont
                //  need to read the svc config file again on every CN (which is slow)
                if (SoaHelper.IsOnAzure())
                {
                    serviceWorkingDirectory = Utility.GetServiceLocalCacheFullPath();
                }
                else
                {
                    serviceWorkingDirectory = Environment.ExpandEnvironmentVariables(
                        Environment.GetEnvironmentVariable(Constant.PrePostTaskOnPremiseWorkingDirEnvVar));
                }

                NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO();
                startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO));

                NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION();

                StringBuilder commandLine = new StringBuilder();

                // Run command from comspec (like node manager babysitter) to ensure env vars are expanded and command runs as if launched from node manager
                commandLine.AppendFormat("\"{0}\" /S /c \"{1}\"", Environment.GetEnvironmentVariable("ComSpec"), prePostTaskCommandLine);

                TraceHelper.TraceInfo(
                    jobId,
                    "Executing '{0}'",
                    prePostTaskCommandLine);

                // Start the task
                bool ret = NativeMethods.CreateProcess(null,
                                                       commandLine,
                                                       IntPtr.Zero,
                                                       IntPtr.Zero,
                                                       true,
                                                       NativeMethods.CREATE_UNICODE_ENVIRONMENT,
                                                       IntPtr.Zero,
                                                       serviceWorkingDirectory,
                                                       ref startupInfo,
                                                       out processInfo);

                // If CreateProcess succeeded
                if (ret)
                {
                    using (SafeWaitHandle processHandle = new SafeWaitHandle(processInfo.hProcess, true))
                        using (SafeWaitHandle threadHandle = new SafeWaitHandle(processInfo.hThread, true))
                        {
                            if (processHandle.IsClosed || processHandle.IsInvalid)
                            {
                                TraceHelper.TraceError(
                                    jobId,
                                    "Process handle is invalid or closed. Task commandline = {0}",
                                    commandLine);

                                exitCode = 1;
                                return(true);
                            }

                            // Wait for task to complete
                            NativeMethods.WaitForSingleObject(processInfo.hProcess, Timeout.Infinite);

                            // Trace the results
                            NativeMethods.GetExitCodeProcess(new SafeProcessHandle(processInfo.hProcess, false), out exitCode);

                            TraceHelper.TraceInfo(
                                jobId,
                                "ExitCode = {0}",
                                exitCode);
                        }
                }
                else
                {
                    int errorCode = Marshal.GetLastWin32Error();

                    TraceHelper.TraceError(
                        jobId,
                        "Cannot start pre/post task: '{0}'. Exit code = {1}",
                        prePostTaskCommandLine, errorCode);

                    exitCode = (uint)errorCode;
                }
            }

            return(prePostTaskExists);
        }
Exemple #9
0
        /// <include file='doc\Executor.uex' path='docs/doc[@for="Executor.ExecWaitWithCapture3"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        internal static int ExecWaitWithCapture(IntPtr userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine)
        {
            IntSecurity.UnmanagedCode.Demand();

            IntPtr output;
            IntPtr error;

            int retValue = 0;

            if (outputName == null || outputName.Length == 0)
            {
                outputName = tempFiles.AddExtension("out");
            }

            if (errorName == null || errorName.Length == 0)
            {
                errorName = tempFiles.AddExtension("err");
            }

            // Create the files
            output = CreateInheritedFile(outputName);
            error  = CreateInheritedFile(errorName);

            bool success = false;

            NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION();
            IntPtr   primaryToken      = IntPtr.Zero;
            GCHandle environmentHandle = new GCHandle();

            try {
                // Output the command line...
                // Make sure the FileStream doesn't own the handle
                FileStream   outputStream = new FileStream(output, FileAccess.ReadWrite, false /*ownsHandle*/);
                StreamWriter sw           = new StreamWriter(outputStream, Encoding.UTF8);
                sw.Write(currentDir);
                sw.Write("> ");
                // 'true' command line is used in case the command line points to
                // a response file
                sw.WriteLine(trueCmdLine != null ? trueCmdLine : cmd);
                sw.WriteLine();
                sw.WriteLine();
                sw.Flush();
                outputStream.Close();

                NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO();

                si.cb         = Marshal.SizeOf(si);
                si.dwFlags    = NativeMethods.STARTF_USESTDHANDLES;
                si.hStdOutput = output;
                si.hStdError  = error;
                si.hStdInput  = UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE);

                //
                // Prepare the environment
                //
                Hashtable environment = new Hashtable();

                // Add the current environment
                foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
                {
                    environment.Add((string)entry.Key, (string)entry.Value);
                }

                // Add the flag to indicate restricted security in the process
                environment.Add("_ClrRestrictSecAttributes", "1");

                // set up the environment block parameter
                IntPtr environmentPtr   = (IntPtr)0;
                byte[] environmentBytes = EnvironmentToByteArray(environment);
                environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                environmentPtr    = environmentHandle.AddrOfPinnedObject();

                if (userToken == IntPtr.Zero)
                {
                    success = UnsafeNativeMethods.CreateProcess(
                        null,                               // String lpApplicationName,
                        new StringBuilder(cmd),             // String lpCommandLine,
                        null,                               // SECURITY_ATTRIBUTES lpProcessAttributes,
                        null,                               // SECURITY_ATTRIBUTES lpThreadAttributes,
                        true,                               // bool bInheritHandles,
                        0,                                  // int dwCreationFlags,
                        environmentPtr,                     // int lpEnvironment,
                        currentDir,                         // String lpCurrentDirectory,
                        si,                                 // STARTUPINFO lpStartupInfo,
                        pi);                                // PROCESS_INFORMATION lpProcessInformation);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            finally {
                // free environment block
                if (environmentHandle.IsAllocated)
                {
                    environmentHandle.Free();
                }

                // Close the file handles
                UnsafeNativeMethods.CloseHandle(output);
                UnsafeNativeMethods.CloseHandle(error);
            }

            if (success)
            {
                try {
                    int ret = SafeNativeMethods.WaitForSingleObject(pi.hProcess, ProcessTimeOut);

                    // Check for timeout
                    if (ret == NativeMethods.WAIT_TIMEOUT)
                    {
                        throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT);
                    }

                    if (ret != NativeMethods.WAIT_OBJECT_0)
                    {
                        throw new ExternalException(SR.GetString(SR.ExecBadreturn, cmd), Marshal.GetLastWin32Error());
                    }

                    // Check the process's exit code
                    int status = NativeMethods.STILL_ACTIVE;
                    if (!UnsafeNativeMethods.GetExitCodeProcess(pi.hProcess, ref status))
                    {
                        throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error());
                    }

                    retValue = status;
                }
                finally {
                    UnsafeNativeMethods.CloseHandle(pi.hThread);
                    UnsafeNativeMethods.CloseHandle(pi.hProcess);

                    if (primaryToken != IntPtr.Zero)
                    {
                        UnsafeNativeMethods.CloseHandle(primaryToken);
                    }
                }
            }
            else
            {
                throw new ExternalException(SR.GetString(SR.ExecCantExec, cmd), Marshal.GetLastWin32Error());
            }

            return(retValue);
        }
Exemple #10
0
        private bool StartWithCreateProcess(ProcessStartInfo startInfo)
        {
            if (startInfo.RedirectStandardInput)
            {
                throw new InvalidOperationException("Standard input redirect not allowed");
            }

            if (startInfo.RedirectStandardOutput)
            {
                throw new InvalidOperationException("Standard output redirect not allowed");
            }

            if (startInfo.RedirectStandardError)
            {
                throw new InvalidOperationException("Standard error redirect not allowed");
            }

            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
            if (this._Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);

            NativeMethods.STARTUPINFO         startupInfo = new NativeMethods.STARTUPINFO();
            NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION();

            bool retVal;
            int  errorCode = 0;

            // set up the creation flags paramater
            int creationFlags = 0;

            if (startInfo.CreateNoWindow)
            {
                creationFlags          |= (int)NativeMethods.CreateProcessFlags.CREATE_NO_WINDOW;
                startupInfo.dwFlags     = NativeMethods.STARTF_USESHOWWINDOW;
                startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE;
            }
            else
            {
                creationFlags |= (int)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE;
                switch (startInfo.WindowStyle)
                {
                case ProcessWindowStyle.Maximized:
                    startupInfo.dwFlags     = NativeMethods.STARTF_USESHOWWINDOW;
                    startupInfo.wShowWindow = (short)NativeMethods.SW_MAXIMIZE;
                    break;

                case ProcessWindowStyle.Minimized:
                    startupInfo.dwFlags     = NativeMethods.STARTF_USESHOWWINDOW;
                    startupInfo.wShowWindow = (short)NativeMethods.SW_MINIMIZE;
                    break;

                case ProcessWindowStyle.Hidden:
                    startupInfo.dwFlags     = NativeMethods.STARTF_USESHOWWINDOW;
                    startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE;
                    break;
                }
            }

            string workingDirectory = startInfo.WorkingDirectory;

            if (workingDirectory == string.Empty)
            {
                workingDirectory = ProcessUtils.StartupPath;
            }

            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally
            {
                retVal = NativeMethods.CreateProcess(
                    null,                   // we don't need this since all the info is in commandLine
                    commandLine.ToString(), // pointer to the command line string
                    IntPtr.Zero,            // pointer to process security attributes, we don't need to inheriat the handle
                    IntPtr.Zero,            // pointer to thread security attributes
                    true,                   // handle inheritance flag
                    creationFlags,          // creation flags
                    IntPtr.Zero,            // pointer to new environment block
                    workingDirectory,       // pointer to current directory name
                    ref startupInfo,        // pointer to STARTUPINFO
                    out processInfo         // pointer to PROCESS_INFORMATION
                    );
                if (!retVal)
                {
                    errorCode = Marshal.GetLastWin32Error();
                }
            }
            if (!retVal)
            {
                if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT)
                {
                    throw new Win32Exception(errorCode, "Invalid application");
                }
                throw new Win32Exception(errorCode);
            }


            bool ret = false;

            if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
            {
                _ProcessHandle     = processInfo.hProcess;
                _HaveProcessHandle = true;
                if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                {
                    NativeMethods.CloseHandle(processInfo.hThread);
                }
                ret = true;
            }

            return(ret);
        }
Exemple #11
0
        private static void StartProcessWithLogonNetOnly(ProcessStartInfo startInfo, bool waitForExit)
        {
            if (startInfo.UseShellExecute)
            {
                throw new InvalidOperationException("UseShellExecute must be false.");
            }

            if (startInfo.LoadUserProfile)
            {
                throw new InvalidOperationException("LoadUserProfile cannot be used.");
            }

            if (string.IsNullOrEmpty(startInfo.UserName))
            {
                throw new InvalidOperationException("UserName is empty.");
            }

            var cmdLine              = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
            var lpStartupInfo        = new NativeMethods.STARTUPINFO();
            var lpProcessInformation = new NativeMethods.PROCESS_INFORMATION();

            int creationFlags = 0;

            if (startInfo.CreateNoWindow)
            {
                creationFlags |= 0x8000000;
            }

            IntPtr zero = IntPtr.Zero;

            string workingDirectory = startInfo.WorkingDirectory;

            if (string.IsNullOrEmpty(workingDirectory))
            {
                workingDirectory = Environment.CurrentDirectory;
            }

            NativeMethods.LogonFlags logonFlags = NativeMethods.LogonFlags.LOGON_NETCREDENTIALS_ONLY;   //NetOnly;

            IntPtr passwordPrt = IntPtr.Zero;

            try
            {
                if (startInfo.Password == null)
                {
                    passwordPrt = Marshal.StringToCoTaskMemUni(string.Empty);
                }
                else
                {
                    passwordPrt = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
                }

                int  error = 0;
                bool flag  = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, passwordPrt, logonFlags, null, cmdLine, creationFlags, zero, workingDirectory, lpStartupInfo, lpProcessInformation);
                if (!flag)
                {
                    error = Marshal.GetLastWin32Error();
                }

                if (!flag)
                {
                    if (error != 0xc1 && error != 0xd8)
                    {
                        throw new Win32Exception(error);
                    }
                    throw new Win32Exception(error, "Invalid Application");
                }
            }
            finally
            {
                if (passwordPrt != IntPtr.Zero)
                {
                    Marshal.ZeroFreeCoTaskMemUnicode(passwordPrt);
                }
            }

            if (waitForExit)
            {
                NativeMethods.WaitForSingleObject(lpProcessInformation.hProcess, 0xFFFFFFFF);
            }
        }
        public Tuple <bool, int> CreateProcessAsUser(IntPtr hUserToken, string appFileName, string appArgs)
        {
            try
            {
                // Identify user from access token.
                WindowsIdentity userId = new WindowsIdentity(hUserToken);
                _logger.Log("Create process for: " + userId.Name + " [" + appFileName + " " + appArgs + "].");
                userId.Dispose();

                // Obtain duplicated user token (elevated if UAC is turned on/enabled).
                IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken);

                // Initialize process info and startup info.
                NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION();
                NativeMethods.STARTUPINFO         si = new NativeMethods.STARTUPINFO();
                si.cb        = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";
                NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
                NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes  = new NativeMethods.SECURITY_ATTRIBUTES();
                IntPtr hEnvironment = IntPtr.Zero;

                if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true))
                {
                    _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN);
                }

                if (!NativeMethods.CreateProcessAsUser(
                        hDuplicateToken,
                        null,
                        appFileName + " " + appArgs,
                        ref lpProcessAttributes,
                        ref lpThreadAttributes,
                        false,
                        (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS |
                        (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT |
                        (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE,
                        hEnvironment,
                        Path.GetDirectoryName(appFileName),
                        ref si,
                        out pi))
                {
                    _logger.Log("Unable to create user process [CreateProcessAsUser="******"].", Logger.MsgType.ERROR);

                    Marshal.FreeHGlobal(hDuplicateToken);
                    Marshal.FreeHGlobal(hEnvironment);
                    Marshal.FreeHGlobal(hUserToken);
                    return(new Tuple <bool, int>(false, -1));
                }
                else
                {
                    _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs);
                    var newProcess = Process.GetProcessById(pi.dwProcessId);

                    try
                    {
                        // For UI apps, wait for idle state, before continuing.
                        newProcess.WaitForInputIdle(2000);
                    }
                    catch (InvalidOperationException)
                    {
                        // Must be a non-UI app, just give it a sec to start.
                        Thread.Sleep(1000);
                    }

                    newProcess.Dispose();
                    Marshal.FreeHGlobal(hDuplicateToken);
                    Marshal.FreeHGlobal(hEnvironment);
                    Marshal.FreeHGlobal(hUserToken);
                    return(new Tuple <bool, int>(true, pi.dwProcessId));
                }
            }
            catch (Exception e)
            {
                _logger.Log(e, "Failed to create process as user.");
                return(new Tuple <bool, int>(false, -1));
            }
        }
        public bool CreateProcessAsUser(WindowsIdentity userId, string appFileName, string appArgs)
        {
            try
            {
                _logger.Log("Create process for: " + userId.Name);
                List <Tuple <uint, string> > userSessions = new WindowsHelper(_logger).GetUserSessions();
                int sessionId = -1;

                foreach (Tuple <uint, string> logonSession in userSessions)
                {
                    if (logonSession.Item2.ToLower().Equals(userId.Name.ToLower()))
                    {
                        sessionId = (int)logonSession.Item1;
                        break;
                    }
                }

                if (sessionId == -1)
                {
                    _logger.Log("Failed to match any/existing logon session with user [" + userId.Name + "].", Logger.MsgType.ERROR);
                    return(false);
                }

                if (!NativeMethods.WTSQueryUserToken((uint)sessionId, out IntPtr hUserToken))
                {
                    _logger.Log("Failed to query user token [WTSQueryUserToken=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.ERROR);
                    return(false);
                }

                // Obtain duplicated user token (elevated if UAC is turned on/enabled).
                IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken, (uint)sessionId);
                Marshal.FreeHGlobal(hUserToken);

                // Initialize process info and startup info.
                NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION();
                NativeMethods.STARTUPINFO         si = new NativeMethods.STARTUPINFO();
                si.cb        = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";
                NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
                NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes  = new NativeMethods.SECURITY_ATTRIBUTES();
                IntPtr hEnvironment = IntPtr.Zero;

                if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true))
                {
                    _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN);
                }

                if (!NativeMethods.CreateProcessAsUser(
                        hDuplicateToken,
                        null,
                        appFileName + " " + appArgs,
                        ref lpProcessAttributes,
                        ref lpThreadAttributes,
                        false,
                        (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS |
                        (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT |
                        (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE,
                        hEnvironment,
                        Path.GetDirectoryName(appFileName),
                        ref si,
                        out pi))
                {
                    _logger.Log("ERROR: Unable to create user process [CreateProcessAsUser="******"].");
                    return(false);
                }
                else
                {
                    _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs);
                    var newProcess = Process.GetProcessById(pi.dwProcessId);

                    try
                    {
                        // For UI apps, wait for idle state, before continuing.
                        newProcess.WaitForInputIdle(2000);
                    }
                    catch (InvalidOperationException)
                    {
                        // Must be a non-UI app, just give it a sec to start.
                        Thread.Sleep(1000);
                    }

                    return(true);
                }
            }
            catch (Exception e)
            {
                _logger.Log(e, "Failed to create process as user.");
                return(false);
            }
        }