Esempio n. 1
0
 private bool StartWithCreateProcess(ProcessStartInfo startInfo)
 {
     if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput)
     {
         throw new InvalidOperationException("StandardOutputEncodingNotAllowed");
     }
     if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError)
     {
         throw new InvalidOperationException("StandardErrorEncodingNotAllowed");
     }
     StringBuilder stringBuilder = Process2.BuildCommandLine(startInfo.FileName, startInfo.Arguments);
     NativeMethods.STARTUPINFO sTARTUPINFO = new NativeMethods.STARTUPINFO();
     SafeNativeMethods.PROCESS_INFORMATION pROCESS_INFORMATION = new SafeNativeMethods.PROCESS_INFORMATION();
     SafeProcessHandle safeProcessHandle = new SafeProcessHandle();
     SafeThreadHandle safeThreadHandle = new SafeThreadHandle();
     int num = 0;
     SafeFileHandle handle = null;
     SafeFileHandle handle2 = null;
     SafeFileHandle handle3 = null;
     GCHandle gCHandle = default(GCHandle);
     lock (Process2.s_CreateProcessLock)
     {
         try
         {
             if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
             {
                 if (startInfo.RedirectStandardInput)
                 {
                     CreatePipe(out handle, out sTARTUPINFO.hStdInput, true);
                 }
                 else
                 {
                     sTARTUPINFO.hStdInput = new SafeFileHandle(NativeMethods.GetStdHandle(-10), false);
                 }
                 if (startInfo.RedirectStandardOutput)
                 {
                     CreatePipe(out handle2, out sTARTUPINFO.hStdOutput, false);
                 }
                 else
                 {
                     sTARTUPINFO.hStdOutput = new SafeFileHandle(NativeMethods.GetStdHandle(-11), false);
                 }
                 if (startInfo.RedirectStandardError)
                 {
                     CreatePipe(out handle3, out sTARTUPINFO.hStdError, false);
                 }
                 else
                 {
                     sTARTUPINFO.hStdError = sTARTUPINFO.hStdOutput;
                 }
                 sTARTUPINFO.dwFlags = 256;
             }
             int num2 = 0;
             if (startInfo.CreateNoWindow)
             {
                 num2 |= 134217728;
             }
             IntPtr intPtr = (IntPtr)0;
             //if (startInfo.environmentVariables != null)
             //{
             //    bool unicode = false;
             //    if (ProcessManager.IsNt)
             //    {
             //        num2 |= 1024;
             //        unicode = true;
             //    }
             //    byte[] value = EnvironmentBlock.ToByteArray(startInfo.environmentVariables, unicode);
             //    gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
             //    intPtr = gCHandle.AddrOfPinnedObject();
             //}
             string text = startInfo.WorkingDirectory;
             if (text == string.Empty)
             {
                 text = Environment.CurrentDirectory;
             }
             bool flag2;
             //if (startInfo.UserName.Length != 0)
             //{
             //    NativeMethods.LogonFlags logonFlags = (NativeMethods.LogonFlags)0;
             //    if (startInfo.LoadUserProfile)
             //    {
             //        logonFlags = NativeMethods.LogonFlags.LOGON_WITH_PROFILE;
             //    }
             //    IntPtr intPtr2 = IntPtr.Zero;
             //    try
             //    {
             //        if (startInfo.Password == null)
             //        {
             //            intPtr2 = Marshal.StringToCoTaskMemUni(string.Empty);
             //        }
             //        else
             //        {
             //            intPtr2 = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password);
             //        }
             //        RuntimeHelpers.PrepareConstrainedRegions();
             //        try
             //        {
             //        }
             //        finally
             //        {
             //            flag2 = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, intPtr2, logonFlags, null, stringBuilder, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION);
             //            if (!flag2)
             //            {
             //                num = Marshal.GetLastWin32Error();
             //            }
             //            if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE)
             //            {
             //                safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess);
             //            }
             //            if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE)
             //            {
             //                safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread);
             //            }
             //        }
             //        if (flag2)
             //        {
             //            goto IL_3B9;
             //        }
             //        if (num == 193 || num == 216)
             //        {
             //            throw new Win32Exception(num, SR.GetString("InvalidApplication"));
             //        }
             //        throw new Win32Exception(num);
             //    }
             //    finally
             //    {
             //        if (intPtr2 != IntPtr.Zero)
             //        {
             //            Marshal.ZeroFreeCoTaskMemUnicode(intPtr2);
             //        }
             //    }
             //}
             RuntimeHelpers.PrepareConstrainedRegions();
             try
             {
             }
             finally
             {
                 flag2 = NativeMethods.CreateProcess(null, stringBuilder, null, null, true, num2, intPtr, text, sTARTUPINFO, pROCESS_INFORMATION);
                 if (!flag2)
                 {
                     num = Marshal.GetLastWin32Error();
                 }
                 if (pROCESS_INFORMATION.hProcess != (IntPtr)0 && pROCESS_INFORMATION.hProcess != NativeMethods.INVALID_HANDLE_VALUE)
                 {
                     safeProcessHandle.InitialSetHandle(pROCESS_INFORMATION.hProcess);
                 }
                 if (pROCESS_INFORMATION.hThread != (IntPtr)0 && pROCESS_INFORMATION.hThread != NativeMethods.INVALID_HANDLE_VALUE)
                 {
                     safeThreadHandle.InitialSetHandle(pROCESS_INFORMATION.hThread);
                 }
             }
             if (!flag2)
             {
                 if (num == 193 || num == 216)
                 {
                     throw new Win32Exception(num, "InvalidApplication");
                 }
                 throw new Win32Exception(num);
             }
         }
         finally
         {
             if (gCHandle.IsAllocated)
             {
                 gCHandle.Free();
             }
             sTARTUPINFO.Dispose();
         }
     }
     if (startInfo.RedirectStandardInput)
     {
         standardInput = new StreamWriter(new FileStream(handle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
         standardInput.AutoFlush = true;
     }
     if (startInfo.RedirectStandardOutput)
     {
         Encoding encoding = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
         standardOutput = new StreamReader(new FileStream(handle2, FileAccess.Read, 4096, false), encoding, true, 4096);
     }
     if (startInfo.RedirectStandardError)
     {
         Encoding encoding2 = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
         standardError = new StreamReader(new FileStream(handle3, FileAccess.Read, 4096, false), encoding2, true, 4096);
     }
     bool result = false;
     if (!safeProcessHandle.IsInvalid)
     {
         SetProcessHandle(safeProcessHandle);
         SetProcessId(pROCESS_INFORMATION.dwProcessId);
         safeThreadHandle.Close();
         result = true;
     }
     return result;
 }
Esempio n. 2
0
        public static bool CreateProcess(ProcessStartInfo startInfo, bool createSuspended, out SafeProcessHandle process, out SafeThreadHandle thread, out uint processID, out uint threadID)
        {
            StringBuilder cmdLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
            STARTUPINFO lpStartupInfo = new STARTUPINFO();
            PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();
            SafeProcessHandle processHandle = new SafeProcessHandle();
            SafeThreadHandle threadHandle = new SafeThreadHandle();
            GCHandle environment = new GCHandle();
            int creationFlags = 0;
            bool success;

            creationFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_PRESERVE_CODE_AUTHZ_LEVEL;

            if (createSuspended)
                creationFlags |= CREATE_SUSPENDED;

            if (startInfo.CreateNoWindow)
                creationFlags |= CREATE_NO_WINDOW;

            IntPtr pinnedEnvironment = IntPtr.Zero;

            if (startInfo.EnvironmentVariables != null)
            {
                bool unicode = false;
                if (IsNt)
                {
                    creationFlags |= CREATE_UNICODE_ENVIRONMENT;
                    unicode = true;
                }
                environment = GCHandle.Alloc(EnvironmentToByteArray(startInfo.EnvironmentVariables, unicode), GCHandleType.Pinned);
                pinnedEnvironment = environment.AddrOfPinnedObject();
            }

            string workingDirectory = startInfo.WorkingDirectory;
            if (workingDirectory == "")
                workingDirectory = Environment.CurrentDirectory;

            success = CreateProcess(null, cmdLine, null, null, false, creationFlags, pinnedEnvironment, workingDirectory, lpStartupInfo, lpProcessInformation);

            if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != INVALID_HANDLE_VALUE))
                processHandle.InitialSetHandle(lpProcessInformation.hProcess);

            if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != INVALID_HANDLE_VALUE))
                threadHandle.InitialSetHandle(lpProcessInformation.hThread);

            if (environment.IsAllocated)
                environment.Free();

            lpStartupInfo.Dispose();

            if (success && !processHandle.IsInvalid && !threadHandle.IsInvalid)
            {
                process = processHandle;
                thread = threadHandle;
                processID = lpProcessInformation.dwProcessId;
                threadID = lpProcessInformation.dwThreadId;
                return true;
            }

            process = null;
            thread = null;
            processID = 0;
            threadID = 0;
            return false;
        }
    /// <summary>
    /// Calls <see cref="CreateProcessAsUserW"/> and safely stores the obtained handles.
    /// </summary>
    /// <param name="userToken">Token to impersonate the external process</param>
    /// <param name="createFlags">Flags used to create the external process</param>
    /// <param name="startupInfo">Startup information used to create the external process</param>
    /// <returns><c>true</c> if the call to <see cref="CreateProcessAsUserW"/> was successful; otherwise <c>false</c></returns>
    private bool SafeCreateProcessAsUserW(IntPtr userToken, CreateProcessFlags createFlags, StartupInfo startupInfo)
    {
      _processHandle = new SafeProcessHandle();
      var threadHandle = new SafeThreadHandle();
      bool success;

      // The following is necessary to make sure that processInformation.hProcess and processInformation.hThread
      // are safely stored in the respective SafeHandle classes. It is, unfortunately, not possible to define
      // processInformation.hProcess and processInformation.hThread as SafeHandles and use processInformation
      // as an out parameter, because the unmanaged code is not able to create these objects. We therefore use
      // IntPtr and ensure in the following that the IntPtrs are stored in SafeHandle objects immediately after
      // they have been obtained.
      // For details see here: https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions(v=vs.110).aspx
      RuntimeHelpers.PrepareConstrainedRegions();
      try { }
      finally
      {
        ProcessInformation processInformation;
        success = CreateProcessAsUserW(userToken, null, GetCommandLine(), IntPtr.Zero, IntPtr.Zero, true, createFlags, IntPtr.Zero, null, startupInfo, out processInformation);
        if (success)
        {
          _processHandle.InitialSetHandle(processInformation.hProcess);
          threadHandle.InitialSetHandle(processInformation.hThread);
          _processId = processInformation.dwProcessId;
        }
      }
      
      // We don't need the threadHandle and therefore immediately dispose it.
      threadHandle.Dispose();

      if (success)
        return true;

      _processHandle.Dispose();
      var error = Marshal.GetLastWin32Error();
      _debugLogger.Error("AsyncImpersonationProcess ({0}): Cannot start process. ErrorCode: {1} ({2})", StartInfo.FileName, error, new Win32Exception(error).Message);
      return false;
    }
Esempio n. 4
0
        /// <summary>Starts the process using the supplied start info.</summary>
        /// <param name="startInfo">The start info with which to start the process.</param>
        private unsafe bool StartWithCreateProcess(ProcessStartInfo startInfo)
        {
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
            //      GetStdHandle for the handles that are not being redirected

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

            Process.AppendArguments(commandLine, StartInfo.ArgumentList);

            Interop.Kernel32.STARTUPINFO         startupInfo     = new Interop.Kernel32.STARTUPINFO();
            Interop.Kernel32.PROCESS_INFORMATION processInfo     = new Interop.Kernel32.PROCESS_INFORMATION();
            Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES();
            SafeProcessHandle procSH   = new SafeProcessHandle();
            SafeThreadHandle  threadSH = new SafeThreadHandle();
            // handles used in parent process
            SafeFileHandle parentInputPipeHandle  = null;
            SafeFileHandle childInputPipeHandle   = null;
            SafeFileHandle parentOutputPipeHandle = null;
            SafeFileHandle childOutputPipeHandle  = null;
            SafeFileHandle parentErrorPipeHandle  = null;
            SafeFileHandle childErrorPipeHandle   = null;

            lock (s_createProcessLock)
            {
                try
                {
                    startupInfo.cb = sizeof(Interop.Kernel32.STARTUPINFO);

                    // set up the streams
                    if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
                    {
                        if (startInfo.RedirectStandardInput)
                        {
                            CreatePipe(out parentInputPipeHandle, out childInputPipeHandle, true);
                        }
                        else
                        {
                            childInputPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardOutput)
                        {
                            CreatePipe(out parentOutputPipeHandle, out childOutputPipeHandle, false);
                        }
                        else
                        {
                            childOutputPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardError)
                        {
                            CreatePipe(out parentErrorPipeHandle, out childErrorPipeHandle, false);
                        }
                        else
                        {
                            childErrorPipeHandle = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_ERROR_HANDLE), false);
                        }

                        startupInfo.hStdInput  = childInputPipeHandle.DangerousGetHandle();
                        startupInfo.hStdOutput = childOutputPipeHandle.DangerousGetHandle();
                        startupInfo.hStdError  = childErrorPipeHandle.DangerousGetHandle();

                        startupInfo.dwFlags = Interop.Advapi32.StartupInfoOptions.STARTF_USESTDHANDLES;
                    }

                    // set up the creation flags parameter
                    int creationFlags = 0;
                    if (startInfo.CreateNoWindow)
                    {
                        creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_NO_WINDOW;
                    }

                    // set up the environment block parameter
                    string environmentBlock = null;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags   |= Interop.Advapi32.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
                        environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables);
                    }
                    string workingDirectory = startInfo.WorkingDirectory;
                    if (workingDirectory == string.Empty)
                    {
                        workingDirectory = Directory.GetCurrentDirectory();
                    }

                    bool retVal;
                    int  errorCode = 0;

                    if (startInfo.UserName.Length != 0)
                    {
                        if (startInfo.Password != null && startInfo.PasswordInClearText != null)
                        {
                            throw new ArgumentException(SR.CantSetDuplicatePassword);
                        }

                        Interop.Advapi32.LogonFlags logonFlags = (Interop.Advapi32.LogonFlags) 0;
                        if (startInfo.LoadUserProfile)
                        {
                            logonFlags = Interop.Advapi32.LogonFlags.LOGON_WITH_PROFILE;
                        }

                        fixed(char *passwordInClearTextPtr = startInfo.PasswordInClearText ?? string.Empty)
                        fixed(char *environmentBlockPtr = environmentBlock)
                        {
                            IntPtr passwordPtr = (startInfo.Password != null) ?
                                                 Marshal.SecureStringToGlobalAllocUnicode(startInfo.Password) : IntPtr.Zero;

                            try
                            {
                                retVal = Interop.Advapi32.CreateProcessWithLogonW(
                                    startInfo.UserName,
                                    startInfo.Domain,
                                    (passwordPtr != IntPtr.Zero) ? passwordPtr : (IntPtr)passwordInClearTextPtr,
                                    logonFlags,
                                    null,            // we don't need this since all the info is in commandLine
                                    commandLine,
                                    creationFlags,
                                    (IntPtr)environmentBlockPtr,
                                    workingDirectory,
                                    ref startupInfo,        // pointer to STARTUPINFO
                                    ref processInfo         // pointer to PROCESS_INFORMATION
                                    );
                                if (!retVal)
                                {
                                    errorCode = Marshal.GetLastWin32Error();
                                }
                            }
                            finally
                            {
                                if (passwordPtr != IntPtr.Zero)
                                {
                                    Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);
                                }
                            }
                        }
                    }
                    else
                    {
                        fixed(char *environmentBlockPtr = environmentBlock)
                        {
                            retVal = Interop.Kernel32.CreateProcess(
                                null,                        // we don't need this since all the info is in commandLine
                                commandLine,                 // pointer to the command line string
                                ref unused_SecAttrs,         // address to process security attributes, we don't need to inherit the handle
                                ref unused_SecAttrs,         // address to thread security attributes.
                                true,                        // handle inheritance flag
                                creationFlags,               // creation flags
                                (IntPtr)environmentBlockPtr, // pointer to new environment block
                                workingDirectory,            // pointer to current directory name
                                ref startupInfo,             // pointer to STARTUPINFO
                                ref processInfo              // pointer to PROCESS_INFORMATION
                                );
                            if (!retVal)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                        }
                    }

                    if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != (IntPtr)INVALID_HANDLE_VALUE)
                    {
                        procSH.InitialSetHandle(processInfo.hProcess);
                    }
                    if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != (IntPtr)INVALID_HANDLE_VALUE)
                    {
                        threadSH.InitialSetHandle(processInfo.hThread);
                    }

                    if (!retVal)
                    {
                        if (errorCode == Interop.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                        {
                            throw new Win32Exception(errorCode, SR.InvalidApplication);
                        }
                        throw new Win32Exception(errorCode);
                    }
                }
                finally
                {
                    childInputPipeHandle?.Dispose();
                    childOutputPipeHandle?.Dispose();
                    childErrorPipeHandle?.Dispose();

                    threadSH?.Dispose();
                }
            }

            if (startInfo.RedirectStandardInput)
            {
                Encoding enc = startInfo.StandardInputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleCP());
                _standardInput           = new StreamWriter(new FileStream(parentInputPipeHandle, FileAccess.Write, 4096, false), enc, 4096);
                _standardInput.AutoFlush = true;
            }
            if (startInfo.RedirectStandardOutput)
            {
                Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(parentOutputPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
                _standardError = new StreamReader(new FileStream(parentErrorPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }

            if (procSH.IsInvalid)
            {
                return(false);
            }

            SetProcessHandle(procSH);
            SetProcessId((int)processInfo.dwProcessId);
            return(true);
        }
Esempio n. 5
0
        /// <summary>Starts the process using the supplied start info.</summary>
        /// <param name="startInfo">The start info with which to start the process.</param>
        private bool StartCore(ProcessStartInfo startInfo)
        {
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
            //      GetStdHandle for the handles that are not being redirected

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

            Interop.mincore.STARTUPINFO         startupInfo     = new Interop.mincore.STARTUPINFO();
            Interop.mincore.PROCESS_INFORMATION processInfo     = new Interop.mincore.PROCESS_INFORMATION();
            Interop.mincore.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.mincore.SECURITY_ATTRIBUTES();
            SafeProcessHandle procSH   = new SafeProcessHandle();
            SafeThreadHandle  threadSH = new SafeThreadHandle();
            bool retVal;
            int  errorCode = 0;
            // handles used in parent process
            SafeFileHandle standardInputWritePipeHandle = null;
            SafeFileHandle standardOutputReadPipeHandle = null;
            SafeFileHandle standardErrorReadPipeHandle  = null;
            GCHandle       environmentHandle            = new GCHandle();

            lock (s_createProcessLock)
            {
                try
                {
                    // set up the streams
                    if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
                    {
                        if (startInfo.RedirectStandardInput)
                        {
                            CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
                        }
                        else
                        {
                            startupInfo.hStdInput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_INPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardOutput)
                        {
                            CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
                        }
                        else
                        {
                            startupInfo.hStdOutput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardError)
                        {
                            CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
                        }
                        else
                        {
                            startupInfo.hStdError = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_ERROR_HANDLE), false);
                        }

                        startupInfo.dwFlags = Interop.mincore.StartupInfoOptions.STARTF_USESTDHANDLES;
                    }

                    // set up the creation flags paramater
                    int creationFlags = 0;
                    if (startInfo.CreateNoWindow)
                    {
                        creationFlags |= Interop.mincore.StartupInfoOptions.CREATE_NO_WINDOW;
                    }

                    // set up the environment block parameter
                    IntPtr environmentPtr = (IntPtr)0;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags |= Interop.mincore.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
                        byte[] environmentBytes = EnvironmentVariablesToByteArray(startInfo._environmentVariables);
                        environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                        environmentPtr    = environmentHandle.AddrOfPinnedObject();
                    }
                    string workingDirectory = startInfo.WorkingDirectory;
                    if (workingDirectory == string.Empty)
                    {
                        workingDirectory = Directory.GetCurrentDirectory();
                    }

                    if (startInfo.UserName.Length != 0)
                    {
                        Interop.mincore.LogonFlags logonFlags = (Interop.mincore.LogonFlags) 0;
                        if (startInfo.LoadUserProfile)
                        {
                            logonFlags = Interop.mincore.LogonFlags.LOGON_WITH_PROFILE;
                        }


                        try { }
                        finally
                        {
                            retVal = Interop.mincore.CreateProcessWithLogonW(
                                startInfo.UserName,
                                startInfo.Domain,
                                startInfo.PasswordInClearText,
                                logonFlags,
                                null,                // we don't need this since all the info is in commandLine
                                commandLine,
                                creationFlags,
                                environmentPtr,
                                workingDirectory,
                                startupInfo,            // pointer to STARTUPINFO
                                processInfo             // pointer to PROCESS_INFORMATION
                                );
                            if (!retVal)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                            if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != (IntPtr)INVALID_HANDLE_VALUE)
                            {
                                procSH.InitialSetHandle(processInfo.hProcess);
                            }
                            if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != (IntPtr)INVALID_HANDLE_VALUE)
                            {
                                threadSH.InitialSetHandle(processInfo.hThread);
                            }
                        }
                        if (!retVal)
                        {
                            if (errorCode == Interop.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                            {
                                throw new Win32Exception(errorCode, SR.InvalidApplication);
                            }

                            throw new Win32Exception(errorCode);
                        }
                    }
                    else
                    {
                        try { }
                        finally
                        {
                            retVal = Interop.mincore.CreateProcess(
                                null,                // we don't need this since all the info is in commandLine
                                commandLine,         // pointer to the command line string
                                ref unused_SecAttrs, // address to process security attributes, we don't need to inheriat the handle
                                ref unused_SecAttrs, // address to thread security attributes.
                                true,                // handle inheritance flag
                                creationFlags,       // creation flags
                                environmentPtr,      // pointer to new environment block
                                workingDirectory,    // pointer to current directory name
                                startupInfo,         // pointer to STARTUPINFO
                                processInfo          // pointer to PROCESS_INFORMATION
                                );
                            if (!retVal)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                            if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)INVALID_HANDLE_VALUE)
                            {
                                procSH.InitialSetHandle(processInfo.hProcess);
                            }
                            if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)INVALID_HANDLE_VALUE)
                            {
                                threadSH.InitialSetHandle(processInfo.hThread);
                            }
                        }
                        if (!retVal)
                        {
                            if (errorCode == Interop.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                            {
                                throw new Win32Exception(errorCode, SR.InvalidApplication);
                            }

                            throw new Win32Exception(errorCode);
                        }
                    }
                }
                finally
                {
                    // free environment block
                    if (environmentHandle.IsAllocated)
                    {
                        environmentHandle.Free();
                    }

                    startupInfo.Dispose();
                }
            }

            if (startInfo.RedirectStandardInput)
            {
                Encoding enc = GetEncoding((int)Interop.mincore.GetConsoleCP());
                _standardInput           = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096);
                _standardInput.AutoFlush = true;
            }
            if (startInfo.RedirectStandardOutput)
            {
                Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }

            bool ret = false;

            if (!procSH.IsInvalid)
            {
                SetProcessHandle(procSH);
                SetProcessId((int)processInfo.dwProcessId);
                threadSH.Dispose();
                ret = true;
            }

            return(ret);
        }
Esempio n. 6
0
        private static unsafe int ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine)
        {
            IntSecurity.UnmanagedCode.Demand();

            FileStream output;
            FileStream 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;

            SafeNativeMethods.PROCESS_INFORMATION pi = new SafeNativeMethods.PROCESS_INFORMATION();
            SafeProcessHandle   procSH       = new SafeProcessHandle();
            SafeThreadHandle    threadSH     = new SafeThreadHandle();
            SafeUserTokenHandle primaryToken = null;

            try {
                // Output the command line...
                StreamWriter sw = new StreamWriter(output, 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();

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

                si.cb = Marshal.SizeOf(si);
#if FEATURE_PAL
                si.dwFlags = NativeMethods.STARTF_USESTDHANDLES;
#else //!FEATURE_PAL
                si.dwFlags     = NativeMethods.STARTF_USESTDHANDLES | NativeMethods.STARTF_USESHOWWINDOW;
                si.wShowWindow = NativeMethods.SW_HIDE;
#endif //!FEATURE_PAL
                si.hStdOutput = output.SafeFileHandle;
                si.hStdError  = error.SafeFileHandle;
                si.hStdInput  = new SafeFileHandle(UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false);

                //
                // Prepare the environment
                //
#if PLATFORM_UNIX
                StringDictionary environment = new CaseSensitiveStringDictionary();
#else
                StringDictionary environment = new StringDictionary();
#endif // PLATFORM_UNIX

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

                // Add the flag to indicate restricted security in the process
                environment["_ClrRestrictSecAttributes"] = "1";

                #if DEBUG
                environment["OANOCACHE"] = "1";
                #endif

                // set up the environment block parameter
                byte[] environmentBytes = EnvironmentBlock.ToByteArray(environment, false);
                fixed(byte *environmentBytesPtr = environmentBytes)
                {
                    IntPtr environmentPtr = new IntPtr((void *)environmentBytesPtr);

                    if (userToken == null || userToken.IsInvalid)
                    {
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try {} finally {
                            success = NativeMethods.CreateProcess(
                                null,                              // String lpApplicationName,
                                new StringBuilder(cmd),            // String lpCommandLine,
                                null,                              // SECURITY_ATTRIBUTES lpProcessAttributes,
                                null,                              // SECURITY_ATTRIBUTES lpThreadAttributes,
                                true,                              // bool bInheritHandles,
                                0,                                 // int dwCreationFlags,
                                environmentPtr,                    // IntPtr lpEnvironment,
                                currentDir,                        // String lpCurrentDirectory,
                                si,                                // STARTUPINFO lpStartupInfo,
                                pi);                               // PROCESS_INFORMATION lpProcessInformation);
                            if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                            {
                                procSH.InitialSetHandle(pi.hProcess);
                            }
                            if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                            {
                                threadSH.InitialSetHandle(pi.hThread);
                            }
                        }
                    }
                    else
                    {
#if FEATURE_PAL
                        throw new NotSupportedException();
#else
                        success = SafeUserTokenHandle.DuplicateTokenEx(
                            userToken,
                            NativeMethods.TOKEN_ALL_ACCESS,
                            null,
                            NativeMethods.IMPERSONATION_LEVEL_SecurityImpersonation,
                            NativeMethods.TOKEN_TYPE_TokenPrimary,
                            out primaryToken
                            );


                        if (success)
                        {
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try {} finally {
                                success = NativeMethods.CreateProcessAsUser(
                                    primaryToken,                        // int token,
                                    null,                                // String lpApplicationName,
                                    cmd,                                 // String lpCommandLine,
                                    null,                                // SECURITY_ATTRIBUTES lpProcessAttributes,
                                    null,                                // SECURITY_ATTRIBUTES lpThreadAttributes,
                                    true,                                // bool bInheritHandles,
                                    0,                                   // int dwCreationFlags,
                                    new HandleRef(null, environmentPtr), // IntPtr lpEnvironment,
                                    currentDir,                          // String lpCurrentDirectory,
                                    si,                                  // STARTUPINFO lpStartupInfo,
                                    pi);                                 // PROCESS_INFORMATION lpProcessInformation);
                                if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                                {
                                    procSH.InitialSetHandle(pi.hProcess);
                                }
                                if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE)
                                {
                                    threadSH.InitialSetHandle(pi.hThread);
                                }
                            }
                        }
#endif // !FEATURE_PAL
                    }
                }
            }
            finally {
                // Close the file handles
                if (!success && (primaryToken != null && !primaryToken.IsInvalid))
                {
                    primaryToken.Close();
                    primaryToken = null;
                }

                output.Close();
                error.Close();
            }

            if (success)
            {
                try {
                    bool signaled;
                    ProcessWaitHandle pwh = null;
                    try {
                        pwh      = new ProcessWaitHandle(procSH);
                        signaled = pwh.WaitOne(ProcessTimeOut, false);
                    } finally {
                        if (pwh != null)
                        {
                            pwh.Close();
                        }
                    }

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

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

                    retValue = status;
                }
                finally {
                    procSH.Close();
                    threadSH.Close();
                    if (primaryToken != null && !primaryToken.IsInvalid)
                    {
                        primaryToken.Close();
                    }
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                if (err == NativeMethods.ERROR_NOT_ENOUGH_MEMORY)
                {
                    throw new OutOfMemoryException();
                }

                Win32Exception    win32Exception = new Win32Exception(err);
                ExternalException ex             = new ExternalException(SR.GetString(SR.ExecCantExec, cmd), win32Exception);
                throw ex;
            }

            return(retValue);
        }
Esempio n. 7
0
        public static bool CreateProcess(ProcessStartInfo startInfo, bool createSuspended, out SafeProcessHandle process, out SafeThreadHandle thread, out uint processID, out uint threadID)
        {
            StringBuilder       cmdLine              = BuildCommandLine(startInfo.FileName, startInfo.Arguments);
            STARTUPINFO         lpStartupInfo        = new STARTUPINFO();
            PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();
            SafeProcessHandle   processHandle        = new SafeProcessHandle();
            SafeThreadHandle    threadHandle         = new SafeThreadHandle();
            GCHandle            environment          = new GCHandle();
            int  creationFlags = 0;
            bool success;

            creationFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_PRESERVE_CODE_AUTHZ_LEVEL;


            if (createSuspended)
            {
                creationFlags |= CREATE_SUSPENDED;
            }

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

            IntPtr pinnedEnvironment = IntPtr.Zero;

            if (startInfo.EnvironmentVariables != null)
            {
                bool unicode = false;
                if (IsNt)
                {
                    creationFlags |= CREATE_UNICODE_ENVIRONMENT;
                    unicode        = true;
                }
                environment       = GCHandle.Alloc(EnvironmentToByteArray(startInfo.EnvironmentVariables, unicode), GCHandleType.Pinned);
                pinnedEnvironment = environment.AddrOfPinnedObject();
            }

            string workingDirectory = startInfo.WorkingDirectory;

            if (workingDirectory == "")
            {
                workingDirectory = Environment.CurrentDirectory;
            }

            success = CreateProcess(null, cmdLine, null, null, false, creationFlags, pinnedEnvironment, workingDirectory, lpStartupInfo, lpProcessInformation);

            if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != INVALID_HANDLE_VALUE))
            {
                processHandle.InitialSetHandle(lpProcessInformation.hProcess);
            }

            if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != INVALID_HANDLE_VALUE))
            {
                threadHandle.InitialSetHandle(lpProcessInformation.hThread);
            }

            if (environment.IsAllocated)
            {
                environment.Free();
            }

            lpStartupInfo.Dispose();

            if (success && !processHandle.IsInvalid && !threadHandle.IsInvalid)
            {
                process   = processHandle;
                thread    = threadHandle;
                processID = lpProcessInformation.dwProcessId;
                threadID  = lpProcessInformation.dwThreadId;
                return(true);
            }

            process   = null;
            thread    = null;
            processID = 0;
            threadID  = 0;
            return(false);
        }