public static extern bool CreateProcess(
     [MarshalAs(UnmanagedType.LPTStr)]
     string lpApplicationName,                                  // LPCTSTR
     StringBuilder lpCommandLine,                               // LPTSTR - note: CreateProcess might insert a null somewhere in this string
     SECURITY_ATTRIBUTES lpProcessAttributes,                   // LPSECURITY_ATTRIBUTES
     SECURITY_ATTRIBUTES lpThreadAttributes,                    // LPSECURITY_ATTRIBUTES
     bool bInheritHandles,                                      // BOOL
     int dwCreationFlags,                                       // DWORD
     IntPtr lpEnvironment,                                      // LPVOID
     [MarshalAs(UnmanagedType.LPTStr)]
     string lpCurrentDirectory,                                 // LPCTSTR
     STARTUPINFO lpStartupInfo,                                 // LPSTARTUPINFO
     SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation // LPPROCESS_INFORMATION
     );
Esempio n. 2
0
        public static System.Diagnostics.Process StartProcessWithToken(IntPtr token, string cmdLine)
        {
            IntPtr environmentBlock = IntPtr.Zero;

            try
            {
                // Default nil security attribute
                SafeNativeMethods.SECURITY_ATTRIBUTES defSec = new SafeNativeMethods.SECURITY_ATTRIBUTES();
                defSec.nLength = Marshal.SizeOf(defSec);
                defSec.lpSecurityDescriptor = IntPtr.Zero;
                defSec.bInheritHandle = 0;

                // Create an environment block
                if (!SafeNativeMethods.CreateEnvironmentBlock(ref environmentBlock, token, false))
                {
                    LibraryLogging.Error("StartProcessWithToken(IntPtr, {1}) CreateEnvironmentBlock Error:{0}", LastError(), cmdLine);
                }

                // Now we can finally get into the business at hand and setup our process info
                SafeNativeMethods.STARTUPINFO startInfo = new SafeNativeMethods.STARTUPINFO();
                startInfo.cb = Marshal.SizeOf(startInfo);
                startInfo.wShowWindow = 0;
                startInfo.lpDesktop = "Winsta0\\Default";   // TBD: Support other desktops?

                SafeNativeMethods.PROCESS_INFORMATION procInfo = new SafeNativeMethods.PROCESS_INFORMATION();
                if (!SafeNativeMethods.CreateProcessAsUser(token, null, cmdLine, ref defSec, ref defSec, false, SafeNativeMethods.CREATE_UNICODE_ENVIRONMENT, environmentBlock, null, ref startInfo, out procInfo))
                {
                    LibraryLogging.Error("StartProcessWithToken(IntPtr, {1}) CreateProcessAsUser Error:{0}", LastError(), cmdLine);
                }

                // We made it, process is running! Closing our handles to it ensures it doesn't orphan,
                //  then we just use its pid to return a process object
                SafeNativeMethods.CloseHandle(procInfo.hProcess);
                SafeNativeMethods.CloseHandle(procInfo.hThread);

                return System.Diagnostics.Process.GetProcessById((int)procInfo.dwProcessId);
            }
            finally
            {
                SafeNativeMethods.CloseHandle(environmentBlock);
            }
        }
        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;
        }