File: system\console.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
// 
//   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;
    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;
    using System.Diagnostics.Contracts;
    using System.Diagnostics.CodeAnalysis;
    using System.Collections.Generic;
 
    // 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;
        private const short AltVKCode = 0x12;
 
#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
 
#if !FEATURE_CORECLR
        private static readonly UnicodeEncoding StdConUnicodeEncoding = new UnicodeEncoding(false, false);
#endif  // !FEATURE_CORECLR
 
        private static volatile TextReader _in;
        private static volatile TextWriter _out;
        private static volatile TextWriter _error;
 
        private static volatile ConsoleCancelEventHandler _cancelCallbacks;
        private static volatile 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.
        [System.Security.SecurityCritical] // auto-generated
        private static Win32Native.InputRecord _cachedInputRecord;
 
        // For ResetColor
        private static volatile bool _haveReadDefaultColors;
        private static volatile byte _defaultColors;
#endif // !FEATURE_PAL
#if FEATURE_CODEPAGES_FILE    // if no codepages file then locked into default       
        private static volatile bool _isOutTextWriterRedirected = false;
        private static volatile bool _isErrorTextWriterRedirected = false;
#endif        
        private static volatile Encoding _inputEncoding = null;
        private static volatile Encoding _outputEncoding = null;
 
#if !FEATURE_CORECLR
        private static volatile bool _stdInRedirectQueried = false;
        private static volatile bool _stdOutRedirectQueried = false;
        private static volatile bool _stdErrRedirectQueried = false;
 
        private static bool _isStdInRedirected;
        private static bool _isStdOutRedirected;
        private static bool _isStdErrRedirected;
#endif  // !FEATURE_CORECLR
 
        // Private object for locking instead of locking on a public type for SQL reliability work.
        // Use this for internal synchronization during initialization, wiring up events, or for short, non-blocking OS calls.
        private static volatile Object s_InternalSyncObject;
        private static Object InternalSyncObject {
            get {
                Contract.Ensures(Contract.Result<Object>() != null);
                if (s_InternalSyncObject == null) {
                    Object o = new Object();
#pragma warning disable 0420
                    Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
#pragma warning restore 0420
                }
                return s_InternalSyncObject;
            }
        }
 
        // Use this for blocking in Console.ReadKey, which needs to protect itself in case multiple threads call it simultaneously.
        // Use a ReadKey-specific lock though, to allow other fields to be initialized on this type.
        private static volatile Object s_ReadKeySyncObject;
        private static Object ReadKeySyncObject
        {
            get
            {
                Contract.Ensures(Contract.Result<Object>() != null);
                if (s_ReadKeySyncObject == null)
                {
                    Object o = new Object();
#pragma warning disable 0420
                    Interlocked.CompareExchange<Object>(ref s_ReadKeySyncObject, o, null);
#pragma warning restore 0420
                }
                return s_ReadKeySyncObject;
            }
        }
 
        // 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 volatile IntPtr _consoleInputHandle;
        private static volatile IntPtr _consoleOutputHandle;
 
        private static IntPtr ConsoleInputHandle {
            [System.Security.SecurityCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                if (_consoleInputHandle == IntPtr.Zero) {
                    _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
                }
                return _consoleInputHandle;
            }
        }
 
        private static IntPtr ConsoleOutputHandle {
            [System.Security.SecurityCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                if (_consoleOutputHandle == IntPtr.Zero) {
                    _consoleOutputHandle = Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE);
                }
                return _consoleOutputHandle;
            }
        }        
 
 
#if !FEATURE_CORECLR
        [System.Security.SecuritySafeCritical]
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private static bool IsHandleRedirected(IntPtr ioHandle) {
 
            // Need this to use GetFileType:
            SafeFileHandle safeIOHandle = new SafeFileHandle(ioHandle, false);
 
            // If handle is not to a character device, we must be redirected:
            int fileType = Win32Native.GetFileType(safeIOHandle);
            if ((fileType & Win32Native.FILE_TYPE_CHAR) != Win32Native.FILE_TYPE_CHAR)
                return true;
 
            // We are on a char device.
            // If GetConsoleMode succeeds, we are NOT redirected.
            int mode;
            bool success = Win32Native.GetConsoleMode(ioHandle, out mode);
            return !success;
        }
 
        
        public static bool IsInputRedirected {
            [System.Security.SecuritySafeCritical]
            get {
 
                if (_stdInRedirectQueried)
                    return _isStdInRedirected;
 
                lock (InternalSyncObject) {
 
                    if (_stdInRedirectQueried)
                        return _isStdInRedirected;
 
                    _isStdInRedirected = IsHandleRedirected(ConsoleInputHandle);
                    _stdInRedirectQueried = true;
 
                    return _isStdInRedirected;
                }
            }
        }  // public static bool IsInputRedirected
 
        
        public static bool IsOutputRedirected {
            [System.Security.SecuritySafeCritical]
            get {
 
                if (_stdOutRedirectQueried)
                    return _isStdOutRedirected;
 
                lock (InternalSyncObject) {
 
                    if (_stdOutRedirectQueried)
                        return _isStdOutRedirected;
                    
                    _isStdOutRedirected = IsHandleRedirected(ConsoleOutputHandle);
                    _stdOutRedirectQueried = true;
 
                    return _isStdOutRedirected;
                }
            } 
        }  // public static bool IsOutputRedirected
 
        
        public static bool IsErrorRedirected {
            [System.Security.SecuritySafeCritical]
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
 
                if (_stdErrRedirectQueried)
                    return _isStdErrRedirected;
 
                lock (InternalSyncObject) {
 
                    if (_stdErrRedirectQueried)
                        return _isStdErrRedirected;
 
                    IntPtr errHndle = Win32Native.GetStdHandle(Win32Native.STD_ERROR_HANDLE);
                    _isStdErrRedirected = IsHandleRedirected(errHndle);
                    _stdErrRedirectQueried = true;
 
                    return _isStdErrRedirected;
                }
            }
        }  // public static bool IsErrorRedirected
#endif  // !FEATURE_CORECLR
        
        public static TextReader In {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [HostProtection(UI=true)]
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Contract.Ensures(Contract.Result<TextReader>() != null);
                // 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.
#if FEATURE_CORECLR
                                Encoding enc = Encoding.UTF8;
#else  // FEATURE_CORECLR                              
                                Encoding enc = InputEncoding;
#endif // FEATURE_CORECLR
                                tr = TextReader.Synchronized(new StreamReader(s, enc, false, DefaultConsoleBufferSize, true));                                    
                            }
                            System.Threading.Thread.MemoryBarrier();
                            _in = tr;
                        }
                    }
                }
                return _in;
            }
        }
 
        public static TextWriter Out {
            [HostProtection(UI=true)]
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Contract.Ensures(Contract.Result<TextWriter>() != null);
                // Hopefully this is inlineable.
                if (_out == null)
                    InitializeStdOutError(true);
                return _out;
            }
        }
 
        public static TextWriter Error {
            [HostProtection(UI=true)]
            get {
                Contract.Ensures(Contract.Result<TextWriter>() != null);
                // Hopefully this is inlineable.
                if (_error == null)
                    InitializeStdOutError(false);
                return _error;
            }
        }
 
        // 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.
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
        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 {
#if FEATURE_CORECLR                    
                    Encoding encoding = Encoding.UTF8;
#else // FEATURE_CORECLR                    
                    Encoding encoding = OutputEncoding;
#endif // FEATURE_CORECLR
                    StreamWriter stdxxx = new StreamWriter(s, encoding, DefaultConsoleBufferSize, true);
                    stdxxx.HaveWrittenPreamble = true;
                    stdxxx.AutoFlush = true;
                    writer = TextWriter.Synchronized(stdxxx);
                }
                if (stdout)
                    _out = writer;
                else
                    _error = writer;
                Contract.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
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static bool CheckOutputDebug()
        {
#if FEATURE_WIN32_REGISTRY    

            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_WIN32_REGISTRY    
#if FEATURE_PAL && !FEATURE_CORECLR
            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;
                }
            }
#endif // FEATURE_PAL && !FEATURE_CORECLR
            return false;
#endif // FEATURE_WIN32_REGISTRY       
        }
#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
 
 
#if !FEATURE_CORECLR
        // We cannot simply compare the encoding to Encoding.Unicode bacasue it incorporates BOM
        // and we do not care about BOM. Instead, we compare by class, codepage and little-endianess only:
        private static bool IsStandardConsoleUnicodeEncoding(Encoding encoding) {
 
            UnicodeEncoding enc = encoding as UnicodeEncoding;
            if (null == enc)
                return false;
 
            return (StdConUnicodeEncoding.CodePage == enc.CodePage)
                    && (StdConUnicodeEncoding.bigEndian == enc.bigEndian);
        }
 
        private static bool GetUseFileAPIs(int handleType) {
 
            switch(handleType) {
 
                case Win32Native.STD_INPUT_HANDLE:
                    return !IsStandardConsoleUnicodeEncoding(InputEncoding) || IsInputRedirected;
 
                case Win32Native.STD_OUTPUT_HANDLE:
                    return !IsStandardConsoleUnicodeEncoding(OutputEncoding) || IsOutputRedirected;
 
                case Win32Native.STD_ERROR_HANDLE:
                    return !IsStandardConsoleUnicodeEncoding(OutputEncoding) || IsErrorRedirected;
 
                default:
                    // This can never happen.
                    Contract.Assert(false, "Unexpected handleType value (" + handleType + ")");
                    return true;                     
            }
        }
#endif  // !FEATURE_CORECLR
 
        // This method is only exposed via methods to get at the console.
        // We won't use any security checks here.
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [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 && !ConsoleHandleIsWritable(sh)) {
                //BCLDebug.ConsoleError("Console::ConsoleHandleIsValid for std handle "+stdHandleName+" failed, setting it to a null stream");
                return Stream.Null;
            }
 
            #if !FEATURE_CORECLR
            bool useFileAPIs = GetUseFileAPIs(stdHandleName);
            #else
            const bool useFileAPIs = true;
            #endif  // !FEATURE_CORECLR
 
            //BCLDebug.ConsoleError("Console::GetStandardFile for std handle "+stdHandleName+" succeeded, returning handle number "+handle.ToString());
            Stream console = new __ConsoleStream(sh, access, useFileAPIs);
            // 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;
        }
 
        // Checks whether stdout or stderr are writable.  Do NOT pass
        // stdin here.
#if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
#else
        [System.Security.SecuritySafeCritical]
#endif
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private static unsafe bool ConsoleHandleIsWritable(SafeFileHandle outErrHandle) {
            // Do NOT call this method on stdin!
 
            // Windows apps may have non-null valid looking handle values for 
            // stdin, stdout and stderr, but they may not be readable or 
            // writable.  Verify this by calling WriteFile in the 
            // appropriate modes.
            // This must handle console-less Windows apps.
 
            int bytesWritten;
            byte junkByte = 0x41;
            int r = Win32Native.WriteFile(outErrHandle, &junkByte, 0, out bytesWritten, IntPtr.Zero);
            // In Win32 apps w/ no console, bResult should be 0 for failure.
            return r != 0;
        }
 
 
        public static Encoding InputEncoding {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
 
                Contract.Ensures(Contract.Result<Encoding>() != null);
 
                if (null != _inputEncoding)
                    return _inputEncoding;
 
                lock(InternalSyncObject) {
 
                    if (null != _inputEncoding)
                        return _inputEncoding;
                   
                    uint cp = Win32Native.GetConsoleCP();
                    _inputEncoding = Encoding.GetEncoding((int) cp);
                    return _inputEncoding;
                }
            }
#if FEATURE_CODEPAGES_FILE    // if no codepages file then locked into default                                                           
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
 
                if (value == null)
                    throw new ArgumentNullException("value");
 
                Contract.EndContractBlock();
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
                lock(InternalSyncObject) {
 
                    if (!IsStandardConsoleUnicodeEncoding(value)) {
 
                        uint cp = (uint) value.CodePage;
                        bool r = Win32Native.SetConsoleCP(cp);
                        if (!r)
                            __Error.WinIOError();
                    }
 
                    _inputEncoding = (Encoding) value.Clone();
 
                    // We need to reinitialize Console.In in the next call to _in
                    // This will discard the current StreamReader, potentially 
                    // losing buffered data
                    _in = null;
                }
            }  // set
#endif // FEATURE_CODEPAGES_FILE
        }  // public static Encoding InputEncoding
 
        public static Encoding OutputEncoding {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
                
                Contract.Ensures(Contract.Result<Encoding>() != null);
 
                if (null != _outputEncoding)
                    return _outputEncoding;
 
                lock(InternalSyncObject) {
 
                    if (null != _outputEncoding)
                        return _outputEncoding;
                   
                    uint cp = Win32Native.GetConsoleOutputCP();
                    _outputEncoding = Encoding.GetEncoding((int) cp);
                    return _outputEncoding;
                }
            }
#if FEATURE_CODEPAGES_FILE    // if no codepages file then locked into default                                                                       
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                if (value == null)
                    throw new ArgumentNullException("value");
                Contract.EndContractBlock();
 
                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 && !_isOutTextWriterRedirected) {
                        _out.Flush();
                        _out = null;
                    }
                    if (_error != null && !_isErrorTextWriterRedirected) {
                        _error.Flush();
                        _error = null;
                    }
 
                    if (!IsStandardConsoleUnicodeEncoding(value)) {
 
                        uint cp = (uint) value.CodePage;
                        bool r = Win32Native.SetConsoleOutputCP(cp);
                        if (!r)
                            __Error.WinIOError();
                    }
 
                    _outputEncoding = (Encoding) value.Clone();
                }
            }  // set
#endif // FEATURE_CODEPAGES_FILE    
        }  // public static Encoding OutputEncoding
 
#if !FEATURE_PAL
        [HostProtection(UI=true)]
        public static void Beep()
        {
            Beep(800, 200);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [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
            Contract.EndContractBlock();
            // work.  Ignore any failures here.
            Win32Native.Beep(frequency, duration);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [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();
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static Win32Native.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground)
        {
            if ((((int)color) & ~0xf) != 0)
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidConsoleColor"));
            Contract.EndContractBlock();
 
            Win32Native.Color c = (Win32Native.Color) color;
 
            // Make these background colors instead of foreground
            if (isBackground)
                c = (Win32Native.Color) ((int)c << 4);
            return c;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            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);
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            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;
 
                Contract.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 BackgroundColor
 
        public static ConsoleColor ForegroundColor {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            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);
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            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;
 
                Contract.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 ConsoleColor ForegroundColor
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        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;
 
            Contract.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);
        }
 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        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);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        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");
            Contract.EndContractBlock();
 
            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<sourceTop + sourceHeight; i++) {
                writeCoord.Y = (short) i;
                r = Win32Native.FillConsoleOutputCharacter(ConsoleOutputHandle, sourceChar, sourceWidth, writeCoord, out numWritten);
                Contract.Assert(numWritten == sourceWidth, "FillConsoleOutputCharacter wrote the wrong number of chars!");
                if (!r)
                    __Error.WinIOError();
 
                r = Win32Native.FillConsoleOutputAttribute(ConsoleOutputHandle, attr, sourceWidth, writeCoord, out numWritten);
                if (!r)
                    __Error.WinIOError();
            }
            
            // Write text to new location
            Win32Native.SMALL_RECT writeRegion = new Win32Native.SMALL_RECT();
            writeRegion.Left = (short) targetLeft;
            writeRegion.Right = (short) (targetLeft + sourceWidth);
            writeRegion.Top = (short) targetTop;
            writeRegion.Bottom = (short) (targetTop + sourceHeight);
 
            fixed(Win32Native.CHAR_INFO* pCharInfo = data)            
                r = Win32Native.WriteConsoleOutput(ConsoleOutputHandle, pCharInfo, bufferSize, bufferCoord, ref writeRegion);
        }  // MoveBufferArea
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private static Win32Native.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo()
        {
            bool junk;
            return GetBufferInfo(true, out junk);
        }
 
        // For apps that don't have a console (like Windows apps), they might
        // run other code that includes color console output.  Allow a mechanism
        // where that code won't throw an exception for simple errors.
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        private static Win32Native.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(bool throwOnNoConsole, out bool succeeded)
        {
            succeeded = false;
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi;
            bool success;
 
            IntPtr hConsole = ConsoleOutputHandle;
            if (hConsole == Win32Native.INVALID_HANDLE_VALUE) {
                if (!throwOnNoConsole)
                    return new Win32Native.CONSOLE_SCREEN_BUFFER_INFO();
                else
                    throw new IOException(Environment.GetResourceString("IO.IO_NoConsole"));
            }
 
            // Note that if stdout is redirected to a file, the console handle
            // may be a file.  If this fails, try stderr and stdin.
            success = Win32Native.GetConsoleScreenBufferInfo(hConsole, out csbi);
            if (!success) {
                success = Win32Native.GetConsoleScreenBufferInfo(Win32Native.GetStdHandle(Win32Native.STD_ERROR_HANDLE), out csbi);
                if (!success)
                    success = Win32Native.GetConsoleScreenBufferInfo(Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE), out csbi);
 
                if (!success) {
                    int errorCode = Marshal.GetLastWin32Error();
                    if (errorCode == Win32Native.ERROR_INVALID_HANDLE && !throwOnNoConsole)
                        return new Win32Native.CONSOLE_SCREEN_BUFFER_INFO();
                    __Error.WinIOError(errorCode, null);
                }
            }
 
            if (!_haveReadDefaultColors) {
                // Fetch the default foreground and background color for the
                // ResetColor method.
                Contract.Assert((int)Win32Native.Color.ColorMask == 0xff, "Make sure one byte is large enough to store a Console color value!");
                _defaultColors = (byte) (csbi.wAttributes & (short) Win32Native.Color.ColorMask);
                _haveReadDefaultColors = true;
            }
 
            succeeded = true;
            return csbi;
        }
 
        public static int BufferHeight {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwSize.Y;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetBufferSize(BufferWidth, value);
            }
        }
 
        public static int BufferWidth {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwSize.X;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetBufferSize(value, BufferHeight);
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static void SetBufferSize(int width, int height)
        {
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            // Ensure the new size is not smaller than the console window
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
            Win32Native.SMALL_RECT srWindow = csbi.srWindow;
            if (width < srWindow.Right + 1 || width >= 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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWindowSize(WindowWidth, value);
            }
        }
 
        public static int WindowWidth {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get { 
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Right - csbi.srWindow.Left + 1;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWindowSize(value, WindowHeight);
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static unsafe void SetWindowSize(int width, int height)
        {
            if (width <= 0)
                throw new ArgumentOutOfRangeException("width", width, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            if (height <= 0)
                throw new ArgumentOutOfRangeException("height", height, Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            Contract.EndContractBlock();
 
            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
 
            // Get the position of the current console window
            Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
            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 unsafe void SetWindowSize(int width, int height)
 
        public static int LargestWindowWidth {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Left;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWindowPosition(value, WindowTop);
            }
        }
 
        public static int WindowTop {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.srWindow.Top;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetWindowPosition(WindowLeft, value);
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwCursorPosition.X;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetCursorPosition(value, CursorTop);
            }
        }
 
        public static int CursorTop {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
                return csbi.dwCursorPosition.Y;
            }
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                SetCursorPosition(CursorLeft, value);
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        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"));
            Contract.EndContractBlock();
 
            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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle;
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r)
                    __Error.WinIOError();
 
                return cci.dwSize;
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            set {
                // Value should be a percentage from [1, 100].
                if (value < 1 || value > 100)
                    throw new ArgumentOutOfRangeException("value", value, Environment.GetResourceString("ArgumentOutOfRange_CursorSize"));
                Contract.EndContractBlock();
 
                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.dwSize = value;
                r = Win32Native.SetConsoleCursorInfo(hConsole, ref cci);
                if (!r)
                    __Error.WinIOError();
            }
        }
 
        public static bool CursorVisible {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                Win32Native.CONSOLE_CURSOR_INFO cci;
                IntPtr hConsole = ConsoleOutputHandle;
                bool r = Win32Native.GetConsoleCursorInfo(hConsole, out cci);
                if (!r)
                    __Error.WinIOError();
 
                return cci.bVisible;
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            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();
            }
        }
 
       
        #if !FEATURE_CORECLR
        [System.Security.SecurityCritical]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Ansi)]
        [ResourceExposure(ResourceScope.None)]
        [SuppressUnmanagedCodeSecurity]
        private static extern Int32 GetTitleNative(StringHandleOnStack outTitle, out Int32 outTitleLength);
         
        public static String Title {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            get {
                string title = null;
                int titleLength = -1;
                Int32 r = GetTitleNative(JitHelpers.GetStringHandleOnStack(ref title), out titleLength);
 
                if (0 != r) {
                    __Error.WinIOError(r, String.Empty);
                }                
 
                if (titleLength > MaxConsoleTitleLength)
                    throw new InvalidOperationException(Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong"));
 
                Contract.Assert(title.Length == titleLength);
 
                return title;                  
            }
 
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
            set {
                if (value == null)
                    throw new ArgumentNullException("value");
                if (value.Length > MaxConsoleTitleLength)
                    throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_ConsoleTitleTooLong"));
                Contract.EndContractBlock();
 
                new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
                
                if (!Win32Native.SetConsoleTitle(value))
                    __Error.WinIOError();
            }
        }
        #endif  // !FEATURE_CORECLR
 
        [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)]
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static ConsoleKeyInfo ReadKey()
        {
            return ReadKey(false);
        }
 
        // For tracking Alt+NumPad unicode key sequence. When you press Alt key down 
        // and press a numpad unicode decimal sequence and then release Alt key, the
        // desired effect is to translate the sequence into one Unicode KeyPress. 
        // We need to keep track of the Alt+NumPad sequence and surface the final
        // unicode char alone when the Alt key is released. 
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsAltKeyDown(Win32Native.InputRecord ir) { 
            return (((ControlKeyState) ir.keyEvent.controlKeyState) 
                              & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0;
        }
 
        // Skip non key events. Generally we want to surface only KeyDown event 
        // and suppress KeyUp event from the same Key press but there are cases
        // where the assumption of KeyDown-KeyUp pairing for a given key press 
        // is invalid. For example in IME Unicode keyboard input, we often see
        // only KeyUp until the key is released.  
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsKeyDownEvent(Win32Native.InputRecord ir) {
            return (ir.eventType == Win32Native.KEY_EVENT && ir.keyEvent.keyDown);
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsModKey(Win32Native.InputRecord ir) {
            // 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.
            short keyCode = ir.keyEvent.virtualKeyCode;
            return ((keyCode >= 0x10 && keyCode <= 0x12) 
                    || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static ConsoleKeyInfo ReadKey(bool intercept)
        {
            Win32Native.InputRecord ir;
            int numEventsRead = -1;
            bool r;
 
            lock (ReadKeySyncObject) {
                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 { // We did NOT have a previous keystroke with repeated characters:
 
                    while (true) {
                        r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                        if (!r || numEventsRead == 0) {
                            // This will fail when stdin is redirected from a file or pipe. 
                            // We could theoretically call Console.Read here, but I 
                            // think we might do some things incorrectly then.
                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConsoleReadKeyOnFile"));
                        }
 
                        short keyCode = ir.keyEvent.virtualKeyCode;
 
                        // First check for non-keyboard events & discard them. Generally we tap into only KeyDown events and ignore the KeyUp events
                        // but it is possible that we are dealing with a Alt+NumPad unicode key sequence, the final unicode char is revealed only when 
                        // the Alt key is released (i.e when the sequence is complete). To avoid noise, when the Alt key is down, we should eat up 
                        // any intermediate key strokes (from NumPad) that collectively forms the Unicode character.  
 
                        if (!IsKeyDownEvent(ir)) {
                            // 
                            if (keyCode != AltVKCode)
                                continue;
                        }
 
                        char ch = (char) ir.keyEvent.uChar;
 
                        // In a Alt+NumPad unicode sequence, when the alt key is released uChar will represent the final unicode character, we need to 
                        // surface this. VirtualKeyCode for this event will be Alt from the Alt-Up key event. This is probably not the right code, 
                        // especially when we don't expose ConsoleKey.Alt, so this will end up being the hex value (0x12). VK_PACKET comes very 
                        // close to being useful and something that we could look into using for this purpose... 
 
                        if (ch == 0) {
                            // Skip mod keys.
                            if (IsModKey(ir))
                                continue;
                        }
 
                        // When Alt is down, it is possible that we are in the middle of a Alt+NumPad unicode sequence.
                        // Escape any intermediate NumPad keys whether NumLock is on or not (notepad behavior)
                        ConsoleKey key = (ConsoleKey) keyCode;
                        if (IsAltKeyDown(ir) && ((key >= ConsoleKey.NumPad0 && key <= ConsoleKey.NumPad9)
                                             || (key == ConsoleKey.Clear) || (key == ConsoleKey.Insert)
                                             || (key >= ConsoleKey.PageUp && key <= ConsoleKey.DownArrow))) {
                            continue;
                        }
 
                        if (ir.keyEvent.repeatCount > 1) {
                            ir.keyEvent.repeatCount--;
                            _cachedInputRecord = ir;
                        }
                        break;
                    }
                }  // we did NOT have a previous keystroke with repeated characters.
            }  // lock(ReadKeySyncObject)
 
            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((char)ir.keyEvent.uChar, (ConsoleKey) ir.keyEvent.virtualKeyCode, shift, alt, control);
            
            if (!intercept)
                Console.Write(ir.keyEvent.uChar);
            return info;
        }  // public static ConsoleKeyInfo ReadKey(bool intercept)
 
        public static bool KeyAvailable {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            [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;
 
                    // Skip non key-down && mod key events.
                    if (!IsKeyDownEvent(ir) || IsModKey(ir)) {
                        // 
                        
                        // Exempt Alt keyUp for possible Alt+NumPad unicode sequence.
                        //short keyCode = ir.keyEvent.virtualKeyCode;
                        //if (!IsKeyDownEvent(ir) && (keyCode == AltVKCode))
                        //    return true;
 
                        r = Win32Native.ReadConsoleInput(ConsoleInputHandle, out ir, 1, out numEventsRead);
                    
                        if (!r)
                            __Error.WinIOError();
                    }
                    else {
                        return true;                        
                    }
                }
            }  // get
        }  // public static bool KeyAvailable
 
        public static bool NumberLock {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                short s = Win32Native.GetKeyState(NumberLockVKCode);
                return (s & 1) == 1;
            }
        }
 
        public static bool CapsLock {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            get {
                short s = Win32Native.GetKeyState(CapsLockVKCode);
                return (s & 1) == 1;
            }
        }
 
        public static bool TreatControlCAsInput {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [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;
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [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;
            [System.Security.SecurityCritical] // auto-generated
            private Win32Native.ConsoleCtrlHandlerRoutine _handler;
 
            [System.Security.SecurityCritical]  // auto-generated
            internal ControlCHooker()
            {
                _handler = new Win32Native.ConsoleCtrlHandlerRoutine(BreakEvent);
            }
 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            ~ControlCHooker()
            {
                Unhook();
            }
 
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.Process)]
            [ResourceConsumption(ResourceScope.Process)]
            internal void Hook()
            {
                if (!_hooked) {
                    bool r = Win32Native.SetConsoleCtrlHandler(_handler, true);
                    if (!r)
                        __Error.WinIOError();
                    _hooked = true;
                }
            }
 
            [System.Security.SecuritySafeCritical]  // auto-generated
            [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;
                }
            }
        }  // internal sealed class ControlCHooker
        
        // 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)) {
                    Contract.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) {
                    Contract.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 guarantee 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 {
            [System.Security.SecuritySafeCritical]  // auto-generated
            [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();
                    }
                }
            }
            [System.Security.SecuritySafeCritical]  // auto-generated
            [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;
                    Contract.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);
        }
    
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #endif
        [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"));
            Contract.EndContractBlock();
            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);
        }
        
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #endif
        [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"));
            Contract.EndContractBlock();
            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);
        }
        
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #endif
        [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"));
            Contract.EndContractBlock();
            return GetStandardFile(Win32Native.STD_OUTPUT_HANDLE,
                                   FileAccess.Write, bufferSize);
        }
        
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetIn(TextReader newIn) {
            if (newIn == null)
                throw new ArgumentNullException("newIn");
            Contract.EndContractBlock();
#pragma warning disable 618
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
 
            newIn = TextReader.Synchronized(newIn);
            lock(InternalSyncObject) {
                _in = newIn;
            }
        }
    
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetOut(TextWriter newOut) {
            if (newOut == null)
                throw new ArgumentNullException("newOut");
            Contract.EndContractBlock();
#pragma warning disable 618
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
#if FEATURE_CODEPAGES_FILE    // if no codepages file then we are locked into default codepage  and this field is not used              
            _isOutTextWriterRedirected = true;
#endif
            newOut = TextWriter.Synchronized(newOut);
            lock(InternalSyncObject) {
                _out = newOut;
            }
        }
    
        #if FEATURE_CORECLR
        [System.Security.SecurityCritical] // auto-generated
        #else
        [System.Security.SecuritySafeCritical]
        #endif
        [HostProtection(UI=true)]
        [ResourceExposure(ResourceScope.AppDomain)]
        public static void SetError(TextWriter newError) {
            if (newError == null)
                throw new ArgumentNullException("newError");
            Contract.EndContractBlock();
#pragma warning disable 618
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
#if FEATURE_CODEPAGES_FILE    // if no codepages file then we are locked into default codepage  and this field is not used              
            _isErrorTextWriterRedirected = true;
#endif
            newError = TextWriter.Synchronized(newError);
            lock(InternalSyncObject) {
                _error = newError;
            }
        }
 
        //
        // Give a hint to the code generator to not inline the common console methods. The console methods are 
        // not performance critical. It is unnecessary code bloat to have them inlined.
        //
        // Moreover, simple repros for codegen bugs are often console-based. It is tedious to manually filter out 
        // the inlined console writelines from them.
        //
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static int Read()
        {
            return In.Read();
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static String ReadLine()
        {
            return In.ReadLine();
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine()
        {
            Out.WriteLine();
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(bool value)
        {
            Out.WriteLine(value);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(char value)
        {
            Out.WriteLine(value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(char[] buffer)
        {
            Out.WriteLine(buffer);
        }
                   
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(char[] buffer, int index, int count)
        {
            Out.WriteLine(buffer, index, count);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(decimal value)
        {
            Out.WriteLine(value);
        }   
 
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(double value)
        {
            Out.WriteLine(value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(float value)
        {
            Out.WriteLine(value);
        }   
           
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(int value)
        {
            Out.WriteLine(value);
        }
        
        [HostProtection(UI=true)]
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(uint value)
        {
            Out.WriteLine(value);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(long value)
        {
            Out.WriteLine(value);
        }
        
        [HostProtection(UI=true)]
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(ulong value)
        {
            Out.WriteLine(value);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(Object value)
        {
            Out.WriteLine(value);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(String value)
        {
            Out.WriteLine(value);
        }
    
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(String format, Object arg0)
        {
            Out.WriteLine(format, arg0);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(String format, Object arg0, Object arg1)
        {
            Out.WriteLine(format, arg0, arg1);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(String format, Object arg0, Object arg1, Object arg2)
        {
            Out.WriteLine(format, arg0, arg1, arg2);
        }
        
        [HostProtection(UI=true)]
        [CLSCompliant(false)] 
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        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<argCount; i++) {
                objArgs[i] = TypedReference.ToObject(args.GetNextArg());
            }
 
            Out.WriteLine(format, objArgs);
        }
 
 
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void WriteLine(String format, params Object[] arg)
        {
            if (arg == null)                       // avoid ArgumentNullException from String.Format
                Out.WriteLine(format, null, null); // faster than Out.WriteLine(format, (Object)arg);
            else
                Out.WriteLine(format, arg);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(String format, Object arg0)
        {
            Out.Write(format, arg0);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(String format, Object arg0, Object arg1)
        {
            Out.Write(format, arg0, arg1);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(String format, Object arg0, Object arg1, Object arg2)
        {
            Out.Write(format, arg0, arg1, arg2);
        }
 
        [HostProtection(UI=true)]
        [CLSCompliant(false)] 
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(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<argCount; i++) {
                objArgs[i] = TypedReference.ToObject(args.GetNextArg());
            }
 
            Out.Write(format, objArgs);
        }
 
            
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(String format, params Object[] arg)
        {
            if (arg == null)                   // avoid ArgumentNullException from String.Format
                Out.Write(format, null, null); // faster than Out.Write(format, (Object)arg);
            else
                Out.Write(format, arg);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(bool value)
        {
            Out.Write(value);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(char value)
        {
            Out.Write(value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(char[] buffer)
        {
            Out.Write(buffer);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(char[] buffer, int index, int count)
        {
            Out.Write(buffer, index, count);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(double value)
        {
            Out.Write (value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(decimal value)
        {
            Out.Write (value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(float value)
        {
            Out.Write (value);
        }   
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(int value)
        {
            Out.Write (value);
        }
        
        [HostProtection(UI=true)]
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(uint value)
        {
            Out.Write (value);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(long value)
        {
            Out.Write (value);
        }
        
        [HostProtection(UI=true)]
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(ulong value)
        {
            Out.Write (value);
        }
    
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(Object value)
        {
            Out.Write (value);
        }
        
        [HostProtection(UI=true)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        public static void Write(String value)
        {
            Out.Write (value);
        }
            
    }  // public static class Console
}  // namespace System