internal static extern unsafe bool CreateProcessWithLogonW(
     string userName,
     string domain,
     IntPtr password,
     LogonFlags logonFlags,
     string?appName,
     char *cmdLine,
     int creationFlags,
     IntPtr environmentBlock,
     string?lpCurrentDirectory,
     ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
     ref Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation);
Пример #2
0
 internal static extern bool CreateProcessWithLogonW(
     string userName,
     string domain,
     string passwordInClearText,
     LogonFlags logonFlags,
     [MarshalAs(UnmanagedType.LPTStr)] string appName,
     StringBuilder cmdLine,
     int creationFlags,
     IntPtr environmentBlock,
     [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory,
     Interop.Kernel32.STARTUPINFO lpStartupInfo,
     Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation);
Пример #3
0
 public static extern bool DetourCreateProcessWithDllExA(
     string lpApplicationName,
     string lpCommandLine,
     IntPtr lpProcessAttributes,
     IntPtr lpThreadAttributes,
     bool bInheritHandles,
     uint dwCreationFlags,
     IntPtr lpEnvironment,
     string lpCurrentDirectory,
     ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
     out Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation,
     string lpDllName,
     IntPtr pfCreateProcessA);
Пример #4
0
        internal static extern bool CreateProcessWithLogonW(
            string userName,
            string domain,
            IntPtr password,
            LogonFlags logonFlags,
            string?appName,
#pragma warning disable CA1838 // reasonable use of StringBuilder to build up a command line
            [In] StringBuilder cmdLine,
#pragma warning restore CA1838
            int creationFlags,
            IntPtr environmentBlock,
            string lpCurrentDirectory,
            ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
            ref Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation);
Пример #5
0
 public static bool DetourCreateProcessWithDllsExW(
     string lpApplicationName,
     string lpCommandLine,
     IntPtr lpProcessAttributes,
     IntPtr lpThreadAttributes,
     bool bInheritHandles,
     uint dwCreationFlags,
     IntPtr lpEnvironment,
     string lpCurrentDirectory,
     ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
     out Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation,
     uint nDlls,
     IntPtr rlpDlls,
     IntPtr pfCreateProcessW)
 {
     if (Is64Bit)
     {
         return(NativeApi64.DetourCreateProcessWithDllsExW(lpApplicationName,
                                                           lpCommandLine,
                                                           lpProcessAttributes,
                                                           lpThreadAttributes,
                                                           bInheritHandles,
                                                           dwCreationFlags,
                                                           lpEnvironment,
                                                           lpCurrentDirectory,
                                                           ref lpStartupInfo,
                                                           out lpProcessInformation,
                                                           nDlls,
                                                           rlpDlls,
                                                           pfCreateProcessW));
     }
     else
     {
         return(NativeApi32.DetourCreateProcessWithDllsExW(lpApplicationName,
                                                           lpCommandLine,
                                                           lpProcessAttributes,
                                                           lpThreadAttributes,
                                                           bInheritHandles,
                                                           dwCreationFlags,
                                                           lpEnvironment,
                                                           lpCurrentDirectory,
                                                           ref lpStartupInfo,
                                                           out lpProcessInformation,
                                                           nDlls,
                                                           rlpDlls,
                                                           pfCreateProcessW));
     }
 }
Пример #6
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 != new IntPtr(-1))
                    {
                        procSH.InitialSetHandle(processInfo.hProcess);
                    }
                    if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != new IntPtr(-1))
                    {
                        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);
        }
Пример #7
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.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();
            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.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE), false);
                        }

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

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

                        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
                    IntPtr environmentPtr = (IntPtr)0;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags |= Interop.Advapi32.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.Advapi32.LogonFlags logonFlags = (Interop.Advapi32.LogonFlags) 0;
                        if (startInfo.LoadUserProfile)
                        {
                            logonFlags = Interop.Advapi32.LogonFlags.LOGON_WITH_PROFILE;
                        }


                        try { }
                        finally
                        {
                            retVal = Interop.Advapi32.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.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                            {
                                throw new Win32Exception(errorCode, SR.InvalidApplication);
                            }

                            throw new Win32Exception(errorCode);
                        }
                    }
                    else
                    {
                        try { }
                        finally
                        {
                            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
                                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.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.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.Kernel32.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.Kernel32.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.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);
        }
Пример #8
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.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();
            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.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE), false);
                        }

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

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

                        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
                    IntPtr environmentPtr = (IntPtr)0;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags |= Interop.Advapi32.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)
                    {
                        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;
                        }

                        if (startInfo.Password != null)
                        {
                            IntPtr passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(startInfo.Password);
                            try
                            {
                                retVal = Interop.Advapi32.CreateProcessWithLogonW(
                                    startInfo.UserName,
                                    startInfo.Domain,
                                    passwordPtr,
                                    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();
                            }
                            finally { Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); }
                        }
                        else
                        {
                            unsafe
                            {
                                fixed (char* passwordPtr = startInfo.PasswordInClearText ?? string.Empty)
                                {
                                    retVal = Interop.Advapi32.CreateProcessWithLogonW(
                                            startInfo.UserName,
                                            startInfo.Domain,
                                            (IntPtr)passwordPtr,
                                            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.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                            {
                                throw new Win32Exception(errorCode, SR.InvalidApplication);
                            }
                            throw new Win32Exception(errorCode);
                        }
                    }
                    else
                    {
                        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
                                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.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.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.Kernel32.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.Kernel32.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.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;
        }