Console.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / clr / src / BCL / System / Console.cs / 5 / Console.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*==============================================================================
** 
** Class: Console 
**
** 
** Purpose: This class provides access to the standard input, standard output
**          and standard error streams.
**
** 
=============================================================================*/
namespace System { 
    using System; 
    using System.IO;
    using System.Text; 
    using System.Globalization;
    using System.Security.Permissions;
    using Microsoft.Win32;
    using System.Runtime.CompilerServices; 
    using System.Threading;
    using System.Runtime.InteropServices; 
    using Microsoft.Win32.SafeHandles; 
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.Versioning; 

    // Provides static fields for console input & output.  Use
    // Console.In for input from the standard input stream (stdin),
    // Console.Out for output to stdout, and Console.Error 
    // for output to stderr.  If any of those console streams are
    // redirected from the command line, these streams will be redirected. 
    // A program can also redirect its own output or input with the 
    // SetIn, SetOut, and SetError methods.
    // 
    // The distinction between Console.Out & Console.Error is useful
    // for programs that redirect output to a file or a pipe.  Note that
    // stdout & stderr can be output to different files at the same
    // time from the DOS command line: 
    //
    // someProgram 1> out 2> err 
    // 
    //Contains only static data.  Serializable attribute not required.
    public static class Console 
    {
        private const int _DefaultConsoleBufferSize = 256;

#if !FEATURE_PAL 
        private const int NumberLockVKCode = 0x90;  // virtual key code
        private const int CapsLockVKCode = 0x14; 
 
        // Beep range - see MSDN.
        private const int MinBeepFrequency = 37; 
        private const int MaxBeepFrequency = 32767;

        // MSDN says console titles can be up to 64 KB in length.
        // But I get an exception if I use buffer lengths longer than 
        // ~24500 Unicode characters.  Oh well.
        private const int MaxConsoleTitleLength = 24500; 
#endif // !FEATURE_PAL 

        private static TextReader _in; 
        private static TextWriter _out;
        private static TextWriter _error;

        private static ConsoleCancelEventHandler _cancelCallbacks; 
        private static ControlCHooker _hooker;
 
#if !FEATURE_PAL 
        // ReadLine & Read can't use this because they need to use ReadFile
        // to be able to handle redirected input.  We have to accept that 
        // we will lose repeated keystrokes when someone switches from
        // calling ReadKey to calling Read or ReadLine.  Those methods should
        // ideally flush this cache as well.
        private static Win32Native.InputRecord _cachedInputRecord; 

        // For ResetColor 
        private static bool _haveReadDefaultColors; 
        private static byte _defaultColors;
#endif // !FEATURE_PAL 

        private static bool _wasOutRedirected;
        private static bool _wasErrorRedirected;
 
        // Private object for locking instead of locking on a public type for SQL reliability work.
        private static Object s_InternalSyncObject; 
        private static Object InternalSyncObject { 
            get {
                if (s_InternalSyncObject == null) { 
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
                }
                return s_InternalSyncObject; 
            }
        } 
 
        // About reliability: I'm not using SafeHandle here.  We don't
        // need to close these handles, and we don't allow the user to close 
        // them so we don't have many of the security problems inherent in
        // something like file handles.  Additionally, in a host like SQL
        // Server, we won't have a console.
        private static IntPtr _consoleInputHandle; 
        private static IntPtr _consoleOutputHandle;
 
        private static IntPtr ConsoleInputHandle { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            get {
                if (_consoleInputHandle == IntPtr.Zero) {
                    _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
                } 
                return _consoleInputHandle;
            } 
        } 

        private static IntPtr ConsoleOutputHandle { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                if (_consoleOutputHandle == IntPtr.Zero) { 
                    _consoleOutputHandle = Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE);
                } 
                return _consoleOutputHandle; 
            }
        } 

        public static TextWriter Error {
            [HostProtection(UI=true)]
            get { 
                // Hopefully this is inlineable.
                if (_error == null) 
                    InitializeStdOutError(false); 
                return _error;
            } 
        }

        public static TextReader In {
            [HostProtection(UI=true)] 
            get {
                // Because most applications don't use stdin, we can delay 
                // initialize it slightly better startup performance. 
                if (_in == null) {
                    lock(InternalSyncObject) { 
                        if (_in == null) {
                            // Set up Console.In
                            Stream s = OpenStandardInput(_DefaultConsoleBufferSize);
                            TextReader tr; 
                            if (s == Stream.Null)
                                tr = StreamReader.Null; 
                            else { 
                                // Hopefully Encoding.GetEncoding doesn't load as many classes now.
                                Encoding enc = Encoding.GetEncoding((int)Win32Native.GetConsoleCP()); 
                                tr = TextReader.Synchronized(new StreamReader(s, enc, false, _DefaultConsoleBufferSize, false));
                            }
                            System.Threading.Thread.MemoryBarrier();
                            _in = tr; 
                        }
                    } 
                } 
                return _in;
            } 
        }

        public static TextWriter Out {
            [HostProtection(UI=true)] 
            get {
                // Hopefully this is inlineable. 
                if (_out == null) 
                    InitializeStdOutError(true);
                return _out; 
            }
        }

        // For console apps, the console handles are set to values like 3, 7, 
        // and 11 OR if you've been created via CreateProcess, possibly -1
        // or 0.  -1 is definitely invalid, while 0 is probably invalid. 
        // Also note each handle can independently be invalid or good. 
        // For Windows apps, the console handles are set to values like 3, 7,
        // and 11 but are invalid handles - you may not write to them.  However, 
        // you can still spawn a Windows app via CreateProcess and read stdout
        // and stderr.
        // So, we always need to check each handle independently for validity
        // by trying to write or read to it, unless it is -1. 

        // We do not do a security check here, under the assumption that this 
        // cannot create a security hole, but only waste a user's time or 
        // cause a possible denial of service attack.
        private static void InitializeStdOutError(bool stdout) 
        {
            // Set up Console.Out or Console.Error.
            lock(InternalSyncObject) {
                if (stdout && _out != null) 
                    return;
                else if (!stdout && _error != null) 
                    return; 

                TextWriter writer = null; 
                Stream s;
                if (stdout)
                    s = OpenStandardOutput(_DefaultConsoleBufferSize);
                else 
                    s = OpenStandardError(_DefaultConsoleBufferSize);
 
                if (s == Stream.Null) { 
#if _DEBUG
                    if (CheckOutputDebug()) 
                        writer = MakeDebugOutputTextWriter((stdout) ? "Console.Out: " : "Console.Error: ");
                    else
#endif // _DEBUG
                        writer = TextWriter.Synchronized(StreamWriter.Null); 
                }
                else { 
                    int codePage = (int) Win32Native.GetConsoleOutputCP(); 
                    Encoding encoding = Encoding.GetEncoding(codePage);
                    StreamWriter stdxxx = new StreamWriter(s, encoding, _DefaultConsoleBufferSize, false); 
                    stdxxx.HaveWrittenPreamble = true;
                    stdxxx.AutoFlush = true;
                    writer = TextWriter.Synchronized(stdxxx);
                } 
                if (stdout)
                    _out = writer; 
                else 
                    _error = writer;
                BCLDebug.Assert((stdout && _out != null) || (!stdout && _error != null), "Didn't set Console::_out or _error appropriately!"); 
            }
        }

        // This is ONLY used in debug builds.  If you have a registry key set, 
        // it will redirect Console.Out & Error on console-less applications to
        // your debugger's output window. 
#if _DEBUG 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static bool CheckOutputDebug()
        {
#if !FEATURE_PAL
            new System.Security.Permissions.RegistryPermission(RegistryPermissionAccess.Read | RegistryPermissionAccess.Write, "HKEY_LOCAL_MACHINE").Assert(); 
            RegistryKey rk = Registry.LocalMachine;
            using (rk = rk.OpenSubKey("Software\\Microsoft\\.NETFramework", false)) { 
                if (rk != null) { 
                    Object obj = rk.GetValue("ConsoleSpewToDebugger", 0);
                    if (obj != null && ((int)obj) != 0) { 
                        return true;
                    }
                }
            } 
            return false;
#else // !FEATURE_PAL 
            const int parameterValueLength = 255; 
            StringBuilder parameterValue = new StringBuilder(parameterValueLength);
            bool rc = Win32Native.FetchConfigurationString(true, "ConsoleSpewToDebugger", parameterValue, parameterValueLength); 
            if (rc) {
                if (0 != parameterValue.Length) {
                    int value = Convert.ToInt32(parameterValue.ToString());
                    if (0 != value) 
                        return true;
                } 
            } 
            return false;
#endif // !FEATURE_PAL 
        }
#endif // _DEBUG

 
#if _DEBUG
        private static TextWriter MakeDebugOutputTextWriter(String streamLabel) 
        { 
            TextWriter output = new __DebugOutputTextWriter(streamLabel);
            output.WriteLine("Output redirected to debugger from a bit bucket."); 
            return TextWriter.Synchronized(output);
        }
#endif // _DEBUG
 
        // This method is only exposed via methods to get at the console.
        // We won't use any security checks here. 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private static Stream GetStandardFile(int stdHandleName, FileAccess access, int bufferSize) { 
            // We shouldn't close the handle for stdout, etc, or we'll break
            // unmanaged code in the process that will print to console.
            // We should have a better way of marking this on SafeHandle.
            IntPtr handle = Win32Native.GetStdHandle(stdHandleName); 
            SafeFileHandle sh = new SafeFileHandle(handle, false);
 
            // If someone launches a managed process via CreateProcess, stdout 
            // stderr, & stdin could independently be set to INVALID_HANDLE_VALUE.
            // Additionally they might use 0 as an invalid handle. 
            if (sh.IsInvalid) {
                // Minor perf optimization - get it out of the finalizer queue.
                sh.SetHandleAsInvalid();
                return Stream.Null; 
            }
 
            // Check whether we can read or write to this handle. 
            if (stdHandleName != Win32Native.STD_INPUT_HANDLE && !ConsoleHandleIsValid(sh)) {
                //BCLDebug.ConsoleError("Console::ConsoleHandleIsValid for std handle "+stdHandleName+" failed, setting it to a null stream"); 
                return Stream.Null;
            }

            //BCLDebug.ConsoleError("Console::GetStandardFile for std handle "+stdHandleName+" succeeded, returning handle number "+handle.ToString()); 
            Stream console = new __ConsoleStream(sh, access);
            // Do not buffer console streams, or we can get into situations where 
            // we end up blocking waiting for you to hit enter twice.  It was 
            // redundant.
            return console; 
        }

        public static Encoding InputEncoding {
            get { 
                uint cp = Win32Native.GetConsoleCP();
                return Encoding.GetEncoding((int) cp); 
            } 
            set {
                if (value == null) 
                    throw new ArgumentNullException("value");

                if (Environment.IsWin9X())
                    throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); 

                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 
 
                uint cp = (uint) value.CodePage;
 
                lock(InternalSyncObject) {
                    bool r = Win32Native.SetConsoleCP(cp);
                    if (!r)
                        __Error.WinIOError(); 

                    // We need to reinitialize Console.In in the next call to _in 
                    // This will discard the current StreamReader, potentially 
                    // losing buffered data
                    _in = null; 
                }
            }
        }
 
        public static Encoding OutputEncoding {
            get { 
                uint cp = Win32Native.GetConsoleOutputCP(); 
                return Encoding.GetEncoding((int) cp);
            } 
            set {
                if (value == null)
                    throw new ArgumentNullException("value");
 
                if (Environment.IsWin9X())
                    throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); 
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                lock(InternalSyncObject) {
                    // Before changing the code page we need to flush the data
                    // if Out hasn't been redirected. Also, have the next call to
                    // _out reinitialize the console code page. 

                    if (_out != null && !_wasOutRedirected) { 
                        _out.Flush(); 
                        _out = null;
                    } 
                    if (_error != null && !_wasErrorRedirected) {
                        _error.Flush();
                        _error = null;
                    } 

                    uint cp = (uint) value.CodePage; 
                    bool r = Win32Native.SetConsoleOutputCP(cp); 
                    if (!r)
                        __Error.WinIOError(); 
                }
            }
        }
 
#if !FEATURE_PAL
        [HostProtection(UI=true)] 
        public static void Beep() 
        {
            Beep(800, 200); 
        }

        [HostProtection(UI=true)]
        public static void Beep(int frequency, int duration) 
        {
            if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency) 
                throw new ArgumentOutOfRangeException("frequency", frequency, Environment.GetResourceString("ArgumentOutOfRange_BeepFrequency", MinBeepFrequency, MaxBeepFrequency)); 
            if (duration <= 0)
                throw new ArgumentOutOfRangeException("duration", duration, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 

            // Note that Beep over Remote Desktop connections does not currently
            // work.  Ignore any failures here.
            Win32Native.Beep(frequency, duration); 
        }
 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static void Clear() 
        {
            Win32Native.COORD coordScreen = new Win32Native.COORD();
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi;
            bool success; 
            int conSize;
 
            IntPtr hConsole = ConsoleOutputHandle; 
            if (hConsole == Win32Native.INVALID_HANDLE_VALUE)
                throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); 

            // get the number of character cells in the current buffer
            // Go through my helper method for fetching a screen buffer info
            // to correctly handle default console colors. 
            csbi = GetBufferInfo();
            conSize = csbi.dwSize.X * csbi.dwSize.Y; 
 
            // fill the entire screen with blanks
 
            int numCellsWritten = 0;
            success = Win32Native.FillConsoleOutputCharacter(hConsole, ' ',
                conSize, coordScreen, out numCellsWritten);
            if (!success) 
                __Error.WinIOError();
 
            // now set the buffer's attributes accordingly 

            numCellsWritten = 0; 
            success = Win32Native.FillConsoleOutputAttribute(hConsole, csbi.wAttributes,
                conSize, coordScreen, out numCellsWritten);
            if (!success)
                __Error.WinIOError(); 

            // put the cursor at (0, 0) 
 
            success = Win32Native.SetConsoleCursorPosition(hConsole, coordScreen);
            if (!success) 
                __Error.WinIOError();
        }

        private static Win32Native.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground) 
        {
            if ((((int)color) & ~0xf) != 0) 
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor")); 

            Win32Native.Color c = (Win32Native.Color) color; 

            // Make these background colors instead of foreground
            if (isBackground)
                c = (Win32Native.Color) ((int)c << 4); 
            return c;
        } 
 
        private static ConsoleColor ColorAttributeToConsoleColor(Win32Native.Color c)
        { 
            // Turn background colors into foreground colors.
            if ((c & Win32Native.Color.BackgroundMask) != 0)
                c = (Win32Native.Color) (((int)c) >> 4);
 
            return (ConsoleColor) c;
        } 
 
        public static ConsoleColor BackgroundColor {
            get { 
                bool succeeded;
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);

                // For code that may be used from Windows app w/ no console 
                if (!succeeded)
                    return ConsoleColor.Black; 
 
                Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.BackgroundMask;
                return ColorAttributeToConsoleColor(c); 
            }
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                Win32Native.Color c = ConsoleColorToColorAttribute(value, true);
 
                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
                // For code that may be used from Windows app w/ no console 
                if (!succeeded)
                    return;

                BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); 

                short attrs = csbi.wAttributes; 
                attrs &= ~((short)Win32Native.Color.BackgroundMask); 
                // C#'s bitwise-or sign-extends to 32 bits.
                attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c)); 
                // Ignore errors here - there are some scenarios for running code that wants
                // to print in colors to the console in a Windows application.
                Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs);
            } 
        }
 
        public static ConsoleColor ForegroundColor { 
            get {
                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);

                // For code that may be used from Windows app w/ no console
                if (!succeeded) 
                    return ConsoleColor.Gray;
 
                Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.ForegroundMask; 
                return ColorAttributeToConsoleColor(c);
            } 
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();

                Win32Native.Color c = ConsoleColorToColorAttribute(value, false); 

                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); 
                // For code that may be used from Windows app w/ no console
                if (!succeeded) 
                    return;

                BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!");
 
                short attrs = csbi.wAttributes;
                attrs &= ~((short)Win32Native.Color.ForegroundMask); 
                // C#'s bitwise-or sign-extends to 32 bits. 
                attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c));
                // Ignore errors here - there are some scenarios for running code that wants 
                // to print in colors to the console in a Windows application.
                Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs);
            }
        } 

        public static void ResetColor() 
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            bool succeeded;
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
            // For code that may be used from Windows app w/ no console
            if (!succeeded) 
                return;
 
            BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); 

            short defaultAttrs = (short) (ushort) _defaultColors; 
            // Ignore errors here - there are some scenarios for running code that wants
            // to print in colors to the console in a Windows application.
            Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, defaultAttrs);
        } 

        public static void MoveBufferArea(int sourceLeft, int sourceTop, 
            int sourceWidth, int sourceHeight, int targetLeft, int targetTop) 
        {
            MoveBufferArea(sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop, ' ', ConsoleColor.Black, BackgroundColor); 
        }

        public unsafe static void MoveBufferArea(int sourceLeft, int sourceTop,
            int sourceWidth, int sourceHeight, int targetLeft, int targetTop, 
            char sourceChar, ConsoleColor sourceForeColor,
            ConsoleColor sourceBackColor) 
        { 
            if (sourceForeColor < ConsoleColor.Black || sourceForeColor > ConsoleColor.White)
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceForeColor"); 
            if (sourceBackColor < ConsoleColor.Black || sourceBackColor > ConsoleColor.White)
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceBackColor");

            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
            Win32Native.COORD bufferSize = csbi.dwSize;
            if (sourceLeft < 0 || sourceLeft > bufferSize.X) 
                throw new ArgumentOutOfRangeException("sourceLeft", sourceLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (sourceTop < 0 || sourceTop > bufferSize.Y)
                throw new ArgumentOutOfRangeException("sourceTop", sourceTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (sourceWidth < 0 || sourceWidth > bufferSize.X - sourceLeft)
                throw new ArgumentOutOfRangeException("sourceWidth", sourceWidth, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
            if (sourceHeight < 0 || sourceTop > bufferSize.Y - sourceHeight)
                throw new ArgumentOutOfRangeException("sourceHeight", sourceHeight, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 

            // Note: if the target range is partially in and partially out 
            // of the buffer, then we let the OS clip it for us. 
            if (targetLeft < 0 || targetLeft > bufferSize.X)
                throw new ArgumentOutOfRangeException("targetLeft", targetLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (targetTop < 0 || targetTop > bufferSize.Y)
                throw new ArgumentOutOfRangeException("targetTop", targetTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));

            // If we're not doing any work, bail out now (Windows will return 
            // an error otherwise)
            if (sourceWidth == 0 || sourceHeight == 0) 
                return; 

            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            // Read data from the original location, blank it out, then write
            // it to the new location.  This will handle overlapping source and
            // destination regions correctly. 

            // See the "Reading and Writing Blocks of Characters and Attributes" 
            // sample for help 

            // Read the old data 
            Win32Native.CHAR_INFO[] data = new Win32Native.CHAR_INFO[sourceWidth * sourceHeight];
            bufferSize.X = (short) sourceWidth;
            bufferSize.Y = (short) sourceHeight;
            Win32Native.COORD bufferCoord = new Win32Native.COORD(); 
            Win32Native.SMALL_RECT readRegion = new Win32Native.SMALL_RECT();
            readRegion.Left = (short) sourceLeft; 
            readRegion.Right = (short) (sourceLeft + sourceWidth - 1); 
            readRegion.Top = (short) sourceTop;
            readRegion.Bottom = (short) (sourceTop + sourceHeight - 1); 

            bool r;
            fixed(Win32Native.CHAR_INFO* pCharInfo = data)
                r = Win32Native.ReadConsoleOutput(ConsoleOutputHandle, pCharInfo, bufferSize, bufferCoord, ref readRegion); 
            if (!r)
                __Error.WinIOError(); 
 
            // Overwrite old section
            // I don't have a good function to blank out a rectangle. 
            Win32Native.COORD writeCoord = new Win32Native.COORD();
            writeCoord.X = (short) sourceLeft;
            Win32Native.Color c = ConsoleColorToColorAttribute(sourceBackColor, true);
            c |= ConsoleColorToColorAttribute(sourceForeColor, false); 
            short attr = (short) c;
            int numWritten; 
            for(int i = sourceTop; i= Int16.MaxValue)
                throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize")); 
            if (height < srWindow.Bottom + 1 || height >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize"));
 
            Win32Native.COORD size = new Win32Native.COORD();
            size.X = (short) width;
            size.Y = (short) height;
            bool r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); 
            if (!r)
                __Error.WinIOError(); 
        } 

 
        public static int WindowHeight {
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 
            }
            set { 
                SetWindowSize(WindowWidth, value); 
            }
        } 

        public static int WindowWidth {
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.srWindow.Right - csbi.srWindow.Left + 1;
            } 
            set { 
                SetWindowSize(value, WindowHeight);
            } 
        }

        public static unsafe void SetWindowSize(int width, int height)
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            // Get the position of the current console window 
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
 
            if (width <= 0)
                throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            if (height <= 0)
                throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 

            bool r; 
 
            // If the buffer is smaller than this new window size, resize the
            // buffer to be large enough.  Include window position. 
            bool resizeBuffer = false;
            Win32Native.COORD size = new Win32Native.COORD();
            size.X = csbi.dwSize.X;
            size.Y = csbi.dwSize.Y; 
            if (csbi.dwSize.X < csbi.srWindow.Left + width) {
                if (csbi.srWindow.Left >= Int16.MaxValue - width) 
                    throw new ArgumentOutOfRangeException("width", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); 
                size.X = (short) (csbi.srWindow.Left + width);
                resizeBuffer = true; 
            }
            if (csbi.dwSize.Y < csbi.srWindow.Top + height) {
                if (csbi.srWindow.Top >= Int16.MaxValue - height)
                    throw new ArgumentOutOfRangeException("height", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); 
                size.Y = (short) (csbi.srWindow.Top + height);
                resizeBuffer = true; 
            } 
            if (resizeBuffer) {
                r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); 
                if (!r)
                    __Error.WinIOError();
            }
 
            Win32Native.SMALL_RECT srWindow = csbi.srWindow;
            // Preserve the position, but change the size. 
            srWindow.Bottom = (short) (srWindow.Top + height - 1); 
            srWindow.Right = (short) (srWindow.Left + width - 1);
 
            r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow);
            if (!r) {
                int errorCode = Marshal.GetLastWin32Error();
 
                // If we resized the buffer, un-resize it.
                if (resizeBuffer) { 
                    Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, csbi.dwSize); 
                }
 
                // Try to give a better error message here
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle);
                if (width > bounds.X)
                    throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.X)); 
                if (height > bounds.Y)
                    throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.Y)); 
 
                __Error.WinIOError(errorCode, String.Empty);
            } 
        }

        public static int LargestWindowWidth {
            get { 
                // Note this varies based on current screen resolution and
                // current console font.  Do not cache this value. 
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); 
                return bounds.X;
            } 
        }

        public static int LargestWindowHeight {
            get { 
                // Note this varies based on current screen resolution and
                // current console font.  Do not cache this value. 
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); 
                return bounds.Y;
            } 
        }

        public static int WindowLeft {
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Left; 
            } 
            set {
                SetWindowPosition(value, WindowTop); 
            }
        }

        public static int WindowTop { 
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.srWindow.Top; 
            }
            set { 
                SetWindowPosition(WindowLeft, value);
            }
        }
 
        public static unsafe void SetWindowPosition(int left, int top)
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            // Get the size of the current console window 
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();

            Win32Native.SMALL_RECT srWindow = csbi.srWindow;
 
            // Check for arithmetic underflows & overflows.
            int newRight = left + srWindow.Right - srWindow.Left + 1; 
            if (left < 0 || newRight > csbi.dwSize.X || newRight < 0) 
                throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos"));
            int newBottom = top + srWindow.Bottom - srWindow.Top + 1; 
            if (top < 0 || newBottom > csbi.dwSize.Y || newBottom < 0)
                throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos"));

            // Preserve the size, but move the position. 
            srWindow.Bottom -= (short) (srWindow.Top - top);
            srWindow.Right -= (short) (srWindow.Left - left); 
            srWindow.Left = (short) left; 
            srWindow.Top = (short) top;
 
            bool r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow);
            if (!r)
                __Error.WinIOError();
        } 

        public static int CursorLeft { 
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwCursorPosition.X; 
            }
            set {
                SetCursorPosition(value, CursorTop);
            } 
        }
 
        public static int CursorTop { 
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.dwCursorPosition.Y;
            }
            set {
                SetCursorPosition(CursorLeft, value); 
            }
        } 
 
        public static void SetCursorPosition(int left, int top)
        { 
            // Note on argument checking - the upper bounds are NOT correct
            // here!  But it looks slightly expensive to compute them.  Let
            // Windows calculate them, then we'll give a nice error message.
            if (left < 0 || left >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
            if (top < 0 || top >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 

            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            IntPtr hConsole = ConsoleOutputHandle;
            Win32Native.COORD coords = new Win32Native.COORD();
            coords.X = (short) left; 
            coords.Y = (short) top;
            bool r = Win32Native.SetConsoleCursorPosition(hConsole, coords); 
            if (!r) { 
                // Give a nice error message for out of range sizes
                int errorCode = Marshal.GetLastWin32Error(); 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                if (left < 0 || left >= csbi.dwSize.X)
                    throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
                if (top < 0 || top >= csbi.dwSize.Y) 
                    throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
 
                __Error.WinIOError(errorCode, String.Empty); 
            }
        } 

        public static int CursorSize {
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci; 
                IntPtr hConsole = ConsoleOutputHandle;
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); 
                if (!r) 
                    __Error.WinIOError();
 
                return cci.dwSize;
            }
            set {
                // Value should be a percentage from [1, 100]. 
                if (value < 1 || value > 100)
                    throw new ArgumentOutOfRangeException("value", value, Environment.GetResourceString("ArgumentOutOfRange_CursorSize")); 
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                // Win9x: setting the value to 100 doesn't work
                // correctly, but sets it to 32675.  Rounding oddity in OS?
                if (value == 100 && (Environment.OSInfo & Environment.OSName.Win9x) != 0)
                    value = 99; 

                Win32Native.CONSOLE_CURSOR_INFO cci; 
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r) 
                    __Error.WinIOError();

                cci.dwSize = value;
                r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci); 
                if (!r)
                    __Error.WinIOError(); 
            } 
        }
 
        public static bool CursorVisible {
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r) 
                    __Error.WinIOError(); 

                return cci.bVisible; 
            }
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); 
                if (!r)
                    __Error.WinIOError(); 

                cci.bVisible = value;
                r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci);
                if (!r) 
                    __Error.WinIOError();
            } 
        } 

        public static String Title { 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                StringBuilder sb = new StringBuilder(MaxConsoleTitleLength + 1); 
                // As of Windows Server 2003 (and probably all prior
                // releases), GetConsoleTitle doesn't do anything useful on 
                // empty strings, such as calling SetLastError so callers can 
                // determine whether that 0 was an error or was a success.
                Win32Native.SetLastError(0); 
                int r = Win32Native.GetConsoleTitle(sb, sb.Capacity);
                if (r == 0) {
                    // Allow a 0-length title
                    int errorCode = Marshal.GetLastWin32Error(); 
                    if (errorCode == 0)
                        sb.Length = 0; 
                    else 
                        __Error.WinIOError(errorCode, String.Empty);
                } 
                else if (r > MaxConsoleTitleLength)
                    throw new InvalidOperationException(Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong"));
                return sb.ToString();
            } 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            set { 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Length > MaxConsoleTitleLength)
                    throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong")); 

                if (!Win32Native.SetConsoleTitle(value)) 
                    __Error.WinIOError(); 
            }
        } 

        [Flags]
        internal enum ControlKeyState
        { 
            RightAltPressed =  0x0001,
            LeftAltPressed =   0x0002, 
            RightCtrlPressed = 0x0004, 
            LeftCtrlPressed =  0x0008,
            ShiftPressed =     0x0010, 
            NumLockOn =        0x0020,
            ScrollLockOn =     0x0040,
            CapsLockOn =       0x0080,
            EnhancedKey =      0x0100 
        }
 
        [HostProtection(UI=true)] 
        public static ConsoleKeyInfo ReadKey()
        { 
            return ReadKey(false);
        }

        private static bool IsKeyDownEvent(Win32Native.InputRecord ir) { 
            // Check for non-keyboard events & discard them.
            return (ir.eventType == Win32Native.KEY_EVENT && ir.keyEvent.keyDown); 
        } 

        private static bool IsModKey(short keyCode) { 
            // We should also skip over Shift, Control, and Alt, as well as caps lock.
            // Apparently we don't need to check for 0xA0 through 0xA5, which are keys like
            // Left Control & Right Control. See the ConsoleKey enum for these values
            return ((keyCode >= 0x10 && keyCode <= 0x12) 
                    || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91);
        } 
 
        [HostProtection(UI=true)]
        public static ConsoleKeyInfo ReadKey(bool intercept) 
        {
            Win32Native.InputRecord ir;
            int numEventsRead = -1;
            bool r; 

            if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT) { 
                // We had a previous keystroke with repeated characters. 
                ir = _cachedInputRecord;
                if (_cachedInputRecord.keyEvent.repeatCount == 0) 
                    _cachedInputRecord.eventType = -1;
                else {
                    _cachedInputRecord.keyEvent.repeatCount--;
                } 
                // We will return one key from this method, so we decrement the
                // repeatCount here, leaving the cachedInputRecord in the "queue". 
            } 
            else {
                while (true) { 
                    r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                    if (!r || numEventsRead == 0) {
                        // This will fail when stdin is a file (ie, foo < a.txt).
                        // We could theoretically call Console.Read here, but I 
                        // think we might do some things incorrectly then.
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleReadKeyOnFile")); 
                    } 

                    // Skip non key-down events. 
                    if (!IsKeyDownEvent(ir))
                        continue;

                    char ch = ir.keyEvent.uChar; 

                    if (ch == 0) { 
                        short keyCode = ir.keyEvent.virtualKeyCode; 

                        // Skip mod keys. 
                        if (IsModKey(keyCode))
                            continue;
                    }
 
                    if (ir.keyEvent.repeatCount > 1) {
                        ir.keyEvent.repeatCount--; 
                        _cachedInputRecord = ir; 
                        //Console.WriteLine("Storing repeated characters from this key event.");
                    } 
                    break;
                }
            }
 
            ControlKeyState state = (ControlKeyState) ir.keyEvent.controlKeyState;
            bool shift = (state & ControlKeyState.ShiftPressed) != 0; 
            bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0; 
            bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0;
 
            ConsoleKeyInfo info = new ConsoleKeyInfo(ir.keyEvent.uChar, (ConsoleKey) ir.keyEvent.virtualKeyCode, shift, alt, control);

            if (!intercept)
                Console.Write(ir.keyEvent.uChar); 
            return info;
        } 
 
        public static bool KeyAvailable {
            [HostProtection(UI=true)] 
            get {
                if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT)
                    return true;
 
                Win32Native.InputRecord ir = new Win32Native.InputRecord();
                int numEventsRead = 0; 
                while (true) { 
                    bool r = Win32Native.PeekConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                    if (!r) { 
                        int errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == Win32Native.ERROR_INVALID_HANDLE)
                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleKeyAvailableOnFile"));
                        __Error.WinIOError(errorCode, "stdin"); 
                    }
 
                    if (numEventsRead == 0) 
                        return false;
 
                    short keyCode = ir.keyEvent.virtualKeyCode;
                    // Skip non key-down && mod key events.
                    if (!IsKeyDownEvent(ir) || IsModKey(keyCode)) {
                        r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead); 
                        if (!r)
                            __Error.WinIOError(); 
                    } 
                    else {
                        return true; 
                    }
                }
            }
        } 

        public static bool NumberLock { 
            get { 
                short s = Win32Native.GetKeyState(NumberLockVKCode);
                return (s & 1) == 1; 
            }
        }

        public static bool CapsLock { 
            get {
                short s = Win32Native.GetKeyState(CapsLockVKCode); 
                return (s & 1) == 1; 
            }
        } 

        public static bool TreatControlCAsInput {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get {
                IntPtr handle = ConsoleInputHandle; 
                if (handle == Win32Native.INVALID_HANDLE_VALUE) 
                    throw new IOException(Environment.GetResourceString("IO.IO_NoConsole"));
                int mode = 0; 
                bool r = Win32Native.GetConsoleMode(handle, out mode);
                if (!r)
                    __Error.WinIOError();
                return (mode & Win32Native.ENABLE_PROCESSED_INPUT) == 0; 
            }
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)] 
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

                IntPtr handle = ConsoleInputHandle;
                if (handle == Win32Native.INVALID_HANDLE_VALUE)
                    throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); 

                int mode = 0; 
                bool r = Win32Native.GetConsoleMode(handle, out mode); 
                if (value)
                    mode &= ~Win32Native.ENABLE_PROCESSED_INPUT; 
                else
                    mode |= Win32Native.ENABLE_PROCESSED_INPUT;
                r = Win32Native.SetConsoleMode(handle, mode);
 
                if (!r)
                    __Error.WinIOError(); 
            } 
        }
#endif // !FEATURE_PAL 

        // During an appdomain unload, we must call into the OS and remove
        // our delegate from the OS's list of console control handlers.  If
        // we don't do this, the OS will call back on a delegate that no 
        // longer exists.  So, subclass CriticalFinalizableObject.
        // This problem would theoretically exist during process exit for a 
        // single appdomain too, so using a critical finalizer is probably 
        // better than the appdomain unload event (I'm not sure we call that
        // in the default appdomain during process exit). 
        internal sealed class ControlCHooker : CriticalFinalizerObject
        {
            private bool _hooked;
            private Win32Native.ConsoleCtrlHandlerRoutine _handler; 

            internal ControlCHooker() 
            { 
                _handler = new Win32Native.ConsoleCtrlHandlerRoutine(BreakEvent);
            } 

            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            ~ControlCHooker() 
            {
                Unhook(); 
            } 

            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            internal void Hook()
            {
                if (!_hooked) { 
                    bool r = Win32Native.SetConsoleCtrlHandler(_handler, true);
                    if (!r) 
                        __Error.WinIOError(); 
                    _hooked = true;
                } 
            }

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            internal void Unhook() 
            { 
                if (_hooked) {
                    bool r = Win32Native.SetConsoleCtrlHandler(_handler, false); 
                    if (!r)
                        __Error.WinIOError();
                    _hooked = false;
                } 
            }
        } 
 
        // A class with data so ControlC handlers can be called on a Threadpool thread.
        private sealed class ControlCDelegateData { 
            internal ConsoleSpecialKey ControlKey;
            internal bool Cancel;
            internal bool DelegateStarted;
            internal ManualResetEvent CompletionEvent; 
            internal ConsoleCancelEventHandler CancelCallbacks;
            internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks) { 
                this.ControlKey = controlKey; 
                this.CancelCallbacks = cancelCallbacks;
                this.CompletionEvent = new ManualResetEvent(false); 
                // this.Cancel defaults to false
                // this.DelegateStarted defaults to false
            }
        } 

        // Returns true if we've "handled" the break request, false if 
        // we want to terminate the process (or at least let the next 
        // control handler function have a chance).
        private static bool BreakEvent(int controlType) { 

            // The thread that this gets called back on has a very small stack on 64 bit systems. There is
            // not enough space to handle a managed exception being caught and thrown. So, queue up a work
            // item on another thread for the actual event callback. 

            if (controlType == Win32Native.CTRL_C_EVENT || 
                controlType == Win32Native.CTRL_BREAK_EVENT) { 

                // To avoid ---- between remove handler and raising the event 
                ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks;
                if (cancelCallbacks == null) {
                    return false;
                } 

                // Create the delegate 
                ConsoleSpecialKey controlKey = (controlType == 0) ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak; 
                ControlCDelegateData delegateData = new ControlCDelegateData(controlKey, cancelCallbacks);
                WaitCallback controlCCallback = new WaitCallback(ControlCDelegate); 

                // Queue the delegate
                if (!ThreadPool.QueueUserWorkItem(controlCCallback, delegateData)) {
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem returned false without throwing. Unable to execute ControlC handler"); 
                    return false;
                } 
                // Block until the delegate is done. We need to be robust in the face of the work item not executing 
                // but we also want to get control back immediately after it is done and we don't want to give the
                // handler a fixed time limit in case it needs to display UI. Wait on the event twice, once with a 
                // timout and a second time without if we are sure that the handler actually started.
                TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30); // 30 seconds
                delegateData.CompletionEvent.WaitOne(controlCWaitTime, false);
                if (!delegateData.DelegateStarted) { 
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem did not execute the handler within 30 seconds.");
                    return false; 
                } 
                delegateData.CompletionEvent.WaitOne();
                delegateData.CompletionEvent.Close(); 
                return delegateData.Cancel;

            }
            return false; 
        }
 
        // This is the worker delegate that is called on the Threadpool thread to fire the actual events. It must guarentee that it 
        // signals the caller on the ControlC thread so that it does not block indefinitely.
        private static void ControlCDelegate(object data) { 
            ControlCDelegateData controlCData = (ControlCDelegateData)data;
            try {
                controlCData.DelegateStarted = true;
                ConsoleCancelEventArgs args = new ConsoleCancelEventArgs(controlCData.ControlKey); 
                controlCData.CancelCallbacks(null, args);
                controlCData.Cancel = args.Cancel; 
            } 
            finally {
                controlCData.CompletionEvent.Set(); 
            }
        }

        // Note: hooking this event allows you to prevent Control-C from 
        // killing a console app, which is somewhat surprising for users.
        // Some permission seems appropriate.  We chose UI permission for lack 
        // of a better one.  However, we also applied host protection 
        // permission here as well, for self-affecting process management.
        // This allows hosts to prevent people from adding a handler for 
        // this event.
        public static event ConsoleCancelEventHandler CancelKeyPress {
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            add {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 
 
                lock(InternalSyncObject) {
                    // Add this delegate to the pile. 
                    _cancelCallbacks += value;

                    // If we haven't registered our control-C handler, do it.
                    if (_hooker == null) { 
                        _hooker = new ControlCHooker();
                        _hooker.Hook(); 
                    } 
                }
            } 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            remove {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

                lock(InternalSyncObject) { 
                    // If count was 0, call SetConsoleCtrlEvent to remove cb. 
                    _cancelCallbacks -= value;
                    BCLDebug.Assert(_cancelCallbacks == null || _cancelCallbacks.GetInvocationList().Length > 0, "Teach Console::CancelKeyPress to handle a non-null but empty list of callbacks"); 
                    if (_hooker != null && _cancelCallbacks == null)
                        _hooker.Unhook();
                }
            } 
        }
 
        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardError() {
            return OpenStandardError(_DefaultConsoleBufferSize);
        }
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardError(int bufferSize) {
            if (bufferSize < 0) 
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            return GetStandardFile(Win32Native.STD_ERROR_HANDLE,
                                   FileAccess.Write, bufferSize);
        } 

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static Stream OpenStandardInput() { 
            return OpenStandardInput(_DefaultConsoleBufferSize);
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardInput(int bufferSize) { 
            if (bufferSize < 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
            return GetStandardFile(Win32Native.STD_INPUT_HANDLE,
                                   FileAccess.Read, bufferSize);
        }
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardOutput() {
            return OpenStandardOutput(_DefaultConsoleBufferSize); 
        }

        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static Stream OpenStandardOutput(int bufferSize) { 
            if (bufferSize < 0) 
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            return GetStandardFile(Win32Native.STD_OUTPUT_HANDLE, 
                                   FileAccess.Write, bufferSize);
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetIn(TextReader newIn) { 
            if (newIn == null) 
                throw new ArgumentNullException("newIn");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            newIn = TextReader.Synchronized(newIn);
            lock(InternalSyncObject) {
                _in = newIn; 
            }
        } 
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.AppDomain)] 
        public static void SetOut(TextWriter newOut) {
            if (newOut == null)
                throw new ArgumentNullException("newOut");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            _wasOutRedirected = true; 
            newOut = TextWriter.Synchronized(newOut); 
            lock(InternalSyncObject) {
                _out = newOut; 
            }
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetError(TextWriter newError) { 
            if (newError == null) 
                throw new ArgumentNullException("newError");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            _wasErrorRedirected = true;
            newError = TextWriter.Synchronized(newError);
            lock(InternalSyncObject) { 
                _error = newError;
            } 
        } 

        [HostProtection(UI=true)] 
        public static int Read()
        {
            return In.Read();
        } 

        [HostProtection(UI=true)] 
        public static String ReadLine() 
        {
            return In.ReadLine(); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine() 
        {
            Out.WriteLine(); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(bool value)
        {
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(char value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(char[] buffer) 
        {
            Out.WriteLine(buffer); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(char[] buffer, int index, int count)
        {
            Out.WriteLine(buffer, index, count);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(decimal value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(double value) 
        {
            Out.WriteLine(value); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(float value)
        {
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(int value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        [CLSCompliant(false)] 
        public static void WriteLine(uint value)
        { 
            Out.WriteLine(value); 
        }
 
        [HostProtection(UI=true)]
        public static void WriteLine(long value)
        {
            Out.WriteLine(value); 
        }
 
        [HostProtection(UI=true)] 
        [CLSCompliant(false)]
        public static void WriteLine(ulong value) 
        {
            Out.WriteLine(value);
        }
 
        [HostProtection(UI=true)]
        public static void WriteLine(Object value) 
        { 
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)]
        public static void WriteLine(String value)
        { 
            Out.WriteLine(value);
        } 
 

        [HostProtection(UI=true)] 
        public static void WriteLine(String format, Object arg0)
        {
            Out.WriteLine(format, arg0);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(String format, Object arg0, Object arg1) 
        {
            Out.WriteLine(format, arg0, arg1); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(String format, Object arg0, Object arg1, Object arg2) 
        {
            Out.WriteLine(format, arg0, arg1, arg2); 
        } 

        [HostProtection(UI=true)] 
        [CLSCompliant(false)]
        public static void WriteLine(String format, Object arg0, Object arg1, Object arg2,Object arg3, __arglist)
        {
            Object[]   objArgs; 
            int        argCount;
 
            ArgIterator args = new ArgIterator(__arglist); 

            //+4 to account for the 4 hard-coded arguments at the beginning of the list. 
            argCount = args.GetRemainingCount() + 4;

            objArgs = new Object[argCount];
 
            //Handle the hard-coded arguments
            objArgs[0] = arg0; 
            objArgs[1] = arg1; 
            objArgs[2] = arg2;
            objArgs[3] = arg3; 

            //Walk all of the args in the variable part of the argument list.
            for (int i=4; i out 2> err 
    // 
    //Contains only static data.  Serializable attribute not required.
    public static class Console 
    {
        private const int _DefaultConsoleBufferSize = 256;

#if !FEATURE_PAL 
        private const int NumberLockVKCode = 0x90;  // virtual key code
        private const int CapsLockVKCode = 0x14; 
 
        // Beep range - see MSDN.
        private const int MinBeepFrequency = 37; 
        private const int MaxBeepFrequency = 32767;

        // MSDN says console titles can be up to 64 KB in length.
        // But I get an exception if I use buffer lengths longer than 
        // ~24500 Unicode characters.  Oh well.
        private const int MaxConsoleTitleLength = 24500; 
#endif // !FEATURE_PAL 

        private static TextReader _in; 
        private static TextWriter _out;
        private static TextWriter _error;

        private static ConsoleCancelEventHandler _cancelCallbacks; 
        private static ControlCHooker _hooker;
 
#if !FEATURE_PAL 
        // ReadLine & Read can't use this because they need to use ReadFile
        // to be able to handle redirected input.  We have to accept that 
        // we will lose repeated keystrokes when someone switches from
        // calling ReadKey to calling Read or ReadLine.  Those methods should
        // ideally flush this cache as well.
        private static Win32Native.InputRecord _cachedInputRecord; 

        // For ResetColor 
        private static bool _haveReadDefaultColors; 
        private static byte _defaultColors;
#endif // !FEATURE_PAL 

        private static bool _wasOutRedirected;
        private static bool _wasErrorRedirected;
 
        // Private object for locking instead of locking on a public type for SQL reliability work.
        private static Object s_InternalSyncObject; 
        private static Object InternalSyncObject { 
            get {
                if (s_InternalSyncObject == null) { 
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
                }
                return s_InternalSyncObject; 
            }
        } 
 
        // About reliability: I'm not using SafeHandle here.  We don't
        // need to close these handles, and we don't allow the user to close 
        // them so we don't have many of the security problems inherent in
        // something like file handles.  Additionally, in a host like SQL
        // Server, we won't have a console.
        private static IntPtr _consoleInputHandle; 
        private static IntPtr _consoleOutputHandle;
 
        private static IntPtr ConsoleInputHandle { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            get {
                if (_consoleInputHandle == IntPtr.Zero) {
                    _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
                } 
                return _consoleInputHandle;
            } 
        } 

        private static IntPtr ConsoleOutputHandle { 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                if (_consoleOutputHandle == IntPtr.Zero) { 
                    _consoleOutputHandle = Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE);
                } 
                return _consoleOutputHandle; 
            }
        } 

        public static TextWriter Error {
            [HostProtection(UI=true)]
            get { 
                // Hopefully this is inlineable.
                if (_error == null) 
                    InitializeStdOutError(false); 
                return _error;
            } 
        }

        public static TextReader In {
            [HostProtection(UI=true)] 
            get {
                // Because most applications don't use stdin, we can delay 
                // initialize it slightly better startup performance. 
                if (_in == null) {
                    lock(InternalSyncObject) { 
                        if (_in == null) {
                            // Set up Console.In
                            Stream s = OpenStandardInput(_DefaultConsoleBufferSize);
                            TextReader tr; 
                            if (s == Stream.Null)
                                tr = StreamReader.Null; 
                            else { 
                                // Hopefully Encoding.GetEncoding doesn't load as many classes now.
                                Encoding enc = Encoding.GetEncoding((int)Win32Native.GetConsoleCP()); 
                                tr = TextReader.Synchronized(new StreamReader(s, enc, false, _DefaultConsoleBufferSize, false));
                            }
                            System.Threading.Thread.MemoryBarrier();
                            _in = tr; 
                        }
                    } 
                } 
                return _in;
            } 
        }

        public static TextWriter Out {
            [HostProtection(UI=true)] 
            get {
                // Hopefully this is inlineable. 
                if (_out == null) 
                    InitializeStdOutError(true);
                return _out; 
            }
        }

        // For console apps, the console handles are set to values like 3, 7, 
        // and 11 OR if you've been created via CreateProcess, possibly -1
        // or 0.  -1 is definitely invalid, while 0 is probably invalid. 
        // Also note each handle can independently be invalid or good. 
        // For Windows apps, the console handles are set to values like 3, 7,
        // and 11 but are invalid handles - you may not write to them.  However, 
        // you can still spawn a Windows app via CreateProcess and read stdout
        // and stderr.
        // So, we always need to check each handle independently for validity
        // by trying to write or read to it, unless it is -1. 

        // We do not do a security check here, under the assumption that this 
        // cannot create a security hole, but only waste a user's time or 
        // cause a possible denial of service attack.
        private static void InitializeStdOutError(bool stdout) 
        {
            // Set up Console.Out or Console.Error.
            lock(InternalSyncObject) {
                if (stdout && _out != null) 
                    return;
                else if (!stdout && _error != null) 
                    return; 

                TextWriter writer = null; 
                Stream s;
                if (stdout)
                    s = OpenStandardOutput(_DefaultConsoleBufferSize);
                else 
                    s = OpenStandardError(_DefaultConsoleBufferSize);
 
                if (s == Stream.Null) { 
#if _DEBUG
                    if (CheckOutputDebug()) 
                        writer = MakeDebugOutputTextWriter((stdout) ? "Console.Out: " : "Console.Error: ");
                    else
#endif // _DEBUG
                        writer = TextWriter.Synchronized(StreamWriter.Null); 
                }
                else { 
                    int codePage = (int) Win32Native.GetConsoleOutputCP(); 
                    Encoding encoding = Encoding.GetEncoding(codePage);
                    StreamWriter stdxxx = new StreamWriter(s, encoding, _DefaultConsoleBufferSize, false); 
                    stdxxx.HaveWrittenPreamble = true;
                    stdxxx.AutoFlush = true;
                    writer = TextWriter.Synchronized(stdxxx);
                } 
                if (stdout)
                    _out = writer; 
                else 
                    _error = writer;
                BCLDebug.Assert((stdout && _out != null) || (!stdout && _error != null), "Didn't set Console::_out or _error appropriately!"); 
            }
        }

        // This is ONLY used in debug builds.  If you have a registry key set, 
        // it will redirect Console.Out & Error on console-less applications to
        // your debugger's output window. 
#if _DEBUG 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static bool CheckOutputDebug()
        {
#if !FEATURE_PAL
            new System.Security.Permissions.RegistryPermission(RegistryPermissionAccess.Read | RegistryPermissionAccess.Write, "HKEY_LOCAL_MACHINE").Assert(); 
            RegistryKey rk = Registry.LocalMachine;
            using (rk = rk.OpenSubKey("Software\\Microsoft\\.NETFramework", false)) { 
                if (rk != null) { 
                    Object obj = rk.GetValue("ConsoleSpewToDebugger", 0);
                    if (obj != null && ((int)obj) != 0) { 
                        return true;
                    }
                }
            } 
            return false;
#else // !FEATURE_PAL 
            const int parameterValueLength = 255; 
            StringBuilder parameterValue = new StringBuilder(parameterValueLength);
            bool rc = Win32Native.FetchConfigurationString(true, "ConsoleSpewToDebugger", parameterValue, parameterValueLength); 
            if (rc) {
                if (0 != parameterValue.Length) {
                    int value = Convert.ToInt32(parameterValue.ToString());
                    if (0 != value) 
                        return true;
                } 
            } 
            return false;
#endif // !FEATURE_PAL 
        }
#endif // _DEBUG

 
#if _DEBUG
        private static TextWriter MakeDebugOutputTextWriter(String streamLabel) 
        { 
            TextWriter output = new __DebugOutputTextWriter(streamLabel);
            output.WriteLine("Output redirected to debugger from a bit bucket."); 
            return TextWriter.Synchronized(output);
        }
#endif // _DEBUG
 
        // This method is only exposed via methods to get at the console.
        // We won't use any security checks here. 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        private static Stream GetStandardFile(int stdHandleName, FileAccess access, int bufferSize) { 
            // We shouldn't close the handle for stdout, etc, or we'll break
            // unmanaged code in the process that will print to console.
            // We should have a better way of marking this on SafeHandle.
            IntPtr handle = Win32Native.GetStdHandle(stdHandleName); 
            SafeFileHandle sh = new SafeFileHandle(handle, false);
 
            // If someone launches a managed process via CreateProcess, stdout 
            // stderr, & stdin could independently be set to INVALID_HANDLE_VALUE.
            // Additionally they might use 0 as an invalid handle. 
            if (sh.IsInvalid) {
                // Minor perf optimization - get it out of the finalizer queue.
                sh.SetHandleAsInvalid();
                return Stream.Null; 
            }
 
            // Check whether we can read or write to this handle. 
            if (stdHandleName != Win32Native.STD_INPUT_HANDLE && !ConsoleHandleIsValid(sh)) {
                //BCLDebug.ConsoleError("Console::ConsoleHandleIsValid for std handle "+stdHandleName+" failed, setting it to a null stream"); 
                return Stream.Null;
            }

            //BCLDebug.ConsoleError("Console::GetStandardFile for std handle "+stdHandleName+" succeeded, returning handle number "+handle.ToString()); 
            Stream console = new __ConsoleStream(sh, access);
            // Do not buffer console streams, or we can get into situations where 
            // we end up blocking waiting for you to hit enter twice.  It was 
            // redundant.
            return console; 
        }

        public static Encoding InputEncoding {
            get { 
                uint cp = Win32Native.GetConsoleCP();
                return Encoding.GetEncoding((int) cp); 
            } 
            set {
                if (value == null) 
                    throw new ArgumentNullException("value");

                if (Environment.IsWin9X())
                    throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); 

                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 
 
                uint cp = (uint) value.CodePage;
 
                lock(InternalSyncObject) {
                    bool r = Win32Native.SetConsoleCP(cp);
                    if (!r)
                        __Error.WinIOError(); 

                    // We need to reinitialize Console.In in the next call to _in 
                    // This will discard the current StreamReader, potentially 
                    // losing buffered data
                    _in = null; 
                }
            }
        }
 
        public static Encoding OutputEncoding {
            get { 
                uint cp = Win32Native.GetConsoleOutputCP(); 
                return Encoding.GetEncoding((int) cp);
            } 
            set {
                if (value == null)
                    throw new ArgumentNullException("value");
 
                if (Environment.IsWin9X())
                    throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); 
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                lock(InternalSyncObject) {
                    // Before changing the code page we need to flush the data
                    // if Out hasn't been redirected. Also, have the next call to
                    // _out reinitialize the console code page. 

                    if (_out != null && !_wasOutRedirected) { 
                        _out.Flush(); 
                        _out = null;
                    } 
                    if (_error != null && !_wasErrorRedirected) {
                        _error.Flush();
                        _error = null;
                    } 

                    uint cp = (uint) value.CodePage; 
                    bool r = Win32Native.SetConsoleOutputCP(cp); 
                    if (!r)
                        __Error.WinIOError(); 
                }
            }
        }
 
#if !FEATURE_PAL
        [HostProtection(UI=true)] 
        public static void Beep() 
        {
            Beep(800, 200); 
        }

        [HostProtection(UI=true)]
        public static void Beep(int frequency, int duration) 
        {
            if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency) 
                throw new ArgumentOutOfRangeException("frequency", frequency, Environment.GetResourceString("ArgumentOutOfRange_BeepFrequency", MinBeepFrequency, MaxBeepFrequency)); 
            if (duration <= 0)
                throw new ArgumentOutOfRangeException("duration", duration, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 

            // Note that Beep over Remote Desktop connections does not currently
            // work.  Ignore any failures here.
            Win32Native.Beep(frequency, duration); 
        }
 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static void Clear() 
        {
            Win32Native.COORD coordScreen = new Win32Native.COORD();
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi;
            bool success; 
            int conSize;
 
            IntPtr hConsole = ConsoleOutputHandle; 
            if (hConsole == Win32Native.INVALID_HANDLE_VALUE)
                throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); 

            // get the number of character cells in the current buffer
            // Go through my helper method for fetching a screen buffer info
            // to correctly handle default console colors. 
            csbi = GetBufferInfo();
            conSize = csbi.dwSize.X * csbi.dwSize.Y; 
 
            // fill the entire screen with blanks
 
            int numCellsWritten = 0;
            success = Win32Native.FillConsoleOutputCharacter(hConsole, ' ',
                conSize, coordScreen, out numCellsWritten);
            if (!success) 
                __Error.WinIOError();
 
            // now set the buffer's attributes accordingly 

            numCellsWritten = 0; 
            success = Win32Native.FillConsoleOutputAttribute(hConsole, csbi.wAttributes,
                conSize, coordScreen, out numCellsWritten);
            if (!success)
                __Error.WinIOError(); 

            // put the cursor at (0, 0) 
 
            success = Win32Native.SetConsoleCursorPosition(hConsole, coordScreen);
            if (!success) 
                __Error.WinIOError();
        }

        private static Win32Native.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground) 
        {
            if ((((int)color) & ~0xf) != 0) 
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor")); 

            Win32Native.Color c = (Win32Native.Color) color; 

            // Make these background colors instead of foreground
            if (isBackground)
                c = (Win32Native.Color) ((int)c << 4); 
            return c;
        } 
 
        private static ConsoleColor ColorAttributeToConsoleColor(Win32Native.Color c)
        { 
            // Turn background colors into foreground colors.
            if ((c & Win32Native.Color.BackgroundMask) != 0)
                c = (Win32Native.Color) (((int)c) >> 4);
 
            return (ConsoleColor) c;
        } 
 
        public static ConsoleColor BackgroundColor {
            get { 
                bool succeeded;
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);

                // For code that may be used from Windows app w/ no console 
                if (!succeeded)
                    return ConsoleColor.Black; 
 
                Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.BackgroundMask;
                return ColorAttributeToConsoleColor(c); 
            }
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                Win32Native.Color c = ConsoleColorToColorAttribute(value, true);
 
                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
                // For code that may be used from Windows app w/ no console 
                if (!succeeded)
                    return;

                BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); 

                short attrs = csbi.wAttributes; 
                attrs &= ~((short)Win32Native.Color.BackgroundMask); 
                // C#'s bitwise-or sign-extends to 32 bits.
                attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c)); 
                // Ignore errors here - there are some scenarios for running code that wants
                // to print in colors to the console in a Windows application.
                Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs);
            } 
        }
 
        public static ConsoleColor ForegroundColor { 
            get {
                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);

                // For code that may be used from Windows app w/ no console
                if (!succeeded) 
                    return ConsoleColor.Gray;
 
                Win32Native.Color c = (Win32Native.Color) csbi.wAttributes & Win32Native.Color.ForegroundMask; 
                return ColorAttributeToConsoleColor(c);
            } 
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();

                Win32Native.Color c = ConsoleColorToColorAttribute(value, false); 

                bool succeeded; 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded); 
                // For code that may be used from Windows app w/ no console
                if (!succeeded) 
                    return;

                BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!");
 
                short attrs = csbi.wAttributes;
                attrs &= ~((short)Win32Native.Color.ForegroundMask); 
                // C#'s bitwise-or sign-extends to 32 bits. 
                attrs = (short) (((uint) (ushort) attrs) | ((uint) (ushort) c));
                // Ignore errors here - there are some scenarios for running code that wants 
                // to print in colors to the console in a Windows application.
                Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, attrs);
            }
        } 

        public static void ResetColor() 
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            bool succeeded;
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
            // For code that may be used from Windows app w/ no console
            if (!succeeded) 
                return;
 
            BCLDebug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!"); 

            short defaultAttrs = (short) (ushort) _defaultColors; 
            // Ignore errors here - there are some scenarios for running code that wants
            // to print in colors to the console in a Windows application.
            Win32Native.SetConsoleTextAttribute(ConsoleOutputHandle, defaultAttrs);
        } 

        public static void MoveBufferArea(int sourceLeft, int sourceTop, 
            int sourceWidth, int sourceHeight, int targetLeft, int targetTop) 
        {
            MoveBufferArea(sourceLeft, sourceTop, sourceWidth, sourceHeight, targetLeft, targetTop, ' ', ConsoleColor.Black, BackgroundColor); 
        }

        public unsafe static void MoveBufferArea(int sourceLeft, int sourceTop,
            int sourceWidth, int sourceHeight, int targetLeft, int targetTop, 
            char sourceChar, ConsoleColor sourceForeColor,
            ConsoleColor sourceBackColor) 
        { 
            if (sourceForeColor < ConsoleColor.Black || sourceForeColor > ConsoleColor.White)
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceForeColor"); 
            if (sourceBackColor < ConsoleColor.Black || sourceBackColor > ConsoleColor.White)
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"), "sourceBackColor");

            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
            Win32Native.COORD bufferSize = csbi.dwSize;
            if (sourceLeft < 0 || sourceLeft > bufferSize.X) 
                throw new ArgumentOutOfRangeException("sourceLeft", sourceLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (sourceTop < 0 || sourceTop > bufferSize.Y)
                throw new ArgumentOutOfRangeException("sourceTop", sourceTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (sourceWidth < 0 || sourceWidth > bufferSize.X - sourceLeft)
                throw new ArgumentOutOfRangeException("sourceWidth", sourceWidth, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
            if (sourceHeight < 0 || sourceTop > bufferSize.Y - sourceHeight)
                throw new ArgumentOutOfRangeException("sourceHeight", sourceHeight, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 

            // Note: if the target range is partially in and partially out 
            // of the buffer, then we let the OS clip it for us. 
            if (targetLeft < 0 || targetLeft > bufferSize.X)
                throw new ArgumentOutOfRangeException("targetLeft", targetLeft, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 
            if (targetTop < 0 || targetTop > bufferSize.Y)
                throw new ArgumentOutOfRangeException("targetTop", targetTop, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));

            // If we're not doing any work, bail out now (Windows will return 
            // an error otherwise)
            if (sourceWidth == 0 || sourceHeight == 0) 
                return; 

            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            // Read data from the original location, blank it out, then write
            // it to the new location.  This will handle overlapping source and
            // destination regions correctly. 

            // See the "Reading and Writing Blocks of Characters and Attributes" 
            // sample for help 

            // Read the old data 
            Win32Native.CHAR_INFO[] data = new Win32Native.CHAR_INFO[sourceWidth * sourceHeight];
            bufferSize.X = (short) sourceWidth;
            bufferSize.Y = (short) sourceHeight;
            Win32Native.COORD bufferCoord = new Win32Native.COORD(); 
            Win32Native.SMALL_RECT readRegion = new Win32Native.SMALL_RECT();
            readRegion.Left = (short) sourceLeft; 
            readRegion.Right = (short) (sourceLeft + sourceWidth - 1); 
            readRegion.Top = (short) sourceTop;
            readRegion.Bottom = (short) (sourceTop + sourceHeight - 1); 

            bool r;
            fixed(Win32Native.CHAR_INFO* pCharInfo = data)
                r = Win32Native.ReadConsoleOutput(ConsoleOutputHandle, pCharInfo, bufferSize, bufferCoord, ref readRegion); 
            if (!r)
                __Error.WinIOError(); 
 
            // Overwrite old section
            // I don't have a good function to blank out a rectangle. 
            Win32Native.COORD writeCoord = new Win32Native.COORD();
            writeCoord.X = (short) sourceLeft;
            Win32Native.Color c = ConsoleColorToColorAttribute(sourceBackColor, true);
            c |= ConsoleColorToColorAttribute(sourceForeColor, false); 
            short attr = (short) c;
            int numWritten; 
            for(int i = sourceTop; i= Int16.MaxValue)
                throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize")); 
            if (height < srWindow.Bottom + 1 || height >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferLessThanWindowSize"));
 
            Win32Native.COORD size = new Win32Native.COORD();
            size.X = (short) width;
            size.Y = (short) height;
            bool r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); 
            if (!r)
                __Error.WinIOError(); 
        } 

 
        public static int WindowHeight {
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 
            }
            set { 
                SetWindowSize(WindowWidth, value); 
            }
        } 

        public static int WindowWidth {
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.srWindow.Right - csbi.srWindow.Left + 1;
            } 
            set { 
                SetWindowSize(value, WindowHeight);
            } 
        }

        public static unsafe void SetWindowSize(int width, int height)
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            // Get the position of the current console window 
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
 
            if (width <= 0)
                throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            if (height <= 0)
                throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 

            bool r; 
 
            // If the buffer is smaller than this new window size, resize the
            // buffer to be large enough.  Include window position. 
            bool resizeBuffer = false;
            Win32Native.COORD size = new Win32Native.COORD();
            size.X = csbi.dwSize.X;
            size.Y = csbi.dwSize.Y; 
            if (csbi.dwSize.X < csbi.srWindow.Left + width) {
                if (csbi.srWindow.Left >= Int16.MaxValue - width) 
                    throw new ArgumentOutOfRangeException("width", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); 
                size.X = (short) (csbi.srWindow.Left + width);
                resizeBuffer = true; 
            }
            if (csbi.dwSize.Y < csbi.srWindow.Top + height) {
                if (csbi.srWindow.Top >= Int16.MaxValue - height)
                    throw new ArgumentOutOfRangeException("height", Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowBufferSize")); 
                size.Y = (short) (csbi.srWindow.Top + height);
                resizeBuffer = true; 
            } 
            if (resizeBuffer) {
                r = Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, size); 
                if (!r)
                    __Error.WinIOError();
            }
 
            Win32Native.SMALL_RECT srWindow = csbi.srWindow;
            // Preserve the position, but change the size. 
            srWindow.Bottom = (short) (srWindow.Top + height - 1); 
            srWindow.Right = (short) (srWindow.Left + width - 1);
 
            r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow);
            if (!r) {
                int errorCode = Marshal.GetLastWin32Error();
 
                // If we resized the buffer, un-resize it.
                if (resizeBuffer) { 
                    Win32Native.SetConsoleScreenBufferSize(ConsoleOutputHandle, csbi.dwSize); 
                }
 
                // Try to give a better error message here
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle);
                if (width > bounds.X)
                    throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.X)); 
                if (height > bounds.Y)
                    throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowSize_Size", bounds.Y)); 
 
                __Error.WinIOError(errorCode, String.Empty);
            } 
        }

        public static int LargestWindowWidth {
            get { 
                // Note this varies based on current screen resolution and
                // current console font.  Do not cache this value. 
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); 
                return bounds.X;
            } 
        }

        public static int LargestWindowHeight {
            get { 
                // Note this varies based on current screen resolution and
                // current console font.  Do not cache this value. 
                Win32Native.COORD bounds = Win32Native.GetLargestConsoleWindowSize(ConsoleOutputHandle); 
                return bounds.Y;
            } 
        }

        public static int WindowLeft {
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Left; 
            } 
            set {
                SetWindowPosition(value, WindowTop); 
            }
        }

        public static int WindowTop { 
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.srWindow.Top; 
            }
            set { 
                SetWindowPosition(WindowLeft, value);
            }
        }
 
        public static unsafe void SetWindowPosition(int left, int top)
        { 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            // Get the size of the current console window 
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();

            Win32Native.SMALL_RECT srWindow = csbi.srWindow;
 
            // Check for arithmetic underflows & overflows.
            int newRight = left + srWindow.Right - srWindow.Left + 1; 
            if (left < 0 || newRight > csbi.dwSize.X || newRight < 0) 
                throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos"));
            int newBottom = top + srWindow.Bottom - srWindow.Top + 1; 
            if (top < 0 || newBottom > csbi.dwSize.Y || newBottom < 0)
                throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleWindowPos"));

            // Preserve the size, but move the position. 
            srWindow.Bottom -= (short) (srWindow.Top - top);
            srWindow.Right -= (short) (srWindow.Left - left); 
            srWindow.Left = (short) left; 
            srWindow.Top = (short) top;
 
            bool r = Win32Native.SetConsoleWindowInfo(ConsoleOutputHandle, true, &srWindow);
            if (!r)
                __Error.WinIOError();
        } 

        public static int CursorLeft { 
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwCursorPosition.X; 
            }
            set {
                SetCursorPosition(value, CursorTop);
            } 
        }
 
        public static int CursorTop { 
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(); 
                return csbi.dwCursorPosition.Y;
            }
            set {
                SetCursorPosition(CursorLeft, value); 
            }
        } 
 
        public static void SetCursorPosition(int left, int top)
        { 
            // Note on argument checking - the upper bounds are NOT correct
            // here!  But it looks slightly expensive to compute them.  Let
            // Windows calculate them, then we'll give a nice error message.
            if (left < 0 || left >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
            if (top < 0 || top >= Int16.MaxValue) 
                throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries")); 

            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

            IntPtr hConsole = ConsoleOutputHandle;
            Win32Native.COORD coords = new Win32Native.COORD();
            coords.X = (short) left; 
            coords.Y = (short) top;
            bool r = Win32Native.SetConsoleCursorPosition(hConsole, coords); 
            if (!r) { 
                // Give a nice error message for out of range sizes
                int errorCode = Marshal.GetLastWin32Error(); 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                if (left < 0 || left >= csbi.dwSize.X)
                    throw new ArgumentOutOfRangeException("left", left, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
                if (top < 0 || top >= csbi.dwSize.Y) 
                    throw new ArgumentOutOfRangeException("top", top, Environment.GetResourceString("ArgumentOutOfRange_ConsoleBufferBoundaries"));
 
                __Error.WinIOError(errorCode, String.Empty); 
            }
        } 

        public static int CursorSize {
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci; 
                IntPtr hConsole = ConsoleOutputHandle;
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); 
                if (!r) 
                    __Error.WinIOError();
 
                return cci.dwSize;
            }
            set {
                // Value should be a percentage from [1, 100]. 
                if (value < 1 || value > 100)
                    throw new ArgumentOutOfRangeException("value", value, Environment.GetResourceString("ArgumentOutOfRange_CursorSize")); 
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                // Win9x: setting the value to 100 doesn't work
                // correctly, but sets it to 32675.  Rounding oddity in OS?
                if (value == 100 && (Environment.OSInfo & Environment.OSName.Win9x) != 0)
                    value = 99; 

                Win32Native.CONSOLE_CURSOR_INFO cci; 
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r) 
                    __Error.WinIOError();

                cci.dwSize = value;
                r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci); 
                if (!r)
                    __Error.WinIOError(); 
            } 
        }
 
        public static bool CursorVisible {
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r) 
                    __Error.WinIOError(); 

                return cci.bVisible; 
            }
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle; 
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci); 
                if (!r)
                    __Error.WinIOError(); 

                cci.bVisible = value;
                r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci);
                if (!r) 
                    __Error.WinIOError();
            } 
        } 

        public static String Title { 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                StringBuilder sb = new StringBuilder(MaxConsoleTitleLength + 1); 
                // As of Windows Server 2003 (and probably all prior
                // releases), GetConsoleTitle doesn't do anything useful on 
                // empty strings, such as calling SetLastError so callers can 
                // determine whether that 0 was an error or was a success.
                Win32Native.SetLastError(0); 
                int r = Win32Native.GetConsoleTitle(sb, sb.Capacity);
                if (r == 0) {
                    // Allow a 0-length title
                    int errorCode = Marshal.GetLastWin32Error(); 
                    if (errorCode == 0)
                        sb.Length = 0; 
                    else 
                        __Error.WinIOError(errorCode, String.Empty);
                } 
                else if (r > MaxConsoleTitleLength)
                    throw new InvalidOperationException(Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong"));
                return sb.ToString();
            } 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            set { 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Length > MaxConsoleTitleLength)
                    throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong")); 

                if (!Win32Native.SetConsoleTitle(value)) 
                    __Error.WinIOError(); 
            }
        } 

        [Flags]
        internal enum ControlKeyState
        { 
            RightAltPressed =  0x0001,
            LeftAltPressed =   0x0002, 
            RightCtrlPressed = 0x0004, 
            LeftCtrlPressed =  0x0008,
            ShiftPressed =     0x0010, 
            NumLockOn =        0x0020,
            ScrollLockOn =     0x0040,
            CapsLockOn =       0x0080,
            EnhancedKey =      0x0100 
        }
 
        [HostProtection(UI=true)] 
        public static ConsoleKeyInfo ReadKey()
        { 
            return ReadKey(false);
        }

        private static bool IsKeyDownEvent(Win32Native.InputRecord ir) { 
            // Check for non-keyboard events & discard them.
            return (ir.eventType == Win32Native.KEY_EVENT && ir.keyEvent.keyDown); 
        } 

        private static bool IsModKey(short keyCode) { 
            // We should also skip over Shift, Control, and Alt, as well as caps lock.
            // Apparently we don't need to check for 0xA0 through 0xA5, which are keys like
            // Left Control & Right Control. See the ConsoleKey enum for these values
            return ((keyCode >= 0x10 && keyCode <= 0x12) 
                    || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91);
        } 
 
        [HostProtection(UI=true)]
        public static ConsoleKeyInfo ReadKey(bool intercept) 
        {
            Win32Native.InputRecord ir;
            int numEventsRead = -1;
            bool r; 

            if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT) { 
                // We had a previous keystroke with repeated characters. 
                ir = _cachedInputRecord;
                if (_cachedInputRecord.keyEvent.repeatCount == 0) 
                    _cachedInputRecord.eventType = -1;
                else {
                    _cachedInputRecord.keyEvent.repeatCount--;
                } 
                // We will return one key from this method, so we decrement the
                // repeatCount here, leaving the cachedInputRecord in the "queue". 
            } 
            else {
                while (true) { 
                    r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                    if (!r || numEventsRead == 0) {
                        // This will fail when stdin is a file (ie, foo < a.txt).
                        // We could theoretically call Console.Read here, but I 
                        // think we might do some things incorrectly then.
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleReadKeyOnFile")); 
                    } 

                    // Skip non key-down events. 
                    if (!IsKeyDownEvent(ir))
                        continue;

                    char ch = ir.keyEvent.uChar; 

                    if (ch == 0) { 
                        short keyCode = ir.keyEvent.virtualKeyCode; 

                        // Skip mod keys. 
                        if (IsModKey(keyCode))
                            continue;
                    }
 
                    if (ir.keyEvent.repeatCount > 1) {
                        ir.keyEvent.repeatCount--; 
                        _cachedInputRecord = ir; 
                        //Console.WriteLine("Storing repeated characters from this key event.");
                    } 
                    break;
                }
            }
 
            ControlKeyState state = (ControlKeyState) ir.keyEvent.controlKeyState;
            bool shift = (state & ControlKeyState.ShiftPressed) != 0; 
            bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0; 
            bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0;
 
            ConsoleKeyInfo info = new ConsoleKeyInfo(ir.keyEvent.uChar, (ConsoleKey) ir.keyEvent.virtualKeyCode, shift, alt, control);

            if (!intercept)
                Console.Write(ir.keyEvent.uChar); 
            return info;
        } 
 
        public static bool KeyAvailable {
            [HostProtection(UI=true)] 
            get {
                if (_cachedInputRecord.eventType == Win32Native.KEY_EVENT)
                    return true;
 
                Win32Native.InputRecord ir = new Win32Native.InputRecord();
                int numEventsRead = 0; 
                while (true) { 
                    bool r = Win32Native.PeekConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                    if (!r) { 
                        int errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == Win32Native.ERROR_INVALID_HANDLE)
                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleKeyAvailableOnFile"));
                        __Error.WinIOError(errorCode, "stdin"); 
                    }
 
                    if (numEventsRead == 0) 
                        return false;
 
                    short keyCode = ir.keyEvent.virtualKeyCode;
                    // Skip non key-down && mod key events.
                    if (!IsKeyDownEvent(ir) || IsModKey(keyCode)) {
                        r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead); 
                        if (!r)
                            __Error.WinIOError(); 
                    } 
                    else {
                        return true; 
                    }
                }
            }
        } 

        public static bool NumberLock { 
            get { 
                short s = Win32Native.GetKeyState(NumberLockVKCode);
                return (s & 1) == 1; 
            }
        }

        public static bool CapsLock { 
            get {
                short s = Win32Native.GetKeyState(CapsLockVKCode); 
                return (s & 1) == 1; 
            }
        } 

        public static bool TreatControlCAsInput {
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] 
            get {
                IntPtr handle = ConsoleInputHandle; 
                if (handle == Win32Native.INVALID_HANDLE_VALUE) 
                    throw new IOException(Environment.GetResourceString("IO.IO_NoConsole"));
                int mode = 0; 
                bool r = Win32Native.GetConsoleMode(handle, out mode);
                if (!r)
                    __Error.WinIOError();
                return (mode & Win32Native.ENABLE_PROCESSED_INPUT) == 0; 
            }
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)] 
            set {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

                IntPtr handle = ConsoleInputHandle;
                if (handle == Win32Native.INVALID_HANDLE_VALUE)
                    throw new IOException(Environment.GetResourceString("IO.IO_NoConsole")); 

                int mode = 0; 
                bool r = Win32Native.GetConsoleMode(handle, out mode); 
                if (value)
                    mode &= ~Win32Native.ENABLE_PROCESSED_INPUT; 
                else
                    mode |= Win32Native.ENABLE_PROCESSED_INPUT;
                r = Win32Native.SetConsoleMode(handle, mode);
 
                if (!r)
                    __Error.WinIOError(); 
            } 
        }
#endif // !FEATURE_PAL 

        // During an appdomain unload, we must call into the OS and remove
        // our delegate from the OS's list of console control handlers.  If
        // we don't do this, the OS will call back on a delegate that no 
        // longer exists.  So, subclass CriticalFinalizableObject.
        // This problem would theoretically exist during process exit for a 
        // single appdomain too, so using a critical finalizer is probably 
        // better than the appdomain unload event (I'm not sure we call that
        // in the default appdomain during process exit). 
        internal sealed class ControlCHooker : CriticalFinalizerObject
        {
            private bool _hooked;
            private Win32Native.ConsoleCtrlHandlerRoutine _handler; 

            internal ControlCHooker() 
            { 
                _handler = new Win32Native.ConsoleCtrlHandlerRoutine(BreakEvent);
            } 

            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            ~ControlCHooker() 
            {
                Unhook(); 
            } 

            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            internal void Hook()
            {
                if (!_hooked) { 
                    bool r = Win32Native.SetConsoleCtrlHandler(_handler, true);
                    if (!r) 
                        __Error.WinIOError(); 
                    _hooked = true;
                } 
            }

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [ResourceExposure(ResourceScope.Process)] 
            [ResourceConsumption(ResourceScope.Process)]
            internal void Unhook() 
            { 
                if (_hooked) {
                    bool r = Win32Native.SetConsoleCtrlHandler(_handler, false); 
                    if (!r)
                        __Error.WinIOError();
                    _hooked = false;
                } 
            }
        } 
 
        // A class with data so ControlC handlers can be called on a Threadpool thread.
        private sealed class ControlCDelegateData { 
            internal ConsoleSpecialKey ControlKey;
            internal bool Cancel;
            internal bool DelegateStarted;
            internal ManualResetEvent CompletionEvent; 
            internal ConsoleCancelEventHandler CancelCallbacks;
            internal ControlCDelegateData(ConsoleSpecialKey controlKey, ConsoleCancelEventHandler cancelCallbacks) { 
                this.ControlKey = controlKey; 
                this.CancelCallbacks = cancelCallbacks;
                this.CompletionEvent = new ManualResetEvent(false); 
                // this.Cancel defaults to false
                // this.DelegateStarted defaults to false
            }
        } 

        // Returns true if we've "handled" the break request, false if 
        // we want to terminate the process (or at least let the next 
        // control handler function have a chance).
        private static bool BreakEvent(int controlType) { 

            // The thread that this gets called back on has a very small stack on 64 bit systems. There is
            // not enough space to handle a managed exception being caught and thrown. So, queue up a work
            // item on another thread for the actual event callback. 

            if (controlType == Win32Native.CTRL_C_EVENT || 
                controlType == Win32Native.CTRL_BREAK_EVENT) { 

                // To avoid ---- between remove handler and raising the event 
                ConsoleCancelEventHandler cancelCallbacks = Console._cancelCallbacks;
                if (cancelCallbacks == null) {
                    return false;
                } 

                // Create the delegate 
                ConsoleSpecialKey controlKey = (controlType == 0) ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak; 
                ControlCDelegateData delegateData = new ControlCDelegateData(controlKey, cancelCallbacks);
                WaitCallback controlCCallback = new WaitCallback(ControlCDelegate); 

                // Queue the delegate
                if (!ThreadPool.QueueUserWorkItem(controlCCallback, delegateData)) {
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem returned false without throwing. Unable to execute ControlC handler"); 
                    return false;
                } 
                // Block until the delegate is done. We need to be robust in the face of the work item not executing 
                // but we also want to get control back immediately after it is done and we don't want to give the
                // handler a fixed time limit in case it needs to display UI. Wait on the event twice, once with a 
                // timout and a second time without if we are sure that the handler actually started.
                TimeSpan controlCWaitTime = new TimeSpan(0, 0, 30); // 30 seconds
                delegateData.CompletionEvent.WaitOne(controlCWaitTime, false);
                if (!delegateData.DelegateStarted) { 
                    BCLDebug.Assert(false, "ThreadPool.QueueUserWorkItem did not execute the handler within 30 seconds.");
                    return false; 
                } 
                delegateData.CompletionEvent.WaitOne();
                delegateData.CompletionEvent.Close(); 
                return delegateData.Cancel;

            }
            return false; 
        }
 
        // This is the worker delegate that is called on the Threadpool thread to fire the actual events. It must guarentee that it 
        // signals the caller on the ControlC thread so that it does not block indefinitely.
        private static void ControlCDelegate(object data) { 
            ControlCDelegateData controlCData = (ControlCDelegateData)data;
            try {
                controlCData.DelegateStarted = true;
                ConsoleCancelEventArgs args = new ConsoleCancelEventArgs(controlCData.ControlKey); 
                controlCData.CancelCallbacks(null, args);
                controlCData.Cancel = args.Cancel; 
            } 
            finally {
                controlCData.CompletionEvent.Set(); 
            }
        }

        // Note: hooking this event allows you to prevent Control-C from 
        // killing a console app, which is somewhat surprising for users.
        // Some permission seems appropriate.  We chose UI permission for lack 
        // of a better one.  However, we also applied host protection 
        // permission here as well, for self-affecting process management.
        // This allows hosts to prevent people from adding a handler for 
        // this event.
        public static event ConsoleCancelEventHandler CancelKeyPress {
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)] 
            add {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 
 
                lock(InternalSyncObject) {
                    // Add this delegate to the pile. 
                    _cancelCallbacks += value;

                    // If we haven't registered our control-C handler, do it.
                    if (_hooker == null) { 
                        _hooker = new ControlCHooker();
                        _hooker.Hook(); 
                    } 
                }
            } 
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            remove {
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand(); 

                lock(InternalSyncObject) { 
                    // If count was 0, call SetConsoleCtrlEvent to remove cb. 
                    _cancelCallbacks -= value;
                    BCLDebug.Assert(_cancelCallbacks == null || _cancelCallbacks.GetInvocationList().Length > 0, "Teach Console::CancelKeyPress to handle a non-null but empty list of callbacks"); 
                    if (_hooker != null && _cancelCallbacks == null)
                        _hooker.Unhook();
                }
            } 
        }
 
        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardError() {
            return OpenStandardError(_DefaultConsoleBufferSize);
        }
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardError(int bufferSize) {
            if (bufferSize < 0) 
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            return GetStandardFile(Win32Native.STD_ERROR_HANDLE,
                                   FileAccess.Write, bufferSize);
        } 

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static Stream OpenStandardInput() { 
            return OpenStandardInput(_DefaultConsoleBufferSize);
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardInput(int bufferSize) { 
            if (bufferSize < 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
            return GetStandardFile(Win32Native.STD_INPUT_HANDLE,
                                   FileAccess.Read, bufferSize);
        }
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        public static Stream OpenStandardOutput() {
            return OpenStandardOutput(_DefaultConsoleBufferSize); 
        }

        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static Stream OpenStandardOutput(int bufferSize) { 
            if (bufferSize < 0) 
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            return GetStandardFile(Win32Native.STD_OUTPUT_HANDLE, 
                                   FileAccess.Write, bufferSize);
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetIn(TextReader newIn) { 
            if (newIn == null) 
                throw new ArgumentNullException("newIn");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            newIn = TextReader.Synchronized(newIn);
            lock(InternalSyncObject) {
                _in = newIn; 
            }
        } 
 
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.AppDomain)] 
        public static void SetOut(TextWriter newOut) {
            if (newOut == null)
                throw new ArgumentNullException("newOut");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            _wasOutRedirected = true; 
            newOut = TextWriter.Synchronized(newOut); 
            lock(InternalSyncObject) {
                _out = newOut; 
            }
        }

        [HostProtection(UI=true)] 
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetError(TextWriter newError) { 
            if (newError == null) 
                throw new ArgumentNullException("newError");
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

            _wasErrorRedirected = true;
            newError = TextWriter.Synchronized(newError);
            lock(InternalSyncObject) { 
                _error = newError;
            } 
        } 

        [HostProtection(UI=true)] 
        public static int Read()
        {
            return In.Read();
        } 

        [HostProtection(UI=true)] 
        public static String ReadLine() 
        {
            return In.ReadLine(); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine() 
        {
            Out.WriteLine(); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(bool value)
        {
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(char value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(char[] buffer) 
        {
            Out.WriteLine(buffer); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(char[] buffer, int index, int count)
        {
            Out.WriteLine(buffer, index, count);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(decimal value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(double value) 
        {
            Out.WriteLine(value); 
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(float value)
        {
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(int value) 
        {
            Out.WriteLine(value); 
        }

        [HostProtection(UI=true)]
        [CLSCompliant(false)] 
        public static void WriteLine(uint value)
        { 
            Out.WriteLine(value); 
        }
 
        [HostProtection(UI=true)]
        public static void WriteLine(long value)
        {
            Out.WriteLine(value); 
        }
 
        [HostProtection(UI=true)] 
        [CLSCompliant(false)]
        public static void WriteLine(ulong value) 
        {
            Out.WriteLine(value);
        }
 
        [HostProtection(UI=true)]
        public static void WriteLine(Object value) 
        { 
            Out.WriteLine(value);
        } 

        [HostProtection(UI=true)]
        public static void WriteLine(String value)
        { 
            Out.WriteLine(value);
        } 
 

        [HostProtection(UI=true)] 
        public static void WriteLine(String format, Object arg0)
        {
            Out.WriteLine(format, arg0);
        } 

        [HostProtection(UI=true)] 
        public static void WriteLine(String format, Object arg0, Object arg1) 
        {
            Out.WriteLine(format, arg0, arg1); 
        }

        [HostProtection(UI=true)]
        public static void WriteLine(String format, Object arg0, Object arg1, Object arg2) 
        {
            Out.WriteLine(format, arg0, arg1, arg2); 
        } 

        [HostProtection(UI=true)] 
        [CLSCompliant(false)]
        public static void WriteLine(String format, Object arg0, Object arg1, Object arg2,Object arg3, __arglist)
        {
            Object[]   objArgs; 
            int        argCount;
 
            ArgIterator args = new ArgIterator(__arglist); 

            //+4 to account for the 4 hard-coded arguments at the beginning of the list. 
            argCount = args.GetRemainingCount() + 4;

            objArgs = new Object[argCount];
 
            //Handle the hard-coded arguments
            objArgs[0] = arg0; 
            objArgs[1] = arg1; 
            objArgs[2] = arg2;
            objArgs[3] = arg3; 

            //Walk all of the args in the variable part of the argument list.
            for (int i=4; i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK