FileStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / IO / FileStream.cs / 1305376 / FileStream.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:  FileStream 
**
** [....] 
**
**
** Purpose: Exposes a Stream around a file, with full
** synchronous and asychronous support, and buffering. 
**
** 
===========================================================*/ 
using System;
using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles;
using System.Security;
#if !FEATURE_PAL && FEATURE_MACL
using System.Security.AccessControl; 
#endif
using System.Security.Permissions; 
using System.Threading; 
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging; 
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts; 

 
/* 
 * FileStream supports different modes of accessing the disk - async mode
 * and [....] mode.  They are two completely different codepaths in the 
 * [....] & async methods (ie, Read/Write vs. BeginRead/BeginWrite).  File
 * handles in NT can be opened in only [....] or overlapped (async) mode,
 * and we have to deal with this pain.  Stream has implementations of
 * the [....] methods in terms of the async ones, so we'll 
 * call through to our base class to get those methods when necessary.
 * 
 * Also buffering is added into FileStream as well. Folded in the 
 * code from BufferedStream, so all the comments about it being mostly
 * aggressive (and the possible perf improvement) apply to FileStream as 
 * well.  Also added some buffering to the async code paths.
 *
 * Class Invariants:
 * The class has one buffer, shared for reading & writing.  It can only be 
 * used for one or the other at any point in time - not both.  The following
 * should be true: 
 *   0 <= _readPos <= _readLen < _bufferSize 
 *   0 <= _writePos < _bufferSize
 *   _readPos == _readLen && _readPos > 0 implies the read buffer is valid, 
 *     but we're at the end of the buffer.
 *   _readPos == _readLen == 0 means the read buffer contains garbage.
 *   Either _writePos can be greater than 0, or _readLen & _readPos can be
 *     greater than zero, but neither can be greater than zero at the same time. 
 *
 */ 
 
namespace System.IO {
    // This is an internal object implementing IAsyncResult with fields 
    // for all of the relevant data necessary to complete the IO operation.
    // This is used by AsyncFSCallback and all of the async methods.
#if IO_CANCELLATION_ENABLED
    unsafe internal sealed class FileStreamAsyncResult : ICancelableAsyncResult, System.Object 
#if false // ugly hack to fix syntax for TrimSrc parser, which ignores #if directives
    { 
    } 
#endif
#else 
    unsafe internal sealed class FileStreamAsyncResult : IAsyncResult
#endif
    {
        // README: 
        // If you modify the order of these fields, make sure to update
        // the native VM definition of this class as well!!! 
 
        // User code callback
        internal AsyncCallback _userCallback; 
        internal Object _userStateObject;
        internal ManualResetEvent _waitHandle;
        [System.Security.SecurityCritical /*auto-generated*/]
        internal SafeFileHandle _handle;      // For cancellation support. 
#if !FEATURE_PAL
        internal NativeOverlapped* _overlapped; 
#endif 
        internal int _EndXxxCalled;   // Whether we've called EndXxx already.
        internal int _numBytes;     // number of bytes read OR written 
        internal int _errorCode;
        internal int _numBufferedBytes;

        internal bool _isWrite;     // Whether this is a read or a write 
        internal bool _isComplete;  // Value for IsCompleted property
        internal bool _completedSynchronously;  // Which thread called callback 
 
        // Adding in a finalizer here to catch the places
        // where users didn't call EndRead or EndWrite on an IAsyncResult, 
        // willn't work.  The unmanaged memory in the NativeOverlapped
        // struct keeps a GCHandle to this IAsyncResult object alive, so this
        // never get finalized.
 
        public Object AsyncState
        { 
            get { return _userStateObject; } 
        }
 
        public bool IsCompleted
        {
            get { return _isComplete; }
        } 

        public WaitHandle AsyncWaitHandle 
        { 
#if !FEATURE_PAL
            [System.Security.SecuritySafeCritical]  // auto-generated 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get {
                // Consider uncommenting this someday soon - the EventHandle 
                // in the Overlapped struct is really useless half of the
                // time today since the OS doesn't signal it.  If users call 
                // EndXxx after the OS call happened to complete, there's no 
                // reason to create a synchronization primitive here.  Fixing
                // this will save us some perf, assuming we can correctly 
                // initialize the ManualResetEvent.
                if (_waitHandle == null) {
                    ManualResetEvent mre = new ManualResetEvent(false);
                    if (_overlapped != null && _overlapped->EventHandle != IntPtr.Zero) { 
                        mre.SafeWaitHandle = new SafeWaitHandle(_overlapped->EventHandle, true);
                    } 
 
                    // make sure only one thread sets _waitHandle
                    if (Interlocked.CompareExchange(ref _waitHandle, mre, null) == null) { 
                        if (_isComplete)
                            _waitHandle.Set();
                    }
                    else { 
                        // There's a slight but acceptable ---- if we weren't
                        // the thread that set _waitHandle and this code path 
                        // returns before the code in the if statement 
                        // executes (on the other thread). However, the
                        // caller is waiting for the wait handle to be set, 
                        // which will still happen.
                        mre.Close();
                    }
                } 
                return _waitHandle;
            } 
#else 
            get { return null; }
#endif //!FEATURE_PAL && FEATURE_MACL 
        }

        // Returns true iff the user callback was called by the thread that
        // called BeginRead or BeginWrite.  If we use an async delegate or 
        // threadpool thread internally, this will be false.  This is used
        // by code to determine whether a successive call to BeginRead needs 
        // to be done on their main thread or in their callback to avoid a 
        // stack overflow on many reads or writes.
        public bool CompletedSynchronously 
        {
            get { return _completedSynchronously; }
        }
 
        internal static FileStreamAsyncResult CreateBufferedReadResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject) {
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); 
            asyncResult._userCallback = userCallback; 
            asyncResult._userStateObject = userStateObject;
            asyncResult._isWrite = false; 
            asyncResult._numBufferedBytes = numBufferedBytes;
            return asyncResult;
        }
 
        private void CallUserCallbackWorker(Object callbackState)
        { 
            _isComplete = true; 

            // ensure _isComplete is set before reading _waitHandle 
            Thread.MemoryBarrier();
            if (_waitHandle != null)
                _waitHandle.Set();
 
            _userCallback(this);
        } 
 
        internal void CallUserCallback()
        { 
            // Convenience method for me, since I have to do this in a number
            // of places in the buffering code for fake IAsyncResults.
            // AsyncFSCallback intentionally does not use this method.
 
            if (_userCallback != null) {
                // Call user's callback on a threadpool thread. 
                // Set completedSynchronously to false, since it's on another 
                // thread, not the main thread.
                _completedSynchronously = false; 
                ThreadPool.QueueUserWorkItem(new WaitCallback(CallUserCallbackWorker));
            }
            else {
                _isComplete = true; 

                // ensure _isComplete is set before reading _waitHandle 
                Thread.MemoryBarrier(); 
                if (_waitHandle != null)
                    _waitHandle.Set(); 
            }
        }

#if IO_CANCELLATION_ENABLED 
        [HostProtection(ExternalThreading=true)]
        public void Cancel() 
        { 
#if !FEATURE_PAL
            if (!Environment.IsWindowsVista) 
                throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_RequiresLonghorn"));

            if (_handle == null || _overlapped == null)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_IOCancellation")); 

            if (_handle.IsInvalid) 
                __Error.StreamIsClosed(); 
            Contract.EndContractBlock();
 
            bool r = Win32Native.CancelIoEx(_handle, _overlapped);
            if (!r)
                __Error.WinIOError();
#else 
            throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_RequiresLonghorn"));
#endif 
        } 
#endif
 
    }

    [ComVisible(true)]
    public class FileStream : Stream 
    {
        internal const int DefaultBufferSize = 4096; 
 

#if !FEATURE_PAL 
#if FEATURE_CORECLR
        // @todo: This #ifdef factoring fixes the public api async behavior for M6 with minimal risk. When more
        // time is available, we should more rigorously scrub out all references for FileStreamAsyncResult and AsyncFSCallback
        // (this requires corresponding changes in the src\vm tree as well.) 
        private static readonly bool _canUseAsync = false;
#else 
        private static readonly bool _canUseAsync = Environment.RunningOnWinNT; 
#endif //FEATURE_CORECLR
        [System.Security.SecurityCritical /*auto-generated*/] 
        private unsafe static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(FileStream.AsyncFSCallback);
#else
        private static readonly bool _canUseAsync = false;
#endif //!FEATURE_PAL 

        private byte[] _buffer;   // Shared read/write buffer.  Alloc on first use. 
        private String _fileName; // Fully qualified file name. 
        private bool _isAsync;    // Whether we opened the handle for overlapped IO
        private bool _canRead; 
        private bool _canWrite;
        private bool _canSeek;
        private bool _exposedHandle; // Could other code be using this handle?
        private bool _isPipe;     // Whether to disable async buffering code. 
        private int _readPos;     // Read pointer within shared buffer.
        private int _readLen;     // Number of bytes read in buffer from file. 
        private int _writePos;    // Write pointer within shared buffer. 
        private int _bufferSize;  // Length of internal buffer, if it's allocated.
        [System.Security.SecurityCritical /*auto-generated*/] 
        private SafeFileHandle _handle;
        private long _pos;        // Cache current location in the file.
        private long _appendStart;// When appending, prevent overwriting file.
 
        [System.Security.SecuritySafeCritical] // static constructors should be safe to call
        static FileStream() 
        { 
        }
 
        //This exists only to support IsolatedStorageFileStream.
        //Any changes to FileStream must include the corresponding changes in IsolatedStorage.
        internal FileStream() {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode) 
            : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access) 
            : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share)
            : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) { 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
            : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false) 
        {
        } 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
            : this(path, mode, access, share, bufferSize, options, Path.GetFileName(path), false)
        { 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
            : this(path, mode, access, share, bufferSize, (useAsync ? FileOptions.Asynchronous : FileOptions.None), Path.GetFileName(path), false)
        {
        } 

#if !FEATURE_PAL && FEATURE_MACL 
        // This constructor is done differently to avoid loading a few more 
        // classes, and more importantly, to build correctly on Rotor.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity)
        { 
            Object pinningHandle;
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share, fileSecurity, out pinningHandle); 
            try { 
                Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false);
            } 
            finally {
                if (pinningHandle != null) {
                    GCHandle pinHandle = (GCHandle) pinningHandle;
                    pinHandle.Free(); 
                }
            } 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options)
        { 
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
            Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false); 
        } 
#endif
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); 
            Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, false); 
        }
 
        [System.Security.SecurityCritical]
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); 
            Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath); 
        }
 
        // AccessControl namespace is not defined in Rotor
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        internal void Init(String path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, Win32Native.SECURITY_ATTRIBUTES secAttrs, String msgPath, bool bFromProxy, bool useLongPath)
        { 
            if (path == null) 
                throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
            if (path.Length == 0) 
                throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
            Contract.EndContractBlock();

#if !FEATURE_PAL && FEATURE_MACL 
            FileSystemRights fileSystemRights = (FileSystemRights)rights;
#endif 
            // msgPath must be safe to hand back to untrusted code. 

            _fileName = msgPath;  // To handle odd cases of finalizing partially constructed objects. 
            _exposedHandle = false;

#if FEATURE_PAL
            Contract.Assert(!useRights, "Specifying FileSystemRights is not supported on this platform!"); 
#endif
 
            // don't include inheritable in our bounds check for share 
            FileShare tempshare = share & ~FileShare.Inheritable;
            String badArg = null; 

            if (mode < FileMode.CreateNew || mode > FileMode.Append)
                badArg = "mode";
            else if (!useRights && (access < FileAccess.Read || access > FileAccess.ReadWrite)) 
                badArg = "access";
#if !FEATURE_PAL && FEATURE_MACL 
            else if (useRights && (fileSystemRights < FileSystemRights.ReadData || fileSystemRights > FileSystemRights.FullControl)) 
                badArg = "rights";
#endif 
            else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete))
                badArg = "share";

            if (badArg != null) 
                throw new ArgumentOutOfRangeException(badArg, Environment.GetResourceString("ArgumentOutOfRange_Enum"));
 
            // NOTE: any change to FileOptions enum needs to be matched here in the error validation 
            if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0)
                throw new ArgumentOutOfRangeException("options", Environment.GetResourceString("ArgumentOutOfRange_Enum")); 

            if (bufferSize <= 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
 
            // Write access validation
#if !FEATURE_PAL && FEATURE_MACL 
            if ((!useRights && (access & FileAccess.Write) == 0) 
                || (useRights && (fileSystemRights & FileSystemRights.Write) == 0))
#else 
            if (!useRights && (access & FileAccess.Write) == 0)
#endif //!FEATURE_PAL && FEATURE_MACL
            {
                if (mode==FileMode.Truncate || mode==FileMode.CreateNew || mode==FileMode.Create || mode==FileMode.Append) { 
                    // No write access
                    if (!useRights) 
                        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo", mode, access)); 
#if !FEATURE_PAL && FEATURE_MACL
                    else 
                        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&RightsCombo", mode, fileSystemRights));
#endif //!FEATURE_PAL && FEATURE_MACL
                }
            } 

#if !FEATURE_PAL && FEATURE_MACL 
            // FileMode.Truncate only works with GENERIC_WRITE (FileAccess.Write), source:MSDN 
            // For backcomp use FileAccess.Write when FileSystemRights.Write is specified
            if (useRights && (mode == FileMode.Truncate)) { 
                if (fileSystemRights == FileSystemRights.Write) {
                    useRights = false;
                    access = FileAccess.Write;
                } 
                else {
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileModeTruncate&RightsCombo", mode, fileSystemRights)); 
                } 
            }
#endif 

            int fAccess;
            if (!useRights) {
                fAccess = access == FileAccess.Read? GENERIC_READ: 
                access == FileAccess.Write? GENERIC_WRITE:
                GENERIC_READ | GENERIC_WRITE; 
            } 
            else {
                fAccess = rights; 
            }

            // Get absolute path - Security needs this to prevent something
            // like trying to create a file in c:\tmp with the name 
            // "..\WinNT\System32\ntoskrnl.exe".  Store it for user convenience.
            int maxPath = useLongPath ? Path.MaxLongPath : Path.MaxPath; 
            String filePath = Path.NormalizePath(path, true, maxPath); 

            _fileName = filePath; 

            // Prevent access to your disk drives as raw block devices.
            if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
                throw new ArgumentException(Environment.GetResourceString("Arg_DevicesNotSupported")); 

            // Build up security permissions required, as well as validate we 
            // have a sensible set of parameters.  IE, creating a brand new file 
            // for reading doesn't make much sense.
            FileIOPermissionAccess secAccess = FileIOPermissionAccess.NoAccess; 
#if !FEATURE_PAL && FEATURE_MACL
            if ((!useRights && (access & FileAccess.Read) != 0) || (useRights && (fileSystemRights & FileSystemRights.ReadAndExecute) != 0))
#else
            if (!useRights && (access & FileAccess.Read) != 0) 
#endif //!FEATURE_PAL && FEATURE_MACL
            { 
                if (mode==FileMode.Append) 
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidAppendMode"));
                else 
                    secAccess = secAccess | FileIOPermissionAccess.Read;
            }
            // I can't think of any combos of FileMode we should disallow if we
            // don't have read access.  Writing would pretty much always be valid 
            // in those cases.
 
            // For any FileSystemRights other than ReadAndExecute, demand Write permission 
            // This is probably bit overkill for TakeOwnership etc but we don't have any
            // matching FileIOPermissionAccess to demand. It is better that we ask for Write permission. 

#if !FEATURE_PAL && FEATURE_MACL
            // FileMode.OpenOrCreate & FileSystemRights.Synchronize can create 0-byte file; demand write
            if ((!useRights && (access & FileAccess.Write) != 0) 
                || (useRights && (fileSystemRights & (FileSystemRights.Write | FileSystemRights.Delete
                                            | FileSystemRights.DeleteSubdirectoriesAndFiles 
                                            | FileSystemRights.ChangePermissions 
                                            | FileSystemRights.TakeOwnership)) != 0)
                || (useRights && ((fileSystemRights & FileSystemRights.Synchronize) != 0) 
                                            && mode==FileMode.OpenOrCreate)
               )
#else
            if (!useRights && (access & FileAccess.Write) != 0) 
#endif //!FEATURE_PAL && FEATURE_MACL
            { 
                if (mode==FileMode.Append) 
                    secAccess = secAccess | FileIOPermissionAccess.Append;
                else 
                    secAccess = secAccess | FileIOPermissionAccess.Write;
            }

#if !FEATURE_PAL && FEATURE_MACL 
            bool specifiedAcl;
            unsafe { 
                specifiedAcl = secAttrs != null && secAttrs.pSecurityDescriptor != null; 
            }
 
            AccessControlActions control = specifiedAcl ? AccessControlActions.Change : AccessControlActions.None;
            new FileIOPermission(secAccess, control, new String[] { filePath }, false, false).Demand();
#else
            new FileIOPermission(secAccess, new String[] { filePath }, false, false).Demand(); 
#endif
            // Our Inheritable bit was stolen from Windows, but should be set in 
            // the security attributes class.  Don't leave this bit set. 
            share &= ~FileShare.Inheritable;
 
            bool seekToEnd = (mode==FileMode.Append);
            // Must use a valid Win32 constant here...
            if (mode == FileMode.Append)
                mode = FileMode.OpenOrCreate; 

            // WRT async IO, do the right thing for whatever platform we're on. 
            // This way, someone can easily write code that opens a file 
            // asynchronously no matter what their platform is.
            if (_canUseAsync && (options & FileOptions.Asynchronous) != 0) 
                _isAsync = true;
            else
                options &= ~FileOptions.Asynchronous;
 
            int flagsAndAttributes = (int) options;
 
#if !FEATURE_PAL 
            // For mitigating local elevation of privilege attack through named pipes
            // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the 
            // named pipe server can't impersonate a high privileged client security context
            flagsAndAttributes|= (Win32Native.SECURITY_SQOS_PRESENT | Win32Native.SECURITY_ANONYMOUS);
#endif
            // Don't pop up a dialog for reading from an emtpy floppy drive 
            int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
            try { 
                String tempPath = filePath; 
                if (useLongPath)
                    tempPath = Path.AddLongPathPrefix(tempPath); 
                _handle = Win32Native.SafeCreateFile(tempPath, fAccess, share, secAttrs, mode, flagsAndAttributes, Win32Native.NULL);

                if (_handle.IsInvalid) {
                    // Return a meaningful exception, using the RELATIVE path to 
                    // the file to avoid returning extra information to the caller
                    // unless they have path discovery permission, in which case 
                    // the full path is fine & useful. 

                    // NT5 oddity - when trying to open "C:\" as a FileStream, 
                    // we usually get ERROR_PATH_NOT_FOUND from the OS.  We should
                    // probably be consistent w/ every other directory.
                    int errorCode = Marshal.GetLastWin32Error();
                    if (errorCode==__Error.ERROR_PATH_NOT_FOUND && filePath.Equals(Directory.InternalGetDirectoryRoot(filePath))) 
                        errorCode = __Error.ERROR_ACCESS_DENIED;
 
                    // We need to give an exception, and preferably it would include 
                    // the fully qualified path name.  Do security check here.  If
                    // we fail, give back the msgPath, which should not reveal much. 
                    // While this logic is largely duplicated in
                    // __Error.WinIOError, we need this for
                    // IsolatedStorageFileStream.
                    bool canGiveFullPath = false; 

                    if (!bFromProxy) 
                    { 
                        try {
                            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand(); 
                            canGiveFullPath = true;
                        }
                        catch(SecurityException) {}
                    } 

                    if (canGiveFullPath) 
                        __Error.WinIOError(errorCode, _fileName); 
                    else
                        __Error.WinIOError(errorCode, msgPath); 
                }
            }
            finally {
                Win32Native.SetErrorMode(oldMode); 
            }
 
            // Disallow access to all non-file devices from the FileStream 
            // constructors that take a String.  Everyone else can call
            // CreateFile themselves then use the constructor that takes an 
            // IntPtr.  Disallows "con:", "com1:", "lpt1:", etc.
            int fileType = Win32Native.GetFileType(_handle);
            if (fileType != Win32Native.FILE_TYPE_DISK) {
                _handle.Close(); 
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
            } 
 
#if !FEATURE_PAL
#if !FEATURE_CORECLR 
            // This is necessary for async IO using IO Completion ports via our
            // managed Threadpool API's.  This (theoretically) calls the OS's
            // BindIoCompletionCallback method, and passes in a stub for the
            // LPOVERLAPPED_COMPLETION_ROUTINE.  This stub looks at the Overlapped 
            // struct for this request and gets a delegate to a managed callback
            // from there, which it then calls on a threadpool thread.  (We allocate 
            // our native OVERLAPPED structs 2 pointers too large and store EE state 
            // & GC handles there, one to an IAsyncResult, the other to a delegate.)
            if (_isAsync) { 
                bool b = false;
                // BindHandle requires UnmanagedCode permission
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                try { 
                    b = ThreadPool.BindHandle(_handle);
                } 
                finally { 
                    CodeAccessPermission.RevertAssert();
                    if (!b) { 
                        // We should close the handle so that the handle is not open until SafeFileHandle GC
                        Contract.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?");
                        _handle.Close();
                    } 
                }
                if (!b) 
                    throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); 
            }
#endif // FEATURE_CORECLR 
#endif //!FEATURE_PAL
            if (!useRights) {
                _canRead = (access & FileAccess.Read) != 0;
                _canWrite = (access & FileAccess.Write) != 0; 
            }
#if !FEATURE_PAL && FEATURE_MACL 
            else { 
                _canRead = (fileSystemRights & FileSystemRights.ReadData) != 0;
                _canWrite = ((fileSystemRights & FileSystemRights.WriteData) != 0) 
                            || ((fileSystemRights & FileSystemRights.AppendData) != 0);
            }
#endif //!FEATURE_PAL && FEATURE_MACL
 
            _canSeek = true;
            _isPipe = false; 
            _pos = 0; 
            _bufferSize = bufferSize;
            _readPos = 0; 
            _readLen = 0;
            _writePos = 0;

            // For Append mode... 
            if (seekToEnd) {
                _appendStart = SeekCore(0, SeekOrigin.End); 
            } 
            else {
                _appendStart = -1; 
            }
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access) instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access)
            : this(handle, access, true, DefaultBufferSize, false) { 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle) 
            : this(handle, access, ownsHandle, DefaultBufferSize, false) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) 
            : this(handle, access, ownsHandle, bufferSize, false) { 
        }
 
        // We explicitly do a Demand, not a LinkDemand here.
        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) 
            : this(new SafeFileHandle(handle, ownsHandle), access, bufferSize, isAsync) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(SafeFileHandle handle, FileAccess access)
            : this(handle, access, DefaultBufferSize, false) { 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize)
            : this(handle, access, bufferSize, false) { 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) {
            // To ensure we don't leak a handle, put it in a SafeFileHandle first
            if (handle.IsInvalid) 
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHandle"), "handle");
            Contract.EndContractBlock(); 
 
            _handle = handle;
            _exposedHandle = true; 

            // Now validate arguments.
            if (access < FileAccess.Read || access > FileAccess.ReadWrite)
                throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum")); 
            if (bufferSize <= 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
 
            int handleType = Win32Native.GetFileType(_handle);
            Contract.Assert(handleType == Win32Native.FILE_TYPE_DISK || handleType == Win32Native.FILE_TYPE_PIPE || handleType == Win32Native.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); 
            _isAsync = isAsync && _canUseAsync;  // On Win9x, just do the right thing.
            _canRead = 0 != (access & FileAccess.Read);
            _canWrite = 0 != (access & FileAccess.Write);
            _canSeek = handleType == Win32Native.FILE_TYPE_DISK; 
            _bufferSize = bufferSize;
            _readPos = 0; 
            _readLen = 0; 
            _writePos = 0;
            _fileName = null; 
            _isPipe = handleType == Win32Native.FILE_TYPE_PIPE;

#if !FEATURE_PAL
            // This is necessary for async IO using IO Completion ports via our 
            // managed Threadpool API's.  This calls the OS's
            // BindIoCompletionCallback method, and passes in a stub for the 
            // LPOVERLAPPED_COMPLETION_ROUTINE.  This stub looks at the Overlapped 
            // struct for this request and gets a delegate to a managed callback
            // from there, which it then calls on a threadpool thread.  (We allocate 
            // our native OVERLAPPED structs 2 pointers too large and store EE
            // state & a handle to a delegate there.)
#if !FEATURE_CORECLR
            if (_isAsync) { 
                bool b = false;
                try { 
                    b = ThreadPool.BindHandle(_handle); 
                }
                catch (ApplicationException) { 
                    // If you passed in a synchronous handle and told us to use
                    // it asynchronously, throw here.
                    throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotAsync"));
                } 
                if (!b) {
                    throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); 
                } 
            }
            else { 
#endif // FEATURE_CORECLR
                if (handleType != Win32Native.FILE_TYPE_PIPE)
                    VerifyHandleIsSync();
#if !FEATURE_CORECLR 
            }
#endif // FEATURE_CORECLR 
#else 
                if (handleType != Win32Native.FILE_TYPE_PIPE)
                    VerifyHandleIsSync(); 
#endif //!FEATURE_PAL
            if (_canSeek)
                SeekCore(0, SeekOrigin.Current);
            else 
                _pos = 0;
        } 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
            if ((share & FileShare.Inheritable) != 0) {
                secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); 
                secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
 
                secAttrs.bInheritHandle = 1; 
            }
            return secAttrs; 
        }

#if !FEATURE_PAL && FEATURE_MACL
        // If pinningHandle is not null, caller must free it AFTER the call to 
        // CreateFile has returned.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share, FileSecurity fileSecurity, out Object pinningHandle) 
        {
            pinningHandle = null; 
            Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
            if ((share & FileShare.Inheritable) != 0 || fileSecurity != null) {
                secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
                secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); 

                if ((share & FileShare.Inheritable) != 0) { 
                    secAttrs.bInheritHandle = 1; 
                }
 
                // For ACL's, get the security descriptor from the FileSecurity.
                if (fileSecurity != null) {
                    byte[] sd = fileSecurity.GetSecurityDescriptorBinaryForm();
                    pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned); 
                    fixed(byte* pSecDescriptor = sd)
                        secAttrs.pSecurityDescriptor = pSecDescriptor; 
                } 
            }
            return secAttrs; 
        }
#endif

        // Verifies that this handle supports synchronous IO operations (unless you 
        // didn't open it for either reading or writing).
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe void VerifyHandleIsSync() 
        {
            // Do NOT use this method on pipes.  Reading or writing to a pipe may 
            // cause an app to block incorrectly, introducing a deadlock (depending
            // on whether a write will wake up an already-blocked thread or this
            // FileStream's thread).
 
            // Do NOT change this to use a byte[] of length 0, or test test won't
            // work.  Our ReadFile & WriteFile methods are special cased to return 
            // for arrays of length 0, since we'd get an IndexOutOfRangeException 
            // while using C#'s fixed syntax.
            byte[] bytes = new byte[1]; 
            int hr = 0;
            int r = 0;

            // If the handle is a pipe, ReadFile will block until there 
            // has been a write on the other end.  We'll just have to deal with it,
            // For the read end of a pipe, you can mess up and 
            // accidentally read synchronously from an async pipe. 
            if (CanRead) {
                r = ReadFileNative(_handle, bytes, 0, 0, null, out hr); 
            }
            else if (CanWrite) {
                r = WriteFileNative(_handle, bytes, 0, 0, null, out hr);
            } 

            if (hr==ERROR_INVALID_PARAMETER) 
                throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync")); 
            if (hr == Win32Native.ERROR_INVALID_HANDLE)
                __Error.WinIOError(hr, ""); 
        }


        public override bool CanRead { 
            [Pure]
            get { return _canRead; } 
        } 

        public override bool CanWrite { 
            [Pure]
            get { return _canWrite; }
        }
 
        public override bool CanSeek {
            [Pure] 
            get { return _canSeek; } 
        }
 
        public virtual bool IsAsync {
            get { return _isAsync; }
        }
 
        public override long Length {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get { 
                if (_handle.IsClosed) __Error.FileNotOpen();
                if (!CanSeek) __Error.SeekNotSupported(); 
                int hi = 0, lo = 0;

                lo = Win32Native.GetFileSize(_handle, out hi);
 
                if (lo==-1) {  // Check for either an error or a 4GB - 1 byte file.
                    int hr = Marshal.GetLastWin32Error(); 
                    if (hr != 0) 
                        __Error.WinIOError(hr, String.Empty);
                } 
                long len = (((long)hi) << 32) | ((uint) lo);
                // If we're writing near the end of the file, we must include our
                // internal buffer in our Length calculation.  Don't flush because
                // we use the length of the file in our async write method. 
                if (_writePos > 0 && _pos + _writePos > len)
                    len = _writePos + _pos; 
                return len; 
            }
        } 

        public String Name {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                if (_fileName == null)
                    return Environment.GetResourceString("IO_UnknownFileName"); 
                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand(); 
                return _fileName;
            } 
        }

        internal String NameInternal {
            get { 
                if (_fileName == null)
                    return ""; 
                return _fileName; 
            }
        } 

        public override long Position {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                if (_handle.IsClosed) __Error.FileNotOpen();
                if (!CanSeek) __Error.SeekNotSupported(); 
 
                Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
                // Verify that internal position is in [....] with the handle
                if (_exposedHandle)
                    VerifyOSHandlePosition();
 
                // Compensate for buffer that we read from the handle (_readLen) Vs what the user
                // read so far from the internel buffer (_readPos). Of course add any unwrittern 
                // buffered data 
                return _pos + (_readPos - _readLen + _writePos);
            } 
            [System.Security.SecuritySafeCritical]  // auto-generated
            set {
                if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
                Contract.EndContractBlock(); 
                if (_writePos > 0) FlushWrite(false);
                _readPos = 0; 
                _readLen = 0; 
                Seek(value, SeekOrigin.Begin);
            } 
        }

#if !FEATURE_PAL && FEATURE_MACL
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileSecurity GetAccessControl() 
        {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            return new FileSecurity(_handle, _fileName, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public void SetAccessControl(FileSecurity fileSecurity)
        { 
            if (fileSecurity == null) 
                throw new ArgumentNullException("fileSecurity");
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen();

            fileSecurity.Persist(_handle, _fileName); 
        }
#endif 
 
#if !FEATURE_PAL
        // When doing IO asynchronously (ie, _isAsync==true), this callback is 
        // called by a free thread in the threadpool when the IO operation
        // completes.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        unsafe private static void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) 
        { 
            //Console.WriteLine("AsyncFSCallback called.  errorCode: "+errorCode+"  numBytes: "+numBytes);
 
            // Unpack overlapped
            Overlapped overlapped = Overlapped.Unpack(pOverlapped);
            // Free the overlapped struct in EndRead/EndWrite.
 
            // Extract async result from overlapped
            FileStreamAsyncResult asyncResult = 
                (FileStreamAsyncResult)overlapped.AsyncResult; 
            asyncResult._numBytes = (int)numBytes;
 
            // Handle reading from & writing to closed pipes.  While I'm not sure
            // this is entirely necessary anymore, maybe it's possible for
            // an async read on a pipe to be issued and then the pipe is closed,
            // returning this error.  This may very well be necessary. 
            if (errorCode == ERROR_BROKEN_PIPE || errorCode == ERROR_NO_DATA)
                errorCode = 0; 
 
            asyncResult._errorCode = (int)errorCode;
 
            //Console.WriteLine("AsyncFSCallback:  errorCode: "+errorCode+"  numBytes: "+numBytes+" was synchronous: "+asyncResult.CompletedSynchronously);

            // Call the user-provided callback.  It can and often should
            // call EndRead or EndWrite.  There's no reason to use an async 
            // delegate here - we're already on a threadpool thread.
            // IAsyncResult's completedSynchronously property must return 
            // false here, saying the user callback was called on another thread. 
            asyncResult._completedSynchronously = false;
            asyncResult._isComplete = true; 

            // ensure _isComplete is set before reading _waitHandle
            Thread.MemoryBarrier();
 
            // The OS does not signal this event.  We must do it ourselves.
            ManualResetEvent wh = asyncResult._waitHandle; 
            if (wh != null) { 
                Contract.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set(); 
                Contract.Assert(r, "ManualResetEvent::Set failed!");
                if (!r) __Error.WinIOError();
            }
 
            AsyncCallback userCallback = asyncResult._userCallback;
            if (userCallback != null) 
                userCallback(asyncResult); 
        }
#endif //!FEATURE_PAL 

        [System.Security.SecuritySafeCritical]  // auto-generated
        protected override void Dispose(bool disposing)
        { 
            // Nothing will be done differently based on whether we are
            // disposing vs. finalizing.  This is taking advantage of the 
            // weak ordering between normal finalizable objects & critical 
            // finalizable objects, which I included in the SafeHandle
            // design for FileStream, which would often "just work" when 
            // finalized.
            try {
                if (_handle != null && !_handle.IsClosed) {
                    // Flush data to disk iff we were writing.  After 
                    // thinking about this, we also don't need to flush
                    // our read position, regardless of whether the handle 
                    // was exposed to the user.  They probably would NOT 
                    // want us to do this.
                    if (_writePos > 0) { 
                        FlushWrite(!disposing);
                    }
                }
            } 
            finally {
                if (_handle != null && !_handle.IsClosed) 
                    _handle.Dispose(); 

                _canRead = false; 
                _canWrite = false;
                _canSeek = false;
                // Don't set the buffer to null, to avoid a NullReferenceException
                // when users have a race condition in their code (ie, they call 
                // Close when calling another method on Stream like Read).
                //_buffer = null; 
                base.Dispose(disposing); 
            }
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        ~FileStream()
        { 
            if (_handle != null) {
                BCLDebug.Correctness(_handle.IsClosed, "You didn't close a FileStream & it got finalized.  Name: \""+_fileName+"\""); 
                Dispose(false); 
            }
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void Flush()
        { 
            Flush(false);
        } 
 
        [System.Security.SecuritySafeCritical]
        public virtual void Flush(Boolean flushToDisk) 
        {
            // This code is duplicated in Dispose
            if (_handle.IsClosed) __Error.FileNotOpen();
            if (_writePos > 0) { 
                FlushWrite(false);
 
                if (flushToDisk) { 
                    if (!Win32Native.FlushFileBuffers(_handle)) {
                        __Error.WinIOError(); 
                    }
                }
            }
            else if (_readPos < _readLen && CanSeek) { 
                FlushRead();
            } 
            _readPos = 0; 
            _readLen = 0;
        } 

        // Reading is done by blocks from the file, but someone could read
        // 1 byte from the buffer then write.  At that point, the OS's file
        // pointer is out of [....] with the stream's position.  All write 
        // functions should call this function to preserve the position in the file.
        private void FlushRead() { 
            Contract.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushRead!"); 
            if (_readPos - _readLen != 0) {
                Contract.Assert(CanSeek, "FileStream will lose buffered read data now."); 
                SeekCore(_readPos - _readLen, SeekOrigin.Current);
            }
            _readPos = 0;
            _readLen = 0; 
        }
 
        // Writes are buffered.  Anytime the buffer fills up 
        // (_writePos + delta > _bufferSize) or the buffer switches to reading
        // and there is left over data (_writePos > 0), this function must be called. 
        private void FlushWrite(bool calledFromFinalizer) {
            Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream: Read buffer must be empty in FlushWrite!");

#if !FEATURE_PAL 
#if !FEATURE_CORECLR
            if (_isAsync) { 
                IAsyncResult asyncResult = BeginWriteCore(_buffer, 0, _writePos, null, null); 
                // With our Whidbey async IO & overlapped support for AD unloads,
                // we don't strictly need to block here to release resources 
                // since that support takes care of the pinning & freeing the
                // overlapped struct.  We need to do this when called from
                // Close so that the handle is closed when Close returns, but
                // we do't need to call EndWrite from the finalizer. 
                // Additionally, if we do call EndWrite, we block forever
                // because AD unloads prevent us from running the managed 
                // callback from the IO completion port.  Blocking here when 
                // called from the finalizer during AD unload is clearly wrong,
                // but we can't use any sort of test for whether the AD is 
                // unloading because if we weren't unloading, an AD unload
                // could happen on a separate thread before we call EndWrite.
                if (!calledFromFinalizer)
                    EndWrite(asyncResult); 
            }
            else 
#endif // FEATURE_CORECLR 
                WriteCore(_buffer, 0, _writePos);
            _writePos = 0; 
#else
            WriteCore(_buffer, 0, _writePos);
            _writePos = 0;
#endif //!FEATURE_PAL 
        }
 
 
        [Obsolete("This property has been deprecated.  Please use FileStream's SafeFileHandle property instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        public virtual IntPtr Handle { 
            [System.Security.SecurityCritical]  // auto-generated_required
            [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            get {
                Flush(); 
                // Explicitly dump any buffered data, since the user could move our 
                // position or write to the file.
                _readPos = 0; 
                _readLen = 0;
                _writePos = 0;
                _exposedHandle = true;
 
                return _handle.DangerousGetHandle();
            } 
        } 

        public virtual SafeFileHandle SafeFileHandle { 
            [System.Security.SecurityCritical]  // auto-generated_required
            [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get {
                Flush(); 
                // Explicitly dump any buffered data, since the user could move our
                // position or write to the file. 
                _readPos = 0; 
                _readLen = 0;
                _writePos = 0; 
                _exposedHandle = true;

                return _handle;
            } 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override void SetLength(long value)
        { 
            if (value < 0)
                throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock();
 
            if (_handle.IsClosed) __Error.FileNotOpen();
            if (!CanSeek) __Error.SeekNotSupported(); 
            if (!CanWrite) __Error.WriteNotSupported(); 

            // Handle buffering updates. 
            if (_writePos > 0) {
                FlushWrite(false);
            }
            else if (_readPos < _readLen) { 
                FlushRead();
            } 
            _readPos = 0; 
            _readLen = 0;
 
            if (_appendStart != -1 && value < _appendStart)
                throw new IOException(Environment.GetResourceString("IO.IO_SetLengthAppendTruncate"));
            SetLengthCore(value);
        } 

        // We absolutely need this method broken out so that BeginWriteCore can call 
        // a method without having to go through buffering code that might call 
        // FlushWrite.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private void SetLengthCore(long value)
        {
            Contract.Assert(value >= 0, "value >= 0");
            long origPos = _pos; 

            if (_exposedHandle) 
                VerifyOSHandlePosition(); 
            if (_pos != value)
                SeekCore(value, SeekOrigin.Begin); 
            if (!Win32Native.SetEndOfFile(_handle)) {
                int hr = Marshal.GetLastWin32Error();
                if (hr==__Error.ERROR_INVALID_PARAMETER)
                    throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig")); 
                __Error.WinIOError(hr, String.Empty);
            } 
            // Return file pointer to where it was before setting length 
            if (origPos != value) {
                if (origPos < value) 
                    SeekCore(origPos, SeekOrigin.Begin);
                else
                    SeekCore(0, SeekOrigin.End);
            } 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override int Read([In, Out] byte[] array, int offset, int count) {
            if (array==null) 
                throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
            if (offset < 0)
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (count < 0) 
                throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < count) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); 
            Contract.EndContractBlock();
 
            if (_handle.IsClosed) __Error.FileNotOpen();

            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            bool isBlocked = false;
            int n = _readLen - _readPos; 
            // if the read buffer is empty, read into either user's array or our 
            // buffer, depending on number of bytes user asked for and buffer size.
            if (n == 0) { 
                if (!CanRead) __Error.ReadNotSupported();
                if (_writePos > 0) FlushWrite(false);
                if (!CanSeek || (count >= _bufferSize)) {
                    n = ReadCore(array, offset, count); 
                    // Throw away read buffer.
                    _readPos = 0; 
                    _readLen = 0; 
                    return n;
                } 
                if (_buffer == null) _buffer = new byte[_bufferSize];
                n = ReadCore(_buffer, 0, _bufferSize);
                if (n == 0) return 0;
                isBlocked = n < _bufferSize; 
                _readPos = 0;
                _readLen = n; 
            } 
            // Now copy min of count or numBytesAvailable (ie, near EOF) to array.
            if (n > count) n = count; 
            Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
            _readPos += n;

            // We may have read less than the number of bytes the user asked 
            // for, but that is part of the Stream contract.  Reading again for
            // more data may cause us to block if we're using a device with 
            // no clear end of file, such as a serial port or pipe.  If we 
            // blocked here & this code was used with redirected pipes for a
            // process's standard output, this can lead to deadlocks involving 
            // two processes. But leave this here for files to avoid what would
            // probably be a breaking change.         --

            // If we are reading from a device with no clear EOF like a 
            // serial port or a pipe, this will cause us to block incorrectly.
            if (!_isPipe) { 
                // If we hit the end of the buffer and didn't have enough bytes, we must 
                // read some more from the underlying stream.  However, if we got
                // fewer bytes from the underlying stream than we asked for (ie, we're 
                // probably blocked), don't ask for more bytes.
                if (n < count && !isBlocked) {
                    Contract.Assert(_readPos == _readLen, "Read buffer should be empty!");
                    int moreBytesRead = ReadCore(array, offset + n, count - n); 
                    n += moreBytesRead;
                    // We've just made our buffer inconsistent with our position 
                    // pointer.  We must throw away the read buffer. 
                    _readPos = 0;
                    _readLen = 0; 
                }
            }

            return n; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe int ReadCore(byte[] buffer, int offset, int count) {
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); 
            Contract.Assert(CanRead, "CanRead");

            Contract.Assert(buffer != null, "buffer != null");
            Contract.Assert(_writePos == 0, "_writePos == 0"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(count >= 0, "count is negative"); 
#if !FEATURE_PAL 
#if !FEATURE_CORECLR
            if (_isAsync) { 
                IAsyncResult result = BeginReadCore(buffer, offset, count, null, null, 0);
                return EndRead(result);
            }
#endif // FEATURE_CORECLR 
#endif //!FEATURE_PAL
 
            // Make sure we are reading from the right spot 
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            int hr = 0;
            int r = ReadFileNative(_handle, buffer, offset, count, null, out hr);
            if (r == -1) { 
                // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe.
                if (hr == ERROR_BROKEN_PIPE) { 
                    r = 0; 
                }
                else { 
                    if (hr == ERROR_INVALID_PARAMETER)
                        throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync"));

                    __Error.WinIOError(hr, String.Empty); 
                }
            } 
            Contract.Assert(r >= 0, "FileStream's ReadCore is likely broken."); 
            _pos += r;
 
            return r;
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override long Seek(long offset, SeekOrigin origin) {
            if (originSeekOrigin.End) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin")); 
            Contract.EndContractBlock();
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (!CanSeek) __Error.SeekNotSupported();

            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            // If we've got bytes in our buffer to write, write them out.
            // If we've read in and consumed some bytes, we'll have to adjust 
            // our seek positions ONLY IF we're seeking relative to the current 
            // position in the stream.  This simulates doing a seek to the new
            // position, then a read for the number of bytes we have in our buffer. 
            if (_writePos > 0) {
                FlushWrite(false);
            }
            else if (origin == SeekOrigin.Current) { 
                // Don't call FlushRead here, which would have caused an infinite
                // loop.  Simply adjust the seek origin.  This isn't necessary 
                // if we're seeking relative to the beginning or end of the stream. 
                offset -= (_readLen - _readPos);
            } 

            // Verify that internal position is in [....] with the handle
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            long oldPos = _pos + (_readPos - _readLen); 
            long pos = SeekCore(offset, origin); 

            // Prevent users from overwriting data in a file that was opened in 
            // append mode.
            if (_appendStart != -1 && pos < _appendStart) {
                SeekCore(oldPos, SeekOrigin.Begin);
                throw new IOException(Environment.GetResourceString("IO.IO_SeekAppendOverwrite")); 
            }
 
            // We now must update the read buffer.  We can in some cases simply 
            // update _readPos within the buffer, copy around the buffer so our
            // Position property is still correct, and avoid having to do more 
            // reads from the disk.  Otherwise, discard the buffer's contents.
            if (_readLen > 0) {
                // We can optimize the following condition:
                // oldPos - _readPos <= pos < oldPos + _readLen - _readPos 
                if (oldPos == pos) {
                    if (_readPos > 0) { 
                        //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+"  _readLen: "+_readLen); 
                        Buffer.InternalBlockCopy(_buffer, _readPos, _buffer, 0, _readLen - _readPos);
                        _readLen -= _readPos; 
                        _readPos = 0;
                    }
                    // If we still have buffered data, we must update the stream's
                    // position so our Position property is correct. 
                    if (_readLen > 0)
                        SeekCore(_readLen, SeekOrigin.Current); 
                } 
                else if (oldPos - _readPos < pos && pos < oldPos + _readLen - _readPos) {
                    int diff = (int)(pos - oldPos); 
                    //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+"  adjusting buffer - shrinking by "+ (_readPos + diff));
                    Buffer.InternalBlockCopy(_buffer, _readPos+diff, _buffer, 0, _readLen - (_readPos + diff));
                    _readLen -= (_readPos + diff);
                    _readPos = 0; 
                    if (_readLen > 0)
                        SeekCore(_readLen, SeekOrigin.Current); 
                } 
                else {
                    // Lose the read buffer. 
                    _readPos = 0;
                    _readLen = 0;
                }
                Contract.Assert(_readLen >= 0 && _readPos <= _readLen, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen"); 
                Contract.Assert(pos == Position, "Seek optimization: pos != Position!  Buffer math was mangled.");
            } 
            return pos; 
        }
 
        // This doesn't do argument checking.  Necessary for SetLength, which must
        // set the file pointer beyond the end of the file. This will update the
        // internal position
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private long SeekCore(long offset, SeekOrigin origin) {
            Contract.Assert(!_handle.IsClosed && CanSeek, "!_handle.IsClosed && CanSeek"); 
            Contract.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End"); 
            int hr = 0;
            long ret = 0; 

            ret = Win32Native.SetFilePointer(_handle, offset, origin, out hr);
            if (ret == -1) {
                // For invalid handles, detect the error and mark our handle 
                // as closed to give slightly better error messages.  Also
                // help ensure we avoid handle recycling bugs. 
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();
                __Error.WinIOError(hr, String.Empty); 
            }

            _pos = ret;
            return ret; 
        }
 
        // Checks the position of the OS's handle equals what we expect it to. 
        // This will fail if someone else moved the FileStream's handle or if
        // we've hit a bug in FileStream's position updating code. 
        private void VerifyOSHandlePosition()
        {
            if (!CanSeek)
                return; 

            // SeekCore will override the current _pos, so save it now 
            long oldPos = _pos; 
            long curPos = SeekCore(0, SeekOrigin.Current);
 
            if (curPos != oldPos) {
                // For reads, this is non-fatal but we still could have returned corrupted
                // data in some cases. So discard the internal buffer. Potential MDA
                _readPos = 0; 
                _readLen = 0;
                if(_writePos > 0) { 
                    // Discard the buffer and let the user know! 
                    _writePos = 0;
                    throw new IOException(Environment.GetResourceString("IO.IO_FileStreamHandlePosition")); 
                }
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void Write(byte[] array, int offset, int count) { 
            if (array==null) 
                throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < count) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 
 
            if (_handle.IsClosed) __Error.FileNotOpen();
 
            if (_writePos == 0)
            {
                // Ensure we can write to the stream, and ready buffer for writing.
                if (!CanWrite) __Error.WriteNotSupported(); 
                if (_readPos < _readLen) FlushRead();
                _readPos = 0; 
                _readLen = 0; 
            }
 
            // If our buffer has data in it, copy data from the user's array into
            // the buffer, and if we can fit it all there, return.  Otherwise, write
            // the buffer to disk and copy any remaining data into our buffer.
            // The assumption here is memcpy is cheaper than disk (or net) IO. 
            // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy)
            // So the extra copying will reduce the total number of writes, in 
            // non-pathological cases (ie, write 1 byte, then write for the buffer 
            // size repeatedly)
            if (_writePos > 0) { 
                int numBytes = _bufferSize - _writePos;   // space left in buffer
                if (numBytes > 0) {
                    if (numBytes > count)
                        numBytes = count; 
                    Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
                    _writePos += numBytes; 
                    if (count==numBytes) return; 
                    offset += numBytes;
                    count -= numBytes; 
                }
                // Reset our buffer.  We essentially want to call FlushWrite
                // without calling Flush on the underlying Stream.
#if !FEATURE_PAL 
#if !FEATURE_CORECLR
 
                if (_isAsync) { 
                    IAsyncResult result = BeginWriteCore(_buffer, 0, _writePos, null, null);
                    EndWrite(result); 
                }
                else {
#endif // FEATURE_CORECLR
                    WriteCore(_buffer, 0, _writePos); 
#if !FEATURE_CORECLR
                } 
#endif // FEATURE_CORECLR 
#else
                WriteCore(_buffer, 0, _writePos); 
#endif //!FEATURE_PAL
                _writePos = 0;
            }
            // If the buffer would slow writes down, avoid buffer completely. 
            if (count >= _bufferSize) {
                Contract.Assert(_writePos == 0, "FileStream cannot have buffered data to write here!  Your stream will be corrupted."); 
                WriteCore(array, offset, count); 
                return;
            } 
            else if (count == 0)
                return;  // Don't allocate a buffer then call memcpy for 0 bytes.
            if (_buffer==null) _buffer = new byte[_bufferSize];
            // Copy remaining bytes into buffer, to write at a later date. 
            Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count);
            _writePos = count; 
            return; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private unsafe void WriteCore(byte[] buffer, int offset, int count) {
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
            Contract.Assert(CanWrite, "CanWrite"); 

            Contract.Assert(buffer != null, "buffer != null"); 
            Contract.Assert(_readPos == _readLen, "_readPos == _readLen"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(count >= 0, "count is negative"); 
#if !FEATURE_PAL
#if !FEATURE_CORECLR
            if (_isAsync) {
                IAsyncResult result = BeginWriteCore(buffer, offset, count, null, null); 
                EndWrite(result);
                return; 
            } 
#endif // FEATURE_CORECLR
#endif //!FEATURE_PAL 

            // Make sure we are writing to the position that we think we are
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            int hr = 0; 
            int r = WriteFileNative(_handle, buffer, offset, count, null, out hr); 
            if (r == -1) {
                // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing. 
                if (hr == ERROR_NO_DATA) {
                    r = 0;
                }
                else { 
                    // ERROR_INVALID_PARAMETER may be returned for writes
                    // where the position is too large (ie, writing at Int64.MaxValue 
                    // on Win9x) OR for synchronous writes to a handle opened 
                    // asynchronously.
                    if (hr == ERROR_INVALID_PARAMETER) 
                        throw new IOException(Environment.GetResourceString("IO.IO_FileTooLongOrHandleNotSync"));
                    __Error.WinIOError(hr, String.Empty);
                }
            } 
            Contract.Assert(r >= 0, "FileStream's WriteCore is likely broken.");
            _pos += r; 
            return; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [HostProtection(ExternalThreading=true)]
        public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            if (array==null)
                throw new ArgumentNullException("array"); 
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (numBytes < 0) 
                throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < numBytes)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen(); 
 
#if !FEATURE_PAL && FEATURE_ASYNC_IO
            if (!_isAsync) 
                return base.BeginRead(array, offset, numBytes, userCallback, stateObject);

            if (!CanRead) __Error.ReadNotSupported();
 
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
            FileStreamAsyncResult asyncResult = null; 
 
            if (_isPipe) {
                // Pipes are ----ed up, at least when you have 2 different pipes 
                // that you want to use simultaneously.  When redirecting stdout
                // & stderr with the Process class, it's easy to deadlock your
                // parent & child processes when doing writes 4K at a time.  The
                // OS appears to use a 4K buffer internally.  If you write to a 
                // pipe that is full, you will block until someone read from
                // that pipe.  If you try reading from an empty pipe and 
                // FileStream's BeginRead blocks waiting for data to fill it's 
                // internal buffer, you will be blocked.  In a case where a child
                // process writes to stdout & stderr while a parent process tries 
                // reading from both, you can easily get into a deadlock here.
                // To avoid this deadlock, don't buffer when doing async IO on
                // pipes.  But don't completely ignore buffered data either.
                if (_readPos < _readLen) { 
                    int n = _readLen - _readPos;
                    if (n > numBytes) n = numBytes; 
                        Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n); 
                    _readPos += n;
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject); 
                    asyncResult.CallUserCallback();
                    return asyncResult;
                }
                Contract.Assert(_writePos == 0, "FileStream must not have buffered write data here!  Pipes should be unidirectional."); 
                return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
            } 
 
            // Handle buffering.
            if (_writePos > 0) FlushWrite(false); 
            if (_readPos == _readLen) {
                // I can't see how to handle buffering of async requests when
                // filling the buffer asynchronously, without a lot of complexity.
                // The problems I see are issuing an async read, we do an async 
                // read to fill the buffer, then someone issues another read
                // (either synchronously or asynchronously) before the first one 
                // returns.  This would involve some sort of complex buffer locking 
                // that we probably don't want to get into, at least not in V1.
                // If we did a [....] read to fill the buffer, we could avoid the 
                // problem, and any async read less than 64K gets turned into a
                // synchronous read by NT anyways...       --

                if (numBytes < _bufferSize) { 
                    if (_buffer == null) _buffer = new byte[_bufferSize];
                    IAsyncResult bufferRead = BeginReadCore(_buffer, 0, _bufferSize, null, null, 0); 
                    _readLen = EndRead(bufferRead); 
                    int n = _readLen;
                    if (n > numBytes) n = numBytes; 
                    Buffer.InternalBlockCopy(_buffer, 0, array, offset, n);
                    _readPos = n;
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject);
                    asyncResult.CallUserCallback(); 
                    return asyncResult;
                } 
 
                // Here we're making our position pointer inconsistent
                // with our read buffer.  Throw away the read buffer's contents. 
                _readPos = 0;
                _readLen = 0;
                return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
            } 
            else {
                int n = _readLen - _readPos; 
                if (n > numBytes) n = numBytes; 
                Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
                _readPos += n; 

                if (n >= numBytes || _isPipe) {
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject);
                    asyncResult.CallUserCallback(); 
                    return asyncResult;
                } 
 
                // For streams with no clear EOF like serial ports or pipes
                // we cannot read more data without causing an app to block 
                // incorrectly.  Pipes don't go down this path
                // though.  This code needs to be fixed.
                // Throw away read buffer.
                _readPos = 0; 
                _readLen = 0;
                asyncResult = BeginReadCore(array, offset + n, numBytes - n, userCallback, stateObject, n); 
                // WARNING: all state on asyncResult objects must be set before 
                // we call ReadFile in BeginReadCore, since the OS can run our
                // callback & the user's callback before ReadFile returns. 
            }
            return asyncResult;
#else
            return base.BeginRead(array, offset, numBytes, userCallback, stateObject); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO
        } 
 
#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)]
        unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
            Contract.Assert(CanRead, "CanRead"); 
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_writePos == 0, "_writePos == 0");
            Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative");

            // Create and store async stream class library specific data in the 
            // async result
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); 
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject; 
            asyncResult._isWrite = false;

            // Must set this here to ensure all the state on the IAsyncResult
            // object is set before we call ReadFile, which gives the OS an 
            // opportunity to run our callback (including the user callback &
            // the call to EndRead) before ReadFile has returned. 
            asyncResult._numBufferedBytes = numBufferedBytesRead; 

            // For Synchronous IO, I could go with either a callback and using 
            // the managed Monitor class, or I could create a handle and wait on it.
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later 
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult); 

            // Pack the Overlapped class, and store it in the async result 
            NativeOverlapped* intOverlapped;
            if (userCallback != null)
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
 
            asyncResult._overlapped = intOverlapped; 

            // Calculate position in the file we should be at after the read is done 
            if (CanSeek) {
                long len = Length;

                // Make sure we are reading from the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition(); 
 
                if (_pos + numBytes > len) {
                    if (_pos <= len) 
                        numBytes = (int) (len - _pos);
                    else
                        numBytes = 0;
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0. 
                intOverlapped->OffsetLow = unchecked((int)_pos);
                intOverlapped->OffsetHigh = (int)(_pos>>32); 

                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it
                // ourselves. This isn't threadsafe. 

                // WriteFile should not update the file pointer when writing 
                // in overlapped mode, according to MSDN.  But it does update 
                // the file pointer when writing to a UNC path!
                // So changed the code below to seek to an absolute 
                // location, not a relative one.  ReadFile seems consistent though.
                SeekCore(numBytes, SeekOrigin.Current);
            }
 
            // queue an async ReadFile operation and pass in a packed overlapped
            int hr = 0; 
            int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
            // ReadFile, the OS version, will return 0 on failure.  But
            // my ReadFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // on async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // read back from this call when using overlapped structures!  You must 
            // not pass in a non-null lpNumBytesRead to ReadFile when using 
            // overlapped structures!  This is by design NT behavior.
            if (r==-1 && numBytes!=-1) { 

                // For pipes, when they hit EOF, they will come here.
                if (hr == ERROR_BROKEN_PIPE) {
                    // Not an error, but EOF.  AsyncFSCallback will NOT be 
                    // called.  Call the user callback here.
 
                    // We clear the overlapped status bit for this special case. 
                    // Failure to do so looks like we are freeing a pending overlapped later.
                    intOverlapped->InternalLow = IntPtr.Zero; 
                    asyncResult.CallUserCallback();
                    // EndRead will free the Overlapped struct correctly.
                }
                else if (hr != ERROR_IO_PENDING) { 
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current); 
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else
                        __Error.WinIOError(hr, String.Empty);
                }
            } 
            else {
                // Due to a workaround for a race condition in NT's ReadFile & 
                // WriteFile routines, we will always be returning 0 from ReadFileNative 
                // when we do async IO instead of the number of bytes read,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not
                // set asyncResult._numBytes here, since will never have correct
                // results.
                //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on a separate thread"); 
            }
 
            return asyncResult; 
        }
#endif //!FEATURE_PAL 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public unsafe override int EndRead(IAsyncResult asyncResult)
        { 
            // There are 3 significantly different IAsyncResults we'll accept
            // here.  One is from Stream::BeginRead.  The other two are variations 
            // on our FileStreamAsyncResult.  One is from BeginReadCore, 
            // while the other is from the BeginRead buffering wrapper.
            if (asyncResult==null) 
                throw new ArgumentNullException("asyncResult");
            Contract.EndContractBlock();

#if !FEATURE_PAL && FEATURE_ASYNC_IO 
            if (!_isAsync)
                return base.EndRead(asyncResult); 
 
            FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
            if (afsar==null || afsar._isWrite) 
                __Error.WrongAsyncResult();

            // Ensure we can't get into any ----s by doing an interlocked
            // CompareExchange here.  Avoids corrupting memory via freeing the 
            // NativeOverlapped class or GCHandle twice.  --
            if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) 
                __Error.EndReadCalledTwice(); 

            // Obtain the WaitHandle, but don't use public property in case we 
            // delay initialize the manual reset event in the future.
            WaitHandle wh = afsar._waitHandle;
            if (wh != null) {
                // We must block to ensure that AsyncFSCallback has completed, 
                // and we should close the WaitHandle in here.  AsyncFSCallback
                // and the hand-ported imitation version in COMThreadPool.cpp 
                // are the only places that set this event. 
                try {
                    wh.WaitOne(); 
                    Contract.Assert(afsar._isComplete == true, "FileStream::EndRead - AsyncFSCallback didn't set _isComplete to true!");
                }
                finally {
                    wh.Close(); 
                }
            } 
 
            // Free memory & GC handles.
            NativeOverlapped* overlappedPtr = afsar._overlapped; 
            if (overlappedPtr != null)
                Overlapped.Free(overlappedPtr);

            // Now check for any error during the read. 
            if (afsar._errorCode != 0)
                __Error.WinIOError(afsar._errorCode, String.Empty); 
 
            return afsar._numBytes + afsar._numBufferedBytes;
#else 
            return base.EndRead(asyncResult);
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO
        }
 
        // Reads a byte from the file stream.  Returns the byte cast to an int
        // or -1 if reading from the end of the stream. 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override int ReadByte() {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (_readLen==0 && !CanRead) __Error.ReadNotSupported();
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
            if (_readPos == _readLen) {
                if (_writePos > 0) FlushWrite(false); 
                Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
                if (_buffer == null) _buffer = new byte[_bufferSize]; 
                _readLen = ReadCore(_buffer, 0, _bufferSize); 
                _readPos = 0;
            } 
            if (_readPos == _readLen)
                return -1;

            int result = _buffer[_readPos]; 
            _readPos++;
            return result; 
        } 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [HostProtection(ExternalThreading=true)]
        public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            if (array==null)
                throw new ArgumentNullException("array"); 
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (numBytes < 0) 
                throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < numBytes)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen(); 
 
#if !FEATURE_PAL && FEATURE_ASYNC_IO
            if (!_isAsync) 
                return base.BeginWrite(array, offset, numBytes, userCallback, stateObject);

            if (!CanWrite) __Error.WriteNotSupported();
 
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            if (_isPipe) { 
                // Pipes are ----ed up, at least when you have 2 different pipes
                // that you want to use simultaneously.  When redirecting stdout 
                // & stderr with the Process class, it's easy to deadlock your
                // parent & child processes when doing writes 4K at a time.  The
                // OS appears to use a 4K buffer internally.  If you write to a
                // pipe that is full, you will block until someone read from 
                // that pipe.  If you try reading from an empty pipe and
                // FileStream's BeginRead blocks waiting for data to fill it's 
                // internal buffer, you will be blocked.  In a case where a child 
                // process writes to stdout & stderr while a parent process tries
                // reading from both, you can easily get into a deadlock here. 
                // To avoid this deadlock, don't buffer when doing async IO on
                // pipes.
                Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream must not have buffered data here!  Pipes should be unidirectional.");
                if (_writePos > 0) 
                    FlushWrite(false);
                return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); 
            } 

            // Handle buffering. 
            FileStreamAsyncResult asyncResult;
            if (_writePos==0) {
                if (_readPos < _readLen) FlushRead();
                _readPos = 0; 
                _readLen = 0;
            } 
            int n = _bufferSize - _writePos; 
            if (numBytes <= n) {
                if (_writePos==0) _buffer = new byte[_bufferSize]; 
                Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
                _writePos += numBytes;
                asyncResult = new FileStreamAsyncResult();
                asyncResult._userCallback = userCallback; 
                asyncResult._userStateObject = stateObject;
                asyncResult._waitHandle = null; 
                asyncResult._isWrite = true; 
                asyncResult._numBufferedBytes = numBytes;
                asyncResult.CallUserCallback(); 
                return asyncResult;
            }
            if (_writePos > 0) FlushWrite(false);
            return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); 
#else
            return base.BeginWrite(array, offset, numBytes, userCallback, stateObject); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO 
        }
 
#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)] 
        unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); 
            Contract.Assert(CanWrite, "CanWrite");
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_readPos == _readLen, "_readPos == _readLen");
            Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative"); 

            // Create and store async stream class library specific data in the 
            // async result 
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult();
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject;
            asyncResult._isWrite = true;
 
            // For Synchronous IO, I could go with either a callback and using
            // the managed Monitor class, or I could create a handle and wait on it. 
            ManualResetEvent waitHandle = new ManualResetEvent(false); 
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
 
            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped* intOverlapped; 
            if (userCallback != null) 
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
            asyncResult._overlapped = intOverlapped;

            if (CanSeek) { 
                // Make sure we set the length of the file appropriately.
                long len = Length; 
                //Console.WriteLine("BeginWrite - Calculating end pos.  pos: "+pos+"  len: "+len+"  numBytes: "+numBytes); 

                // Make sure we are writing to the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition();

                if (_pos + numBytes > len) { 
                    //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes));
                    SetLengthCore(_pos + numBytes); 
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0.
                intOverlapped->OffsetLow = (int)_pos;
                intOverlapped->OffsetHigh = (int)(_pos>>32);
 
                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it 
                // ourselves.  This isn't threadsafe. 

                // 



 

 
 
                SeekCore(numBytes, SeekOrigin.Current);
            } 

            //Console.WriteLine("BeginWrite finishing.  pos: "+pos+"  numBytes: "+numBytes+"  _pos: "+_pos+"  Position: "+Position);

            int hr = 0; 
            // queue an async WriteFile operation and pass in a packed overlapped
            int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
 
            // WriteFile, the OS version, will return 0 on failure.  But
            // my WriteFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // On async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // written back from this call when using overlapped IO!  You must 
            // not pass in a non-null lpNumBytesWritten to WriteFile when using 
            // overlapped structures!  This is ByDesign NT behavior.
            if (r==-1 && numBytes!=-1) { 
                //Console.WriteLine("WriteFile returned 0;  Write will complete asynchronously (if hr==3e5)  hr: 0x{0:x}", hr);

                // For pipes, when they are closed on the other side, they will come here.
                if (hr == ERROR_NO_DATA) { 
                    // Not an error, but EOF.  AsyncFSCallback will NOT be
                    // called.  Call the user callback here. 
                    asyncResult.CallUserCallback(); 
                    // EndWrite will free the Overlapped struct correctly.
                } 
                else if (hr != ERROR_IO_PENDING) {
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current);
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else 
                        __Error.WinIOError(hr, String.Empty);
                } 
            }
            else {
                // Due to a workaround for a race condition in NT's ReadFile &
                // WriteFile routines, we will always be returning 0 from WriteFileNative 
                // when we do async IO instead of the number of bytes written,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not 
                // set asyncResult._numBytes here, since will never have correct
                // results. 
                //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on another thread.");
            }

            return asyncResult; 
        }
#endif //!FEATURE_PAL 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public unsafe override void EndWrite(IAsyncResult asyncResult) 
        {
            if (asyncResult==null)
                throw new ArgumentNullException("asyncResult");
            Contract.EndContractBlock(); 

#if !FEATURE_PAL && FEATURE_ASYNC_IO 
            if (!_isAsync) { 
                base.EndWrite(asyncResult);
                return; 
            }

            FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
            if (afsar==null || !afsar._isWrite) 
                __Error.WrongAsyncResult();
 
            // Ensure we can't get into any ----s by doing an interlocked 
            // CompareExchange here.  Avoids corrupting memory via freeing the
            // NativeOverlapped class or GCHandle twice.  -- 
            if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0))
                __Error.EndWriteCalledTwice();

            // Obtain the WaitHandle, but don't use public property in case we 
            // delay initialize the manual reset event in the future.
            WaitHandle wh = afsar._waitHandle; 
            if (wh != null) { 
                // We must block to ensure that AsyncFSCallback has completed,
                // and we should close the WaitHandle in here.  AsyncFSCallback 
                // and the hand-ported imitation version in COMThreadPool.cpp
                // are the only places that set this event.
                try {
                    wh.WaitOne(); 
                    Contract.Assert(afsar._isComplete == true, "FileStream::EndWrite - AsyncFSCallback didn't set _isComplete to true!");
                } 
                finally { 
                    wh.Close();
                } 
            }

            // Free memory & GC handles.
            NativeOverlapped* overlappedPtr = afsar._overlapped; 
            if (overlappedPtr != null)
                Overlapped.Free(overlappedPtr); 
 
            // Now check for any error during the write.
            if (afsar._errorCode != 0) 
                __Error.WinIOError(afsar._errorCode, String.Empty);

            // Number of bytes written is afsar._numBytes + afsar._numBufferedBytes.
            return; 
#else
            base.EndWrite(asyncResult); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void WriteByte(byte value)
        {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (_writePos==0) {
                if (!CanWrite) __Error.WriteNotSupported(); 
                if (_readPos < _readLen) FlushRead(); 
                _readPos = 0;
                _readLen = 0; 
                Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
                if (_buffer==null) _buffer = new byte[_bufferSize];
            }
            if (_writePos == _bufferSize) 
                FlushWrite(false);
 
            _buffer[_writePos] = value; 
            _writePos++;
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public virtual void Lock(long position, long length) {
            if (position < 0 || length < 0) 
                throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock(); 
            if (_handle.IsClosed) __Error.FileNotOpen(); 

            int positionLow     = unchecked((int)(position      )); 
            int positionHigh    = unchecked((int)(position >> 32));
            int lengthLow       = unchecked((int)(length        ));
            int lengthHigh      = unchecked((int)(length   >> 32));
 
            if (!Win32Native.LockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
                __Error.WinIOError(); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public virtual void Unlock(long position, long length) {
            if (position < 0 || length < 0)
                throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock(); 
            if (_handle.IsClosed) __Error.FileNotOpen();
 
            int positionLow     = unchecked((int)(position      )); 
            int positionHigh    = unchecked((int)(position >> 32));
            int lengthLow       = unchecked((int)(length        )); 
            int lengthHigh      = unchecked((int)(length   >> 32));

            if (!Win32Native.UnlockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
                __Error.WinIOError(); 
        }
 
        // Windows API definitions, from winbase.h and others 

        private const int FILE_ATTRIBUTE_NORMAL = 0x00000080; 
        private const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
        private const int FILE_FLAG_OVERLAPPED = 0x40000000;
        internal const int GENERIC_READ = unchecked((int)0x80000000);
        private const int GENERIC_WRITE = 0x40000000; 

        private const int FILE_BEGIN = 0; 
        private const int FILE_CURRENT = 1; 
        private const int FILE_END = 2;
 
        // Error codes (not HRESULTS), from winerror.h
        private const int ERROR_BROKEN_PIPE = 109;
        private const int ERROR_NO_DATA = 232;
        private const int ERROR_HANDLE_EOF = 38; 
        private const int ERROR_INVALID_PARAMETER = 87;
        private const int ERROR_IO_PENDING = 997; 
 

        // __ConsoleStream also uses this code. 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr)
        {
            Contract.Requires(handle != null, "handle != null"); 
            Contract.Requires(offset >= 0, "offset >= 0");
            Contract.Requires(count >= 0, "count >= 0"); 
            Contract.Requires(bytes != null, "bytes != null"); 
            // Don't corrupt memory when multiple threads are erroneously writing
            // to this stream simultaneously. 
            if (bytes.Length - offset < count)
                throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
            Contract.EndContractBlock();
 
            Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter ----up in call to ReadFileNative.");
 
            // You can't use the fixed statement on an array of length 0. 
            if (bytes.Length==0) {
                hr = 0; 
                return 0;
            }

            int r = 0; 
            int numBytesRead = 0;
 
            fixed(byte* p = bytes) { 
                if (_isAsync)
                    r = Win32Native.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); 
                else
                    r = Win32Native.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero);
            }
 
            if (r==0) {
                hr = Marshal.GetLastWin32Error(); 
                // We should never silently ---- an error here without some 
                // extra work.  We must make sure that BeginReadCore won't return an
                // IAsyncResult that will cause EndRead to block, since the OS won't 
                // call AsyncFSCallback for us.
                if (hr == ERROR_BROKEN_PIPE || hr == Win32Native.ERROR_PIPE_NOT_CONNECTED) {
                    // This handle was a pipe, and it's done. Not an error, but EOF.
                    // However, the OS will not call AsyncFSCallback! 
                    // Let the caller handle this, since BeginReadCore & ReadCore
                    // need to do different things. 
                    return -1; 
                }
 
                // For invalid handles, detect the error and mark our handle
                // as closed to give slightly better error messages.  Also
                // help ensure we avoid handle recycling bugs.
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();
 
                return -1; 
            }
            else 
                hr = 0;
            return numBytesRead;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) { 
            Contract.Requires(handle != null, "handle != null"); 
            Contract.Requires(offset >= 0, "offset >= 0");
            Contract.Requires(count >= 0, "count >= 0"); 
            Contract.Requires(bytes != null, "bytes != null");
            // Don't corrupt memory when multiple threads are erroneously writing
            // to this stream simultaneously.  (the OS is reading from
            // the array we pass to WriteFile, but if we read beyond the end and 
            // that memory isn't allocated, we could get an AV.)
            if (bytes.Length - offset < count) 
                throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition")); 
            Contract.EndContractBlock();
 
            Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter ----up in call to WriteFileNative.");

            // You can't use the fixed statement on an array of length 0.
            if (bytes.Length==0) { 
                hr = 0;
                return 0; 
            } 

            int numBytesWritten = 0; 
            int r = 0;

            fixed(byte* p = bytes) {
                if (_isAsync) 
                    r = Win32Native.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped);
                else 
                    r = Win32Native.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); 
            }
 
            if (r==0) {
                hr = Marshal.GetLastWin32Error();
                // We should never silently ---- an error here without some
                // extra work.  We must make sure that BeginWriteCore won't return an 
                // IAsyncResult that will cause EndWrite to block, since the OS won't
                // call AsyncFSCallback for us. 
 
                if (hr==ERROR_NO_DATA) {
                    // This handle was a pipe, and the pipe is being closed on the 
                    // other side.  Let the caller handle this, since BeginWriteCore
                    // & WriteCore need to do different things.
                    return -1;
                } 

                // For invalid handles, detect the error and mark our handle 
                // as closed to give slightly better error messages.  Also 
                // help ensure we avoid handle recycling bugs.
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();

                return -1;
            } 
            else
                hr = 0; 
            return numBytesWritten; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:  FileStream 
**
** [....] 
**
**
** Purpose: Exposes a Stream around a file, with full
** synchronous and asychronous support, and buffering. 
**
** 
===========================================================*/ 
using System;
using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles;
using System.Security;
#if !FEATURE_PAL && FEATURE_MACL
using System.Security.AccessControl; 
#endif
using System.Security.Permissions; 
using System.Threading; 
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging; 
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts; 

 
/* 
 * FileStream supports different modes of accessing the disk - async mode
 * and [....] mode.  They are two completely different codepaths in the 
 * [....] & async methods (ie, Read/Write vs. BeginRead/BeginWrite).  File
 * handles in NT can be opened in only [....] or overlapped (async) mode,
 * and we have to deal with this pain.  Stream has implementations of
 * the [....] methods in terms of the async ones, so we'll 
 * call through to our base class to get those methods when necessary.
 * 
 * Also buffering is added into FileStream as well. Folded in the 
 * code from BufferedStream, so all the comments about it being mostly
 * aggressive (and the possible perf improvement) apply to FileStream as 
 * well.  Also added some buffering to the async code paths.
 *
 * Class Invariants:
 * The class has one buffer, shared for reading & writing.  It can only be 
 * used for one or the other at any point in time - not both.  The following
 * should be true: 
 *   0 <= _readPos <= _readLen < _bufferSize 
 *   0 <= _writePos < _bufferSize
 *   _readPos == _readLen && _readPos > 0 implies the read buffer is valid, 
 *     but we're at the end of the buffer.
 *   _readPos == _readLen == 0 means the read buffer contains garbage.
 *   Either _writePos can be greater than 0, or _readLen & _readPos can be
 *     greater than zero, but neither can be greater than zero at the same time. 
 *
 */ 
 
namespace System.IO {
    // This is an internal object implementing IAsyncResult with fields 
    // for all of the relevant data necessary to complete the IO operation.
    // This is used by AsyncFSCallback and all of the async methods.
#if IO_CANCELLATION_ENABLED
    unsafe internal sealed class FileStreamAsyncResult : ICancelableAsyncResult, System.Object 
#if false // ugly hack to fix syntax for TrimSrc parser, which ignores #if directives
    { 
    } 
#endif
#else 
    unsafe internal sealed class FileStreamAsyncResult : IAsyncResult
#endif
    {
        // README: 
        // If you modify the order of these fields, make sure to update
        // the native VM definition of this class as well!!! 
 
        // User code callback
        internal AsyncCallback _userCallback; 
        internal Object _userStateObject;
        internal ManualResetEvent _waitHandle;
        [System.Security.SecurityCritical /*auto-generated*/]
        internal SafeFileHandle _handle;      // For cancellation support. 
#if !FEATURE_PAL
        internal NativeOverlapped* _overlapped; 
#endif 
        internal int _EndXxxCalled;   // Whether we've called EndXxx already.
        internal int _numBytes;     // number of bytes read OR written 
        internal int _errorCode;
        internal int _numBufferedBytes;

        internal bool _isWrite;     // Whether this is a read or a write 
        internal bool _isComplete;  // Value for IsCompleted property
        internal bool _completedSynchronously;  // Which thread called callback 
 
        // Adding in a finalizer here to catch the places
        // where users didn't call EndRead or EndWrite on an IAsyncResult, 
        // willn't work.  The unmanaged memory in the NativeOverlapped
        // struct keeps a GCHandle to this IAsyncResult object alive, so this
        // never get finalized.
 
        public Object AsyncState
        { 
            get { return _userStateObject; } 
        }
 
        public bool IsCompleted
        {
            get { return _isComplete; }
        } 

        public WaitHandle AsyncWaitHandle 
        { 
#if !FEATURE_PAL
            [System.Security.SecuritySafeCritical]  // auto-generated 
            [ResourceExposure(ResourceScope.None)]
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get {
                // Consider uncommenting this someday soon - the EventHandle 
                // in the Overlapped struct is really useless half of the
                // time today since the OS doesn't signal it.  If users call 
                // EndXxx after the OS call happened to complete, there's no 
                // reason to create a synchronization primitive here.  Fixing
                // this will save us some perf, assuming we can correctly 
                // initialize the ManualResetEvent.
                if (_waitHandle == null) {
                    ManualResetEvent mre = new ManualResetEvent(false);
                    if (_overlapped != null && _overlapped->EventHandle != IntPtr.Zero) { 
                        mre.SafeWaitHandle = new SafeWaitHandle(_overlapped->EventHandle, true);
                    } 
 
                    // make sure only one thread sets _waitHandle
                    if (Interlocked.CompareExchange(ref _waitHandle, mre, null) == null) { 
                        if (_isComplete)
                            _waitHandle.Set();
                    }
                    else { 
                        // There's a slight but acceptable ---- if we weren't
                        // the thread that set _waitHandle and this code path 
                        // returns before the code in the if statement 
                        // executes (on the other thread). However, the
                        // caller is waiting for the wait handle to be set, 
                        // which will still happen.
                        mre.Close();
                    }
                } 
                return _waitHandle;
            } 
#else 
            get { return null; }
#endif //!FEATURE_PAL && FEATURE_MACL 
        }

        // Returns true iff the user callback was called by the thread that
        // called BeginRead or BeginWrite.  If we use an async delegate or 
        // threadpool thread internally, this will be false.  This is used
        // by code to determine whether a successive call to BeginRead needs 
        // to be done on their main thread or in their callback to avoid a 
        // stack overflow on many reads or writes.
        public bool CompletedSynchronously 
        {
            get { return _completedSynchronously; }
        }
 
        internal static FileStreamAsyncResult CreateBufferedReadResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject) {
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); 
            asyncResult._userCallback = userCallback; 
            asyncResult._userStateObject = userStateObject;
            asyncResult._isWrite = false; 
            asyncResult._numBufferedBytes = numBufferedBytes;
            return asyncResult;
        }
 
        private void CallUserCallbackWorker(Object callbackState)
        { 
            _isComplete = true; 

            // ensure _isComplete is set before reading _waitHandle 
            Thread.MemoryBarrier();
            if (_waitHandle != null)
                _waitHandle.Set();
 
            _userCallback(this);
        } 
 
        internal void CallUserCallback()
        { 
            // Convenience method for me, since I have to do this in a number
            // of places in the buffering code for fake IAsyncResults.
            // AsyncFSCallback intentionally does not use this method.
 
            if (_userCallback != null) {
                // Call user's callback on a threadpool thread. 
                // Set completedSynchronously to false, since it's on another 
                // thread, not the main thread.
                _completedSynchronously = false; 
                ThreadPool.QueueUserWorkItem(new WaitCallback(CallUserCallbackWorker));
            }
            else {
                _isComplete = true; 

                // ensure _isComplete is set before reading _waitHandle 
                Thread.MemoryBarrier(); 
                if (_waitHandle != null)
                    _waitHandle.Set(); 
            }
        }

#if IO_CANCELLATION_ENABLED 
        [HostProtection(ExternalThreading=true)]
        public void Cancel() 
        { 
#if !FEATURE_PAL
            if (!Environment.IsWindowsVista) 
                throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_RequiresLonghorn"));

            if (_handle == null || _overlapped == null)
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_IOCancellation")); 

            if (_handle.IsInvalid) 
                __Error.StreamIsClosed(); 
            Contract.EndContractBlock();
 
            bool r = Win32Native.CancelIoEx(_handle, _overlapped);
            if (!r)
                __Error.WinIOError();
#else 
            throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_RequiresLonghorn"));
#endif 
        } 
#endif
 
    }

    [ComVisible(true)]
    public class FileStream : Stream 
    {
        internal const int DefaultBufferSize = 4096; 
 

#if !FEATURE_PAL 
#if FEATURE_CORECLR
        // @todo: This #ifdef factoring fixes the public api async behavior for M6 with minimal risk. When more
        // time is available, we should more rigorously scrub out all references for FileStreamAsyncResult and AsyncFSCallback
        // (this requires corresponding changes in the src\vm tree as well.) 
        private static readonly bool _canUseAsync = false;
#else 
        private static readonly bool _canUseAsync = Environment.RunningOnWinNT; 
#endif //FEATURE_CORECLR
        [System.Security.SecurityCritical /*auto-generated*/] 
        private unsafe static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(FileStream.AsyncFSCallback);
#else
        private static readonly bool _canUseAsync = false;
#endif //!FEATURE_PAL 

        private byte[] _buffer;   // Shared read/write buffer.  Alloc on first use. 
        private String _fileName; // Fully qualified file name. 
        private bool _isAsync;    // Whether we opened the handle for overlapped IO
        private bool _canRead; 
        private bool _canWrite;
        private bool _canSeek;
        private bool _exposedHandle; // Could other code be using this handle?
        private bool _isPipe;     // Whether to disable async buffering code. 
        private int _readPos;     // Read pointer within shared buffer.
        private int _readLen;     // Number of bytes read in buffer from file. 
        private int _writePos;    // Write pointer within shared buffer. 
        private int _bufferSize;  // Length of internal buffer, if it's allocated.
        [System.Security.SecurityCritical /*auto-generated*/] 
        private SafeFileHandle _handle;
        private long _pos;        // Cache current location in the file.
        private long _appendStart;// When appending, prevent overwriting file.
 
        [System.Security.SecuritySafeCritical] // static constructors should be safe to call
        static FileStream() 
        { 
        }
 
        //This exists only to support IsolatedStorageFileStream.
        //Any changes to FileStream must include the corresponding changes in IsolatedStorage.
        internal FileStream() {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode) 
            : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access) 
            : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share)
            : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) { 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
            : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false) 
        {
        } 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
            : this(path, mode, access, share, bufferSize, options, Path.GetFileName(path), false)
        { 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
            : this(path, mode, access, share, bufferSize, (useAsync ? FileOptions.Asynchronous : FileOptions.None), Path.GetFileName(path), false)
        {
        } 

#if !FEATURE_PAL && FEATURE_MACL 
        // This constructor is done differently to avoid loading a few more 
        // classes, and more importantly, to build correctly on Rotor.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity)
        { 
            Object pinningHandle;
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share, fileSecurity, out pinningHandle); 
            try { 
                Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false);
            } 
            finally {
                if (pinningHandle != null) {
                    GCHandle pinHandle = (GCHandle) pinningHandle;
                    pinHandle.Free(); 
                }
            } 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options)
        { 
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
            Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false); 
        } 
#endif
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); 
            Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, false); 
        }
 
        [System.Security.SecurityCritical]
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); 
            Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath); 
        }
 
        // AccessControl namespace is not defined in Rotor
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        internal void Init(String path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, Win32Native.SECURITY_ATTRIBUTES secAttrs, String msgPath, bool bFromProxy, bool useLongPath)
        { 
            if (path == null) 
                throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
            if (path.Length == 0) 
                throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
            Contract.EndContractBlock();

#if !FEATURE_PAL && FEATURE_MACL 
            FileSystemRights fileSystemRights = (FileSystemRights)rights;
#endif 
            // msgPath must be safe to hand back to untrusted code. 

            _fileName = msgPath;  // To handle odd cases of finalizing partially constructed objects. 
            _exposedHandle = false;

#if FEATURE_PAL
            Contract.Assert(!useRights, "Specifying FileSystemRights is not supported on this platform!"); 
#endif
 
            // don't include inheritable in our bounds check for share 
            FileShare tempshare = share & ~FileShare.Inheritable;
            String badArg = null; 

            if (mode < FileMode.CreateNew || mode > FileMode.Append)
                badArg = "mode";
            else if (!useRights && (access < FileAccess.Read || access > FileAccess.ReadWrite)) 
                badArg = "access";
#if !FEATURE_PAL && FEATURE_MACL 
            else if (useRights && (fileSystemRights < FileSystemRights.ReadData || fileSystemRights > FileSystemRights.FullControl)) 
                badArg = "rights";
#endif 
            else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete))
                badArg = "share";

            if (badArg != null) 
                throw new ArgumentOutOfRangeException(badArg, Environment.GetResourceString("ArgumentOutOfRange_Enum"));
 
            // NOTE: any change to FileOptions enum needs to be matched here in the error validation 
            if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0)
                throw new ArgumentOutOfRangeException("options", Environment.GetResourceString("ArgumentOutOfRange_Enum")); 

            if (bufferSize <= 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
 
            // Write access validation
#if !FEATURE_PAL && FEATURE_MACL 
            if ((!useRights && (access & FileAccess.Write) == 0) 
                || (useRights && (fileSystemRights & FileSystemRights.Write) == 0))
#else 
            if (!useRights && (access & FileAccess.Write) == 0)
#endif //!FEATURE_PAL && FEATURE_MACL
            {
                if (mode==FileMode.Truncate || mode==FileMode.CreateNew || mode==FileMode.Create || mode==FileMode.Append) { 
                    // No write access
                    if (!useRights) 
                        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo", mode, access)); 
#if !FEATURE_PAL && FEATURE_MACL
                    else 
                        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&RightsCombo", mode, fileSystemRights));
#endif //!FEATURE_PAL && FEATURE_MACL
                }
            } 

#if !FEATURE_PAL && FEATURE_MACL 
            // FileMode.Truncate only works with GENERIC_WRITE (FileAccess.Write), source:MSDN 
            // For backcomp use FileAccess.Write when FileSystemRights.Write is specified
            if (useRights && (mode == FileMode.Truncate)) { 
                if (fileSystemRights == FileSystemRights.Write) {
                    useRights = false;
                    access = FileAccess.Write;
                } 
                else {
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileModeTruncate&RightsCombo", mode, fileSystemRights)); 
                } 
            }
#endif 

            int fAccess;
            if (!useRights) {
                fAccess = access == FileAccess.Read? GENERIC_READ: 
                access == FileAccess.Write? GENERIC_WRITE:
                GENERIC_READ | GENERIC_WRITE; 
            } 
            else {
                fAccess = rights; 
            }

            // Get absolute path - Security needs this to prevent something
            // like trying to create a file in c:\tmp with the name 
            // "..\WinNT\System32\ntoskrnl.exe".  Store it for user convenience.
            int maxPath = useLongPath ? Path.MaxLongPath : Path.MaxPath; 
            String filePath = Path.NormalizePath(path, true, maxPath); 

            _fileName = filePath; 

            // Prevent access to your disk drives as raw block devices.
            if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
                throw new ArgumentException(Environment.GetResourceString("Arg_DevicesNotSupported")); 

            // Build up security permissions required, as well as validate we 
            // have a sensible set of parameters.  IE, creating a brand new file 
            // for reading doesn't make much sense.
            FileIOPermissionAccess secAccess = FileIOPermissionAccess.NoAccess; 
#if !FEATURE_PAL && FEATURE_MACL
            if ((!useRights && (access & FileAccess.Read) != 0) || (useRights && (fileSystemRights & FileSystemRights.ReadAndExecute) != 0))
#else
            if (!useRights && (access & FileAccess.Read) != 0) 
#endif //!FEATURE_PAL && FEATURE_MACL
            { 
                if (mode==FileMode.Append) 
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidAppendMode"));
                else 
                    secAccess = secAccess | FileIOPermissionAccess.Read;
            }
            // I can't think of any combos of FileMode we should disallow if we
            // don't have read access.  Writing would pretty much always be valid 
            // in those cases.
 
            // For any FileSystemRights other than ReadAndExecute, demand Write permission 
            // This is probably bit overkill for TakeOwnership etc but we don't have any
            // matching FileIOPermissionAccess to demand. It is better that we ask for Write permission. 

#if !FEATURE_PAL && FEATURE_MACL
            // FileMode.OpenOrCreate & FileSystemRights.Synchronize can create 0-byte file; demand write
            if ((!useRights && (access & FileAccess.Write) != 0) 
                || (useRights && (fileSystemRights & (FileSystemRights.Write | FileSystemRights.Delete
                                            | FileSystemRights.DeleteSubdirectoriesAndFiles 
                                            | FileSystemRights.ChangePermissions 
                                            | FileSystemRights.TakeOwnership)) != 0)
                || (useRights && ((fileSystemRights & FileSystemRights.Synchronize) != 0) 
                                            && mode==FileMode.OpenOrCreate)
               )
#else
            if (!useRights && (access & FileAccess.Write) != 0) 
#endif //!FEATURE_PAL && FEATURE_MACL
            { 
                if (mode==FileMode.Append) 
                    secAccess = secAccess | FileIOPermissionAccess.Append;
                else 
                    secAccess = secAccess | FileIOPermissionAccess.Write;
            }

#if !FEATURE_PAL && FEATURE_MACL 
            bool specifiedAcl;
            unsafe { 
                specifiedAcl = secAttrs != null && secAttrs.pSecurityDescriptor != null; 
            }
 
            AccessControlActions control = specifiedAcl ? AccessControlActions.Change : AccessControlActions.None;
            new FileIOPermission(secAccess, control, new String[] { filePath }, false, false).Demand();
#else
            new FileIOPermission(secAccess, new String[] { filePath }, false, false).Demand(); 
#endif
            // Our Inheritable bit was stolen from Windows, but should be set in 
            // the security attributes class.  Don't leave this bit set. 
            share &= ~FileShare.Inheritable;
 
            bool seekToEnd = (mode==FileMode.Append);
            // Must use a valid Win32 constant here...
            if (mode == FileMode.Append)
                mode = FileMode.OpenOrCreate; 

            // WRT async IO, do the right thing for whatever platform we're on. 
            // This way, someone can easily write code that opens a file 
            // asynchronously no matter what their platform is.
            if (_canUseAsync && (options & FileOptions.Asynchronous) != 0) 
                _isAsync = true;
            else
                options &= ~FileOptions.Asynchronous;
 
            int flagsAndAttributes = (int) options;
 
#if !FEATURE_PAL 
            // For mitigating local elevation of privilege attack through named pipes
            // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the 
            // named pipe server can't impersonate a high privileged client security context
            flagsAndAttributes|= (Win32Native.SECURITY_SQOS_PRESENT | Win32Native.SECURITY_ANONYMOUS);
#endif
            // Don't pop up a dialog for reading from an emtpy floppy drive 
            int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
            try { 
                String tempPath = filePath; 
                if (useLongPath)
                    tempPath = Path.AddLongPathPrefix(tempPath); 
                _handle = Win32Native.SafeCreateFile(tempPath, fAccess, share, secAttrs, mode, flagsAndAttributes, Win32Native.NULL);

                if (_handle.IsInvalid) {
                    // Return a meaningful exception, using the RELATIVE path to 
                    // the file to avoid returning extra information to the caller
                    // unless they have path discovery permission, in which case 
                    // the full path is fine & useful. 

                    // NT5 oddity - when trying to open "C:\" as a FileStream, 
                    // we usually get ERROR_PATH_NOT_FOUND from the OS.  We should
                    // probably be consistent w/ every other directory.
                    int errorCode = Marshal.GetLastWin32Error();
                    if (errorCode==__Error.ERROR_PATH_NOT_FOUND && filePath.Equals(Directory.InternalGetDirectoryRoot(filePath))) 
                        errorCode = __Error.ERROR_ACCESS_DENIED;
 
                    // We need to give an exception, and preferably it would include 
                    // the fully qualified path name.  Do security check here.  If
                    // we fail, give back the msgPath, which should not reveal much. 
                    // While this logic is largely duplicated in
                    // __Error.WinIOError, we need this for
                    // IsolatedStorageFileStream.
                    bool canGiveFullPath = false; 

                    if (!bFromProxy) 
                    { 
                        try {
                            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand(); 
                            canGiveFullPath = true;
                        }
                        catch(SecurityException) {}
                    } 

                    if (canGiveFullPath) 
                        __Error.WinIOError(errorCode, _fileName); 
                    else
                        __Error.WinIOError(errorCode, msgPath); 
                }
            }
            finally {
                Win32Native.SetErrorMode(oldMode); 
            }
 
            // Disallow access to all non-file devices from the FileStream 
            // constructors that take a String.  Everyone else can call
            // CreateFile themselves then use the constructor that takes an 
            // IntPtr.  Disallows "con:", "com1:", "lpt1:", etc.
            int fileType = Win32Native.GetFileType(_handle);
            if (fileType != Win32Native.FILE_TYPE_DISK) {
                _handle.Close(); 
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
            } 
 
#if !FEATURE_PAL
#if !FEATURE_CORECLR 
            // This is necessary for async IO using IO Completion ports via our
            // managed Threadpool API's.  This (theoretically) calls the OS's
            // BindIoCompletionCallback method, and passes in a stub for the
            // LPOVERLAPPED_COMPLETION_ROUTINE.  This stub looks at the Overlapped 
            // struct for this request and gets a delegate to a managed callback
            // from there, which it then calls on a threadpool thread.  (We allocate 
            // our native OVERLAPPED structs 2 pointers too large and store EE state 
            // & GC handles there, one to an IAsyncResult, the other to a delegate.)
            if (_isAsync) { 
                bool b = false;
                // BindHandle requires UnmanagedCode permission
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                try { 
                    b = ThreadPool.BindHandle(_handle);
                } 
                finally { 
                    CodeAccessPermission.RevertAssert();
                    if (!b) { 
                        // We should close the handle so that the handle is not open until SafeFileHandle GC
                        Contract.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?");
                        _handle.Close();
                    } 
                }
                if (!b) 
                    throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); 
            }
#endif // FEATURE_CORECLR 
#endif //!FEATURE_PAL
            if (!useRights) {
                _canRead = (access & FileAccess.Read) != 0;
                _canWrite = (access & FileAccess.Write) != 0; 
            }
#if !FEATURE_PAL && FEATURE_MACL 
            else { 
                _canRead = (fileSystemRights & FileSystemRights.ReadData) != 0;
                _canWrite = ((fileSystemRights & FileSystemRights.WriteData) != 0) 
                            || ((fileSystemRights & FileSystemRights.AppendData) != 0);
            }
#endif //!FEATURE_PAL && FEATURE_MACL
 
            _canSeek = true;
            _isPipe = false; 
            _pos = 0; 
            _bufferSize = bufferSize;
            _readPos = 0; 
            _readLen = 0;
            _writePos = 0;

            // For Append mode... 
            if (seekToEnd) {
                _appendStart = SeekCore(0, SeekOrigin.End); 
            } 
            else {
                _appendStart = -1; 
            }
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access) instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access)
            : this(handle, access, true, DefaultBufferSize, false) { 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")] 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle) 
            : this(handle, access, ownsHandle, DefaultBufferSize, false) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize) 
            : this(handle, access, ownsHandle, bufferSize, false) { 
        }
 
        // We explicitly do a Demand, not a LinkDemand here.
        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("This constructor has been deprecated.  Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed.  http://go.microsoft.com/fwlink/?linkid=14202")]
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync) 
            : this(new SafeFileHandle(handle, ownsHandle), access, bufferSize, isAsync) {
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileStream(SafeFileHandle handle, FileAccess access)
            : this(handle, access, DefaultBufferSize, false) { 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize)
            : this(handle, access, bufferSize, false) { 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) {
            // To ensure we don't leak a handle, put it in a SafeFileHandle first
            if (handle.IsInvalid) 
                throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHandle"), "handle");
            Contract.EndContractBlock(); 
 
            _handle = handle;
            _exposedHandle = true; 

            // Now validate arguments.
            if (access < FileAccess.Read || access > FileAccess.ReadWrite)
                throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum")); 
            if (bufferSize <= 0)
                throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
 
            int handleType = Win32Native.GetFileType(_handle);
            Contract.Assert(handleType == Win32Native.FILE_TYPE_DISK || handleType == Win32Native.FILE_TYPE_PIPE || handleType == Win32Native.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); 
            _isAsync = isAsync && _canUseAsync;  // On Win9x, just do the right thing.
            _canRead = 0 != (access & FileAccess.Read);
            _canWrite = 0 != (access & FileAccess.Write);
            _canSeek = handleType == Win32Native.FILE_TYPE_DISK; 
            _bufferSize = bufferSize;
            _readPos = 0; 
            _readLen = 0; 
            _writePos = 0;
            _fileName = null; 
            _isPipe = handleType == Win32Native.FILE_TYPE_PIPE;

#if !FEATURE_PAL
            // This is necessary for async IO using IO Completion ports via our 
            // managed Threadpool API's.  This calls the OS's
            // BindIoCompletionCallback method, and passes in a stub for the 
            // LPOVERLAPPED_COMPLETION_ROUTINE.  This stub looks at the Overlapped 
            // struct for this request and gets a delegate to a managed callback
            // from there, which it then calls on a threadpool thread.  (We allocate 
            // our native OVERLAPPED structs 2 pointers too large and store EE
            // state & a handle to a delegate there.)
#if !FEATURE_CORECLR
            if (_isAsync) { 
                bool b = false;
                try { 
                    b = ThreadPool.BindHandle(_handle); 
                }
                catch (ApplicationException) { 
                    // If you passed in a synchronous handle and told us to use
                    // it asynchronously, throw here.
                    throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotAsync"));
                } 
                if (!b) {
                    throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed")); 
                } 
            }
            else { 
#endif // FEATURE_CORECLR
                if (handleType != Win32Native.FILE_TYPE_PIPE)
                    VerifyHandleIsSync();
#if !FEATURE_CORECLR 
            }
#endif // FEATURE_CORECLR 
#else 
                if (handleType != Win32Native.FILE_TYPE_PIPE)
                    VerifyHandleIsSync(); 
#endif //!FEATURE_PAL
            if (_canSeek)
                SeekCore(0, SeekOrigin.Current);
            else 
                _pos = 0;
        } 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) 
        {
            Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
            if ((share & FileShare.Inheritable) != 0) {
                secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); 
                secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
 
                secAttrs.bInheritHandle = 1; 
            }
            return secAttrs; 
        }

#if !FEATURE_PAL && FEATURE_MACL
        // If pinningHandle is not null, caller must free it AFTER the call to 
        // CreateFile has returned.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share, FileSecurity fileSecurity, out Object pinningHandle) 
        {
            pinningHandle = null; 
            Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
            if ((share & FileShare.Inheritable) != 0 || fileSecurity != null) {
                secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
                secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); 

                if ((share & FileShare.Inheritable) != 0) { 
                    secAttrs.bInheritHandle = 1; 
                }
 
                // For ACL's, get the security descriptor from the FileSecurity.
                if (fileSecurity != null) {
                    byte[] sd = fileSecurity.GetSecurityDescriptorBinaryForm();
                    pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned); 
                    fixed(byte* pSecDescriptor = sd)
                        secAttrs.pSecurityDescriptor = pSecDescriptor; 
                } 
            }
            return secAttrs; 
        }
#endif

        // Verifies that this handle supports synchronous IO operations (unless you 
        // didn't open it for either reading or writing).
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe void VerifyHandleIsSync() 
        {
            // Do NOT use this method on pipes.  Reading or writing to a pipe may 
            // cause an app to block incorrectly, introducing a deadlock (depending
            // on whether a write will wake up an already-blocked thread or this
            // FileStream's thread).
 
            // Do NOT change this to use a byte[] of length 0, or test test won't
            // work.  Our ReadFile & WriteFile methods are special cased to return 
            // for arrays of length 0, since we'd get an IndexOutOfRangeException 
            // while using C#'s fixed syntax.
            byte[] bytes = new byte[1]; 
            int hr = 0;
            int r = 0;

            // If the handle is a pipe, ReadFile will block until there 
            // has been a write on the other end.  We'll just have to deal with it,
            // For the read end of a pipe, you can mess up and 
            // accidentally read synchronously from an async pipe. 
            if (CanRead) {
                r = ReadFileNative(_handle, bytes, 0, 0, null, out hr); 
            }
            else if (CanWrite) {
                r = WriteFileNative(_handle, bytes, 0, 0, null, out hr);
            } 

            if (hr==ERROR_INVALID_PARAMETER) 
                throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync")); 
            if (hr == Win32Native.ERROR_INVALID_HANDLE)
                __Error.WinIOError(hr, ""); 
        }


        public override bool CanRead { 
            [Pure]
            get { return _canRead; } 
        } 

        public override bool CanWrite { 
            [Pure]
            get { return _canWrite; }
        }
 
        public override bool CanSeek {
            [Pure] 
            get { return _canSeek; } 
        }
 
        public virtual bool IsAsync {
            get { return _isAsync; }
        }
 
        public override long Length {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get { 
                if (_handle.IsClosed) __Error.FileNotOpen();
                if (!CanSeek) __Error.SeekNotSupported(); 
                int hi = 0, lo = 0;

                lo = Win32Native.GetFileSize(_handle, out hi);
 
                if (lo==-1) {  // Check for either an error or a 4GB - 1 byte file.
                    int hr = Marshal.GetLastWin32Error(); 
                    if (hr != 0) 
                        __Error.WinIOError(hr, String.Empty);
                } 
                long len = (((long)hi) << 32) | ((uint) lo);
                // If we're writing near the end of the file, we must include our
                // internal buffer in our Length calculation.  Don't flush because
                // we use the length of the file in our async write method. 
                if (_writePos > 0 && _pos + _writePos > len)
                    len = _writePos + _pos; 
                return len; 
            }
        } 

        public String Name {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                if (_fileName == null)
                    return Environment.GetResourceString("IO_UnknownFileName"); 
                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand(); 
                return _fileName;
            } 
        }

        internal String NameInternal {
            get { 
                if (_fileName == null)
                    return ""; 
                return _fileName; 
            }
        } 

        public override long Position {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                if (_handle.IsClosed) __Error.FileNotOpen();
                if (!CanSeek) __Error.SeekNotSupported(); 
 
                Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
                // Verify that internal position is in [....] with the handle
                if (_exposedHandle)
                    VerifyOSHandlePosition();
 
                // Compensate for buffer that we read from the handle (_readLen) Vs what the user
                // read so far from the internel buffer (_readPos). Of course add any unwrittern 
                // buffered data 
                return _pos + (_readPos - _readLen + _writePos);
            } 
            [System.Security.SecuritySafeCritical]  // auto-generated
            set {
                if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
                Contract.EndContractBlock(); 
                if (_writePos > 0) FlushWrite(false);
                _readPos = 0; 
                _readLen = 0; 
                Seek(value, SeekOrigin.Begin);
            } 
        }

#if !FEATURE_PAL && FEATURE_MACL
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public FileSecurity GetAccessControl() 
        {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            return new FileSecurity(_handle, _fileName, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public void SetAccessControl(FileSecurity fileSecurity)
        { 
            if (fileSecurity == null) 
                throw new ArgumentNullException("fileSecurity");
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen();

            fileSecurity.Persist(_handle, _fileName); 
        }
#endif 
 
#if !FEATURE_PAL
        // When doing IO asynchronously (ie, _isAsync==true), this callback is 
        // called by a free thread in the threadpool when the IO operation
        // completes.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        unsafe private static void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) 
        { 
            //Console.WriteLine("AsyncFSCallback called.  errorCode: "+errorCode+"  numBytes: "+numBytes);
 
            // Unpack overlapped
            Overlapped overlapped = Overlapped.Unpack(pOverlapped);
            // Free the overlapped struct in EndRead/EndWrite.
 
            // Extract async result from overlapped
            FileStreamAsyncResult asyncResult = 
                (FileStreamAsyncResult)overlapped.AsyncResult; 
            asyncResult._numBytes = (int)numBytes;
 
            // Handle reading from & writing to closed pipes.  While I'm not sure
            // this is entirely necessary anymore, maybe it's possible for
            // an async read on a pipe to be issued and then the pipe is closed,
            // returning this error.  This may very well be necessary. 
            if (errorCode == ERROR_BROKEN_PIPE || errorCode == ERROR_NO_DATA)
                errorCode = 0; 
 
            asyncResult._errorCode = (int)errorCode;
 
            //Console.WriteLine("AsyncFSCallback:  errorCode: "+errorCode+"  numBytes: "+numBytes+" was synchronous: "+asyncResult.CompletedSynchronously);

            // Call the user-provided callback.  It can and often should
            // call EndRead or EndWrite.  There's no reason to use an async 
            // delegate here - we're already on a threadpool thread.
            // IAsyncResult's completedSynchronously property must return 
            // false here, saying the user callback was called on another thread. 
            asyncResult._completedSynchronously = false;
            asyncResult._isComplete = true; 

            // ensure _isComplete is set before reading _waitHandle
            Thread.MemoryBarrier();
 
            // The OS does not signal this event.  We must do it ourselves.
            ManualResetEvent wh = asyncResult._waitHandle; 
            if (wh != null) { 
                Contract.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set(); 
                Contract.Assert(r, "ManualResetEvent::Set failed!");
                if (!r) __Error.WinIOError();
            }
 
            AsyncCallback userCallback = asyncResult._userCallback;
            if (userCallback != null) 
                userCallback(asyncResult); 
        }
#endif //!FEATURE_PAL 

        [System.Security.SecuritySafeCritical]  // auto-generated
        protected override void Dispose(bool disposing)
        { 
            // Nothing will be done differently based on whether we are
            // disposing vs. finalizing.  This is taking advantage of the 
            // weak ordering between normal finalizable objects & critical 
            // finalizable objects, which I included in the SafeHandle
            // design for FileStream, which would often "just work" when 
            // finalized.
            try {
                if (_handle != null && !_handle.IsClosed) {
                    // Flush data to disk iff we were writing.  After 
                    // thinking about this, we also don't need to flush
                    // our read position, regardless of whether the handle 
                    // was exposed to the user.  They probably would NOT 
                    // want us to do this.
                    if (_writePos > 0) { 
                        FlushWrite(!disposing);
                    }
                }
            } 
            finally {
                if (_handle != null && !_handle.IsClosed) 
                    _handle.Dispose(); 

                _canRead = false; 
                _canWrite = false;
                _canSeek = false;
                // Don't set the buffer to null, to avoid a NullReferenceException
                // when users have a race condition in their code (ie, they call 
                // Close when calling another method on Stream like Read).
                //_buffer = null; 
                base.Dispose(disposing); 
            }
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        ~FileStream()
        { 
            if (_handle != null) {
                BCLDebug.Correctness(_handle.IsClosed, "You didn't close a FileStream & it got finalized.  Name: \""+_fileName+"\""); 
                Dispose(false); 
            }
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void Flush()
        { 
            Flush(false);
        } 
 
        [System.Security.SecuritySafeCritical]
        public virtual void Flush(Boolean flushToDisk) 
        {
            // This code is duplicated in Dispose
            if (_handle.IsClosed) __Error.FileNotOpen();
            if (_writePos > 0) { 
                FlushWrite(false);
 
                if (flushToDisk) { 
                    if (!Win32Native.FlushFileBuffers(_handle)) {
                        __Error.WinIOError(); 
                    }
                }
            }
            else if (_readPos < _readLen && CanSeek) { 
                FlushRead();
            } 
            _readPos = 0; 
            _readLen = 0;
        } 

        // Reading is done by blocks from the file, but someone could read
        // 1 byte from the buffer then write.  At that point, the OS's file
        // pointer is out of [....] with the stream's position.  All write 
        // functions should call this function to preserve the position in the file.
        private void FlushRead() { 
            Contract.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushRead!"); 
            if (_readPos - _readLen != 0) {
                Contract.Assert(CanSeek, "FileStream will lose buffered read data now."); 
                SeekCore(_readPos - _readLen, SeekOrigin.Current);
            }
            _readPos = 0;
            _readLen = 0; 
        }
 
        // Writes are buffered.  Anytime the buffer fills up 
        // (_writePos + delta > _bufferSize) or the buffer switches to reading
        // and there is left over data (_writePos > 0), this function must be called. 
        private void FlushWrite(bool calledFromFinalizer) {
            Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream: Read buffer must be empty in FlushWrite!");

#if !FEATURE_PAL 
#if !FEATURE_CORECLR
            if (_isAsync) { 
                IAsyncResult asyncResult = BeginWriteCore(_buffer, 0, _writePos, null, null); 
                // With our Whidbey async IO & overlapped support for AD unloads,
                // we don't strictly need to block here to release resources 
                // since that support takes care of the pinning & freeing the
                // overlapped struct.  We need to do this when called from
                // Close so that the handle is closed when Close returns, but
                // we do't need to call EndWrite from the finalizer. 
                // Additionally, if we do call EndWrite, we block forever
                // because AD unloads prevent us from running the managed 
                // callback from the IO completion port.  Blocking here when 
                // called from the finalizer during AD unload is clearly wrong,
                // but we can't use any sort of test for whether the AD is 
                // unloading because if we weren't unloading, an AD unload
                // could happen on a separate thread before we call EndWrite.
                if (!calledFromFinalizer)
                    EndWrite(asyncResult); 
            }
            else 
#endif // FEATURE_CORECLR 
                WriteCore(_buffer, 0, _writePos);
            _writePos = 0; 
#else
            WriteCore(_buffer, 0, _writePos);
            _writePos = 0;
#endif //!FEATURE_PAL 
        }
 
 
        [Obsolete("This property has been deprecated.  Please use FileStream's SafeFileHandle property instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        public virtual IntPtr Handle { 
            [System.Security.SecurityCritical]  // auto-generated_required
            [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            get {
                Flush(); 
                // Explicitly dump any buffered data, since the user could move our 
                // position or write to the file.
                _readPos = 0; 
                _readLen = 0;
                _writePos = 0;
                _exposedHandle = true;
 
                return _handle.DangerousGetHandle();
            } 
        } 

        public virtual SafeFileHandle SafeFileHandle { 
            [System.Security.SecurityCritical]  // auto-generated_required
            [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get {
                Flush(); 
                // Explicitly dump any buffered data, since the user could move our
                // position or write to the file. 
                _readPos = 0; 
                _readLen = 0;
                _writePos = 0; 
                _exposedHandle = true;

                return _handle;
            } 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override void SetLength(long value)
        { 
            if (value < 0)
                throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock();
 
            if (_handle.IsClosed) __Error.FileNotOpen();
            if (!CanSeek) __Error.SeekNotSupported(); 
            if (!CanWrite) __Error.WriteNotSupported(); 

            // Handle buffering updates. 
            if (_writePos > 0) {
                FlushWrite(false);
            }
            else if (_readPos < _readLen) { 
                FlushRead();
            } 
            _readPos = 0; 
            _readLen = 0;
 
            if (_appendStart != -1 && value < _appendStart)
                throw new IOException(Environment.GetResourceString("IO.IO_SetLengthAppendTruncate"));
            SetLengthCore(value);
        } 

        // We absolutely need this method broken out so that BeginWriteCore can call 
        // a method without having to go through buffering code that might call 
        // FlushWrite.
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private void SetLengthCore(long value)
        {
            Contract.Assert(value >= 0, "value >= 0");
            long origPos = _pos; 

            if (_exposedHandle) 
                VerifyOSHandlePosition(); 
            if (_pos != value)
                SeekCore(value, SeekOrigin.Begin); 
            if (!Win32Native.SetEndOfFile(_handle)) {
                int hr = Marshal.GetLastWin32Error();
                if (hr==__Error.ERROR_INVALID_PARAMETER)
                    throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig")); 
                __Error.WinIOError(hr, String.Empty);
            } 
            // Return file pointer to where it was before setting length 
            if (origPos != value) {
                if (origPos < value) 
                    SeekCore(origPos, SeekOrigin.Begin);
                else
                    SeekCore(0, SeekOrigin.End);
            } 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override int Read([In, Out] byte[] array, int offset, int count) {
            if (array==null) 
                throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
            if (offset < 0)
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (count < 0) 
                throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < count) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); 
            Contract.EndContractBlock();
 
            if (_handle.IsClosed) __Error.FileNotOpen();

            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            bool isBlocked = false;
            int n = _readLen - _readPos; 
            // if the read buffer is empty, read into either user's array or our 
            // buffer, depending on number of bytes user asked for and buffer size.
            if (n == 0) { 
                if (!CanRead) __Error.ReadNotSupported();
                if (_writePos > 0) FlushWrite(false);
                if (!CanSeek || (count >= _bufferSize)) {
                    n = ReadCore(array, offset, count); 
                    // Throw away read buffer.
                    _readPos = 0; 
                    _readLen = 0; 
                    return n;
                } 
                if (_buffer == null) _buffer = new byte[_bufferSize];
                n = ReadCore(_buffer, 0, _bufferSize);
                if (n == 0) return 0;
                isBlocked = n < _bufferSize; 
                _readPos = 0;
                _readLen = n; 
            } 
            // Now copy min of count or numBytesAvailable (ie, near EOF) to array.
            if (n > count) n = count; 
            Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
            _readPos += n;

            // We may have read less than the number of bytes the user asked 
            // for, but that is part of the Stream contract.  Reading again for
            // more data may cause us to block if we're using a device with 
            // no clear end of file, such as a serial port or pipe.  If we 
            // blocked here & this code was used with redirected pipes for a
            // process's standard output, this can lead to deadlocks involving 
            // two processes. But leave this here for files to avoid what would
            // probably be a breaking change.         --

            // If we are reading from a device with no clear EOF like a 
            // serial port or a pipe, this will cause us to block incorrectly.
            if (!_isPipe) { 
                // If we hit the end of the buffer and didn't have enough bytes, we must 
                // read some more from the underlying stream.  However, if we got
                // fewer bytes from the underlying stream than we asked for (ie, we're 
                // probably blocked), don't ask for more bytes.
                if (n < count && !isBlocked) {
                    Contract.Assert(_readPos == _readLen, "Read buffer should be empty!");
                    int moreBytesRead = ReadCore(array, offset + n, count - n); 
                    n += moreBytesRead;
                    // We've just made our buffer inconsistent with our position 
                    // pointer.  We must throw away the read buffer. 
                    _readPos = 0;
                    _readLen = 0; 
                }
            }

            return n; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private unsafe int ReadCore(byte[] buffer, int offset, int count) {
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); 
            Contract.Assert(CanRead, "CanRead");

            Contract.Assert(buffer != null, "buffer != null");
            Contract.Assert(_writePos == 0, "_writePos == 0"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(count >= 0, "count is negative"); 
#if !FEATURE_PAL 
#if !FEATURE_CORECLR
            if (_isAsync) { 
                IAsyncResult result = BeginReadCore(buffer, offset, count, null, null, 0);
                return EndRead(result);
            }
#endif // FEATURE_CORECLR 
#endif //!FEATURE_PAL
 
            // Make sure we are reading from the right spot 
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            int hr = 0;
            int r = ReadFileNative(_handle, buffer, offset, count, null, out hr);
            if (r == -1) { 
                // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe.
                if (hr == ERROR_BROKEN_PIPE) { 
                    r = 0; 
                }
                else { 
                    if (hr == ERROR_INVALID_PARAMETER)
                        throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync"));

                    __Error.WinIOError(hr, String.Empty); 
                }
            } 
            Contract.Assert(r >= 0, "FileStream's ReadCore is likely broken."); 
            _pos += r;
 
            return r;
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override long Seek(long offset, SeekOrigin origin) {
            if (originSeekOrigin.End) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin")); 
            Contract.EndContractBlock();
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (!CanSeek) __Error.SeekNotSupported();

            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            // If we've got bytes in our buffer to write, write them out.
            // If we've read in and consumed some bytes, we'll have to adjust 
            // our seek positions ONLY IF we're seeking relative to the current 
            // position in the stream.  This simulates doing a seek to the new
            // position, then a read for the number of bytes we have in our buffer. 
            if (_writePos > 0) {
                FlushWrite(false);
            }
            else if (origin == SeekOrigin.Current) { 
                // Don't call FlushRead here, which would have caused an infinite
                // loop.  Simply adjust the seek origin.  This isn't necessary 
                // if we're seeking relative to the beginning or end of the stream. 
                offset -= (_readLen - _readPos);
            } 

            // Verify that internal position is in [....] with the handle
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            long oldPos = _pos + (_readPos - _readLen); 
            long pos = SeekCore(offset, origin); 

            // Prevent users from overwriting data in a file that was opened in 
            // append mode.
            if (_appendStart != -1 && pos < _appendStart) {
                SeekCore(oldPos, SeekOrigin.Begin);
                throw new IOException(Environment.GetResourceString("IO.IO_SeekAppendOverwrite")); 
            }
 
            // We now must update the read buffer.  We can in some cases simply 
            // update _readPos within the buffer, copy around the buffer so our
            // Position property is still correct, and avoid having to do more 
            // reads from the disk.  Otherwise, discard the buffer's contents.
            if (_readLen > 0) {
                // We can optimize the following condition:
                // oldPos - _readPos <= pos < oldPos + _readLen - _readPos 
                if (oldPos == pos) {
                    if (_readPos > 0) { 
                        //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+"  _readLen: "+_readLen); 
                        Buffer.InternalBlockCopy(_buffer, _readPos, _buffer, 0, _readLen - _readPos);
                        _readLen -= _readPos; 
                        _readPos = 0;
                    }
                    // If we still have buffered data, we must update the stream's
                    // position so our Position property is correct. 
                    if (_readLen > 0)
                        SeekCore(_readLen, SeekOrigin.Current); 
                } 
                else if (oldPos - _readPos < pos && pos < oldPos + _readLen - _readPos) {
                    int diff = (int)(pos - oldPos); 
                    //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+"  adjusting buffer - shrinking by "+ (_readPos + diff));
                    Buffer.InternalBlockCopy(_buffer, _readPos+diff, _buffer, 0, _readLen - (_readPos + diff));
                    _readLen -= (_readPos + diff);
                    _readPos = 0; 
                    if (_readLen > 0)
                        SeekCore(_readLen, SeekOrigin.Current); 
                } 
                else {
                    // Lose the read buffer. 
                    _readPos = 0;
                    _readLen = 0;
                }
                Contract.Assert(_readLen >= 0 && _readPos <= _readLen, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen"); 
                Contract.Assert(pos == Position, "Seek optimization: pos != Position!  Buffer math was mangled.");
            } 
            return pos; 
        }
 
        // This doesn't do argument checking.  Necessary for SetLength, which must
        // set the file pointer beyond the end of the file. This will update the
        // internal position
        [System.Security.SecuritySafeCritical]  // auto-generated 
        private long SeekCore(long offset, SeekOrigin origin) {
            Contract.Assert(!_handle.IsClosed && CanSeek, "!_handle.IsClosed && CanSeek"); 
            Contract.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End"); 
            int hr = 0;
            long ret = 0; 

            ret = Win32Native.SetFilePointer(_handle, offset, origin, out hr);
            if (ret == -1) {
                // For invalid handles, detect the error and mark our handle 
                // as closed to give slightly better error messages.  Also
                // help ensure we avoid handle recycling bugs. 
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();
                __Error.WinIOError(hr, String.Empty); 
            }

            _pos = ret;
            return ret; 
        }
 
        // Checks the position of the OS's handle equals what we expect it to. 
        // This will fail if someone else moved the FileStream's handle or if
        // we've hit a bug in FileStream's position updating code. 
        private void VerifyOSHandlePosition()
        {
            if (!CanSeek)
                return; 

            // SeekCore will override the current _pos, so save it now 
            long oldPos = _pos; 
            long curPos = SeekCore(0, SeekOrigin.Current);
 
            if (curPos != oldPos) {
                // For reads, this is non-fatal but we still could have returned corrupted
                // data in some cases. So discard the internal buffer. Potential MDA
                _readPos = 0; 
                _readLen = 0;
                if(_writePos > 0) { 
                    // Discard the buffer and let the user know! 
                    _writePos = 0;
                    throw new IOException(Environment.GetResourceString("IO.IO_FileStreamHandlePosition")); 
                }
            }
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void Write(byte[] array, int offset, int count) { 
            if (array==null) 
                throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < count) 
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 
 
            if (_handle.IsClosed) __Error.FileNotOpen();
 
            if (_writePos == 0)
            {
                // Ensure we can write to the stream, and ready buffer for writing.
                if (!CanWrite) __Error.WriteNotSupported(); 
                if (_readPos < _readLen) FlushRead();
                _readPos = 0; 
                _readLen = 0; 
            }
 
            // If our buffer has data in it, copy data from the user's array into
            // the buffer, and if we can fit it all there, return.  Otherwise, write
            // the buffer to disk and copy any remaining data into our buffer.
            // The assumption here is memcpy is cheaper than disk (or net) IO. 
            // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy)
            // So the extra copying will reduce the total number of writes, in 
            // non-pathological cases (ie, write 1 byte, then write for the buffer 
            // size repeatedly)
            if (_writePos > 0) { 
                int numBytes = _bufferSize - _writePos;   // space left in buffer
                if (numBytes > 0) {
                    if (numBytes > count)
                        numBytes = count; 
                    Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
                    _writePos += numBytes; 
                    if (count==numBytes) return; 
                    offset += numBytes;
                    count -= numBytes; 
                }
                // Reset our buffer.  We essentially want to call FlushWrite
                // without calling Flush on the underlying Stream.
#if !FEATURE_PAL 
#if !FEATURE_CORECLR
 
                if (_isAsync) { 
                    IAsyncResult result = BeginWriteCore(_buffer, 0, _writePos, null, null);
                    EndWrite(result); 
                }
                else {
#endif // FEATURE_CORECLR
                    WriteCore(_buffer, 0, _writePos); 
#if !FEATURE_CORECLR
                } 
#endif // FEATURE_CORECLR 
#else
                WriteCore(_buffer, 0, _writePos); 
#endif //!FEATURE_PAL
                _writePos = 0;
            }
            // If the buffer would slow writes down, avoid buffer completely. 
            if (count >= _bufferSize) {
                Contract.Assert(_writePos == 0, "FileStream cannot have buffered data to write here!  Your stream will be corrupted."); 
                WriteCore(array, offset, count); 
                return;
            } 
            else if (count == 0)
                return;  // Don't allocate a buffer then call memcpy for 0 bytes.
            if (_buffer==null) _buffer = new byte[_bufferSize];
            // Copy remaining bytes into buffer, to write at a later date. 
            Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count);
            _writePos = count; 
            return; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private unsafe void WriteCore(byte[] buffer, int offset, int count) {
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
            Contract.Assert(CanWrite, "CanWrite"); 

            Contract.Assert(buffer != null, "buffer != null"); 
            Contract.Assert(_readPos == _readLen, "_readPos == _readLen"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(count >= 0, "count is negative"); 
#if !FEATURE_PAL
#if !FEATURE_CORECLR
            if (_isAsync) {
                IAsyncResult result = BeginWriteCore(buffer, offset, count, null, null); 
                EndWrite(result);
                return; 
            } 
#endif // FEATURE_CORECLR
#endif //!FEATURE_PAL 

            // Make sure we are writing to the position that we think we are
            if (_exposedHandle)
                VerifyOSHandlePosition(); 

            int hr = 0; 
            int r = WriteFileNative(_handle, buffer, offset, count, null, out hr); 
            if (r == -1) {
                // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing. 
                if (hr == ERROR_NO_DATA) {
                    r = 0;
                }
                else { 
                    // ERROR_INVALID_PARAMETER may be returned for writes
                    // where the position is too large (ie, writing at Int64.MaxValue 
                    // on Win9x) OR for synchronous writes to a handle opened 
                    // asynchronously.
                    if (hr == ERROR_INVALID_PARAMETER) 
                        throw new IOException(Environment.GetResourceString("IO.IO_FileTooLongOrHandleNotSync"));
                    __Error.WinIOError(hr, String.Empty);
                }
            } 
            Contract.Assert(r >= 0, "FileStream's WriteCore is likely broken.");
            _pos += r; 
            return; 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [HostProtection(ExternalThreading=true)]
        public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            if (array==null)
                throw new ArgumentNullException("array"); 
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (numBytes < 0) 
                throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < numBytes)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen(); 
 
#if !FEATURE_PAL && FEATURE_ASYNC_IO
            if (!_isAsync) 
                return base.BeginRead(array, offset, numBytes, userCallback, stateObject);

            if (!CanRead) __Error.ReadNotSupported();
 
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
            FileStreamAsyncResult asyncResult = null; 
 
            if (_isPipe) {
                // Pipes are ----ed up, at least when you have 2 different pipes 
                // that you want to use simultaneously.  When redirecting stdout
                // & stderr with the Process class, it's easy to deadlock your
                // parent & child processes when doing writes 4K at a time.  The
                // OS appears to use a 4K buffer internally.  If you write to a 
                // pipe that is full, you will block until someone read from
                // that pipe.  If you try reading from an empty pipe and 
                // FileStream's BeginRead blocks waiting for data to fill it's 
                // internal buffer, you will be blocked.  In a case where a child
                // process writes to stdout & stderr while a parent process tries 
                // reading from both, you can easily get into a deadlock here.
                // To avoid this deadlock, don't buffer when doing async IO on
                // pipes.  But don't completely ignore buffered data either.
                if (_readPos < _readLen) { 
                    int n = _readLen - _readPos;
                    if (n > numBytes) n = numBytes; 
                        Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n); 
                    _readPos += n;
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject); 
                    asyncResult.CallUserCallback();
                    return asyncResult;
                }
                Contract.Assert(_writePos == 0, "FileStream must not have buffered write data here!  Pipes should be unidirectional."); 
                return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
            } 
 
            // Handle buffering.
            if (_writePos > 0) FlushWrite(false); 
            if (_readPos == _readLen) {
                // I can't see how to handle buffering of async requests when
                // filling the buffer asynchronously, without a lot of complexity.
                // The problems I see are issuing an async read, we do an async 
                // read to fill the buffer, then someone issues another read
                // (either synchronously or asynchronously) before the first one 
                // returns.  This would involve some sort of complex buffer locking 
                // that we probably don't want to get into, at least not in V1.
                // If we did a [....] read to fill the buffer, we could avoid the 
                // problem, and any async read less than 64K gets turned into a
                // synchronous read by NT anyways...       --

                if (numBytes < _bufferSize) { 
                    if (_buffer == null) _buffer = new byte[_bufferSize];
                    IAsyncResult bufferRead = BeginReadCore(_buffer, 0, _bufferSize, null, null, 0); 
                    _readLen = EndRead(bufferRead); 
                    int n = _readLen;
                    if (n > numBytes) n = numBytes; 
                    Buffer.InternalBlockCopy(_buffer, 0, array, offset, n);
                    _readPos = n;
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject);
                    asyncResult.CallUserCallback(); 
                    return asyncResult;
                } 
 
                // Here we're making our position pointer inconsistent
                // with our read buffer.  Throw away the read buffer's contents. 
                _readPos = 0;
                _readLen = 0;
                return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
            } 
            else {
                int n = _readLen - _readPos; 
                if (n > numBytes) n = numBytes; 
                Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
                _readPos += n; 

                if (n >= numBytes || _isPipe) {
                    asyncResult = FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject);
                    asyncResult.CallUserCallback(); 
                    return asyncResult;
                } 
 
                // For streams with no clear EOF like serial ports or pipes
                // we cannot read more data without causing an app to block 
                // incorrectly.  Pipes don't go down this path
                // though.  This code needs to be fixed.
                // Throw away read buffer.
                _readPos = 0; 
                _readLen = 0;
                asyncResult = BeginReadCore(array, offset + n, numBytes - n, userCallback, stateObject, n); 
                // WARNING: all state on asyncResult objects must be set before 
                // we call ReadFile in BeginReadCore, since the OS can run our
                // callback & the user's callback before ReadFile returns. 
            }
            return asyncResult;
#else
            return base.BeginRead(array, offset, numBytes, userCallback, stateObject); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO
        } 
 
#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)]
        unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
            Contract.Assert(CanRead, "CanRead"); 
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_writePos == 0, "_writePos == 0");
            Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative");

            // Create and store async stream class library specific data in the 
            // async result
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); 
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject; 
            asyncResult._isWrite = false;

            // Must set this here to ensure all the state on the IAsyncResult
            // object is set before we call ReadFile, which gives the OS an 
            // opportunity to run our callback (including the user callback &
            // the call to EndRead) before ReadFile has returned. 
            asyncResult._numBufferedBytes = numBufferedBytesRead; 

            // For Synchronous IO, I could go with either a callback and using 
            // the managed Monitor class, or I could create a handle and wait on it.
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later 
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult); 

            // Pack the Overlapped class, and store it in the async result 
            NativeOverlapped* intOverlapped;
            if (userCallback != null)
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
 
            asyncResult._overlapped = intOverlapped; 

            // Calculate position in the file we should be at after the read is done 
            if (CanSeek) {
                long len = Length;

                // Make sure we are reading from the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition(); 
 
                if (_pos + numBytes > len) {
                    if (_pos <= len) 
                        numBytes = (int) (len - _pos);
                    else
                        numBytes = 0;
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0. 
                intOverlapped->OffsetLow = unchecked((int)_pos);
                intOverlapped->OffsetHigh = (int)(_pos>>32); 

                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it
                // ourselves. This isn't threadsafe. 

                // WriteFile should not update the file pointer when writing 
                // in overlapped mode, according to MSDN.  But it does update 
                // the file pointer when writing to a UNC path!
                // So changed the code below to seek to an absolute 
                // location, not a relative one.  ReadFile seems consistent though.
                SeekCore(numBytes, SeekOrigin.Current);
            }
 
            // queue an async ReadFile operation and pass in a packed overlapped
            int hr = 0; 
            int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
            // ReadFile, the OS version, will return 0 on failure.  But
            // my ReadFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // on async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // read back from this call when using overlapped structures!  You must 
            // not pass in a non-null lpNumBytesRead to ReadFile when using 
            // overlapped structures!  This is by design NT behavior.
            if (r==-1 && numBytes!=-1) { 

                // For pipes, when they hit EOF, they will come here.
                if (hr == ERROR_BROKEN_PIPE) {
                    // Not an error, but EOF.  AsyncFSCallback will NOT be 
                    // called.  Call the user callback here.
 
                    // We clear the overlapped status bit for this special case. 
                    // Failure to do so looks like we are freeing a pending overlapped later.
                    intOverlapped->InternalLow = IntPtr.Zero; 
                    asyncResult.CallUserCallback();
                    // EndRead will free the Overlapped struct correctly.
                }
                else if (hr != ERROR_IO_PENDING) { 
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current); 
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else
                        __Error.WinIOError(hr, String.Empty);
                }
            } 
            else {
                // Due to a workaround for a race condition in NT's ReadFile & 
                // WriteFile routines, we will always be returning 0 from ReadFileNative 
                // when we do async IO instead of the number of bytes read,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not
                // set asyncResult._numBytes here, since will never have correct
                // results.
                //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on a separate thread"); 
            }
 
            return asyncResult; 
        }
#endif //!FEATURE_PAL 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public unsafe override int EndRead(IAsyncResult asyncResult)
        { 
            // There are 3 significantly different IAsyncResults we'll accept
            // here.  One is from Stream::BeginRead.  The other two are variations 
            // on our FileStreamAsyncResult.  One is from BeginReadCore, 
            // while the other is from the BeginRead buffering wrapper.
            if (asyncResult==null) 
                throw new ArgumentNullException("asyncResult");
            Contract.EndContractBlock();

#if !FEATURE_PAL && FEATURE_ASYNC_IO 
            if (!_isAsync)
                return base.EndRead(asyncResult); 
 
            FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
            if (afsar==null || afsar._isWrite) 
                __Error.WrongAsyncResult();

            // Ensure we can't get into any ----s by doing an interlocked
            // CompareExchange here.  Avoids corrupting memory via freeing the 
            // NativeOverlapped class or GCHandle twice.  --
            if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) 
                __Error.EndReadCalledTwice(); 

            // Obtain the WaitHandle, but don't use public property in case we 
            // delay initialize the manual reset event in the future.
            WaitHandle wh = afsar._waitHandle;
            if (wh != null) {
                // We must block to ensure that AsyncFSCallback has completed, 
                // and we should close the WaitHandle in here.  AsyncFSCallback
                // and the hand-ported imitation version in COMThreadPool.cpp 
                // are the only places that set this event. 
                try {
                    wh.WaitOne(); 
                    Contract.Assert(afsar._isComplete == true, "FileStream::EndRead - AsyncFSCallback didn't set _isComplete to true!");
                }
                finally {
                    wh.Close(); 
                }
            } 
 
            // Free memory & GC handles.
            NativeOverlapped* overlappedPtr = afsar._overlapped; 
            if (overlappedPtr != null)
                Overlapped.Free(overlappedPtr);

            // Now check for any error during the read. 
            if (afsar._errorCode != 0)
                __Error.WinIOError(afsar._errorCode, String.Empty); 
 
            return afsar._numBytes + afsar._numBufferedBytes;
#else 
            return base.EndRead(asyncResult);
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO
        }
 
        // Reads a byte from the file stream.  Returns the byte cast to an int
        // or -1 if reading from the end of the stream. 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override int ReadByte() {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (_readLen==0 && !CanRead) __Error.ReadNotSupported();
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
            if (_readPos == _readLen) {
                if (_writePos > 0) FlushWrite(false); 
                Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
                if (_buffer == null) _buffer = new byte[_bufferSize]; 
                _readLen = ReadCore(_buffer, 0, _bufferSize); 
                _readPos = 0;
            } 
            if (_readPos == _readLen)
                return -1;

            int result = _buffer[_readPos]; 
            _readPos++;
            return result; 
        } 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [HostProtection(ExternalThreading=true)]
        public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            if (array==null)
                throw new ArgumentNullException("array"); 
            if (offset < 0) 
                throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (numBytes < 0) 
                throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            if (array.Length - offset < numBytes)
                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
            Contract.EndContractBlock(); 

            if (_handle.IsClosed) __Error.FileNotOpen(); 
 
#if !FEATURE_PAL && FEATURE_ASYNC_IO
            if (!_isAsync) 
                return base.BeginWrite(array, offset, numBytes, userCallback, stateObject);

            if (!CanWrite) __Error.WriteNotSupported();
 
            Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
 
            if (_isPipe) { 
                // Pipes are ----ed up, at least when you have 2 different pipes
                // that you want to use simultaneously.  When redirecting stdout 
                // & stderr with the Process class, it's easy to deadlock your
                // parent & child processes when doing writes 4K at a time.  The
                // OS appears to use a 4K buffer internally.  If you write to a
                // pipe that is full, you will block until someone read from 
                // that pipe.  If you try reading from an empty pipe and
                // FileStream's BeginRead blocks waiting for data to fill it's 
                // internal buffer, you will be blocked.  In a case where a child 
                // process writes to stdout & stderr while a parent process tries
                // reading from both, you can easily get into a deadlock here. 
                // To avoid this deadlock, don't buffer when doing async IO on
                // pipes.
                Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream must not have buffered data here!  Pipes should be unidirectional.");
                if (_writePos > 0) 
                    FlushWrite(false);
                return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); 
            } 

            // Handle buffering. 
            FileStreamAsyncResult asyncResult;
            if (_writePos==0) {
                if (_readPos < _readLen) FlushRead();
                _readPos = 0; 
                _readLen = 0;
            } 
            int n = _bufferSize - _writePos; 
            if (numBytes <= n) {
                if (_writePos==0) _buffer = new byte[_bufferSize]; 
                Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
                _writePos += numBytes;
                asyncResult = new FileStreamAsyncResult();
                asyncResult._userCallback = userCallback; 
                asyncResult._userStateObject = stateObject;
                asyncResult._waitHandle = null; 
                asyncResult._isWrite = true; 
                asyncResult._numBufferedBytes = numBytes;
                asyncResult.CallUserCallback(); 
                return asyncResult;
            }
            if (_writePos > 0) FlushWrite(false);
            return BeginWriteCore(array, offset, numBytes, userCallback, stateObject); 
#else
            return base.BeginWrite(array, offset, numBytes, userCallback, stateObject); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO 
        }
 
#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)] 
        unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); 
            Contract.Assert(CanWrite, "CanWrite");
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_readPos == _readLen, "_readPos == _readLen");
            Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative"); 

            // Create and store async stream class library specific data in the 
            // async result 
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult();
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject;
            asyncResult._isWrite = true;
 
            // For Synchronous IO, I could go with either a callback and using
            // the managed Monitor class, or I could create a handle and wait on it. 
            ManualResetEvent waitHandle = new ManualResetEvent(false); 
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
 
            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped* intOverlapped; 
            if (userCallback != null) 
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
            asyncResult._overlapped = intOverlapped;

            if (CanSeek) { 
                // Make sure we set the length of the file appropriately.
                long len = Length; 
                //Console.WriteLine("BeginWrite - Calculating end pos.  pos: "+pos+"  len: "+len+"  numBytes: "+numBytes); 

                // Make sure we are writing to the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition();

                if (_pos + numBytes > len) { 
                    //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes));
                    SetLengthCore(_pos + numBytes); 
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0.
                intOverlapped->OffsetLow = (int)_pos;
                intOverlapped->OffsetHigh = (int)(_pos>>32);
 
                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it 
                // ourselves.  This isn't threadsafe. 

                // 



 

 
 
                SeekCore(numBytes, SeekOrigin.Current);
            } 

            //Console.WriteLine("BeginWrite finishing.  pos: "+pos+"  numBytes: "+numBytes+"  _pos: "+_pos+"  Position: "+Position);

            int hr = 0; 
            // queue an async WriteFile operation and pass in a packed overlapped
            int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
 
            // WriteFile, the OS version, will return 0 on failure.  But
            // my WriteFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // On async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // written back from this call when using overlapped IO!  You must 
            // not pass in a non-null lpNumBytesWritten to WriteFile when using 
            // overlapped structures!  This is ByDesign NT behavior.
            if (r==-1 && numBytes!=-1) { 
                //Console.WriteLine("WriteFile returned 0;  Write will complete asynchronously (if hr==3e5)  hr: 0x{0:x}", hr);

                // For pipes, when they are closed on the other side, they will come here.
                if (hr == ERROR_NO_DATA) { 
                    // Not an error, but EOF.  AsyncFSCallback will NOT be
                    // called.  Call the user callback here. 
                    asyncResult.CallUserCallback(); 
                    // EndWrite will free the Overlapped struct correctly.
                } 
                else if (hr != ERROR_IO_PENDING) {
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current);
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else 
                        __Error.WinIOError(hr, String.Empty);
                } 
            }
            else {
                // Due to a workaround for a race condition in NT's ReadFile &
                // WriteFile routines, we will always be returning 0 from WriteFileNative 
                // when we do async IO instead of the number of bytes written,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not 
                // set asyncResult._numBytes here, since will never have correct
                // results. 
                //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on another thread.");
            }

            return asyncResult; 
        }
#endif //!FEATURE_PAL 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public unsafe override void EndWrite(IAsyncResult asyncResult) 
        {
            if (asyncResult==null)
                throw new ArgumentNullException("asyncResult");
            Contract.EndContractBlock(); 

#if !FEATURE_PAL && FEATURE_ASYNC_IO 
            if (!_isAsync) { 
                base.EndWrite(asyncResult);
                return; 
            }

            FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
            if (afsar==null || !afsar._isWrite) 
                __Error.WrongAsyncResult();
 
            // Ensure we can't get into any ----s by doing an interlocked 
            // CompareExchange here.  Avoids corrupting memory via freeing the
            // NativeOverlapped class or GCHandle twice.  -- 
            if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0))
                __Error.EndWriteCalledTwice();

            // Obtain the WaitHandle, but don't use public property in case we 
            // delay initialize the manual reset event in the future.
            WaitHandle wh = afsar._waitHandle; 
            if (wh != null) { 
                // We must block to ensure that AsyncFSCallback has completed,
                // and we should close the WaitHandle in here.  AsyncFSCallback 
                // and the hand-ported imitation version in COMThreadPool.cpp
                // are the only places that set this event.
                try {
                    wh.WaitOne(); 
                    Contract.Assert(afsar._isComplete == true, "FileStream::EndWrite - AsyncFSCallback didn't set _isComplete to true!");
                } 
                finally { 
                    wh.Close();
                } 
            }

            // Free memory & GC handles.
            NativeOverlapped* overlappedPtr = afsar._overlapped; 
            if (overlappedPtr != null)
                Overlapped.Free(overlappedPtr); 
 
            // Now check for any error during the write.
            if (afsar._errorCode != 0) 
                __Error.WinIOError(afsar._errorCode, String.Empty);

            // Number of bytes written is afsar._numBytes + afsar._numBufferedBytes.
            return; 
#else
            base.EndWrite(asyncResult); 
#endif // !FEATURE_PAL && FEATURE_ASYNC_IO 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public override void WriteByte(byte value)
        {
            if (_handle.IsClosed) __Error.FileNotOpen(); 
            if (_writePos==0) {
                if (!CanWrite) __Error.WriteNotSupported(); 
                if (_readPos < _readLen) FlushRead(); 
                _readPos = 0;
                _readLen = 0; 
                Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
                if (_buffer==null) _buffer = new byte[_bufferSize];
            }
            if (_writePos == _bufferSize) 
                FlushWrite(false);
 
            _buffer[_writePos] = value; 
            _writePos++;
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        public virtual void Lock(long position, long length) {
            if (position < 0 || length < 0) 
                throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock(); 
            if (_handle.IsClosed) __Error.FileNotOpen(); 

            int positionLow     = unchecked((int)(position      )); 
            int positionHigh    = unchecked((int)(position >> 32));
            int lengthLow       = unchecked((int)(length        ));
            int lengthHigh      = unchecked((int)(length   >> 32));
 
            if (!Win32Native.LockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
                __Error.WinIOError(); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public virtual void Unlock(long position, long length) {
            if (position < 0 || length < 0)
                throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock(); 
            if (_handle.IsClosed) __Error.FileNotOpen();
 
            int positionLow     = unchecked((int)(position      )); 
            int positionHigh    = unchecked((int)(position >> 32));
            int lengthLow       = unchecked((int)(length        )); 
            int lengthHigh      = unchecked((int)(length   >> 32));

            if (!Win32Native.UnlockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
                __Error.WinIOError(); 
        }
 
        // Windows API definitions, from winbase.h and others 

        private const int FILE_ATTRIBUTE_NORMAL = 0x00000080; 
        private const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
        private const int FILE_FLAG_OVERLAPPED = 0x40000000;
        internal const int GENERIC_READ = unchecked((int)0x80000000);
        private const int GENERIC_WRITE = 0x40000000; 

        private const int FILE_BEGIN = 0; 
        private const int FILE_CURRENT = 1; 
        private const int FILE_END = 2;
 
        // Error codes (not HRESULTS), from winerror.h
        private const int ERROR_BROKEN_PIPE = 109;
        private const int ERROR_NO_DATA = 232;
        private const int ERROR_HANDLE_EOF = 38; 
        private const int ERROR_INVALID_PARAMETER = 87;
        private const int ERROR_IO_PENDING = 997; 
 

        // __ConsoleStream also uses this code. 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr)
        {
            Contract.Requires(handle != null, "handle != null"); 
            Contract.Requires(offset >= 0, "offset >= 0");
            Contract.Requires(count >= 0, "count >= 0"); 
            Contract.Requires(bytes != null, "bytes != null"); 
            // Don't corrupt memory when multiple threads are erroneously writing
            // to this stream simultaneously. 
            if (bytes.Length - offset < count)
                throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
            Contract.EndContractBlock();
 
            Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter ----up in call to ReadFileNative.");
 
            // You can't use the fixed statement on an array of length 0. 
            if (bytes.Length==0) {
                hr = 0; 
                return 0;
            }

            int r = 0; 
            int numBytesRead = 0;
 
            fixed(byte* p = bytes) { 
                if (_isAsync)
                    r = Win32Native.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); 
                else
                    r = Win32Native.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero);
            }
 
            if (r==0) {
                hr = Marshal.GetLastWin32Error(); 
                // We should never silently ---- an error here without some 
                // extra work.  We must make sure that BeginReadCore won't return an
                // IAsyncResult that will cause EndRead to block, since the OS won't 
                // call AsyncFSCallback for us.
                if (hr == ERROR_BROKEN_PIPE || hr == Win32Native.ERROR_PIPE_NOT_CONNECTED) {
                    // This handle was a pipe, and it's done. Not an error, but EOF.
                    // However, the OS will not call AsyncFSCallback! 
                    // Let the caller handle this, since BeginReadCore & ReadCore
                    // need to do different things. 
                    return -1; 
                }
 
                // For invalid handles, detect the error and mark our handle
                // as closed to give slightly better error messages.  Also
                // help ensure we avoid handle recycling bugs.
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();
 
                return -1; 
            }
            else 
                hr = 0;
            return numBytesRead;
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) { 
            Contract.Requires(handle != null, "handle != null"); 
            Contract.Requires(offset >= 0, "offset >= 0");
            Contract.Requires(count >= 0, "count >= 0"); 
            Contract.Requires(bytes != null, "bytes != null");
            // Don't corrupt memory when multiple threads are erroneously writing
            // to this stream simultaneously.  (the OS is reading from
            // the array we pass to WriteFile, but if we read beyond the end and 
            // that memory isn't allocated, we could get an AV.)
            if (bytes.Length - offset < count) 
                throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition")); 
            Contract.EndContractBlock();
 
            Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter ----up in call to WriteFileNative.");

            // You can't use the fixed statement on an array of length 0.
            if (bytes.Length==0) { 
                hr = 0;
                return 0; 
            } 

            int numBytesWritten = 0; 
            int r = 0;

            fixed(byte* p = bytes) {
                if (_isAsync) 
                    r = Win32Native.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped);
                else 
                    r = Win32Native.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); 
            }
 
            if (r==0) {
                hr = Marshal.GetLastWin32Error();
                // We should never silently ---- an error here without some
                // extra work.  We must make sure that BeginWriteCore won't return an 
                // IAsyncResult that will cause EndWrite to block, since the OS won't
                // call AsyncFSCallback for us. 
 
                if (hr==ERROR_NO_DATA) {
                    // This handle was a pipe, and the pipe is being closed on the 
                    // other side.  Let the caller handle this, since BeginWriteCore
                    // & WriteCore need to do different things.
                    return -1;
                } 

                // For invalid handles, detect the error and mark our handle 
                // as closed to give slightly better error messages.  Also 
                // help ensure we avoid handle recycling bugs.
                if (hr == Win32Native.ERROR_INVALID_HANDLE) 
                    _handle.SetHandleAsInvalid();

                return -1;
            } 
            else
                hr = 0; 
            return numBytesWritten; 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

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