Example #1
0
        private static unsafe void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
        {
            PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)Overlapped.Unpack(pOverlapped).AsyncResult;

            asyncResult._numBytes = (int)numBytes;
            if (!asyncResult._isWrite && (((errorCode == 0x6d) || (errorCode == 0xe9)) || (errorCode == 0xe8)))
            {
                errorCode = 0;
                numBytes  = 0;
            }
            if (errorCode == 0xea)
            {
                errorCode = 0;
                asyncResult._isMessageComplete = false;
            }
            else
            {
                asyncResult._isMessageComplete = true;
            }
            asyncResult._errorCode = (int)errorCode;
            asyncResult._completedSynchronously = false;
            asyncResult._isComplete             = true;
            ManualResetEvent event2 = asyncResult._waitHandle;

            if ((event2 != null) && !event2.Set())
            {
                System.IO.__Error.WinIOError();
            }
            AsyncCallback callback = asyncResult._userCallback;

            if (callback != null)
            {
                callback(asyncResult);
            }
        }
Example #2
0
        private unsafe PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            PipeStreamAsyncResult ar = new PipeStreamAsyncResult {
                _userCallback    = callback,
                _userStateObject = state,
                _isWrite         = true,
                _handle          = this.m_handle
            };

            if (buffer.Length == 0)
            {
                ar.CallUserCallback();
                return(ar);
            }
            ManualResetEvent event2 = new ManualResetEvent(false);

            ar._waitHandle = event2;
            NativeOverlapped *overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer);

            ar._overlapped = overlapped;
            int hr = 0;

            if ((this.WriteFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) && (hr != 0x3e5))
            {
                if (overlapped != null)
                {
                    Overlapped.Free(overlapped);
                }
                this.WinIOError(hr);
            }
            return(ar);
        }
 internal void CallUserCallback()
 {
     if (_userCallback != null)
     {
         _completedSynchronously = false;
         ThreadPool.QueueUserWorkItem(s =>
         {
             PipeStreamAsyncResult ar = (PipeStreamAsyncResult)s;
             ar._isComplete           = true;
             if (ar._waitHandle != null)
             {
                 ar._waitHandle.Set();
             }
             ar._userCallback(ar);
         }, this);
     }
     else
     {
         _isComplete = true;
         if (_waitHandle != null)
         {
             _waitHandle.Set();
         }
     }
 }
Example #4
0
        private IAsyncResult BeginRead(AsyncCallback callback, Object state)
        {
            ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;

            Debug.Assert(readWriteParams != null);
            byte[] buffer = readWriteParams.Buffer;
            int    offset = readWriteParams.Offset;
            int    count  = readWriteParams.Count;

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", SR.ArgumentNull_Buffer);
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", SR.ArgumentOutOfRange_NeedNonNegNum);
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
            }
            if (buffer.Length - offset < count)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }
            if (!CanRead)
            {
                throw __Error.GetReadNotSupported();
            }
            CheckReadOperations();

            if (!_isAsync)
            {
                // special case when this is called for sync broken pipes because otherwise Stream's
                // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's
                // callback immediately
                if (_state == PipeState.Broken)
                {
                    PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();
                    asyncResult._handle          = _handle;
                    asyncResult._userCallback    = callback;
                    asyncResult._userStateObject = state;
                    asyncResult._isWrite         = false;
                    asyncResult.CallUserCallback();
                    return(asyncResult);
                }
                else
                {
                    return(_streamAsyncHelper.BeginRead(buffer, offset, count, callback, state));
                }
            }
            else
            {
                return(BeginReadCore(buffer, offset, count, callback, state));
            }
        }
Example #5
0
        public override unsafe int EndRead(IAsyncResult asyncResult)
        {
            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }
            if (!this.m_isAsync)
            {
                return(base.EndRead(asyncResult));
            }
            PipeStreamAsyncResult result = asyncResult as PipeStreamAsyncResult;

            if ((result == null) || result._isWrite)
            {
                System.IO.__Error.WrongAsyncResult();
            }
            if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0))
            {
                System.IO.__Error.EndReadCalledTwice();
            }
            WaitHandle handle = result._waitHandle;

            if (handle != null)
            {
                try
                {
                    handle.WaitOne();
                }
                finally
                {
                    handle.Close();
                }
            }
            NativeOverlapped *nativeOverlappedPtr = result._overlapped;

            if (nativeOverlappedPtr != null)
            {
                Overlapped.Free(nativeOverlappedPtr);
            }
            if (result._errorCode != 0)
            {
                this.WinIOError(result._errorCode);
            }
            this.m_isMessageComplete = (this.m_state == PipeState.Broken) || result._isMessageComplete;
            return(result._numBytes);
        }
Example #6
0
 public override unsafe void EndWrite(IAsyncResult asyncResult)
 {
     if (asyncResult == null)
     {
         throw new ArgumentNullException("asyncResult");
     }
     if (!this.m_isAsync)
     {
         base.EndWrite(asyncResult);
     }
     else
     {
         PipeStreamAsyncResult result = asyncResult as PipeStreamAsyncResult;
         if ((result == null) || !result._isWrite)
         {
             System.IO.__Error.WrongAsyncResult();
         }
         if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0))
         {
             System.IO.__Error.EndWriteCalledTwice();
         }
         WaitHandle handle = result._waitHandle;
         if (handle != null)
         {
             try
             {
                 handle.WaitOne();
             }
             finally
             {
                 handle.Close();
             }
         }
         NativeOverlapped *nativeOverlappedPtr = result._overlapped;
         if (nativeOverlappedPtr != null)
         {
             Overlapped.Free(nativeOverlappedPtr);
         }
         if (result._errorCode != 0)
         {
             this.WinIOError(result._errorCode);
         }
     }
 }
Example #7
0
 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 {
     if (buffer == null)
     {
         throw new ArgumentNullException("buffer", System.SR.GetString("ArgumentNull_Buffer"));
     }
     if (offset < 0)
     {
         throw new ArgumentOutOfRangeException("offset", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum"));
     }
     if (count < 0)
     {
         throw new ArgumentOutOfRangeException("count", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum"));
     }
     if ((buffer.Length - offset) < count)
     {
         throw new ArgumentException(System.SR.GetString("Argument_InvalidOffLen"));
     }
     if (!this.CanRead)
     {
         System.IO.__Error.ReadNotSupported();
     }
     this.CheckReadOperations();
     if (this.m_isAsync)
     {
         return(this.BeginReadCore(buffer, offset, count, callback, state));
     }
     if (this.m_state == PipeState.Broken)
     {
         PipeStreamAsyncResult result = new PipeStreamAsyncResult {
             _handle          = this.m_handle,
             _userCallback    = callback,
             _userStateObject = state,
             _isWrite         = false
         };
         result.CallUserCallback();
         return(result);
     }
     return(base.BeginRead(buffer, offset, count, callback, state));
 }
Example #8
0
        private unsafe PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            PipeStreamAsyncResult ar = new PipeStreamAsyncResult {
                _handle          = this.m_handle,
                _userCallback    = callback,
                _userStateObject = state,
                _isWrite         = false
            };

            if (buffer.Length == 0)
            {
                ar.CallUserCallback();
                return(ar);
            }
            ManualResetEvent event2 = new ManualResetEvent(false);

            ar._waitHandle = event2;
            NativeOverlapped *overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer);

            ar._overlapped = overlapped;
            int hr = 0;

            if (this.ReadFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1)
            {
                if ((hr == 0x6d) || (hr == 0xe9))
                {
                    this.State = PipeState.Broken;
                    overlapped->InternalLow = IntPtr.Zero;
                    ar.CallUserCallback();
                    return(ar);
                }
                if (hr != 0x3e5)
                {
                    System.IO.__Error.WinIOError(hr, string.Empty);
                }
            }
            return(ar);
        }
Example #9
0
        unsafe private PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count,
                                                           AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanRead, "can't read");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

            // Create and store async stream class library specific data in the async result
            PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();

            asyncResult._handle          = _handle;
            asyncResult._userCallback    = callback;
            asyncResult._userStateObject = state;
            asyncResult._isWrite         = false;

            // handle zero-length buffers separately; fixed keyword ReadFileNative doesn't like
            // 0-length buffers. Call user callback and we're done
            if (buffer.Length == 0)
            {
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback and using
                // the managed Monitor class, or I could create a handle and wait on it.
                ManualResetEvent waitHandle = new ManualResetEvent(false);
                asyncResult._waitHandle = waitHandle;

                NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped(s_IOCallback, asyncResult, buffer);
                asyncResult._overlapped = intOverlapped;

                // Queue an async ReadFile operation and pass in a packed overlapped
                int errorCode = 0;
                int r         = ReadFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper
                // returns -1. This 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 buffer 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)
                {
                    // One side has closed its handle or server disconnected. Set the state to Broken
                    // and do some cleanup work
                    if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE ||
                        errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED)
                    {
                        State = PipeState.Broken;

                        // Clear the overlapped status bit for this special case. Failure to do so looks
                        // like we are freeing a pending overlapped.
                        intOverlapped->InternalLow = IntPtr.Zero;

                        // EndRead will free the Overlapped struct
                        asyncResult.CallUserCallback();
                    }
                    else if (errorCode != Interop.mincore.Errors.ERROR_IO_PENDING)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                    }
                }
                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }
            return(asyncResult);
        }
Example #10
0
        private unsafe void EndWrite(IAsyncResult asyncResult)
        {
            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }

            if (!_isAsync)
            {
                _streamAsyncHelper.EndWrite(asyncResult);
                return;
            }

            PipeStreamAsyncResult afsar = asyncResult as PipeStreamAsyncResult;

            if (afsar == null || !afsar._isWrite)
            {
                throw __Error.GetWrongAsyncResult();
            }

            // Ensure we can't get into any races 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))
            {
                throw __Error.GetEndWriteCalledTwice();
            }

            ReadWriteAsyncParams readWriteParams    = afsar.AsyncState as ReadWriteAsyncParams;
            IOCancellationHelper cancellationHelper = null;

            if (readWriteParams != null)
            {
                cancellationHelper = readWriteParams.CancellationHelper;
                if (cancellationHelper != null)
                {
                    cancellationHelper.SetOperationCompleted();
                }
            }

            // 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 AsyncPSCallback has completed,
                // and we should close the WaitHandle in here.  AsyncPSCallback
                // and the hand-ported imitation version in COMThreadPool.cpp
                // are the only places that set this event.
                using (wh)
                {
                    wh.WaitOne();
                    Debug.Assert(afsar._isComplete == true, "PipeStream::EndWrite - AsyncPSCallback didn't set _isComplete to true!");
                }
            }

            // Free memory & GC handles.
            NativeOverlapped *overlappedPtr = afsar._overlapped;

            if (overlappedPtr != null)
            {
                _threadPoolBinding.FreeNativeOverlapped(overlappedPtr);
            }

            // Now check for any error during the write.
            if (afsar._errorCode != 0)
            {
                if (afsar._errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.ThrowIOOperationAborted();
                    }
                }
                WinIOError(afsar._errorCode);
            }

            // Number of buffer written is afsar._numBytes.
            return;
        }
 private unsafe PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 {
     PipeStreamAsyncResult ar = new PipeStreamAsyncResult {
         _handle = this.m_handle,
         _userCallback = callback,
         _userStateObject = state,
         _isWrite = false
     };
     if (buffer.Length == 0)
     {
         ar.CallUserCallback();
         return ar;
     }
     ManualResetEvent event2 = new ManualResetEvent(false);
     ar._waitHandle = event2;
     NativeOverlapped* overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer);
     ar._overlapped = overlapped;
     int hr = 0;
     if (this.ReadFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1)
     {
         if ((hr == 0x6d) || (hr == 0xe9))
         {
             this.State = PipeState.Broken;
             overlapped->InternalLow = IntPtr.Zero;
             ar.CallUserCallback();
             return ar;
         }
         if (hr != 0x3e5)
         {
             System.IO.__Error.WinIOError(hr, string.Empty);
         }
     }
     return ar;
 }
        private IAsyncResult BeginRead(AsyncCallback callback, Object state)
        {
            ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
            Debug.Assert(readWriteParams != null);
            byte[] buffer = readWriteParams.Buffer;
            int offset = readWriteParams.Offset;
            int count = readWriteParams.Count;

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", SR.ArgumentNull_Buffer);
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", SR.ArgumentOutOfRange_NeedNonNegNum);
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
            }
            if (buffer.Length - offset < count)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }
            if (!CanRead)
            {
                throw __Error.GetReadNotSupported();
            }
            CheckReadOperations();

            if (!_isAsync)
            {
                // special case when this is called for sync broken pipes because otherwise Stream's
                // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's
                // callback immediately
                if (_state == PipeState.Broken)
                {
                    PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();
                    asyncResult._handle = _handle;
                    asyncResult._userCallback = callback;
                    asyncResult._userStateObject = state;
                    asyncResult._isWrite = false;
                    asyncResult.CallUserCallback();
                    return asyncResult;
                }
                else
                {
                    return _streamAsyncHelper.BeginRead(buffer, offset, count, callback, state);
                }
            }
            else
            {
                return BeginReadCore(buffer, offset, count, callback, state);
            }
        }
Example #13
0
        unsafe private PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count,
                                                            AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanWrite, "can't write");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

            // Create and store async stream class library specific data in the async result
            PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();

            asyncResult._userCallback    = callback;
            asyncResult._userStateObject = state;
            asyncResult._isWrite         = true;
            asyncResult._handle          = _handle;

            // fixed doesn't work well with zero length arrays. Set the zero-byte flag in case
            // caller needs to do any cleanup
            if (buffer.Length == 0)
            {
                //intOverlapped->InternalLow = IntPtr.Zero;

                // EndRead will free the Overlapped struct
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback and using the managed
                // Monitor class, or I could create a handle and wait on it.
                ManualResetEvent waitHandle = new ManualResetEvent(false);
                asyncResult._waitHandle = waitHandle;

                NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped(s_IOCallback, asyncResult, buffer);
                asyncResult._overlapped = intOverlapped;

                int errorCode = 0;

                // Queue an async WriteFile operation and pass in a packed overlapped
                int r = WriteFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // WriteFile, the OS version, will return 0 on failure, but this WriteFileNative
                // wrapper returns -1. This 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 buffer written back from this
                // call when using overlapped structures!  You must not pass in a non-null
                // lpNumBytesWritten to WriteFile when using overlapped structures!  This is by design
                // NT behavior.
                if (r == -1 && errorCode != Interop.mincore.Errors.ERROR_IO_PENDING)
                {
                    // Clean up
                    if (intOverlapped != null)
                    {
                        _threadPoolBinding.FreeNativeOverlapped(intOverlapped);
                    }
                    WinIOError(errorCode);
                }

                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }

            return(asyncResult);
        }
        unsafe private PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count,
                AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanWrite, "can't write");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

            // Create and store async stream class library specific data in the async result
            PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();
            asyncResult._userCallback = callback;
            asyncResult._userStateObject = state;
            asyncResult._isWrite = true;
            asyncResult._handle = _handle;

            // fixed doesn't work well with zero length arrays. Set the zero-byte flag in case
            // caller needs to do any cleanup
            if (buffer.Length == 0)
            {
                //intOverlapped->InternalLow = IntPtr.Zero;

                // EndRead will free the Overlapped struct
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback 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; set the file offsets later
                Overlapped overlapped = new Overlapped();
                overlapped.OffsetLow = 0;
                overlapped.OffsetHigh = 0;
                overlapped.AsyncResult = asyncResult;

                // Pack the Overlapped class, and store it in the async result
                NativeOverlapped* intOverlapped = overlapped.Pack(s_IOCallback, buffer);
                asyncResult._overlapped = intOverlapped;

                int errorCode = 0;

                // Queue an async WriteFile operation and pass in a packed overlapped
                int r = WriteFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // WriteFile, the OS version, will return 0 on failure, but this WriteFileNative 
                // wrapper returns -1. This 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 buffer written back from this 
                // call when using overlapped structures!  You must not pass in a non-null 
                // lpNumBytesWritten to WriteFile when using overlapped structures!  This is by design 
                // NT behavior.
                if (r == -1 && errorCode != Interop.ERROR_IO_PENDING)
                {
                    // Clean up
                    if (intOverlapped != null) Overlapped.Free(intOverlapped);
                    WinIOError(errorCode);
                }

                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }

            return asyncResult;
        }
        unsafe private PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count,
                AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanRead, "can't read");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

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

            // handle zero-length buffers separately; fixed keyword ReadFileNative doesn't like
            // 0-length buffers. Call user callback and we're done
            if (buffer.Length == 0)
            {
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback 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; set the file offsets later
                Overlapped overlapped = new Overlapped();
                overlapped.OffsetLow = 0;
                overlapped.OffsetHigh = 0;
                overlapped.AsyncResult = asyncResult;

                // Pack the Overlapped class, and store it in the async result
                NativeOverlapped* intOverlapped;
                intOverlapped = overlapped.Pack(s_IOCallback, buffer);


                asyncResult._overlapped = intOverlapped;

                // Queue an async ReadFile operation and pass in a packed overlapped
                int errorCode = 0;
                int r = ReadFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper
                // returns -1. This 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 buffer 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)
                {
                    // One side has closed its handle or server disconnected. Set the state to Broken 
                    // and do some cleanup work
                    if (errorCode == Interop.ERROR_BROKEN_PIPE ||
                        errorCode == Interop.ERROR_PIPE_NOT_CONNECTED)
                    {
                        State = PipeState.Broken;

                        // Clear the overlapped status bit for this special case. Failure to do so looks 
                        // like we are freeing a pending overlapped.
                        intOverlapped->InternalLow = IntPtr.Zero;

                        // EndRead will free the Overlapped struct
                        asyncResult.CallUserCallback();
                    }
                    else if (errorCode != Interop.ERROR_IO_PENDING)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                    }
                }
                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }
            return asyncResult;
        }
 private unsafe PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 {
     PipeStreamAsyncResult ar = new PipeStreamAsyncResult {
         _userCallback = callback,
         _userStateObject = state,
         _isWrite = true,
         _handle = this.m_handle
     };
     if (buffer.Length == 0)
     {
         ar.CallUserCallback();
         return ar;
     }
     ManualResetEvent event2 = new ManualResetEvent(false);
     ar._waitHandle = event2;
     NativeOverlapped* overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(IOCallback, buffer);
     ar._overlapped = overlapped;
     int hr = 0;
     if ((this.WriteFileNative(this.m_handle, buffer, offset, count, overlapped, out hr) == -1) && (hr != 0x3e5))
     {
         if (overlapped != null)
         {
             Overlapped.Free(overlapped);
         }
         this.WinIOError(hr);
     }
     return ar;
 }
Example #17
0
        private unsafe 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 PipeStreamAsyncResult.  One is from BeginReadCore,
            // while the other is from the BeginRead buffering wrapper.
            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }
            if (!_isAsync)
            {
                return(_streamAsyncHelper.EndRead(asyncResult));
            }

            PipeStreamAsyncResult afsar = asyncResult as PipeStreamAsyncResult;

            if (afsar == null || afsar._isWrite)
            {
                throw __Error.GetWrongAsyncResult();
            }

            // Ensure we can't get into any races 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))
            {
                throw __Error.GetEndReadCalledTwice();
            }

            ReadWriteAsyncParams readWriteParams    = asyncResult.AsyncState as ReadWriteAsyncParams;
            IOCancellationHelper cancellationHelper = null;

            if (readWriteParams != null)
            {
                cancellationHelper = readWriteParams.CancellationHelper;
                if (cancellationHelper != null)
                {
                    readWriteParams.CancellationHelper.SetOperationCompleted();
                }
            }

            // 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 AsyncPSCallback has completed,
                // and we should close the WaitHandle in here.  AsyncPSCallback
                // and the hand-ported imitation version in COMThreadPool.cpp
                // are the only places that set this event.
                using (wh)
                {
                    wh.WaitOne();
                    Debug.Assert(afsar._isComplete == true,
                                 "FileStream::EndRead - AsyncPSCallback didn't set _isComplete to true!");
                }
            }

            // Free memory & GC handles.
            NativeOverlapped *overlappedPtr = afsar._overlapped;

            if (overlappedPtr != null)
            {
                _threadPoolBinding.FreeNativeOverlapped(overlappedPtr);
            }

            // Now check for any error during the read.
            if (afsar._errorCode != 0)
            {
                if (afsar._errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.ThrowIOOperationAborted();
                    }
                }
                WinIOError(afsar._errorCode);
            }

            // set message complete to true if the pipe is broken as well; need this to signal to readers
            // to stop reading
            _isMessageComplete = _state == PipeState.Broken ||
                                 afsar._isMessageComplete;

            return(afsar._numBytes);
        }
 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 {
     if (buffer == null)
     {
         throw new ArgumentNullException("buffer", System.SR.GetString("ArgumentNull_Buffer"));
     }
     if (offset < 0)
     {
         throw new ArgumentOutOfRangeException("offset", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum"));
     }
     if (count < 0)
     {
         throw new ArgumentOutOfRangeException("count", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum"));
     }
     if ((buffer.Length - offset) < count)
     {
         throw new ArgumentException(System.SR.GetString("Argument_InvalidOffLen"));
     }
     if (!this.CanRead)
     {
         System.IO.__Error.ReadNotSupported();
     }
     this.CheckReadOperations();
     if (this.m_isAsync)
     {
         return this.BeginReadCore(buffer, offset, count, callback, state);
     }
     if (this.m_state == PipeState.Broken)
     {
         PipeStreamAsyncResult result = new PipeStreamAsyncResult {
             _handle = this.m_handle,
             _userCallback = callback,
             _userStateObject = state,
             _isWrite = false
         };
         result.CallUserCallback();
         return result;
     }
     return base.BeginRead(buffer, offset, count, callback, state);
 }
Example #19
0
        unsafe private static void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
        {
            // Extract async result from overlapped
            PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);

            asyncResult._numBytes = (int)numBytes;

            // Allow async read to finish
            if (!asyncResult._isWrite)
            {
                if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE ||
                    errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED ||
                    errorCode == Interop.mincore.Errors.ERROR_NO_DATA)
                {
                    errorCode = 0;
                    numBytes  = 0;
                }
            }

            // For message type buffer.
            if (errorCode == Interop.mincore.Errors.ERROR_MORE_DATA)
            {
                errorCode = 0;
                asyncResult._isMessageComplete = false;
            }
            else
            {
                asyncResult._isMessageComplete = true;
            }

            asyncResult._errorCode = (int)errorCode;

            // 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;

            // The OS does not signal this event.  We must do it ourselves.
            ManualResetEvent wh = asyncResult._waitHandle;

            if (wh != null)
            {
                Debug.Assert(!wh.GetSafeWaitHandle().IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set();
                Debug.Assert(r, "ManualResetEvent::Set failed!");
                if (!r)
                {
                    throw Win32Marshal.GetExceptionForLastWin32Error();
                }
            }

            AsyncCallback callback = asyncResult._userCallback;

            if (callback != null)
            {
                callback(asyncResult);
            }
        }
Example #20
0
        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) {
            if (buffer == null) {
                throw new ArgumentNullException("buffer", SR.GetString(SR.ArgumentNull_Buffer));
            }
            if (offset < 0) {
                throw new ArgumentOutOfRangeException("offset", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum));
            }
            if (count < 0) {
                throw new ArgumentOutOfRangeException("count", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum));
            }
            if (buffer.Length - offset < count) {
                throw new ArgumentException(SR.GetString(SR.Argument_InvalidOffLen));
            }
            if (!CanRead) {
                __Error.ReadNotSupported();
            }
            CheckReadOperations();

            if (!m_isAsync) {
                // special case when this is called for sync broken pipes because otherwise Stream's
                // Begin/EndRead hang. Reads return 0 bytes in this case so we can call the user's
                // callback immediately
                if (m_state == PipeState.Broken) {
                    PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();
                    asyncResult._handle = m_handle;
                    asyncResult._userCallback = callback;
                    asyncResult._userStateObject = state;
                    asyncResult._isWrite = false;
                    asyncResult.CallUserCallback();
                    return asyncResult;
                }
                else {
                    return base.BeginRead(buffer, offset, count, callback, state);
                }
            }
            else {
                return BeginReadCore(buffer, offset, count, callback, state);
            }
        }