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); }
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); }