/// <include file='doc\Executor.uex' path='docs/doc[@for="Executor.ExecWaitWithCapture3"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> internal static int ExecWaitWithCapture(IntPtr userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine) { IntSecurity.UnmanagedCode.Demand(); IntPtr output; IntPtr error; int retValue = 0; if (outputName == null || outputName.Length == 0) outputName = tempFiles.AddExtension("out"); if (errorName == null || errorName.Length == 0) errorName = tempFiles.AddExtension("err"); // Create the files output = CreateInheritedFile(outputName); error = CreateInheritedFile(errorName); bool success = false; NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); IntPtr primaryToken = IntPtr.Zero; GCHandle environmentHandle = new GCHandle(); try { // Output the command line... // Make sure the FileStream doesn't own the handle FileStream outputStream = new FileStream(output, FileAccess.ReadWrite, false /*ownsHandle*/); StreamWriter sw = new StreamWriter(outputStream, Encoding.UTF8); sw.Write(currentDir); sw.Write("> "); // 'true' command line is used in case the command line points to // a response file sw.WriteLine(trueCmdLine != null ? trueCmdLine : cmd); sw.WriteLine(); sw.WriteLine(); sw.Flush(); outputStream.Close(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; si.hStdOutput = output; si.hStdError = error; si.hStdInput = UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE); // // Prepare the environment // Hashtable environment = new Hashtable(); // Add the current environment foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) environment.Add((string)entry.Key, (string)entry.Value); // Add the flag to indicate restricted security in the process environment.Add("_ClrRestrictSecAttributes", "1"); // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; byte[] environmentBytes = EnvironmentToByteArray(environment); environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned); environmentPtr = environmentHandle.AddrOfPinnedObject(); if (userToken == IntPtr.Zero) { success = UnsafeNativeMethods.CreateProcess( null, // String lpApplicationName, new StringBuilder(cmd), // String lpCommandLine, null, // SECURITY_ATTRIBUTES lpProcessAttributes, null, // SECURITY_ATTRIBUTES lpThreadAttributes, true, // bool bInheritHandles, 0, // int dwCreationFlags, environmentPtr, // int lpEnvironment, currentDir, // String lpCurrentDirectory, si, // STARTUPINFO lpStartupInfo, pi); // PROCESS_INFORMATION lpProcessInformation); } else { throw new NotSupportedException(); } } finally { // free environment block if (environmentHandle.IsAllocated) environmentHandle.Free(); // Close the file handles UnsafeNativeMethods.CloseHandle(output); UnsafeNativeMethods.CloseHandle(error); } if (success) { try { int ret = SafeNativeMethods.WaitForSingleObject(pi.hProcess, ProcessTimeOut); // Check for timeout if (ret == NativeMethods.WAIT_TIMEOUT) { throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT); } if (ret != NativeMethods.WAIT_OBJECT_0) { throw new ExternalException(SR.GetString(SR.ExecBadreturn, cmd), Marshal.GetLastWin32Error()); } // Check the process's exit code int status = NativeMethods.STILL_ACTIVE; if (!UnsafeNativeMethods.GetExitCodeProcess(pi.hProcess, ref status)) { throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error()); } retValue = status; } finally { UnsafeNativeMethods.CloseHandle(pi.hThread); UnsafeNativeMethods.CloseHandle(pi.hProcess); if (primaryToken != IntPtr.Zero) UnsafeNativeMethods.CloseHandle(primaryToken); } } else { throw new ExternalException(SR.GetString(SR.ExecCantExec, cmd), Marshal.GetLastWin32Error()); } return retValue; }
public extern static bool CreateProcess(string lpApplicationName, StringBuilder lpCommandLine, NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes, NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, HandleRef lpEnvironment, string lpCurrentDirectory, NativeMethods.STARTUPINFO lpStartupInfo, NativeMethods.PROCESS_INFORMATION lpProcessInformation);
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; }