Esempio n. 1
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);
        }
Esempio n. 2
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 IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state)
        {
            CheckConnectOperationsServerWithHandle();

            if (!IsAsync)
            {
                throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
            }

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

            asyncResult._threadPoolBinding = _threadPoolBinding;
            asyncResult._userCallback      = callback;
            asyncResult._userStateObject   = state;

            IOCancellationHelper cancellationHelper = state as IOCancellationHelper;

            // Create wait handle and store in async result
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            asyncResult._waitHandle = waitHandle;

            NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped((errorCode, numBytes, pOverlapped) =>
            {
                // Unpack overlapped, free the pinned overlapped, and complete the operation
                PipeAsyncResult ar = (PipeAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);
                Debug.Assert(ar._overlapped == pOverlapped);
                ar._threadPoolBinding.FreeNativeOverlapped(pOverlapped);
                ar._overlapped = null;
                AsyncWaitForConnectionCallback(errorCode, numBytes, ar);
            }, asyncResult, null);

            asyncResult._overlapped = intOverlapped;

            if (!Interop.mincore.ConnectNamedPipe(InternalHandle, intOverlapped))
            {
                int errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Interop.mincore.Errors.ERROR_IO_PENDING)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
                    }
                    return(asyncResult);
                }

                // WaitForConnectionCallback will not be called because we completed synchronously.
                // Either the pipe is already connected, or there was an error. Unpin and free the overlapped again.
                _threadPoolBinding.FreeNativeOverlapped(intOverlapped);
                asyncResult._overlapped = null;

                // Did the client already connect to us?
                if (errorCode == Interop.mincore.Errors.ERROR_PIPE_CONNECTED)
                {
                    if (State == PipeState.Connected)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected);
                    }
                    asyncResult.CallUserCallback();
                    return(asyncResult);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }
            // will set state to Connected when EndWait is called
            if (cancellationHelper != null)
            {
                cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
            }

            return(asyncResult);
        }
        private unsafe void EndWaitForConnection(IAsyncResult asyncResult)
        {
            CheckConnectOperationsServerWithHandle();

            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }
            if (!IsAsync)
            {
                throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
            }

            PipeAsyncResult afsar = asyncResult as PipeAsyncResult;

            if (afsar == null)
            {
                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.GetEndWaitForConnectionCalledTwice();
            }

            IOCancellationHelper cancellationHelper = afsar.AsyncState as IOCancellationHelper;

            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 ConnectionIOCallback 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.
                using (wh)
                {
                    wh.WaitOne();
                    Debug.Assert(afsar._isComplete == true, "NamedPipeServerStream::EndWaitForConnection - AsyncFSCallback didn't set _isComplete to true!");
                }
            }

            // We should have freed the overlapped and set it to null either in the Begin
            // method (if ConnectNamedPipe completed synchronously) or in AsyncWaitForConnectionCallback.
            // If it is not nulled out, we should not be past the above wait:
            Debug.Assert(afsar._overlapped == null);

            // 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();
                    }
                }
                throw Win32Marshal.GetExceptionForWin32Error(afsar._errorCode);
            }

            // Success
            State = PipeState.Connected;
        }
        private unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state)
        {
            CheckConnectOperationsServerWithHandle();

            if (!IsAsync)
            {
                throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
            }

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

            asyncResult._handle          = InternalHandle;
            asyncResult._userCallback    = callback;
            asyncResult._userStateObject = state;

            IOCancellationHelper cancellationHelper = state as IOCancellationHelper;

            // Create wait handle and store in async result
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            asyncResult._waitHandle = waitHandle;

            // Create a managed overlapped class
            // We will 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_WaitForConnectionCallback, null);

            asyncResult._overlapped = intOverlapped;
            if (!Interop.mincore.ConnectNamedPipe(InternalHandle, intOverlapped))
            {
                int errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Interop.ERROR_IO_PENDING)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
                    }
                    return(asyncResult);
                }

                // WaitForConnectionCallback will not be called because we completed synchronously.
                // Either the pipe is already connected, or there was an error. Unpin and free the overlapped again.
                Overlapped.Free(intOverlapped);
                asyncResult._overlapped = null;

                // Did the client already connect to us?
                if (errorCode == Interop.ERROR_PIPE_CONNECTED)
                {
                    if (State == PipeState.Connected)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected);
                    }
                    asyncResult.CallUserCallback();
                    return(asyncResult);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }
            // will set state to Connected when EndWait is called
            if (cancellationHelper != null)
            {
                cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
            }

            return(asyncResult);
        }