public static void PropertyTest1() { IAsyncResult asyncResult = new Task(() => Console.WriteLine("this is a dummy task")); var obj = new Overlapped(); Assert.Null(obj.AsyncResult); obj.AsyncResult = asyncResult; Assert.Same(obj.AsyncResult, asyncResult); #pragma warning disable 618 Assert.Equal(obj.EventHandle, 0); obj.EventHandle = 3; Assert.Equal(obj.EventHandle, 3); #pragma warning restore 618 var _handle = new ManualResetEvent(false).SafeWaitHandle; Assert.NotSame(obj.EventHandleIntPtr, IntPtr.Zero); obj.EventHandleIntPtr = _handle.DangerousGetHandle(); Assert.Equal(obj.EventHandleIntPtr, _handle.DangerousGetHandle()); Assert.Equal(obj.OffsetHigh, 0); obj.OffsetHigh = 3; Assert.Equal(obj.OffsetHigh, 3); Assert.Equal(obj.OffsetLow, 0); obj.OffsetLow = 1; Assert.Equal(obj.OffsetLow, 1); }
public static void PropertyTest3() { IAsyncResult asyncResult = new Task(() => Console.WriteLine("this is a dummy task")); var _event = new ManualResetEvent(false); var _handle = _event.SafeWaitHandle; var obj = new Overlapped(1, 3, _handle.DangerousGetHandle(), asyncResult); Assert.Same(obj.AsyncResult, asyncResult); #pragma warning disable 618 Assert.Equal(obj.EventHandle, _event.Handle.ToInt32()); #pragma warning restore 618 Assert.Equal(obj.EventHandleIntPtr, _handle.DangerousGetHandle()); Assert.Equal(obj.OffsetHigh, 3); Assert.Equal(obj.OffsetLow, 1); }
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); } }
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 }
public static VirtualHardDisk Create(string filename, ulong maximumSize, VirtualStorageDeviceTypes deviceType = VirtualStorageDeviceTypes.Vhd, VirtualDiskAccessMasks mask = VirtualDiskAccessMasks.All, RawSecurityDescriptor securityDescriptor = null, CreateVirtualDiskFlags flags = CreateVirtualDiskFlags.None, uint providerSpecificFlags = 0, Guid uniqueId = default(Guid), uint blockSizeInBytes = 0, uint sectorSizeInBytes = 0, string parentPath = null, string sourcePath = null, Overlapped overlapped = null) { if () var storageType = new VirtualStorageType {DeviceId = deviceType}; var parameters = new CreateVirtualDiskParameters { Version = CreateVirtualDiskVersions.Version1, Version1 = new CreateVirtualDiskParametersVersion1 { UniqueId = uniqueId, MaximumSize = maximumSize, BlockSizeInBytes = blockSizeInBytes, SectorSizeInBytes = sectorSizeInBytes, ParentPath = parentPath, SourcePath = sourcePath } }; var handle = VirtualDiskCore.CreateVirtualDisk(storageType, filename, mask, securityDescriptor, flags, providerSpecificFlags, parameters, overlapped); var vhd = new VirtualHardDisk(filename, handle); // ReSharper disable once InvertIf if (vhd.VirtualStorageType.DeviceId == VirtualStorageDeviceTypes.Iso) { vhd.Dispose(); throw new NotSupportedException("This class does not support ISO files."); } return vhd; }
public static extern bool GetOverlappedResult( SafeFileHandle hFile, //IntPtr hFile, //Puntero hacia el manejador del archivo creado [In] ref Overlapped lpOverlapped, //[In] ref System.Threading.NativeOverlapped lpOverlapped, //Puntero a la estructura overlapped que se creo con readfile ref long lpNumberofBytesTransferred, //IntPtr lpNumberofBytesTransferred,//out uint lpNumberofBytesTransferred, //Vriable donde se van a recibir los datos bool bWait //Si esta variable es true, la funcion no regresara hasta que se haya terminado la transferencia asincrona );
internal static extern bool ReadFile( HandleRef hndRef, StringBuilder buffer, int numberOfBytesToRead, out int numberOfBytesRead, ref Overlapped flag);
private static unsafe void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped) { ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped); // // The Win32 thread pool implementation of ThreadPoolBoundHandle does not permit reuse of NativeOverlapped // pointers without freeing them and allocating new a new one. We need to ensure that code using the CLR // ThreadPool implementation follows those rules. // if (overlapped._completed) { throw new InvalidOperationException(SR.InvalidOperation_NativeOverlappedReused); } overlapped._completed = true; if (overlapped._boundHandle == null) { throw new InvalidOperationException(SR.Argument_NativeOverlappedAlreadyFree); } overlapped._userCallback(errorCode, numBytes, nativeOverlapped); }
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; }
/// <devdoc> /// Calls native API and sets up handle with the directory change API. /// </devdoc> /// <internalonly/> private unsafe void Monitor(byte[] buffer) { if (!_enabled || IsHandleInvalid) { return; } Overlapped overlapped = new Overlapped(); if (buffer == null) { buffer = AllocateBuffer(); } // Pass "session" counter to callback: FSWAsyncResult asyncResult = new FSWAsyncResult(); asyncResult.session = _currentSession; asyncResult.buffer = buffer; // Pack overlapped. The buffer will be pinned by Overlapped: overlapped.AsyncResult = asyncResult; NativeOverlapped *overlappedPointer = overlapped.Pack(new IOCompletionCallback(this.CompletionStatusChanged), buffer); // Can now call OS: int size; bool ok = false; try { // There could be a race in user code between calling StopRaisingEvents (where we close the handle) // and when we get here from CompletionStatusChanged. // We might need to take a lock to prevent race absolutely, instead just catch // ObjectDisposedException from SafeHandle in case it is disposed if (!IsHandleInvalid) { // An interrupt is possible here fixed(byte *buffPtr = buffer) { ok = UnsafeNativeMethods.ReadDirectoryChangesW(_directoryHandle, buffPtr, _internalBufferSize, _includeSubdirectories ? 1 : 0, (int)_notifyFilters, out size, overlappedPointer, IntPtr.Zero); } } } catch (ObjectDisposedException) { //Ignore } catch (ArgumentNullException) { //Ignore Debug.Assert(IsHandleInvalid, "ArgumentNullException from something other than SafeHandle?"); } finally { if (!ok) { Overlapped.Free(overlappedPointer); // 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 (!IsHandleInvalid) { OnError(new ErrorEventArgs(new Win32Exception())); } } } }
public static extern bool WriteFile( UInt32 hFile, // handle to file byte[] lpBuffer, // data buffer UInt32 nNumberOfBytesToWrite, // number of bytes to write out UInt32 lpNumberOfBytesWritten, // number of bytes written Overlapped lpOverlapped // overlapped buffer );
private void AsyncReadPageCallback <TContext>(uint errorCode, uint numBytes, NativeOverlapped *overlap) { if (errorCode != 0) { Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode); } PageAsyncReadResult <TContext> result = (PageAsyncReadResult <TContext>)Overlapped.Unpack(overlap).AsyncResult; if (Interlocked.Decrement(ref result.count) == 1) { // We will be issuing another I/O, so free this overlap Overlapped.Free(overlap); long ptr = (long)pointers[result.page % BufferSize]; // Correct for page 0 of HLOG if (result.page == 0) { ptr += Constants.kFirstValidAddress; } long minObjAddress = long.MaxValue; long maxObjAddress = long.MinValue; while (ptr < (long)pointers[result.page % BufferSize] + PageSize) { if (!Layout.GetInfo(ptr)->Invalid) { if (Key.HasObjectsToSerialize()) { Key *key = Layout.GetKey(ptr); var addr = ((AddressInfo *)key)->Address; if (addr < minObjAddress) { minObjAddress = addr; } addr += ((AddressInfo *)key)->Size; if (addr > maxObjAddress) { maxObjAddress = addr; } } if (Value.HasObjectsToSerialize()) { Value *value = Layout.GetValue(ptr); var addr = ((AddressInfo *)value)->Address; if (addr < minObjAddress) { minObjAddress = addr; } addr += ((AddressInfo *)value)->Size; if (addr > maxObjAddress) { maxObjAddress = addr; } } } ptr += Layout.GetPhysicalSize(ptr); } // Object log fragment should be aligned by construction Debug.Assert(minObjAddress % sectorSize == 0); var to_read = (int)(maxObjAddress - minObjAddress); var objBuffer = ioBufferPool.Get(to_read); result.freeBuffer1 = objBuffer; var alignedLength = (to_read + (sectorSize - 1)) & ~(sectorSize - 1); // Request objects from objlog result.objlogDevice.ReadAsync( (int)(result.page >> (LogSegmentSizeBits - LogPageSizeBits)), (ulong)minObjAddress, (IntPtr)objBuffer.aligned_pointer, (uint)alignedLength, AsyncReadPageCallback <TContext>, result); } else { // Load objects from buffer into memory long ptr = (long)pointers[result.page % BufferSize]; // Correct for page 0 of HLOG if (result.page == 0) { ptr += Constants.kFirstValidAddress; } MemoryStream ms = new MemoryStream(result.freeBuffer1.buffer); ms.Seek(result.freeBuffer1.offset + result.freeBuffer1.valid_offset, SeekOrigin.Begin); while (ptr < (long)pointers[result.page % BufferSize] + PageSize) { if (!Layout.GetInfo(ptr)->Invalid) { if (Key.HasObjectsToSerialize()) { Key.Deserialize(Layout.GetKey(ptr), ms); } if (Value.HasObjectsToSerialize()) { Value.Deserialize(Layout.GetValue(ptr), ms); } } ptr += Layout.GetPhysicalSize(ptr); } ms.Dispose(); result.Free(); // Call the "real" page read callback result.callback(errorCode, numBytes, overlap); } }
private static unsafe Task <TOut?> ExplicitDeviceIoControlAsync <TIn, TOut>(SafeFileHandle hDevice, uint ioControlCode, TIn?inVal, TOut?outVal) where TIn : struct where TOut : struct { ThreadPool.BindHandle(hDevice); var tcs = new TaskCompletionSource <TOut?>(); var buffer = Pack(inVal, outVal); var nativeOverlapped = new Overlapped().Pack((code, bytes, overlap) => { try { switch (code) { case Win32Error.ERROR_SUCCESS: outVal = Unpack <TIn, TOut>(buffer).Item2; tcs.TrySetResult(outVal); break; case Win32Error.ERROR_OPERATION_ABORTED: tcs.TrySetCanceled(); break; default: tcs.TrySetException(new Win32Exception((int)code)); break; } } finally { Overlapped.Unpack(overlap); Overlapped.Free(overlap); } }, buffer); var unpack = true; try { var inSz = Marshal.SizeOf(typeof(TIn)); fixed(byte *pIn = buffer, pOut = &buffer[inSz]) { uint bRet; var ret = DeviceIoControl(hDevice, ioControlCode, pIn, (uint)inSz, pOut, (uint)(buffer.Length - inSz), out bRet, nativeOverlapped); if (ret) { outVal = Unpack <TIn, TOut>(buffer).Item2; tcs.SetResult(outVal); return(tcs.Task); } } var lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error != Win32Error.ERROR_IO_PENDING && lastWin32Error != Win32Error.ERROR_SUCCESS) { throw new Win32Exception(lastWin32Error); } unpack = false; return(tcs.Task); } finally { if (unpack) { Overlapped.Unpack(nativeOverlapped); Overlapped.Free(nativeOverlapped); } } }
// // 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; }
public virtual void Attach(AttachVirtualDiskFlags flags = AttachVirtualDiskFlags.None, RawSecurityDescriptor securityDescriptor = null, uint providerSpecificFlags = 0, Overlapped overlapped = null) { var parameters = new AttachVirtualDiskParameters { Version = AttachVirtualDiskVersions.Version1 }; VirtualDiskCore.AttachVirtualDisk(Handle, securityDescriptor, flags, providerSpecificFlags, parameters, overlapped); }
public unsafe void EndReceive(uint code, uint bytes, NativeOverlapped *native) { Overlapped.Free(native); Message.Props.Free(); lock (Outstanding) Outstanding.Remove(this); if (code == 995) // operation aborted { Tcs.TrySetException(new QueueException(ErrorCode.OperationCanceled)); return; } var result = Native.GetOverlappedResult(native); try { switch (result) { case 0: Message.Props.ResizeBody(); Tcs.TrySetResult(Message); break; case (int)ErrorCode.InsufficientResources: Tcs.SetException(new OutOfMemoryException("async receive operation reported InsufficientResources")); break; case (int)ErrorCode.IOTimeout: Tcs.TrySetResult(null); break; default: // successfully completed but no enough memory if (Native.NotEnoughMemory(result)) { Message.Props.Free(); Message.Props.IncreaseBufferSize(); Props = Message.Props.Allocate(); var overlapped = new Overlapped(); var nativeOverlapped = overlapped.Pack(EndReceive, null); int res = Native.ReceiveMessage(handle, timeoutMS, action, Props, nativeOverlapped, null, cursor, IntPtr.Zero); if (res == MQ_INFORMATION_OPERATION_PENDING) // running asynchronously { return; } // call completed synchronously Message.Props.Free(); Overlapped.Free(nativeOverlapped); if (!Native.IsError(res)) { Message.Props.ResizeBody(); Tcs.TrySetResult(Message); return; } } // some other error Tcs.TrySetException(new QueueException(unchecked ((int)code))); // or do we use the result? break; } } catch (ObjectDisposedException ex) { Tcs.TrySetException(new QueueException(ErrorCode.OperationCanceled)); } }
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; }
protected void AsyncGetFromDiskCallback( uint errorCode, uint numBytes, NativeOverlapped *overlap) { //Debugger.Break(); var result = (AsyncGetFromDiskResult <AsyncIOContext>)Overlapped.Unpack(overlap).AsyncResult; try { if (errorCode != 0) { Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode); } } catch (Exception ex) { Trace.TraceError("Completion Callback error, {0}", ex.Message); } finally { Interlocked.Decrement(ref numPendingReads); var ctx = result.context; var record = ctx.record.GetValidPointer(); if (Layout.HasTotalRecord(record, ctx.record.available_bytes, out int requiredBytes)) { //We have the complete record. if (RetrievedObjects(record, ctx)) { if (Key.Equals(ctx.key, Layout.GetKey((long)record))) { //The keys are same, so I/O is complete // ctx.record = result.record; ctx.callbackQueue.Add(ctx); } else { var oldAddress = ctx.logicalAddress; //keys are not same. I/O is not complete ctx.logicalAddress = ((RecordInfo *)record)->PreviousAddress; if (ctx.logicalAddress != Constants.kInvalidAddress) { // Delete key, value, record if (Key.HasObjectsToSerialize()) { var physicalAddress = (long)ctx.record.GetValidPointer(); Key.Free(Layout.GetKey(physicalAddress)); } if (Value.HasObjectsToSerialize()) { var physicalAddress = (long)ctx.record.GetValidPointer(); Value.Free(Layout.GetValue(physicalAddress)); } ctx.record.Return(); AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx); } else { //Console.WriteLine("Lookup Address = " + oldAddress); //Console.WriteLine("RecordInfo: " + RecordInfo.ToString((RecordInfo*)record)); // Console.WriteLine("Record not found. Looking for: " + ctx.key->value + " found: " + Layout.GetKey((long)record)->value + " req bytes: " + requiredBytes); ctx.callbackQueue.Add(ctx); } } } } else { ctx.record.Return(); AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx); } Overlapped.Free(overlap); } }
public static extern bool ReadFile( UInt32 hFile, // handle to file byte[] lpBuffer, // data buffer UInt32 nNumberOfBytesToRead, // number of bytes to read out UInt32 lpNumberOfBytesRead, // number of bytes read Overlapped lpOverlapped // overlapped buffer );
public static extern bool ConnectNamedPipe( IntPtr hHandle, // handle to named pipe Overlapped lpOverlapped // overlapped structure );
public QueuedBuffer(int bufferSizeBytes) { BufferSize = bufferSizeBytes; Overlapped = new Overlapped(); PinnedBuffer = Marshal.AllocHGlobal(BufferSize); }
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 static void Main(string[] args) { using (var sw = File.CreateText("test.txt")) sw.WriteLine("Test!"); SafeFileHandle handle = CreateFile( "test.txt", EFileAccess.FILE_GENERIC_READ, EFileShare.Read | EFileShare.Write | EFileShare.Delete, (IntPtr)null, ECreationDisposition.OpenExisting, EFileAttributes.Overlapped, new SafeFileHandle(IntPtr.Zero, false)); if (!ThreadPool.BindHandle(handle)) { Console.WriteLine("Failed to bind handle to the threadpool."); return; } byte[] bytes = new byte[0x8000]; IOCompletionCallback iocomplete = delegate(uint errorCode, uint numBytes, NativeOverlapped *_overlapped) { unsafe { try { if (errorCode == ERROR_HANDLE_EOF) { Console.WriteLine("End of file in callback."); } if (errorCode != 0 && numBytes != 0) { Console.WriteLine("Error {0} when reading file.", errorCode); } Console.WriteLine("Read {0} bytes.", numBytes); } finally { Overlapped.Free(_overlapped); } } }; Overlapped overlapped = new Overlapped(); NativeOverlapped *pOverlapped = overlapped.Pack(iocomplete, bytes); pOverlapped->OffsetLow = 0; fixed(byte *p = bytes) { int r = ReadFile(handle, p, bytes.Length, IntPtr.Zero, pOverlapped); if (r == 0) { r = Marshal.GetLastWin32Error(); if (r == ERROR_HANDLE_EOF) { Console.WriteLine("Done."); } if (r != ERROR_IO_PENDING) { Console.WriteLine("Failed to read file. LastError is {0}", Marshal.GetLastWin32Error()); Overlapped.Free(pOverlapped); return; } } } Console.ReadLine(); }
/// <devdoc> /// Callback from thread pool. /// </devdoc> /// <internalonly/> private unsafe void CompletionStatusChanged(uint errorCode, uint numBytes, NativeOverlapped *overlappedPointer) { Overlapped overlapped = Overlapped.Unpack(overlappedPointer); FSWAsyncResult asyncResult = (FSWAsyncResult)overlapped.AsyncResult; try { if (_stopListening) { return; } lock (this) { if (errorCode != 0) { if (errorCode == 995 /* ERROR_OPERATION_ABORTED */) { //Inside a service the first completion status is false //cannot return without monitoring again. //Because this return statement is inside a try/finally block, //the finally block will execute. It does restart the monitoring. return; } else { OnError(new ErrorEventArgs(new Win32Exception((int)errorCode))); EnableRaisingEvents = false; return; } } // Ignore any events that occurred before this "session", // so we don't get changed or error events after we // told FSW to stop. if (asyncResult.session != _currentSession) { return; } if (numBytes == 0) { NotifyInternalBufferOverflowEvent(); } else { // Else, parse each of them and notify appropriate delegates /****** * Format for the buffer is the following C struct: * * typedef struct _FILE_NOTIFY_INFORMATION { * DWORD NextEntryOffset; * DWORD Action; * DWORD FileNameLength; * WCHAR FileName[1]; * } FILE_NOTIFY_INFORMATION; * * NOTE1: FileNameLength is length in bytes. * NOTE2: The Filename is a Unicode string that's NOT NULL terminated. * NOTE3: A NextEntryOffset of zero means that it's the last entry *******/ // Parse the file notify buffer: int offset = 0; int nextOffset, action, nameLength; string oldName = null; string name = null; do { fixed(byte *buffPtr = asyncResult.buffer) { // Get next offset: nextOffset = *((int *)(buffPtr + offset)); // Get change flag: action = *((int *)(buffPtr + offset + 4)); // Get filename length (in bytes): nameLength = *((int *)(buffPtr + offset + 8)); name = new string((char *)(buffPtr + offset + 12), 0, nameLength / 2); } /* A slightly convoluted piece of code follows. Here's what's happening: * * We wish to collapse the poorly done rename notifications from the * ReadDirectoryChangesW API into a nice rename event. So to do that, * it's assumed that a FILE_ACTION_RENAMED_OLD_NAME will be followed * immediately by a FILE_ACTION_RENAMED_NEW_NAME in the buffer, which is * all that the following code is doing. * * On a FILE_ACTION_RENAMED_OLD_NAME, it asserts that no previous one existed * and saves its name. If there are no more events in the buffer, it'll * assert and fire a RenameEventArgs with the Name field null. * * If a NEW_NAME action comes in with no previous OLD_NAME, we assert and fire * a rename event with the OldName field null. * * If the OLD_NAME and NEW_NAME actions are indeed there one after the other, * we'll fire the RenamedEventArgs normally and clear oldName. * * If the OLD_NAME is followed by another action, we assert and then fire the * rename event with the Name field null and then fire the next action. * * In case it's not a OLD_NAME or NEW_NAME action, we just fire the event normally. * * (Phew!) */ // If the action is RENAMED_FROM, save the name of the file if (action == Direct.FILE_ACTION_RENAMED_OLD_NAME) { Debug.Assert(oldName == null, "FileSystemWatcher: Two FILE_ACTION_RENAMED_OLD_NAME " + "in a row! [" + oldName + "], [ " + name + "]"); oldName = name; } else if (action == Direct.FILE_ACTION_RENAMED_NEW_NAME) { if (oldName != null) { NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName); oldName = null; } else { Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_NEW_NAME with no" + "old name! [ " + name + "]"); NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName); oldName = null; } } else { if (oldName != null) { Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" + "new name! [" + oldName + "]"); NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName); oldName = null; } // Notify each file of change NotifyFileSystemEventArgs(action, name); } offset += nextOffset; } while (nextOffset != 0); if (oldName != null) { Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" + "new name! [" + oldName + "]"); NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName); oldName = null; } } } } finally { Overlapped.Free(overlappedPointer); if (!_stopListening) { Monitor(asyncResult.buffer); } } }
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); } }
public static unsafe Task WriteAsync(SafeFileHandle hFile, long fileOffset, ArraySegment <byte> bytes) { if (fileOffset < 0) { throw new ArgumentOutOfRangeException(nameof(fileOffset)); } var asyncResult = new AsyncResult(); int low = (int)(fileOffset & 0xFFFFFFFF); int high = (int)(fileOffset >> 32); var o = new Overlapped(low, high, IntPtr.Zero, asyncResult); fixed(byte *bufferBase = bytes.Array) { // 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, bytes.Array); bool needToFree = true; try { if (WriteFile(hFile, bufferBase + bytes.Offset, bytes.Count, 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 bytesWritten = (int)pOverlapped->InternalHigh.ToInt64(); if (bytesWritten != bytes.Count) { throw new EndOfStreamException("Could not write all the bytes."); } return(CompletedTask); } else { int systemErrorCode = Marshal.GetLastWin32Error(); if (systemErrorCode == ERROR_IO_DEVICE) { throw new IOException($"WriteFile failed with system error ERROR_IO_DEVICE", new Win32Exception(systemErrorCode)); } else if (systemErrorCode == ERROR_IO_PENDING) { needToFree = false; } else { throw new Win32Exception(systemErrorCode, $"WriteFile failed with system error code:{systemErrorCode}"); } return(asyncResult.CompletionSource.Value.Task.ContinueWith(t => { if (t.Status == TaskStatus.RanToCompletion && t.Result != bytes.Count) { throw new EndOfStreamException("Could not write all the bytes."); } return t; })); } } finally { if (needToFree) { Overlapped.Unpack(pOverlapped); Overlapped.Free(pOverlapped); } } } }
internal HttpResponseStreamAsyncResult(object asyncObject, object userState, AsyncCallback callback, byte[] buffer, int offset, int size, bool chunked, bool sentHeaders) : base(asyncObject, userState, callback) { m_SentHeaders = sentHeaders; Overlapped overlapped = new Overlapped(); overlapped.AsyncResult = this; if (size == 0) { m_DataChunks = null; m_pOverlapped = overlapped.Pack(s_IOCallback, null); } else { m_DataChunks = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK[chunked ? 3 : 1]; GlobalLog.Print("HttpResponseStreamAsyncResult#" + ValidationHelper.HashString(this) + "::.ctor() m_pOverlapped:0x" + ((IntPtr)m_pOverlapped).ToString("x8")); object[] objectsToPin = new object[1 + m_DataChunks.Length]; objectsToPin[m_DataChunks.Length] = m_DataChunks; int chunkHeaderOffset = 0; byte[] chunkHeaderBuffer = null; if (chunked) { chunkHeaderBuffer = ConnectStream.GetChunkHeader(size, out chunkHeaderOffset); m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[0].BufferLength = (uint)(chunkHeaderBuffer.Length - chunkHeaderOffset); objectsToPin[0] = chunkHeaderBuffer; m_DataChunks[1] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[1].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[1].BufferLength = (uint)size; objectsToPin[1] = buffer; m_DataChunks[2] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[2].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[2].BufferLength = (uint)NclConstants.CRLF.Length; objectsToPin[2] = NclConstants.CRLF; } else { m_DataChunks[0] = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK(); m_DataChunks[0].DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; m_DataChunks[0].BufferLength = (uint)size; objectsToPin[0] = buffer; } // This call will pin needed memory m_pOverlapped = overlapped.Pack(s_IOCallback, objectsToPin); if (chunked) { m_DataChunks[0].pBuffer = (byte *)(Marshal.UnsafeAddrOfPinnedArrayElement(chunkHeaderBuffer, chunkHeaderOffset)); m_DataChunks[1].pBuffer = (byte *)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); m_DataChunks[2].pBuffer = (byte *)(Marshal.UnsafeAddrOfPinnedArrayElement(NclConstants.CRLF, 0)); } else { m_DataChunks[0].pBuffer = (byte *)(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset)); } } }
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.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. Overlapped.Free(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 static unsafe void WaitCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped *nativeOverlapped) { ListenerClientCertAsyncResult asyncResult = (ListenerClientCertAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult; HttpListenerRequest asyncObject = (HttpListenerRequest)asyncResult.AsyncObject; object result = null; try { if (errorCode == 0xea) { UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *requestBlob = asyncResult.RequestBlob; asyncResult.Reset(numBytes + requestBlob->CertEncodedSize); uint pBytesReceived = 0; errorCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(asyncObject.HttpListenerContext.RequestQueueHandle, asyncObject.m_ConnectionId, 0, asyncResult.m_MemoryBlob, asyncResult.m_Size, &pBytesReceived, asyncResult.m_pOverlapped); if ((errorCode == 0x3e5) || (errorCode == 0)) { return; } } if (errorCode != 0) { asyncResult.ErrorCode = (int)errorCode; result = new HttpListenerException((int)errorCode); } else { UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *memoryBlob = asyncResult.m_MemoryBlob; if (memoryBlob != null) { if (memoryBlob->pCertEncoded != null) { try { byte[] destination = new byte[memoryBlob->CertEncodedSize]; Marshal.Copy((IntPtr)memoryBlob->pCertEncoded, destination, 0, destination.Length); result = asyncObject.ClientCertificate = new X509Certificate2(destination); } catch (CryptographicException exception) { result = exception; } catch (SecurityException exception2) { result = exception2; } } asyncObject.SetClientCertificateError((int)memoryBlob->CertFlags); } } } catch (Exception exception3) { if (NclUtilities.IsFatal(exception3)) { throw; } result = exception3; } finally { if (errorCode != 0x3e5) { asyncObject.ClientCertState = ListenerClientCertState.Completed; } } asyncResult.InvokeCallback(result); }
public static extern bool WriteFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, ref Overlapped lpOverlapped );
public static extern bool ReadFileEx( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref Overlapped lpNumberOfBytesRead, EvtFileIOCompletionRoutine lpOverlapped );
public static extern bool ReadFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, ref Overlapped lpOverlapped );
public static extern bool GetOverlappedResultEx( IntPtr hHandle, ref Overlapped lpOverlapped, ref uint lpNumberOfBytesTransferred, uint dwMilliseconds, bool bWait );
public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) : base(addressFamily, socketType, protocolType) { m_disposed = false; m_inOverlapped = new Overlapped(this); m_outOverlapped = new Overlapped(this); m_sendWSABuffer = new WSABuffer(); m_receiveWSABuffer = new WSABuffer(); InitSocket(); InitDynamicMethods(); }