/// <summary> /// Constructor /// </summary> public DeviceAsyncResult( SafePinnedObject outDeviceBuffer, AsyncCallback asyncCallback, object state ) : base(asyncCallback, state) { mOutDeviceBuffer = outDeviceBuffer; }
/// <summary> /// The completion callback for when the operation completes. This is /// an internal callback that frees the native memory and subsequently /// invokes the original caller's completion callback so it can /// retrieve the result. /// </summary> private unsafe void CompletionCallback( UInt32 errorCode, UInt32 numBytes, NativeOverlapped *nativeOverlapped ) { // First, free the NativeOverlapped structure and let this // IAsyncResult be collectable by the garbage collector Overlapped.Free(nativeOverlapped); try { if (errorCode != 0) { // Check if an error occurred and record the error if so base.SetAsCompleted(new Win32Exception((Int32)errorCode), false); } else { // No error occurred, so the output buffer must contain the // result! TResult result = (TResult)mOutDeviceBuffer.Target; // The result is going to be an array of bytes, so we need // to resize the array to the exact size so that the Length // property is accurate if ((result != null) && result.GetType().IsArray) { // Only resize if the number of elements initialized in // the array is less than the size of the array itself Type elementType = result.GetType().GetElementType(); Int64 numElements = numBytes / Marshal.SizeOf(elementType); Array originalArray = (Array)(object)result; if (numElements < originalArray.Length) { // Create a new array whose size is the number of // initialized elements Array newArray = Array.CreateInstance(elementType, numElements ); // Copy the initialized elements from the original // array to the new one Array.Copy(originalArray, newArray, numElements); result = (TResult)(object)newArray; } } // Record the result and call the AsyncCallback method base.SetAsCompleted(result, false); } } finally { // Make sure that the input and output buffers are unpinned mOutDeviceBuffer.Dispose(); mOutDeviceBuffer = null; // Allow early GC } }
public unsafe static extern bool DeviceIoControl( SafeFileHandle hDevice, int dwIoControlCode, byte[] lpInBuffer, int nInBufferSize, SafePinnedObject lpOutBuffer, int nOutBufferSize, ref uint lpBytesReturned, NativeOverlapped *lpOverlapped );
private DeviceAsyncResult <T> AsyncControl <T>(DeviceControlCode deviceControlCode, Object inBuffer, T outBuffer, AsyncCallback asyncCallback, Object state) { SafePinnedObject inDeviceBuffer = SafePinnedObject.FromObject(inBuffer); SafePinnedObject outDeviceBuffer = SafePinnedObject.FromObject(outBuffer); DeviceAsyncResult <T> asyncResult = new DeviceAsyncResult <T>(inDeviceBuffer, outDeviceBuffer, asyncCallback, state); unsafe { Int32 bytesReturned; NativeControl(deviceControlCode, inDeviceBuffer, outDeviceBuffer, out bytesReturned, asyncResult.GetNativeOverlapped()); } return(asyncResult); }
private Object SyncControl(DeviceControlCode deviceControlCode, Object inBuffer, Object outBuffer, out Int32 bytesReturned) { using (SafePinnedObject inDeviceBuffer = SafePinnedObject.FromObject(inBuffer)) using (SafePinnedObject outDeviceBuffer = SafePinnedObject.FromObject(outBuffer)) { unsafe { NativeControl(deviceControlCode, inDeviceBuffer, outDeviceBuffer, out bytesReturned, null); } } // When passed, the argument for outBuffer got boxed so we return a reference // to the object that contains the data returned from DeviceIoControl. return(outBuffer); }
// This method is called by a thread pool thread when native overlapped I/O completes private unsafe void CompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped *nativeOverlapped) { // Release the native OVERLAPPED structure and // let the IAsyncResult object (this) be collectable. Overlapped.Free(nativeOverlapped); try { if (errorCode != 0) { // An error occurred, record the Win32 error code base.SetAsCompleted(new Win32Exception((Int32)errorCode), false); } else { // No error occurred, the output buffer contains the result TResult result = (TResult)m_outBuffer.Target; // If the result is an array of values, resize the array // to the exact size so that the Length property is accurate if ((result != null) && result.GetType().IsArray) { // Only resize if the number of elements initialized in the // array is less than the size of the array itself Type elementType = result.GetType().GetElementType(); Int64 numElements = numBytes / Marshal.SizeOf(elementType); Array origArray = (Array)(Object)result; if (numElements < origArray.Length) { // Create a new array whose size equals the number of initialized elements Array newArray = Array.CreateInstance(elementType, numElements); // Copy the initialized elements from the original array to the new array Array.Copy(origArray, newArray, numElements); result = (TResult)(Object)newArray; } } // Record result and call AsyncCallback method passed to BeginXxx method base.SetAsCompleted(result, false); } } finally { // Make sure that the input and output buffers are unpinned m_inBuffer.Dispose(); m_outBuffer.Dispose(); m_inBuffer = m_outBuffer = null; // Allow early GC } }
private unsafe void NativeControl(DeviceControlCode deviceControlCode, SafePinnedObject inBuffer, SafePinnedObject outBuffer, out Int32 bytesReturned, NativeOverlapped *nativeOverlapped) { Boolean ok = NativeMethods.DeviceIoControl(m_device, deviceControlCode.Code, inBuffer, inBuffer.Size, outBuffer, outBuffer.Size, out bytesReturned, nativeOverlapped); if (ok) { return; } Int32 error = Marshal.GetLastWin32Error(); const Int32 c_ErrorIOPending = 997; if (error == c_ErrorIOPending) { return; } throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, "Control failed (code={0})", error)); }
// Constructs an instance specifying the input/output buffers public DeviceAsyncResult(SafePinnedObject inBuffer, SafePinnedObject outBuffer, AsyncCallback asyncCallback, Object state) : base(asyncCallback, state) { m_inBuffer = inBuffer; m_outBuffer = outBuffer; }
public static unsafe extern Boolean DeviceIoControl(SafeFileHandle device, Int32 controlCode, SafePinnedObject inBuffer, Int32 inBufferSize, SafePinnedObject outBuffer, Int32 outBufferSize, out Int32 bytesReturned, NativeOverlapped *nativeOverlapped);