[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void AllocateNativeOverlapped_PreAllocated_ReusedReturnedNativeOverlapped_OffsetLowAndOffsetHighSetToZero(bool useUnsafe) { // The CLR reuses NativeOverlapped underneath, check to make sure that they reset fields back to zero using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { PreAllocatedOverlapped preAlloc = useUnsafe ? PreAllocatedOverlapped.UnsafeCreate((_, __, ___) => { }, new object(), new byte[256]) : new PreAllocatedOverlapped((_, __, ___) => { }, new object(), new byte[256]); NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc); overlapped->OffsetHigh = 1; overlapped->OffsetLow = 1; handle.FreeNativeOverlapped(overlapped); overlapped = handle.AllocateNativeOverlapped(preAlloc); Assert.Equal(IntPtr.Zero, overlapped->InternalLow); Assert.Equal(IntPtr.Zero, overlapped->InternalHigh); Assert.Equal(0, overlapped->OffsetLow); Assert.Equal(0, overlapped->OffsetHigh); Assert.Equal(IntPtr.Zero, overlapped->EventHandle); handle.FreeNativeOverlapped(overlapped); } }
private Interop.HttpApi.HTTP_REQUEST *Allocate(ThreadPoolBoundHandle boundHandle, uint size) { uint newSize = size != 0 ? size : RequestBuffer == null ? 4096 : Size; if (_nativeOverlapped != null) { #if DEBUG DebugRefCountReleaseNativeOverlapped(); #endif NativeOverlapped *nativeOverlapped = _nativeOverlapped; _nativeOverlapped = null; _boundHandle.FreeNativeOverlapped(nativeOverlapped); } if (_nativeOverlapped == null) { #if DEBUG DebugRefCountAllocNativeOverlapped(); #endif SetBuffer(checked ((int)newSize)); _boundHandle = boundHandle; _nativeOverlapped = boundHandle.AllocateNativeOverlapped(ListenerAsyncResult.IOCallback, state: _result, pinData: RequestBuffer); return((Interop.HttpApi.HTTP_REQUEST *)Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0)); } return(RequestBlob); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void MultipleOperationsOverSingleHandle() { const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverSingleHandle.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext result1 = new OverlappedContext(); OverlappedContext result2 = new OverlappedContext(); byte[] data1 = new byte[DATA_SIZE]; data1[0] = (byte)'A'; data1[1] = (byte)'B'; byte[] data2 = new byte[DATA_SIZE]; data2[0] = (byte)'C'; data2[1] = (byte)'D'; NativeOverlapped *overlapped1 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result1, data1); NativeOverlapped *overlapped2 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result2, data2); fixed(byte *p1 = data1, p2 = data2) { int retval = DllImport.WriteFile(boundHandle.Handle, p1, DATA_SIZE, IntPtr.Zero, overlapped1); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Start the offset after the above write, so that it doesn't overwrite the previous write overlapped2->OffsetLow = DATA_SIZE; retval = DllImport.WriteFile(boundHandle.Handle, p2, DATA_SIZE, IntPtr.Zero, overlapped2); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operations to complete WaitHandle.WaitAll(new WaitHandle[] { result1.Event, result2.Event }); } boundHandle.FreeNativeOverlapped(overlapped1); boundHandle.FreeNativeOverlapped(overlapped2); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(0, result1.ErrorCode); Assert.Equal(0, result2.ErrorCode); Assert.Equal(DATA_SIZE, result1.BytesWritten); Assert.Equal(DATA_SIZE, result2.BytesWritten); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void AllocateNativeOverlapped_NullAsContext_DoesNotThrow() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[256]); Assert.True(result != null); handle.FreeNativeOverlapped(result); result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[256]); Assert.True(result != null); handle.FreeNativeOverlapped(result); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void AllocateNativeOverlapped_EmptyArrayAsPinData_DoesNotThrow() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[0]); Assert.True(result != null); handle.FreeNativeOverlapped(result); result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[0]); Assert.True(result != null); handle.FreeNativeOverlapped(result); } }
public void Complete(Exception exception, int transferred) { Debug.Assert(_overlapped != null); RegisteredSocket socket = _socket; _socket = null; _buffersHandle.Free(); _boundHandle.FreeNativeOverlapped(_overlapped); _boundHandle = null; _overlapped = null; _thisRef.Value = null; if (exception == null) { _valueTaskSource.SetResult(transferred); } else { _valueTaskSource.SetException(exception); } Interlocked.Exchange(ref _isSend ? ref socket._cachedSendArgs : ref socket._cachedRecvArgs, this); }
private void FreeNativeOverlapped() { IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero); // Do not call free during AppDomain shutdown, there may be an outstanding operation. // Overlapped will take care calling free when the native callback completes. if (oldHandle != IntPtr.Zero && !Environment.HasShutdownStarted) { unsafe { Debug.Assert(_safeCloseSocket != null, "m_SafeCloseSocket is null."); ThreadPoolBoundHandle boundHandle = _safeCloseSocket.IOCPBoundHandle; Debug.Assert(boundHandle != null, "SafeNativeOverlapped::ImmediatelyFreeNativeOverlapped - boundHandle is null"); if (boundHandle != null) { // FreeNativeOverlapped will be called even if boundHandle was previously disposed. boundHandle.FreeNativeOverlapped((NativeOverlapped *)oldHandle); } #if DEBUG _safeCloseSocket.Release(); #endif _safeCloseSocket = null; } } return; }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void SingleOperationOverSingleHandle() { const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"SingleOverlappedOverSingleHandle.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext result = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; data[0] = (byte)'A'; data[1] = (byte)'B'; NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result, data); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operation to complete result.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(0, result.ErrorCode); Assert.Equal(DATA_SIZE, result.BytesWritten); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FreeNativeOverlapped_WhenDisposed_DoesNotThrow() { ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle(); NativeOverlapped * overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]); boundHandle.Dispose(); boundHandle.FreeNativeOverlapped(overlapped); }
// Will be called from the base class upon InvokeCallback() protected override void Cleanup() { base.Cleanup(); if (_pOverlapped != null) { _boundHandle.FreeNativeOverlapped(_pOverlapped); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FreeNativeOverlapped_NullAsNativeOverlapped_ThrowsArgumentNullException() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { AssertExtensions.Throws <ArgumentNullException>("overlapped", () => { handle.FreeNativeOverlapped((NativeOverlapped *)null); }); } }
public unsafe void AllocateNativeOverlapped_PossibleReusedReturnedNativeOverlapped_OffsetLowAndOffsetHighSetToZero() { // The CLR reuses NativeOverlapped underneath, check to make sure that they reset fields back to zero using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]); overlapped->OffsetHigh = 1; overlapped->OffsetLow = 1; handle.FreeNativeOverlapped(overlapped); overlapped = handle.AllocateNativeOverlapped((errorCode, numBytes, overlap) => { }, new object(), new byte[256]); Assert.Equal(IntPtr.Zero, overlapped->InternalLow); Assert.Equal(IntPtr.Zero, overlapped->InternalHigh); Assert.Equal(0, overlapped->OffsetLow); Assert.Equal(0, overlapped->OffsetHigh); Assert.Equal(IntPtr.Zero, overlapped->EventHandle); handle.FreeNativeOverlapped(overlapped); } }
internal void ReleaseResources() { _cancellationRegistration.Dispose(); // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory // (this is why we disposed the registration above) if (Overlapped != null) { _threadPoolBinding.FreeNativeOverlapped(Overlapped); _overlapped = null; } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FlowsAsyncLocalsToCallback_PreAllocatedOverlapped(bool shouldFlow) { // Makes sure that we flow async locals to callback const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"AsyncLocal.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext context = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; AsyncLocal <int> asyncLocal = new AsyncLocal <int>(); asyncLocal.Value = 10; int?result = null; IOCompletionCallback callback = (_, __, ___) => { result = asyncLocal.Value; OnOverlappedOperationCompleted(_, __, ___); }; using (PreAllocatedOverlapped preAlloc = shouldFlow ? new PreAllocatedOverlapped(callback, context, data) : PreAllocatedOverlapped.UnsafeCreate(callback, context, data)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(preAlloc); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastPInvokeError()); } // Wait for overlapped operation to complete context.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); } boundHandle.Dispose(); handle.Dispose(); Assert.Equal( shouldFlow ? 10 : 0, result); }
internal void Reset(uint size) { if (size == _size) { return; } if (_size != 0) { _boundHandle.FreeNativeOverlapped(_pOverlapped); } _size = size; if (size == 0) { _pOverlapped = null; _memoryBlob = null; _backingBuffer = null; return; } _backingBuffer = new byte[checked ((int)size)]; _pOverlapped = _boundHandle.AllocateNativeOverlapped(s_IOCallback, state: this, pinData: _backingBuffer); _memoryBlob = (Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void AllocateNativeOverlapped_ObjectArrayAsPinData_DoesNotThrow() { var array = new object[] { new BlittableType() { i = 1 }, new byte[5], }; using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), array); Assert.True(result != null); handle.FreeNativeOverlapped(result); result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, new object(), array); Assert.True(result != null); handle.FreeNativeOverlapped(result); } }
public unsafe void AllocateNativeOverlapped_BlittableTypeAsPinData_DoesNotThrow() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new BlittableType() { i = 42 }); Assert.True(result != null); handle.FreeNativeOverlapped(result); } }
internal void ReleaseNativeResource() { // Ensure that cancellation has been completed and cleaned up _cancellationRegistration.Dispose(); // Free the overlapped // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory // (this is why we disposed the registration above) if (_overlapped != null) { _handle.FreeNativeOverlapped(_overlapped); _overlapped = null; } }
private Interop.HttpApi.HTTP_REQUEST *Allocate(ThreadPoolBoundHandle boundHandle, uint size) { uint newSize = size != 0 ? size : RequestBuffer == IntPtr.Zero ? 4096 : Size; if (_nativeOverlapped != null) { #if DEBUG DebugRefCountReleaseNativeOverlapped(); #endif NativeOverlapped *nativeOverlapped = _nativeOverlapped; _nativeOverlapped = null; _boundHandle.FreeNativeOverlapped(nativeOverlapped); } #if DEBUG DebugRefCountAllocNativeOverlapped(); #endif SetBuffer(checked ((int)newSize)); _boundHandle = boundHandle; _nativeOverlapped = boundHandle.AllocateNativeOverlapped(ListenerAsyncResult.IOCallback, state: _result, pinData: RequestBuffer); return((Interop.HttpApi.HTTP_REQUEST *)RequestBuffer.ToPointer()); }
public unsafe void AllocateNativeOverlapped_ReturnedNativeOverlapped_AllFieldsZero() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]); Assert.Equal(IntPtr.Zero, overlapped->InternalLow); Assert.Equal(IntPtr.Zero, overlapped->InternalHigh); Assert.Equal(0, overlapped->OffsetLow); Assert.Equal(0, overlapped->OffsetHigh); Assert.Equal(IntPtr.Zero, overlapped->EventHandle); handle.FreeNativeOverlapped(overlapped); } }
protected override bool ReleaseHandle() { IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero); // Do not call free durring AppDomain shutdown, there may be an outstanding operation. // Overlapped will take care calling free when the native callback completes. if (oldHandle != IntPtr.Zero && !NclUtilities.HasShutdownStarted) { unsafe { _boundHandle.FreeNativeOverlapped((NativeOverlapped *)oldHandle); } } return(true); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void AllocateNativeOverlapped_PreAllocated_WhenAlreadyAllocated_ThrowsArgumentException(bool useUnsafe) { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { using PreAllocatedOverlapped preAlloc = useUnsafe ? PreAllocatedOverlapped.UnsafeCreate(delegate { }, null, null) : new PreAllocatedOverlapped(delegate { }, null, null); NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc); AssertExtensions.Throws <ArgumentException>("preAllocated", () => handle.AllocateNativeOverlapped(preAlloc)); handle.FreeNativeOverlapped(overlapped); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsNull_ReturnsNull() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Null(result); boundHandle.FreeNativeOverlapped(overlapped); } } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FreeNativeOverlapped_WithWrongHandle_ThrowsArgumentException() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, (byte[])null); using (ThreadPoolBoundHandle handle2 = CreateThreadPoolBoundHandle()) { Assert.Throws <ArgumentException>(() => { handle2.FreeNativeOverlapped(overlapped); }); } handle.FreeNativeOverlapped(overlapped); } }
public unsafe void AllocateNativeOverlapped_PreAllocated_WhenAlreadyAllocated_ThrowsArgumentException() { using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle()) { using (PreAllocatedOverlapped preAlloc = new PreAllocatedOverlapped(delegate { }, null, null)) { NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc); Assert.Throws <ArgumentException>(() => { handle.AllocateNativeOverlapped(preAlloc); }); handle.FreeNativeOverlapped(overlapped); } } }
private unsafe void FreeNativeOverlapped() { // Do not call free during AppDomain shutdown, there may be an outstanding operation. // Overlapped will take care calling free when the native callback completes. IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero); if (oldHandle != IntPtr.Zero && !Environment.HasShutdownStarted) { Debug.Assert(OperatingSystem.IsWindows()); Debug.Assert(_socketHandle != null, "_socketHandle is null."); ThreadPoolBoundHandle?boundHandle = _socketHandle.IOCPBoundHandle; Debug.Assert(boundHandle != null, "SafeNativeOverlapped::FreeNativeOverlapped - boundHandle is null"); // FreeNativeOverlapped will be called even if boundHandle was previously disposed. boundHandle?.FreeNativeOverlapped((NativeOverlapped *)oldHandle); } }
public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsObject_ReturnsObject() { object context = new object(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
// Method to clean up any existing Overlapped object and related state variables. private unsafe void FreeOverlapped(bool checkForShutdown) { if (!checkForShutdown || !Environment.HasShutdownStarted) { // Free the overlapped object if (_ptrNativeOverlapped != null) { _boundHandle.FreeNativeOverlapped(_ptrNativeOverlapped); _ptrNativeOverlapped = null; } if (_dataChunksGCHandle.IsAllocated) { _dataChunksGCHandle.Free(); _dataChunks = null; } } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsIAsyncResult_ReturnsIAsyncResult() { // CoreCLR/Desktop CLR version of overlapped sits on top of Overlapped class // and treats IAsyncResult specially, which is why we special case this case. AsyncResult context = new AsyncResult(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
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); }