internal void CallUserCallback() { if (_userCallback != null) { _completedSynchronously = false; ThreadPool.QueueUserWorkItem(s => { PipeAsyncResult ar = (PipeAsyncResult)s; ar._isComplete = true; if (ar._waitHandle != null) { ar._waitHandle.Set(); } ar._userCallback(ar); }, this); } else { _isComplete = true; if (_waitHandle != null) { _waitHandle.Set(); } } }
unsafe private static void AsyncWaitForConnectionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped) { // Unpack overlapped Overlapped overlapped = Overlapped.Unpack(pOverlapped); // Extract async result from overlapped PipeAsyncResult asyncResult = (PipeAsyncResult)overlapped.AsyncResult; // Free the pinned overlapped: Debug.Assert(asyncResult._overlapped == pOverlapped); Overlapped.Free(pOverlapped); asyncResult._overlapped = null; // Special case for when the client has already connected to us. if (errorCode == Interop.ERROR_PIPE_CONNECTED) { errorCode = 0; } asyncResult._errorCode = (int)errorCode; // Call the user-provided callback. It can and often should // call EndWaitForConnection. 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 userCallback = asyncResult._userCallback; if (userCallback != null) { userCallback(asyncResult); } }
public unsafe void EndWaitForConnection(IAsyncResult asyncResult) { this.CheckConnectOperationsServer(); if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!base.IsAsync) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_PipeNotAsync")); } PipeAsyncResult result = asyncResult as PipeAsyncResult; if (result == null) { System.IO.__Error.WrongAsyncResult(); } if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0)) { System.IO.__Error.EndWaitForConnectionCalledTwice(); } 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) { System.IO.__Error.WinIOError(result._errorCode, string.Empty); } base.State = PipeState.Connected; }
public unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, object state) { this.CheckConnectOperationsServer(); if (!base.IsAsync) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_PipeNotAsync")); } PipeAsyncResult ar = new PipeAsyncResult { _handle = base.InternalHandle, _userCallback = callback, _userStateObject = state }; ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped *overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(WaitForConnectionCallback, null); ar._overlapped = overlapped; if (!Microsoft.Win32.UnsafeNativeMethods.ConnectNamedPipe(base.InternalHandle, overlapped)) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0x217) { overlapped->InternalLow = IntPtr.Zero; if (base.State == PipeState.Connected) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_PipeAlreadyConnected")); } ar.CallUserCallback(); return(ar); } if (errorCode != 0x3e5) { System.IO.__Error.WinIOError(errorCode, string.Empty); } } return(ar); }
private static unsafe void AsyncWaitForConnectionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped) { PipeAsyncResult asyncResult = (PipeAsyncResult)Overlapped.Unpack(pOverlapped).AsyncResult; if (errorCode == 0x217) { errorCode = 0; } 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); } }
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._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); }
public unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state) { CheckConnectOperationsServer(); if (!IsAsync) { throw new InvalidOperationException(SR.GetString(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(0, 0, IntPtr.Zero, asyncResult); // Pack the Overlapped class, and store it in the async result NativeOverlapped* intOverlapped = overlapped.Pack(WaitForConnectionCallback, null); asyncResult._overlapped = intOverlapped; if (!UnsafeNativeMethods.ConnectNamedPipe(InternalHandle, intOverlapped)) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == UnsafeNativeMethods.ERROR_IO_PENDING) { if (cancellationHelper != null) { cancellationHelper.AllowCancellation(InternalHandle, intOverlapped); } return asyncResult; } // WaitForConnectionCallback will not be called becasue 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 == UnsafeNativeMethods.ERROR_PIPE_CONNECTED) { if (State == PipeState.Connected) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected)); } asyncResult.CallUserCallback(); return asyncResult; } __Error.WinIOError(errorCode, String.Empty); } // will set state to Connected when EndWait is called if (cancellationHelper != null) { cancellationHelper.AllowCancellation(InternalHandle, intOverlapped); } return asyncResult; }
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); }
public unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, object state) { this.CheckConnectOperationsServer(); if (!base.IsAsync) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_PipeNotAsync")); } PipeAsyncResult ar = new PipeAsyncResult { _handle = base.InternalHandle, _userCallback = callback, _userStateObject = state }; ManualResetEvent event2 = new ManualResetEvent(false); ar._waitHandle = event2; NativeOverlapped* overlapped = new Overlapped(0, 0, IntPtr.Zero, ar).Pack(WaitForConnectionCallback, null); ar._overlapped = overlapped; if (!Microsoft.Win32.UnsafeNativeMethods.ConnectNamedPipe(base.InternalHandle, overlapped)) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0x217) { overlapped->InternalLow = IntPtr.Zero; if (base.State == PipeState.Connected) { throw new InvalidOperationException(System.SR.GetString("InvalidOperation_PipeAlreadyConnected")); } ar.CallUserCallback(); return ar; } if (errorCode != 0x3e5) { System.IO.__Error.WinIOError(errorCode, string.Empty); } } return ar; }
unsafe private static void AsyncWaitForConnectionCallback(uint errorCode, uint numBytes, PipeAsyncResult asyncResult) { // Special case for when the client has already connected to us. if (errorCode == Interop.mincore.Errors.ERROR_PIPE_CONNECTED) { errorCode = 0; } asyncResult._errorCode = (int)errorCode; // Call the user-provided callback. It can and often should // call EndWaitForConnection. 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 userCallback = asyncResult._userCallback; if (userCallback != null) { userCallback(asyncResult); } }
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; }