/// <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
     );
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        // 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
            }
        }
Example #7
0
        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));
        }
Example #8
0
 // 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;
 }
Example #9
0
 public static unsafe extern Boolean DeviceIoControl(SafeFileHandle device, Int32 controlCode,
                                                     SafePinnedObject inBuffer, Int32 inBufferSize, SafePinnedObject outBuffer, Int32 outBufferSize,
                                                     out Int32 bytesReturned, NativeOverlapped *nativeOverlapped);