The Labs \ Source Viewer \ SSCLI \ System \ ControlCHooker

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*=============================================================================
  16. **
  17. ** Class: Console
  18. **
  19. **
  20. ** Purpose: This class provides access to the standard input, standard output
  21. **          and standard error streams.
  22. **
  23. **
  24. =============================================================================*/
  25. namespace System
  26. {
  27.     using System;
  28.     using System.IO;
  29.     using System.Text;
  30.     using System.Globalization;
  31.     using System.Security.Permissions;
  32.     using Microsoft.Win32;
  33.     using System.Runtime.CompilerServices;
  34.     using System.Threading;
  35.     using System.Runtime.InteropServices;
  36.     using Microsoft.Win32.SafeHandles;
  37.     using System.Runtime.ConstrainedExecution;
  38.     using System.Runtime.Versioning;
  39.    
  40.     // Provides static fields for console input & output. Use
  41.     // Console.In for input from the standard input stream (stdin),
  42.     // Console.Out for output to stdout, and Console.Error
  43.     // for output to stderr. If any of those console streams are
  44.     // redirected from the command line, these streams will be redirected.
  45.     // A program can also redirect its own output or input with the
  46.     // SetIn, SetOut, and SetError methods.
  47.     //
  48.     // The distinction between Console.Out & Console.Error is useful
  49.     // for programs that redirect output to a file or a pipe. Note that
  50.     // stdout & stderr can be output to different files at the same
  51.     // time from the DOS command line:
  52.     //
  53.     // someProgram 1> out 2> err
  54.     //
  55.     //Contains only static data. Serializable attribute not required.
  56.     public static class Console
  57.     {
  58.         private const int _DefaultConsoleBufferSize = 256;
  59.        
  60.        
  61.         private static TextReader _in;
  62.         private static TextWriter _out;
  63.         private static TextWriter _error;
  64.        
  65.         private static ConsoleCancelEventHandler _cancelCallbacks;
  66.         private static ControlCHooker _hooker;
  67.        
  68.        
  69.         private static bool _wasOutRedirected;
  70.         private static bool _wasErrorRedirected;
  71.        
  72.         // Private object for locking instead of locking on a public type for SQL reliability work.
  73.         private static object s_InternalSyncObject;
  74.         private static object InternalSyncObject {
  75.             get {
  76.                 if (s_InternalSyncObject == null) {
  77.                     object o = new object();
  78.                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
  79.                 }
  80.                 return s_InternalSyncObject;
  81.             }
  82.         }
  83.        
  84.         // About reliability: I'm not using SafeHandle here. We don't
  85.         // need to close these handles, and we don't allow the user to close
  86.         // them so we don't have many of the security problems inherent in
  87.         // something like file handles. Additionally, in a host like SQL
  88.         // Server, we won't have a console.
  89.         private static IntPtr _consoleInputHandle;
  90.         private static IntPtr _consoleOutputHandle;
  91.        
  92.         private static IntPtr ConsoleInputHandle {
  93.             [ResourceExposure(ResourceScope.Process)]
  94.             [ResourceConsumption(ResourceScope.Process)]
  95.             get {
  96.                 if (_consoleInputHandle == IntPtr.Zero) {
  97.                     _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
  98.                 }
  99.                 return _consoleInputHandle;
  100.             }
  101.         }
  102.        
  103.         private static IntPtr ConsoleOutputHandle {
  104.             [ResourceExposure(ResourceScope.Process)]
  105.             [ResourceConsumption(ResourceScope.Process)]
  106.             get {
  107.                 if (_consoleOutputHandle == IntPtr.Zero) {
  108.                     _consoleOutputHandle = Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE);
  109.                 }
  110.                 return _consoleOutputHandle;
  111.             }
  112.         }
  113.        
  114.         public static TextWriter Error {
  115.             [HostProtection(UI = true)]
  116.             get {
  117.                 // Hopefully this is inlineable.
  118.                 if (_error == null)
  119.                     InitializeStdOutError(false);
  120.                 return _error;
  121.             }
  122.         }
  123.        
  124.         public static TextReader In {
  125.             [HostProtection(UI = true)]
  126.             get {
  127.                 // Because most applications don't use stdin, we can delay
  128.                 // initialize it slightly better startup performance.
  129.                 if (_in == null) {
  130.                     lock (InternalSyncObject) {
  131.                         if (_in == null) {
  132.                             // Set up Console.In
  133.                             Stream s = OpenStandardInput(_DefaultConsoleBufferSize);
  134.                             TextReader tr;
  135.                             if (s == Stream.Null)
  136.                                 tr = StreamReader.Null;
  137.                             else {
  138.                                 // Hopefully Encoding.GetEncoding doesn't load as many classes now.
  139.                                 Encoding enc = Encoding.GetEncoding((int)Win32Native.GetConsoleCP());
  140.                                 tr = TextReader.Synchronized(new StreamReader(s, enc, false, _DefaultConsoleBufferSize, false));
  141.                             }
  142.                             System.Threading.Thread.MemoryBarrier();
  143.                             _in = tr;
  144.                         }
  145.                     }
  146.                 }
  147.                 return _in;
  148.             }
  149.         }
  150.        
  151.         public static TextWriter Out {
  152.             [HostProtection(UI = true)]
  153.             get {
  154.                 // Hopefully this is inlineable.
  155.                 if (_out == null)
  156.                     InitializeStdOutError(true);
  157.                 return _out;
  158.             }
  159.         }
  160.        
  161.         // For console apps, the console handles are set to values like 3, 7,
  162.         // and 11 OR if you've been created via CreateProcess, possibly -1
  163.         // or 0. -1 is definitely invalid, while 0 is probably invalid.
  164.         // Also note each handle can independently be invalid or good.
  165.         // For Windows apps, the console handles are set to values like 3, 7,
  166.         // and 11 but are invalid handles - you may not write to them. However,
  167.         // you can still spawn a Windows app via CreateProcess and read stdout
  168.         // and stderr.
  169.         // So, we always need to check each handle independently for validity
  170.         // by trying to write or read to it, unless it is -1.
  171.        
  172.         // We do not do a security check here, under the assumption that this
  173.         // cannot create a security hole, but only waste a user's time or
  174.         // cause a possible denial of service attack.
  175.         private static void InitializeStdOutError(bool stdout)
  176.         {
  177.             // Set up Console.Out or Console.Error.
  178.             lock (InternalSyncObject) {
  179.                 if (stdout && _out != null)
  180.                     return;
  181.                 else if (!stdout && _error != null)
  182.                     return;
  183.                
  184.                 TextWriter writer = null;
  185.                 Stream s;
  186.                 if (stdout)
  187.                     s = OpenStandardOutput(_DefaultConsoleBufferSize);
  188.                 else
  189.                     s = OpenStandardError(_DefaultConsoleBufferSize);
  190.                
  191.                 if (s == Stream.Null) {
  192.                     #if _DEBUG
  193.                     if (CheckOutputDebug())
  194.                         writer = MakeDebugOutputTextWriter((stdout) ? "Console.Out: " : "Console.Error: ");
  195.                     else
  196.                         #endif // _DEBUG
  197.                         writer = TextWriter.Synchronized(StreamWriter.Null);
  198.                 }
  199.                 else {
  200.                     int codePage = (int)Win32Native.GetConsoleOutputCP();
  201.                     Encoding encoding = Encoding.GetEncoding(codePage);
  202.                     StreamWriter stdxxx = new StreamWriter(s, encoding, _DefaultConsoleBufferSize, false);
  203.                     stdxxx.HaveWrittenPreamble = true;
  204.                     stdxxx.AutoFlush = true;
  205.                     writer = TextWriter.Synchronized(stdxxx);
  206.                 }
  207.                 if (stdout)
  208.                     _out = writer;
  209.                 else
  210.                     _error = writer;
  211.                 BCLDebug.Assert((stdout && _out != null) || (!stdout && _error != null), "Didn't set Console::_out or _error appropriately!");
  212.             }
  213.         }
  214.        
  215.         // This is ONLY used in debug builds. If you have a registry key set,
  216.         // it will redirect Console.Out & Error on console-less applications to
  217.         // your debugger's output window.
  218.         #if _DEBUG
  219.         [ResourceExposure(ResourceScope.None)]
  220.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  221.         private static bool CheckOutputDebug()
  222.         {
  223.             const int parameterValueLength = 255;
  224.             StringBuilder parameterValue = new StringBuilder(parameterValueLength);
  225.             bool rc = Win32Native.FetchConfigurationString(true, "ConsoleSpewToDebugger", parameterValue, parameterValueLength);
  226.             if (rc) {
  227.                 if (0 != parameterValue.Length) {
  228.                     int value = Convert.ToInt32(parameterValue.ToString());
  229.                     if (0 != value)
  230.                         return true;
  231.                 }
  232.             }
  233.             return false;
  234.         }
  235.         #endif // _DEBUG
  236.        
  237.        
  238.         #if _DEBUG
  239.         private static TextWriter MakeDebugOutputTextWriter(string streamLabel)
  240.         {
  241.             TextWriter output = new __DebugOutputTextWriter(streamLabel);
  242.             output.WriteLine("Output redirected to debugger from a bit bucket.");
  243.             return TextWriter.Synchronized(output);
  244.         }
  245.         #endif // _DEBUG
  246.        
  247.         // This method is only exposed via methods to get at the console.
  248.         // We won't use any security checks here.
  249.         [ResourceExposure(ResourceScope.Process)]
  250.         [ResourceConsumption(ResourceScope.Process)]
  251.         private static Stream GetStandardFile(int stdHandleName, FileAccess access, int bufferSize)
  252.         {
  253.             // We shouldn't close the handle for stdout, etc, or we'll break
  254.             // unmanaged code in the process that will print to console.
  255.             // We should have a better way of marking this on SafeHandle.
  256.             IntPtr handle = Win32Native.GetStdHandle(stdHandleName);
  257.             SafeFileHandle sh = new SafeFileHandle(handle, false);
  258.            
  259.             // If someone launches a managed process via CreateProcess, stdout
  260.             // stderr, & stdin could independently be set to INVALID_HANDLE_VALUE.
  261.             // Additionally they might use 0 as an invalid handle.
  262.             if (sh.IsInvalid) {
  263.                 // Minor perf optimization - get it out of the finalizer queue.
  264.                 sh.SetHandleAsInvalid();
  265.                 return Stream.Null;
  266.             }
  267.            
  268.             // Check whether we can read or write to this handle.
  269.             if (stdHandleName != Win32Native.STD_INPUT_HANDLE && !ConsoleHandleIsValid(sh)) {
  270.                 //BCLDebug.ConsoleError("Console::ConsoleHandleIsValid for std handle "+stdHandleName+" failed, setting it to a null stream");
  271.                 return Stream.Null;
  272.             }
  273.            
  274.             //BCLDebug.ConsoleError("Console::GetStandardFile for std handle "+stdHandleName+" succeeded, returning handle number "+handle.ToString());
  275.             Stream console = new __ConsoleStream(sh, access);
  276.             // Do not buffer console streams, or we can get into situations where
  277.             // we end up blocking waiting for you to hit enter twice. It was
  278.             // redundant.
  279.             return console;
  280.         }
  281.        
  282.         public static Encoding InputEncoding {
  283.             get {
  284.                 uint cp = Win32Native.GetConsoleCP();
  285.                 return Encoding.GetEncoding((int)cp);
  286.             }
  287.             set {
  288.                 if (value == null)
  289.                     throw new ArgumentNullException("value");
  290.                
  291.                 if (Environment.IsWin9X())
  292.                     throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x"));
  293.                
  294.                 new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
  295.                
  296.                 uint cp = (uint)value.CodePage;
  297.                 bool r = Win32Native.SetConsoleCP(cp);
  298.                 if (!r)
  299.                     __Error.WinIOError();
  300.                
  301.                 // We need to reinitialize Console.In in the next call to _in
  302.                 // This will discard the current StreamReader, potentially
  303.                 // losing buffered data
  304.                 _in = null;
  305.             }
  306.         }
  307.        
  308.         public static Encoding OutputEncoding {
  309.             get {
  310.                 uint cp = Win32Native.GetConsoleOutputCP();
  311.                 return Encoding.GetEncoding((int)cp);
  312.             }
  313.             set {
  314.                 if (value == null)
  315.                     throw new ArgumentNullException("value");
  316.                
  317.                 if (Environment.IsWin9X())
  318.                     throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x"));
  319.                
  320.                 new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
  321.                
  322.                 // Before changing the code page we need to flush the data
  323.                 // if Out hasn't been redirected. Also, have the next call to
  324.                 // _out reinitialize the console code page.
  325.                
  326.                 if (_out != null && !_wasOutRedirected) {
  327.                     _out.Flush();
  328.                     _out = null;
  329.                 }
  330.                 if (_error != null && !_wasErrorRedirected) {
  331.                     _error.Flush();
  332.                     _error = null;
  333.                 }
  334.                
  335.                 uint cp = (uint)value.CodePage;
  336.                 bool r = Win32Native.SetConsoleOutputCP(cp);
  337.                 if (!r)
  338.                     __Error.WinIOError();
  339.             }
  340.         }
  341.        
  342.        
  343.         // During an appdomain unload, we must call into the OS and remove
  344.         // our delegate from the OS's list of console control handlers. If
  345.         // we don't do this, the OS will call back on a delegate that no
  346.         // longer exists. So, subclass CriticalFinalizableObject.
  347.         // This problem would theoretically exist during process exit for a
  348.         // single appdomain too, so using a critical finalizer is probably
  349.         // better than the appdomain unload event (I'm not sure we call that
  350.         // in the default appdomain during process exit).
  351.         internal sealed class ControlCHooker : CriticalFinalizerObject
  352.         {
  353.             private bool _hooked;
  354.             private Win32Native.ConsoleCtrlHandlerRoutine _handler;
  355.            
  356.             internal ControlCHooker()
  357.             {
  358.                 _handler = new Win32Native.ConsoleCtrlHandlerRoutine(BreakEvent);
  359.             }
  360.            
  361.             [ResourceExposure(ResourceScope.None)]
  362.             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  363.             ~ControlCHooker()
  364.             {
  365.                 Unhook();
  366.             }
  367.            
  368.             [ResourceExposure(ResourceScope.Process)]
  369.             [ResourceConsumption(ResourceScope.Process)]
  370.             internal void Hook()
  371.             {
  372.                 if (!_hooked) {
  373.                     bool r = Win32Native.SetConsoleCtrlHandler(_handler, true);
  374.                     if (!r)
  375.                         __Error.WinIOError();
  376.                     _hooked = true;
  377.                 }
  378.             }
  379.            
  380.             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  381.             [ResourceExposure(ResourceScope.Process)]
  382.             [ResourceConsumption(ResourceScope.Process)]
  383.             internal void Unhook()
  384.             {
  385.                 if (_hooked) {
  386.                     bool r = Win32Native.SetConsoleCtrlHandler(_handler, false);
  387.                     if (!r)
  388.                         __Error.WinIOError();
  389.                     _hooked = false;
  390.                 }
  391.             }
  392.         }
  393.        
  394.         // A class with data so ControlC handlers can be called on a Threadpool thread.
  395.         private sealed class ControlCDelegateData
  396.         {
  397.             internal ConsoleSpecialKey ControlKey;
  398.             internal bool Cancel;
  399.             internal bool DelegateStarted;
  400.             internal ManualResetEvent CompletionEvent;
  401.             internal ConsoleCancelEventHandler CancelCallbacks;
  402.             internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks)
  403.             {
  404.                 this.ControlKey = controlKey;
  405.                 this.CancelCallbacks = cancelCallbacks;
  406.                 this.CompletionEvent = new ManualResetEvent(false);
  407.                 // this.Cancel defaults to false
  408.                 // this.DelegateStarted defaults to false
  409.             }
  410.         }
  411.        
  412.         // Returns true if we've "handled" the break request, false if
  413.         // we want to terminate the process (or at least let the next
  414.         // control handler function have a chance).
  415.         private static bool BreakEvent(int controlType)
  416.         {
  417.            
  418.             // The thread that this gets called back on has a very small stack on 64 bit systems. There is
  419.             // not enough space to handle a managed exception being caught and thrown. So, queue up a work
  420.             // item on another thread for the actual event callback.
  421.            
  422.             if (controlType == Win32Native.CTRL_C_EVENT || controlType == Win32Native.CTRL_BREAK_EVENT) {
  423.                
  424.                 // To avoid race between remove handler and raising the event
  425.                 ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks;
  426.                 if (cancelCallbacks == null) {
  427.                     return false;
  428.                 }
  429.                
  430.                 // Create the delegate
  431.                 ConsoleSpecialKey controlKey = (controlType == 0) ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak;
  432.                 ControlCDelegateData delegateData = new ControlCDelegateData(controlKey, cancelCallbacks);
  433.                 WaitCallback controlCCallback = new WaitCallback(ControlCDelegate);
  434.                
  435.                 // Queue the delegate
  436.                 if (!ThreadPool.QueueUserWorkItem(controlCCallback, delegateData)) {
  437.                     BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem returned false without throwing. Unable to execute ControlC handler");
  438.                     return false;
  439.                 }
  440.                 // Block until the delegate is done. We need to be robust in the face of the work item not executing
  441.                 // but we also want to get control back immediately after it is done and we don't want to give the
  442.                 // handler a fixed time limit in case it needs to display UI. Wait on the event twice, once with a
  443.                 // timout and a second time without if we are sure that the handler actually started.
  444.                 TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30);
  445.                 // 30 seconds
  446.                 delegateData.CompletionEvent.WaitOne(controlCWaitTime, false);
  447.                 if (!delegateData.DelegateStarted) {
  448.                     BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem did not execute the handler within 30 seconds.");
  449.                     return false;
  450.                 }
  451.                 delegateData.CompletionEvent.WaitOne();
  452.                 delegateData.CompletionEvent.Close();
  453.                 return delegateData.Cancel;
  454.                
  455.             }
  456.             return false;
  457.         }
  458.        
  459.         // This is the worker delegate that is called on the Threadpool thread to fire the actual events. It must guarentee that it
  460.         // signals the caller on the ControlC thread so that it does not block indefinitely.
  461.         private static void ControlCDelegate(object data)
  462.         {
  463.             ControlCDelegateData controlCData = (ControlCDelegateData)data;
  464.             try {
  465.                 controlCData.DelegateStarted = true;
  466.                 ConsoleCancelEventArgs args = new ConsoleCancelEventArgs(controlCData.ControlKey);
  467.                 controlCData.CancelCallbacks(null, args);
  468.                 controlCData.Cancel = args.Cancel;
  469.             }
  470.             finally {
  471.                 controlCData.CompletionEvent.Set();
  472.             }
  473.         }
  474.        
  475.         // Note: hooking this event allows you to prevent Control-C from
  476.         // killing a console app, which is somewhat surprising for users.
  477.         // Some permission seems appropriate. We chose UI permission for lack
  478.         // of a better one. However, we also applied host protection
  479.         // permission here as well, for self-affecting process management.
  480.         // This allows hosts to prevent people from adding a handler for
  481.         // this event.
  482.         public static event ConsoleCancelEventHandler CancelKeyPress {
  483.             [ResourceExposure(ResourceScope.Process)]
  484.             [ResourceConsumption(ResourceScope.Process)]
  485.             add {
  486.                 new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
  487.                
  488.                 lock (InternalSyncObject) {
  489.                     // Add this delegate to the pile.
  490.                     _cancelCallbacks += value;
  491.                    
  492.                     // If we haven't registered our control-C handler, do it.
  493.                     if (_hooker == null) {
  494.                         _hooker = new ControlCHooker();
  495.                         _hooker.Hook();
  496.                     }
  497.                 }
  498.             }
  499.             [ResourceExposure(ResourceScope.Process)]
  500.             [ResourceConsumption(ResourceScope.Process)]
  501.             remove {
  502.                 new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
  503.                
  504.                 lock (InternalSyncObject) {
  505.                     // If count was 0, call SetConsoleCtrlEvent to remove cb.
  506.                     _cancelCallbacks -= value;
  507.                     BCLDebug.Assert(_cancelCallbacks == null || _cancelCallbacks.GetInvocationList().Length > 0, "Teach Console::CancelKeyPress to handle a non-null but empty list of callbacks");
  508.                     if (_hooker != null && _cancelCallbacks == null)
  509.                         _hooker.Unhook();
  510.                 }
  511.             }
  512.         }
  513.        
  514.         [HostProtection(UI = true)]
  515.         [ResourceExposure(ResourceScope.Process)]
  516.         [ResourceConsumption(ResourceScope.Process)]
  517.         public static Stream OpenStandardError()
  518.         {
  519.             return OpenStandardError(_DefaultConsoleBufferSize);
  520.         }
  521.        
  522.         [HostProtection(UI = true)]
  523.         [ResourceExposure(ResourceScope.Process)]
  524.         [ResourceConsumption(ResourceScope.Process)]
  525.         public static Stream OpenStandardError(int bufferSize)
  526.         {
  527.             if (bufferSize < 0)
  528.                 throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  529.             return GetStandardFile(Win32Native.STD_ERROR_HANDLE, FileAccess.Write, bufferSize);
  530.         }
  531.        
  532.         [HostProtection(UI = true)]
  533.         [ResourceExposure(ResourceScope.Process)]
  534.         [ResourceConsumption(ResourceScope.Process)]
  535.         public static Stream OpenStandardInput()
  536.         {
  537.             return OpenStandardInput(_DefaultConsoleBufferSize);
  538.         }
  539.        
  540.         [HostProtection(UI = true)]
  541.         [ResourceExposure(ResourceScope.Process)]
  542.         [ResourceConsumption(ResourceScope.Process)]
  543.         public static Stream OpenStandardInput(int bufferSize)
  544.         {
  545.             if (bufferSize < 0)
  546.                 throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  547.             return GetStandardFile(Win32Native.STD_INPUT_HANDLE, FileAccess.Read, bufferSize);
  548.         }
  549.        
  550.         [HostProtection(UI = true)]
  551.         [ResourceExposure(ResourceScope.Process)]
  552.         [ResourceConsumption(ResourceScope.Process)]
  553.         public static Stream OpenStandardOutput()
  554.         {
  555.             return OpenStandardOutput(_DefaultConsoleBufferSize);
  556.         }
  557.        
  558.         [HostProtection(UI = true)]
  559.         [ResourceExposure(ResourceScope.Process)]
  560.         [ResourceConsumption(ResourceScope.Process)]
  561.         public static Stream OpenStandardOutput(int bufferSize)
  562.         {
  563.             if (bufferSize < 0)
  564.                 throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  565.             return GetStandardFile(Win32Native.STD_OUTPUT_HANDLE, FileAccess.Write, bufferSize);
  566.         }
  567.        
  568.         [HostProtection(UI = true)]
  569.         [ResourceExposure(ResourceScope.AppDomain)]
  570.         public static void SetIn(TextReader newIn)
  571.         {
  572.             if (newIn == null)
  573.                 throw new ArgumentNullException("newIn");
  574.             new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  575.            
  576.             newIn = TextReader.Synchronized(newIn);
  577.             _in = newIn;
  578.         }
  579.        
  580.         [HostProtection(UI = true)]
  581.         [ResourceExposure(ResourceScope.AppDomain)]
  582.         public static void SetOut(TextWriter newOut)
  583.         {
  584.             if (newOut == null)
  585.                 throw new ArgumentNullException("newOut");
  586.             new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  587.            
  588.             _wasOutRedirected = true;
  589.             newOut = TextWriter.Synchronized(newOut);
  590.             _out = newOut;
  591.         }
  592.        
  593.         [HostProtection(UI = true)]
  594.         [ResourceExposure(ResourceScope.AppDomain)]
  595.         public static void SetError(TextWriter newError)
  596.         {
  597.             if (newError == null)
  598.                 throw new ArgumentNullException("newError");
  599.             new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  600.            
  601.             _wasErrorRedirected = true;
  602.             newError = TextWriter.Synchronized(newError);
  603.             _error = newError;
  604.         }
  605.        
  606.         [HostProtection(UI = true)]
  607.         public static int Read()
  608.         {
  609.             return In.Read();
  610.         }
  611.        
  612.         [HostProtection(UI = true)]
  613.         public static string ReadLine()
  614.         {
  615.             return In.ReadLine();
  616.         }
  617.        
  618.         [HostProtection(UI = true)]
  619.         public static void WriteLine()
  620.         {
  621.             Out.WriteLine();
  622.         }
  623.        
  624.         [HostProtection(UI = true)]
  625.         public static void WriteLine(bool value)
  626.         {
  627.             Out.WriteLine(value);
  628.         }
  629.        
  630.         [HostProtection(UI = true)]
  631.         public static void WriteLine(char value)
  632.         {
  633.             Out.WriteLine(value);
  634.         }
  635.        
  636.         [HostProtection(UI = true)]
  637.         public static void WriteLine(char[] buffer)
  638.         {
  639.             Out.WriteLine(buffer);
  640.         }
  641.        
  642.         [HostProtection(UI = true)]
  643.         public static void WriteLine(char[] buffer, int index, int count)
  644.         {
  645.             Out.WriteLine(buffer, index, count);
  646.         }
  647.        
  648.         [HostProtection(UI = true)]
  649.         public static void WriteLine(decimal value)
  650.         {
  651.             Out.WriteLine(value);
  652.         }
  653.        
  654.         [HostProtection(UI = true)]
  655.         public static void WriteLine(double value)
  656.         {
  657.             Out.WriteLine(value);
  658.         }
  659.        
  660.         [HostProtection(UI = true)]
  661.         public static void WriteLine(float value)
  662.         {
  663.             Out.WriteLine(value);
  664.         }
  665.        
  666.         [HostProtection(UI = true)]
  667.         public static void WriteLine(int value)
  668.         {
  669.             Out.WriteLine(value);
  670.         }
  671.        
  672.         [HostProtection(UI = true)]
  673.         [CLSCompliant(false)]
  674.         public static void WriteLine(uint value)
  675.         {
  676.             Out.WriteLine(value);
  677.         }
  678.        
  679.         [HostProtection(UI = true)]
  680.         public static void WriteLine(long value)
  681.         {
  682.             Out.WriteLine(value);
  683.         }
  684.        
  685.         [HostProtection(UI = true)]
  686.         [CLSCompliant(false)]
  687.         public static void WriteLine(ulong value)
  688.         {
  689.             Out.WriteLine(value);
  690.         }
  691.        
  692.         [HostProtection(UI = true)]
  693.         public static void WriteLine(object value)
  694.         {
  695.             Out.WriteLine(value);
  696.         }
  697.        
  698.         [HostProtection(UI = true)]
  699.         public static void WriteLine(string value)
  700.         {
  701.             Out.WriteLine(value);
  702.         }
  703.        
  704.        
  705.         [HostProtection(UI = true)]
  706.         public static void WriteLine(string format, object arg0)
  707.         {
  708.             Out.WriteLine(format, arg0);
  709.         }
  710.        
  711.         [HostProtection(UI = true)]
  712.         public static void WriteLine(string format, object arg0, object arg1)
  713.         {
  714.             Out.WriteLine(format, arg0, arg1);
  715.         }
  716.        
  717.         [HostProtection(UI = true)]
  718.         public static void WriteLine(string format, object arg0, object arg1, object arg2)
  719.         {
  720.             Out.WriteLine(format, arg0, arg1, arg2);
  721.         }
  722.        
  723.         [HostProtection(UI = true)]
  724.         [CLSCompliant(false)]
  725.         public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3, __arglist __arglist)
  726.         {
  727.             object[] objArgs;
  728.             int argCount;
  729.            
  730.             ArgIterator args = new ArgIterator(__arglist);
  731.            
  732.             //+4 to account for the 4 hard-coded arguments at the beginning of the list.
  733.             argCount = args.GetRemainingCount() + 4;
  734.            
  735.             objArgs = new object[argCount];
  736.            
  737.             //Handle the hard-coded arguments
  738.             objArgs[0] = arg0;
  739.             objArgs[1] = arg1;
  740.             objArgs[2] = arg2;
  741.             objArgs[3] = arg3;
  742.            
  743.             //Walk all of the args in the variable part of the argument list.
  744.             for (int i = 4; i < argCount; i++) {
  745.                 objArgs[i] = TypedReference.ToObject(args.GetNextArg());
  746.             }
  747.            
  748.             Out.WriteLine(format, objArgs);
  749.         }
  750.        
  751.        
  752.         [HostProtection(UI = true)]
  753.         public static void WriteLine(string format, params object[] arg)
  754.         {
  755.             Out.WriteLine(format, arg);
  756.         }
  757.        
  758.         [HostProtection(UI = true)]
  759.         public static void Write(string format, object arg0)
  760.         {
  761.             Out.Write(format, arg0);
  762.         }
  763.        
  764.         [HostProtection(UI = true)]
  765.         public static void Write(string format, object arg0, object arg1)
  766.         {
  767.             Out.Write(format, arg0, arg1);
  768.         }
  769.        
  770.         [HostProtection(UI = true)]
  771.         public static void Write(string format, object arg0, object arg1, object arg2)
  772.         {
  773.             Out.Write(format, arg0, arg1, arg2);
  774.         }
  775.        
  776.         [HostProtection(UI = true)]
  777.         [CLSCompliant(false)]
  778.         public static void Write(string format, object arg0, object arg1, object arg2, object arg3, __arglist __arglist)
  779.         {
  780.             object[] objArgs;
  781.             int argCount;
  782.            
  783.             ArgIterator args = new ArgIterator(__arglist);
  784.            
  785.             //+4 to account for the 4 hard-coded arguments at the beginning of the list.
  786.             argCount = args.GetRemainingCount() + 4;
  787.            
  788.             objArgs = new object[argCount];
  789.            
  790.             //Handle the hard-coded arguments
  791.             objArgs[0] = arg0;
  792.             objArgs[1] = arg1;
  793.             objArgs[2] = arg2;
  794.             objArgs[3] = arg3;
  795.            
  796.             //Walk all of the args in the variable part of the argument list.
  797.             for (int i = 4; i < argCount; i++) {
  798.                 objArgs[i] = TypedReference.ToObject(args.GetNextArg());
  799.             }
  800.            
  801.             Out.Write(format, objArgs);
  802.         }
  803.        
  804.        
  805.         [HostProtection(UI = true)]
  806.         public static void Write(string format, params object[] arg)
  807.         {
  808.             Out.Write(format, arg);
  809.         }
  810.        
  811.         [HostProtection(UI = true)]
  812.         public static void Write(bool value)
  813.         {
  814.             Out.Write(value);
  815.         }
  816.        
  817.         [HostProtection(UI = true)]
  818.         public static void Write(char value)
  819.         {
  820.             Out.Write(value);
  821.         }
  822.        
  823.         [HostProtection(UI = true)]
  824.         public static void Write(char[] buffer)
  825.         {
  826.             Out.Write(buffer);
  827.         }
  828.        
  829.         [HostProtection(UI = true)]
  830.         public static void Write(char[] buffer, int index, int count)
  831.         {
  832.             Out.Write(buffer, index, count);
  833.         }
  834.        
  835.         [HostProtection(UI = true)]
  836.         public static void Write(double value)
  837.         {
  838.             Out.Write(value);
  839.         }
  840.        
  841.         [HostProtection(UI = true)]
  842.         public static void Write(decimal value)
  843.         {
  844.             Out.Write(value);
  845.         }
  846.        
  847.         [HostProtection(UI = true)]
  848.         public static void Write(float value)
  849.         {
  850.             Out.Write(value);
  851.         }
  852.        
  853.         [HostProtection(UI = true)]
  854.         public static void Write(int value)
  855.         {
  856.             Out.Write(value);
  857.         }
  858.        
  859.         [HostProtection(UI = true)]
  860.         [CLSCompliant(false)]
  861.         public static void Write(uint value)
  862.         {
  863.             Out.Write(value);
  864.         }
  865.        
  866.         [HostProtection(UI = true)]
  867.         public static void Write(long value)
  868.         {
  869.             Out.Write(value);
  870.         }
  871.        
  872.         [HostProtection(UI = true)]
  873.         [CLSCompliant(false)]
  874.         public static void Write(ulong value)
  875.         {
  876.             Out.Write(value);
  877.         }
  878.        
  879.         [HostProtection(UI = true)]
  880.         public static void Write(object value)
  881.         {
  882.             Out.Write(value);
  883.         }
  884.        
  885.         [HostProtection(UI = true)]
  886.         public static void Write(string value)
  887.         {
  888.             Out.Write(value);
  889.         }
  890.        
  891.         // Checks whether stdout or stderr are writable. Do NOT pass
  892.         // stdin here.
  893.         [ResourceExposure(ResourceScope.Process)]
  894.         [ResourceConsumption(ResourceScope.Process)]
  895.         unsafe private static bool ConsoleHandleIsValid(SafeFileHandle handle)
  896.         {
  897.             // Do NOT call this method on stdin!
  898.            
  899.             // Windows apps may have non-null valid looking handle values for
  900.             // stdin, stdout and stderr, but they may not be readable or
  901.             // writable. Verify this by calling ReadFile & WriteFile in the
  902.             // appropriate modes.
  903.             // This must handle console-less Windows apps.
  904.             if (handle.IsInvalid)
  905.                 return false;
  906.             // WinCE would return here, if we ran on CE.
  907.             int bytesWritten;
  908.             byte junkByte = 65;
  909.             int r;
  910.             r = __ConsoleStream.WriteFile(handle, &junkByte, 0, out bytesWritten, IntPtr.Zero);
  911.             // In Win32 apps w/ no console, bResult should be 0 for failure.
  912.             return r != 0;
  913.         }
  914.     }
  915. }

Developer Fusion