internal unsafe HttpResponseStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback, byte[] buffer, int offset, int size, bool chunked, bool sentHeaders) : base(asyncObject, userState, callback) { this.m_SentHeaders = sentHeaders; Overlapped overlapped = new Overlapped { AsyncResult = this }; if (size == 0) { this.m_DataChunks = null; this.m_pOverlapped = overlapped.Pack(s_IOCallback, null); } else { this.m_DataChunks = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK[chunked ? 3 : 1]; object[] userData = new object[1 + this.m_DataChunks.Length]; userData[this.m_DataChunks.Length] = this.m_DataChunks; int num = 0; byte[] arr = null; if (chunked) { arr = ConnectStream.GetChunkHeader(size, out num); this.m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); this.m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; this.m_DataChunks[0].BufferLength = (uint)(arr.Length - num); userData[0] = arr; this.m_DataChunks[1] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); this.m_DataChunks[1].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; this.m_DataChunks[1].BufferLength = (uint)size; userData[1] = buffer; this.m_DataChunks[2] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); this.m_DataChunks[2].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; this.m_DataChunks[2].BufferLength = (uint)NclConstants.CRLF.Length; userData[2] = NclConstants.CRLF; } else { this.m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); this.m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; this.m_DataChunks[0].BufferLength = (uint)size; userData[0] = buffer; } this.m_pOverlapped = overlapped.Pack(s_IOCallback, userData); if (chunked) { this.m_DataChunks[0].pBuffer = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(arr, num); this.m_DataChunks[1].pBuffer = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset); this.m_DataChunks[2].pBuffer = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(NclConstants.CRLF, 0); } else { this.m_DataChunks[0].pBuffer = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset); } } }
private unsafe void SubmitReadRequest() { _rxBuffer = new byte[64]; Overlapped overlapped = new Overlapped(); NativeOverlapped *nativeOverlapped = overlapped.Pack(ReadComplete, _rxBuffer); bool success; UInt32 numBytes; int errorCode; fixed(byte *buf = _rxBuffer) { success = WinUsb_ReadPipe(_interfaceHandle, RxEndpointAddress, buf, (UInt32)_rxBuffer.Length, out numBytes, nativeOverlapped); errorCode = Marshal.GetLastWin32Error(); } if (success) { // call was executed synchronously ReadComplete(0, numBytes, nativeOverlapped); } else { if (errorCode != ERROR_IO_PENDING) { Overlapped.Unpack(nativeOverlapped); Overlapped.Free(nativeOverlapped); WirekiteException.ThrowWin32Exception("Failed to submit read request for Wirekite device"); } } }
public void ControlTransferOverlapped(byte requestType, byte request, ushort value, ushort index, ushort length, byte[] data, WinUSBAsyncResult result) { uint bytesReturned = 0; NativeInterface.WINUSB_SETUP_PACKET setupPacket; setupPacket.RequestType = requestType; setupPacket.Request = request; setupPacket.Value = value; setupPacket.Index = index; setupPacket.Length = length; Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = result; unsafe { NativeOverlapped *pOverlapped = null; pOverlapped = overlapped.Pack(_PipeIOCallback, data); bool success = NativeInterface.WinUsb_ControlTransfer(_winUsbHandle, setupPacket, data, length, ref bytesReturned, pOverlapped); _HandleOverlappedAPI(success, "Asynchronous control transfer on WinUSB device failed.", pOverlapped, result, (int)bytesReturned); } }
public void WritePipeOverlapped(int ifaceIndex, byte pipeID, byte[] buffer, int offset, int bytesToWrite, WinUSBAsyncResult result) { Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = result; unsafe { NativeOverlapped *pOverlapped = null; uint bytesWritten; pOverlapped = overlapped.Pack(_PipeIOCallback, buffer); bool success; // Buffer is pinned already by overlapped.Pack fixed(byte *pBuffer = buffer) { success = NativeInterface.WinUsb_WritePipe(_InterfaceHandle(ifaceIndex), pipeID, pBuffer + offset, (uint)bytesToWrite, out bytesWritten, pOverlapped); } _HandleOverlappedAPI(success, "Failed to asynchronously write pipe on WinUSB device.", pOverlapped, result, (int)bytesWritten); } }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { SerialAsyncResult ar = new SerialAsyncResult(this); ar.Init(state, callback, false); Overlapped ov = new Overlapped(0, 0, ar.AsyncWaitHandle.Handle.ToInt32(), ar); unsafe { fixed(byte *data = &buffer[0]) { int write = 0; NativeOverlapped *nov = ov.Pack(m_IOCompletionCallback); WriteFile(m_hFile, data, count, &write, nov); } } if (GetLastError() == ERROR_IO_PENDING) { return(ar); } else { throw new Exception("Unable to initialize write. Errorcode: " + GetLastError().ToString()); } }
internal void Pack(object pinnedObjects) { if (this.nativeOverlapped != null) { // If we reach this condition, we have a bug in a derived AsyncResult class. // It attempted to initiate a new async I/O operation before the previous // one completed. This is a fatal condition, so we cannot continue execution. DiagnosticUtility.FailFast("Must allow previous I/O to complete before packing"); } GC.ReRegisterForFinalize(this); Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this); if (this.callback == null) { this.nativeOverlapped = overlapped.UnsafePack( IOCompletionCallback, pinnedObjects); } else { this.nativeOverlapped = overlapped.Pack( IOCompletionCallback, pinnedObjects); } }
private void Dispose(bool disposing) { if (_handle == null || _handle.IsClosed) { return; } var overlapped = new Overlapped { OffsetHigh = (int)(_position >> 32), OffsetLow = (int)_position }; var native = overlapped.Pack(null, null); try { if (!UnlockFileEx(_handle, 0, (uint)_length, (uint)(_length >> 32), native)) { WinIoError(); } } finally { Overlapped.Free(native); _handle = null; } }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { GCHandle gchBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); SerialAsyncResult sar = new SerialAsyncResult(this, state, callback, false, gchBuffer); Overlapped ov = new Overlapped(0, 0, sar.AsyncWaitHandle.Handle.ToInt32(), sar); unsafe { NativeOverlapped *nov = ov.Pack(m_IOCompletionCallback); byte * data = (byte *)((int)gchBuffer.AddrOfPinnedObject() + offset); uint written = 0; if (WriteFile(m_hFile, data, (uint)count, out written, nov)) { sar.m_bCompletedSynchronously = true; return(sar); } else if (GetLastError() == ERROR_IO_PENDING) { return(sar); } else { throw new Exception("Não foi possível inicializar escrita. Código de erro: " + GetLastError().ToString()); } } }
public static unsafe Task <int> ReadAsync(SafeFileHandle hFile, long fileOffset, byte[] buffer, int bytesToRead) { if (fileOffset < 0) { throw new ArgumentOutOfRangeException(nameof(fileOffset)); } if (bytesToRead < 0 || bytesToRead > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(bytesToRead)); } var asyncResult = new AsyncResult(); var o = new Overlapped((int)(fileOffset & 0xFFFFFFFF), (int)(fileOffset >> 32), IntPtr.Zero, asyncResult); fixed(byte *bufferBase = buffer) { // https://docs.microsoft.com/en-us/dotnet/api/system.threading.overlapped.pack?view=netframework-4.7#System_Threading_Overlapped_Pack_System_Threading_IOCompletionCallback_System_Object_ // The buffer or buffers specified in userData must be the same as those passed to the unmanaged operating system function that performs the asynchronous I/O. // The runtime pins the buffer or buffers specified in userData for the duration of the I/O operation. NativeOverlapped *pOverlapped = o.Pack(CompletionCallback, buffer); bool needToFree = true; try { if (ReadFile(hFile, bufferBase, bytesToRead, IntPtr.Zero, pOverlapped) != 0) { // Completed synchronously. // The number of bytes transferred for the I/ O request.The system sets this member if the request is completed without errors. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684342(v=vs.85).aspx int bytesRead = (int)pOverlapped->InternalHigh.ToInt64(); return(Task.FromResult(bytesRead)); } else { int systemErrorCode = Marshal.GetLastWin32Error(); if (systemErrorCode == ERROR_IO_PENDING) { needToFree = false; } else { throw new Win32Exception(systemErrorCode, $"ReadFile failed with system error code:{systemErrorCode}"); } return(asyncResult.CompletionSource.Value.Task); } } finally { if (needToFree) { Overlapped.Unpack(pOverlapped); Overlapped.Free(pOverlapped); } } } }
//solucion de https://stackoverflow.com/questions/33389896/c-sharp-wcf-hosted-in-windows-service-goes-idle-after-5-minutes/33396091#33396091 private static unsafe void QueueDummyIOCPWork() { Overlapped ovl = new Overlapped(); NativeOverlapped *pOvl = null; pOvl = ovl.Pack((a, b, c) => { Overlapped.Unpack(pOvl); Overlapped.Free(pOvl); }, null); ThreadPool.UnsafeQueueNativeOverlapped(pOvl); }
internal HttpRequestStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback, byte[] buffer, int offset, uint size, uint dataAlreadyRead) : base(asyncObject, userState, callback) { m_dataAlreadyRead = dataAlreadyRead; Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = this; m_pOverlapped = overlapped.Pack(s_IOCallback, buffer); m_pPinnedBuffer = (void *)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); }
public static unsafe void PackNegTest() { var helper = new AsyncHelper(); IOCompletionCallback callback = MyCallback(helper); Overlapped ov = new Overlapped(); NativeOverlapped *nativeOverlapped = ov.Pack(new IOCompletionCallback(callback), null); try { Assert.True(nativeOverlapped != null); Assert.Throws <InvalidOperationException>(() => ov.Pack(new IOCompletionCallback(callback), null)); } finally { Overlapped.Free(nativeOverlapped); } }
private unsafe void PostAcceptRequestToIOCP() { _shutdownEvent.AddCount(); Overlapped ov = new Overlapped(); NativeOverlapped *nov = ov.Pack(AcceptRequestIOCompletionCallback, null); ThreadPool.UnsafeQueueNativeOverlapped(nov); }
// clear out the USB input buffer public void FlushReadUSB() { // note the starting time so we don't wait forever DateTime t0 = DateTime.Now; // wait until a read would block int rptLen = inputReportLength; while ((DateTime.Now - t0).TotalMilliseconds < 100) { // set up a non-blocking read IntPtr buf = Marshal.AllocHGlobal(rptLen); try { unsafe { // set up the overlapped I/O descriptor Overlapped o = new Overlapped(0, 0, evov.SafeWaitHandle.DangerousGetHandle(), null); NativeOverlapped *no = o.Pack(null, null); // start the non-blocking read Marshal.WriteByte(buf, 0); HIDImports.ReadFile(fp, buf, rptLen, IntPtr.Zero, no); // check to see if it's ready immediately bool ready = evov.WaitOne(0); if (ready) { // it's ready - complete the read UInt32 readLen; int result = HIDImports.GetOverlappedResult(fp, no, out readLen, 0); } else { // Not ready - we'd have to wait to do a read, so the // buffer is empty. Cancel the read. HIDImports.CancelIo(fp); } // done with the overlapped I/O descriptor Overlapped.Unpack(no); Overlapped.Free(no); // if there was nothing ready to read, we've cleared out buffered // inputs, so we're done if (!ready) { return; } } } finally { Marshal.FreeHGlobal(buf); } } }
// // This method enables completion ports on the AsyncResult // internal unsafe void EnableCompletionPort() { // // Bind the Win32 Socket Handle to the ThreadPool // ((Socket)AsyncObject).BindToCompletionPort(); m_NativeOverlapped = m_Overlapped.Pack(s_IOCallback); GlobalLog.Print("OverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() m_Overlapped:" + ValidationHelper.HashString(m_Overlapped) + " m_NativeOverlapped = " + ((int)m_NativeOverlapped).ToString()); }
public unsafe void Write(byte[] buffer, int offset) { Overlapped ovl = new Overlapped(offset, 0, IntPtr.Zero, null); NativeOverlapped *pOverlapped = ovl.Pack(WriteComplete, buffer); fixed(byte *bytes = buffer) { NativeMethods.WriteFile(_fileHandle, bytes, buffer.Length, IntPtr.Zero, pOverlapped); } }
public static unsafe void PackNegTest() { var helper = new AsyncHelper(); IOCompletionCallback callback = MyCallback(helper); NativeOverlapped* nativeOverlapped; Overlapped ov = new Overlapped(); nativeOverlapped = ov.Pack(new IOCompletionCallback(callback), null); try { Assert.True(nativeOverlapped != null); Assert.Throws<InvalidOperationException>(() => ov.Pack(new IOCompletionCallback(callback), null)); } finally { Overlapped.Free(nativeOverlapped); } }
internal static unsafe IOCompletionCallback MyCallback(AsyncHelper helper) { IOCompletionCallback del = delegate(uint param1, uint param2, NativeOverlapped *overlapped) { Overlapped ov = new Overlapped(); NativeOverlapped *nativeOverlapped2 = ov.Pack(helper.Callback, null); ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped2); }; return(del); }
public NativeOverlapped *PackOverlapped(Object userData) { if (pOverlapped != null) { throw new InvalidOperationException(); } //Passing a real WaitHandle to the Overlapped constructor results in a race condition between CompletionCallback / Complete because the event may be signalled before the callback completes Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this); return(pOverlapped = overlapped.Pack(CompletionCallback, userData)); }
public unsafe void WriteSync(byte[] buffer, Func <int, bool> checkOffset, bool withLock = true) { int temp = 0, offset; do { temp = _offset; offset = temp + buffer.Length; } while (Interlocked.CompareExchange(ref _offset, offset, temp) != temp); if (checkOffset((int)_offset)) { Overlapped ovl = new Overlapped(temp, 0, IntPtr.Zero, null); NativeOverlapped *pOverlapped = ovl.Pack(WriteComplete, buffer); try { if (withLock) { while (!(withLock = NativeMethods.LockFile(_fileHandle, offset, 0, buffer.Length, 0))) { Thread.Sleep(0); } } fixed(byte *bytes = buffer) { if (0 == NativeMethods.WriteFile(_fileHandle, bytes, buffer.Length, IntPtr.Zero, pOverlapped)) { var dwResult = NativeMethods.GetLastError(); if (ERROR_IO_PENDING == dwResult) { IntPtr transferred = Marshal.AllocHGlobal(sizeof(ulong)); try { NativeMethods.GetOverlappedResult(_fileHandle, pOverlapped, transferred, true); } finally { Marshal.FreeHGlobal(transferred); } } } } } finally { if (withLock) { NativeMethods.UnlockFile(_fileHandle, offset, 0, buffer.Length, 0); } } } }
/// <summary> /// Creates and returns a NativeOverlapped structure to be passed to /// native code (i.e. the driver). /// </summary> /// <returns></returns> public unsafe NativeOverlapped *GetNativeOverlapped() { // Create a managed Overlapped structure that refers to this // IAsyncResult Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this); // Pack the managed Overlapped structure into a NativeOverlapped // structure, which pins the memory until the operation completes return(overlapped.Pack(new IOCompletionCallback(CompletionCallback), mOutDeviceBuffer.Target )); }
// Creates and returns a NativeOverlapped structure to be passed to native code public unsafe NativeOverlapped *GetNativeOverlapped() { // Create a managed Overlapped structure that refers to our IAsyncResult (this) Overlapped o = new Overlapped(0, 0, IntPtr.Zero, this); // Pack the managed Overlapped structure into a NativeOverlapped structure // Pack causes the CLR to ensure that: // 1. the input/output objects are pinned // 2. the IAsyncResult object (this) isn't GC'd while the I/O is pending // 3. the thread pool thread calls CompletionCallback in the invoking thread's AppDomain return(o.Pack(CompletionCallback, new Object[] { m_inBuffer.Target, m_outBuffer.Target })); }
internal AsyncFileStream_AsyncResult(AsyncCallback userCallback, Object stateObject, bool isWrite) { m_userCallback = userCallback; m_userStateObject = stateObject; m_waitHandle = new ManualResetEvent(false); m_isWrite = isWrite; Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this); m_overlapped = overlapped.Pack(s_callback, null); }
public static unsafe void PackNegTest1() { #pragma warning disable 618 var helper = new AsyncHelper(); IOCompletionCallback callback = MyCallback(helper); NativeOverlapped *nativeOverlapped; Overlapped ov = new Overlapped(); nativeOverlapped = ov.Pack(new IOCompletionCallback(callback)); try { Assert.True(nativeOverlapped != null); Assert.Throws <InvalidOperationException>(() => ov.Pack(new IOCompletionCallback(callback))); } finally { Overlapped.Free(nativeOverlapped); } #pragma warning restore 618 }
/// <include file='doc\FileSystemWatcher.uex' path='docs/doc[@for="FileSystemWatcher.Monitor"]/*' /> /// <devdoc> /// Calls native API and sets up handle with the directory change API. /// </devdoc> /// <internalonly/> private unsafe void Monitor(IntPtr bufferPtr) { if (!enabled || (directoryHandle == (IntPtr)(-1))) { return; } Overlapped overlapped = new Overlapped(); if (bufferPtr == (IntPtr)0) { try { bufferPtr = Marshal.AllocHGlobal((INTPTR_INTPTRCAST)internalBufferSize); } catch (OutOfMemoryException) { throw new OutOfMemoryException(SR.GetString(SR.BufferSizeTooLarge, internalBufferSize.ToString())); } } ulong bufferPtrTemp = (ulong)bufferPtr; overlapped.OffsetHigh = (int)(0xffffffff00000000 & bufferPtrTemp); overlapped.OffsetLow = (int)(0x00000000ffffffff & bufferPtrTemp); NativeOverlapped *overlappedPointer = overlapped.Pack(new IOCompletionCallback(this.CompletionStatusChanged)); IntPtr h = directoryHandle; int size; bool ok = UnsafeNativeMethods.ReadDirectoryChangesW(new HandleRef(this, h), new HandleRef(this, bufferPtr), internalBufferSize, includeSubdirectories ? 1 : 0, (int)notifyFilters, out size, overlappedPointer, NativeMethods.NullHandleRef); if (!ok) { Overlapped.Free(overlappedPointer); Marshal.FreeHGlobal(bufferPtr); // If the handle was for some reason changed or closed during this call, then don't throw an // exception. Else, it's a valid error. if ((h == directoryHandle) && (directoryHandle != (IntPtr)(-1))) { OnError(new ErrorEventArgs(new Win32Exception())); } } }
public unsafe static bool ConnectNamedPipe(IntPtr hNamedPipe, // handle to named pipe Overlapped lpOverlapped // overlapped structure ) { NativeOverlapped *overlappedPack = lpOverlapped.Pack(null, null); bool fRet = false; if (overlappedPack != null) { fRet = ConnectNamedPipe(hNamedPipe, overlappedPack); Overlapped.Free(overlappedPack); } return(fRet); }
public unsafe void ReadControlOverlapped(uint controlCode, byte[] writeBuffer, byte[] readBuffer) { var completedEvent = new ManualResetEvent(false); uint bytesReturned = 0; var inOverlapped = new Overlapped(); inOverlapped.EventHandleIntPtr = completedEvent.SafeWaitHandle.DangerousGetHandle(); NativeOverlapped *inNativeOverlapped = inOverlapped.Pack(null, null); try { fixed(byte *inBuffer = writeBuffer) { fixed(byte *outBuffer = readBuffer) { var success = false; try { success = InteropKernel32.DeviceIoControl(_readHandle, controlCode, inBuffer, writeBuffer == null ? 0 : (uint)writeBuffer.Length, outBuffer, readBuffer == null ? 0 : (uint)readBuffer.Length, ref bytesReturned, inNativeOverlapped); } catch (ObjectDisposedException) { throw new Exception("File handle already closed"); } if (!success) { HandleIOError(true); CancelOverlapped(_readHandle, completedEvent); } } } } finally { Overlapped.Free(inNativeOverlapped); } }
unsafe public void Write(string value) { if (value.Length > bufferSize) { throw new ArgumentException($"Value '{value}' longer than specified buffer size of {bufferSize}", nameof(value)); } int errorCode; var overlapped = new Overlapped(); NativeOverlapped *nativeOverlapped = overlapped.Pack(WriteCompletionCallback, null); try { var valueAsByteArray = Encoding.ASCII.GetBytes(value); uint bytesWritten = 0; var writeFileResult = UnsafeNativeMethods.WriteFile(fileHandle, valueAsByteArray, (uint)value.Length, ref bytesWritten, nativeOverlapped); errorCode = Marshal.GetLastWin32Error(); if (writeFileResult != 0) { if (bytesWritten != value.Length) { throw new InvalidOperationException($"Expected to write {value.Length} bytes, wrote {bytesWritten}"); } return; //write was successful } if (errorCode == SafeNativeMethods.ERROR_IO_PENDING) { uint bytesTransferred = 0; if (UnsafeNativeMethods.GetOverlappedResult(fileHandle, nativeOverlapped, ref bytesTransferred, 1) == 0) { errorCode = Marshal.GetLastWin32Error(); throw new InvalidOperationException($"GetOverlappedResult returned FALSE. Last Win32 error code is {errorCode}."); } if (bytesTransferred != value.Length) { throw new InvalidOperationException($"Expected to transfer {value.Length}, transferred {bytesTransferred}"); } return; } throw new InvalidOperationException($"WriteFile returned FALSE. Last Win32 error code is {errorCode}"); } finally { Overlapped.Free(nativeOverlapped); } }
public void WriteData(byte[] data) { if (Device != null) { uint bytesWritten = 0; Overlapped overlapped = new Overlapped(); WriteOverlapped = overlapped.Pack(WriteDeviceIOCompletionCallback, null); WriteFile( Device, data, (uint)data.Length, ref bytesWritten, WriteOverlapped ); } }
unsafe public string Read(int numberOfBytes) { if (numberOfBytes > bufferSize) { throw new ArgumentException($"Cannot read {numberOfBytes} bytes because buffer size specified in constructor is only {bufferSize}.", nameof(numberOfBytes)); } var overlapped = new Overlapped(); NativeOverlapped *nativeOverlapped = overlapped.Pack(ReadCompletionCallback, null); try { int errorCode; var buffer = new byte[numberOfBytes]; uint bytesRead = 0; var readFileResult = UnsafeNativeMethods.ReadFile(fileHandle, buffer, numberOfBytes, ref bytesRead, nativeOverlapped); errorCode = Marshal.GetLastWin32Error(); if (readFileResult != 0) { if (bytesRead != numberOfBytes) { throw new InvalidOperationException($"Expected to read {numberOfBytes}, read {bytesRead}"); } return(Encoding.ASCII.GetString(buffer)); } if (errorCode == SafeNativeMethods.ERROR_IO_PENDING) { uint bytesTransferred = 0; if (UnsafeNativeMethods.GetOverlappedResult(fileHandle, nativeOverlapped, ref bytesTransferred, 1) == 0) { errorCode = Marshal.GetLastWin32Error(); throw new InvalidOperationException($"GetOverlappedResult returned FALSE. Last Win32 error code is {errorCode}."); } if (bytesTransferred != numberOfBytes) { throw new InvalidOperationException($"Expected to transfer {numberOfBytes} bytes, transferred {bytesTransferred}"); } return(Encoding.ASCII.GetString(buffer)); } throw new InvalidOperationException($"ReadFile returned FALSE. Last Win32 error code is {errorCode}"); } finally { Overlapped.Free(nativeOverlapped); } }
public bool Read(long pageNumber, byte *buffer, int count) { if (_readHandle == null) { _readHandle = Win32NativeFileMethods.CreateFile(_filename, Win32NativeFileAccess.GenericRead, Win32NativeFileShare.Write | Win32NativeFileShare.Read | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenExisting, Win32NativeFileAttributes.Normal, IntPtr.Zero); } long position = pageNumber * AbstractPager.PageSize; var overlapped = new Overlapped((int)(position & 0xffffffff), (int)(position >> 32), IntPtr.Zero, null); NativeOverlapped *nativeOverlapped = overlapped.Pack(null, null); try { while (count > 0) { int read; if (Win32NativeFileMethods.ReadFile(_readHandle, buffer, count, out read, nativeOverlapped) == false) { int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == Win32NativeFileMethods.ErrorHandleEof) { return(false); } throw new Win32Exception(lastWin32Error); } count -= read; buffer += read; position += read; nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(position >> 32); } return(true); } finally { Overlapped.Free(nativeOverlapped); } }
public static unsafe void PackPosTest() { #pragma warning disable 618 Overlapped ov = new Overlapped(); var helper = new AsyncHelper(); IOCompletionCallback callback = MyCallback(helper); NativeOverlapped* nativeOverlapped = ov.Pack(callback); try { Assert.True(nativeOverlapped != null); Assert.True(ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped)); Assert.True(helper.Wait()); } finally { Overlapped.Free(nativeOverlapped); } #pragma warning restore 618 }
internal static unsafe IOCompletionCallback MyCallback(AsyncHelper helper) { IOCompletionCallback del = delegate (uint param1, uint param2, NativeOverlapped* overlapped) { Overlapped ov = new Overlapped(); NativeOverlapped* nativeOverlapped2 = ov.Pack(helper.Callback, null); ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped2); }; return del; }
unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject) { Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); Contract.Assert(CanWrite, "CanWrite"); Contract.Assert(bytes != null, "bytes != null"); Contract.Assert(_readPos == _readLen, "_readPos == _readLen"); Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!"); Contract.Assert(offset >= 0, "offset is negative"); Contract.Assert(numBytes >= 0, "numBytes is negative"); // Create and store async stream class library specific data in the // async result FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = userCallback; asyncResult._userStateObject = stateObject; asyncResult._isWrite = true; // For Synchronous IO, I could go with either a callback 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 // 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; if (userCallback != null) intOverlapped = overlapped.Pack(IOCallback, bytes); else intOverlapped = overlapped.UnsafePack(null, bytes); asyncResult._overlapped = intOverlapped; if (CanSeek) { // Make sure we set the length of the file appropriately. long len = Length; //Console.WriteLine("BeginWrite - Calculating end pos. pos: "+pos+" len: "+len+" numBytes: "+numBytes); // Make sure we are writing to the position that we think we are if (_exposedHandle) VerifyOSHandlePosition(); if (_pos + numBytes > len) { //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes)); SetLengthCore(_pos + numBytes); } // Now set the position to read from in the NativeOverlapped struct // For pipes, we should leave the offset fields set to 0. intOverlapped->OffsetLow = (int)_pos; intOverlapped->OffsetHigh = (int)(_pos>>32); // When using overlapped IO, the OS is not supposed to // touch the file pointer location at all. We will adjust it // ourselves. This isn't threadsafe. // SeekCore(numBytes, SeekOrigin.Current); } //Console.WriteLine("BeginWrite finishing. pos: "+pos+" numBytes: "+numBytes+" _pos: "+_pos+" Position: "+Position); int hr = 0; // queue an async WriteFile operation and pass in a packed overlapped int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); // WriteFile, the OS version, will return 0 on failure. But // my WriteFileNative wrapper returns -1. My wrapper 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 bytes // written back from this call when using overlapped IO! You must // not pass in a non-null lpNumBytesWritten to WriteFile when using // overlapped structures! This is ByDesign NT behavior. if (r==-1 && numBytes!=-1) { //Console.WriteLine("WriteFile returned 0; Write will complete asynchronously (if hr==3e5) hr: 0x{0:x}", hr); // For pipes, when they are closed on the other side, they will come here. if (hr == ERROR_NO_DATA) { // Not an error, but EOF. AsyncFSCallback will NOT be // called. Call the user callback here. asyncResult.CallUserCallback(); // EndWrite will free the Overlapped struct correctly. } else if (hr != ERROR_IO_PENDING) { if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere. SeekCore(0, SeekOrigin.Current); if (hr == ERROR_HANDLE_EOF) __Error.EndOfFile(); else __Error.WinIOError(hr, String.Empty); } } else { // Due to a workaround for a race condition in NT's ReadFile & // WriteFile routines, we will always be returning 0 from WriteFileNative // when we do async IO instead of the number of bytes written, // irregardless of whether the operation completed // synchronously or asynchronously. We absolutely must not // set asyncResult._numBytes here, since will never have correct // results. //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on another thread."); } return asyncResult; }
// // Starts an asynchronous read operation. // public override unsafe IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback userCallback, object userState) { if (!_isAsync) { return base.BeginRead(buffer, offset, count, userCallback, userState); } NativeOverlapped* overlappedPtr; SimpleFileStreamAsyncResult fsar = new SimpleFileStreamAsyncResult(userCallback, userState); Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, fsar); overlappedPtr = overlapped.Pack(IOCallback, buffer); long length = Length; if (_position + count > length) { if (_position <= length) { count = (int)(length - _position); } else { count = 0; } } overlappedPtr->OffsetLow = (int)_position; overlappedPtr->OffsetHigh = (int) (_position >> 32); Seek((long)count, SeekOrigin.Current); int errorCode; if (ReadFileNative(buffer, offset, count, overlappedPtr, out errorCode) == -1) { if (errorCode == Win32Native.ERROR_IO_PENDING) return fsar; throw GetIOException(errorCode); } return fsar; }
unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead) { Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); Contract.Assert(CanRead, "CanRead"); Contract.Assert(bytes != null, "bytes != null"); Contract.Assert(_writePos == 0, "_writePos == 0"); Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); Contract.Assert(offset >= 0, "offset is negative"); Contract.Assert(numBytes >= 0, "numBytes is negative"); // Create and store async stream class library specific data in the // async result FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); asyncResult._handle = _handle; asyncResult._userCallback = userCallback; asyncResult._userStateObject = stateObject; asyncResult._isWrite = false; // Must set this here to ensure all the state on the IAsyncResult // object is set before we call ReadFile, which gives the OS an // opportunity to run our callback (including the user callback & // the call to EndRead) before ReadFile has returned. asyncResult._numBufferedBytes = numBufferedBytesRead; // For Synchronous IO, I could go with either a callback 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 // 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; if (userCallback != null) intOverlapped = overlapped.Pack(IOCallback, bytes); else intOverlapped = overlapped.UnsafePack(null, bytes); asyncResult._overlapped = intOverlapped; // Calculate position in the file we should be at after the read is done if (CanSeek) { long len = Length; // Make sure we are reading from the position that we think we are if (_exposedHandle) VerifyOSHandlePosition(); if (_pos + numBytes > len) { if (_pos <= len) numBytes = (int) (len - _pos); else numBytes = 0; } // Now set the position to read from in the NativeOverlapped struct // For pipes, we should leave the offset fields set to 0. intOverlapped->OffsetLow = unchecked((int)_pos); intOverlapped->OffsetHigh = (int)(_pos>>32); // When using overlapped IO, the OS is not supposed to // touch the file pointer location at all. We will adjust it // ourselves. This isn't threadsafe. // WriteFile should not update the file pointer when writing // in overlapped mode, according to MSDN. But it does update // the file pointer when writing to a UNC path! // So changed the code below to seek to an absolute // location, not a relative one. ReadFile seems consistent though. SeekCore(numBytes, SeekOrigin.Current); } // queue an async ReadFile operation and pass in a packed overlapped int hr = 0; int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); // ReadFile, the OS version, will return 0 on failure. But // my ReadFileNative wrapper returns -1. My wrapper 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 bytes // 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 && numBytes!=-1) { // For pipes, when they hit EOF, they will come here. if (hr == ERROR_BROKEN_PIPE) { // Not an error, but EOF. AsyncFSCallback will NOT be // called. Call the user callback here. // We clear the overlapped status bit for this special case. // Failure to do so looks like we are freeing a pending overlapped later. intOverlapped->InternalLow = IntPtr.Zero; asyncResult.CallUserCallback(); // EndRead will free the Overlapped struct correctly. } else if (hr != ERROR_IO_PENDING) { if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere. SeekCore(0, SeekOrigin.Current); if (hr == ERROR_HANDLE_EOF) __Error.EndOfFile(); else __Error.WinIOError(hr, String.Empty); } } else { // Due to a workaround for a race condition in NT's ReadFile & // WriteFile routines, we will always be returning 0 from ReadFileNative // when we do async IO instead of the number of bytes read, // irregardless of whether the operation completed // synchronously or asynchronously. We absolutely must not // set asyncResult._numBytes here, since will never have correct // results. //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on a separate thread"); } return asyncResult; }
public static unsafe void UnPackTest() { Assert.Throws<ArgumentNullException>(() => Overlapped.Unpack(null)); Overlapped ov = new Overlapped(); var helper = new AsyncHelper(); IOCompletionCallback callback = MyCallback(helper); NativeOverlapped* nativeOverlapped = ov.Pack(new IOCompletionCallback(callback), null); try { Assert.True(null != nativeOverlapped); Overlapped ov1 = Overlapped.Unpack(nativeOverlapped); Assert.Same(ov1, ov); } finally { Overlapped.Free(nativeOverlapped); } }