/// <summary> /// Method to initiate a SYNCHRONOUS control command to the driver. /// /// The device handle MUST have been opened without the async option /// set prior to calling this method. /// /// This overload takes an int input and is used to query the driver /// what the mesh role is for this device. /// /// The main return value of this function is whether the /// DeviceIoControl operation succeeded or not; therefore, to determine /// if this device is a border router or not, the caller must verify /// both the result and the isBorderRouter parameter. /// </summary> /// <param name="device"></param> /// <param name="controlCode"></param> public unsafe static bool SynchronousControl( SafeFileHandle device, int controlCode, out bool isBorderRouter ) { uint meshRole = 0; uint bytesReturned = 0; // don't care about this in synchronous I/O bool result = Kernel32Import.DeviceIoControl(device, controlCode, 0, sizeof(uint), ref meshRole, sizeof(uint), ref bytesReturned, null ); if (result) { // Record the answer from the driver if (meshRole == 1) { isBorderRouter = true; } else { isBorderRouter = false; } } else { isBorderRouter = false; } // Close the driver handle Kernel32Import.CloseHandle(device); return(result); }
/// <summary> /// Method to initiate a SYNCHRONOUS control command to the driver. /// /// The device handle MUST have been opened without the async option /// set prior to calling this method. /// /// This overload does not take any input and is used only in the /// list purge IOCTLs that have no input or output. /// </summary> /// <param name="device"></param> /// <param name="controlCode"></param> public unsafe static bool SynchronousControl( SafeFileHandle device, int controlCode ) { uint bytesReturned = 0; // don't care about this in synchronous I/O bool result = Kernel32Import.DeviceIoControl(device, controlCode, new byte[0], 0, new byte[0], 0, ref bytesReturned, null ); // Close the driver handle Kernel32Import.CloseHandle(device); return(result); }
/// <summary> /// Method to initiate a SYNCHRONOUS control command to the driver. /// /// The device handle MUST have been opened without the async option /// set prior to calling this method. /// /// This overload takes a string input and is used for list operations. /// </summary> /// <param name="device"></param> /// <param name="controlCode"></param> public unsafe static bool SynchronousControl( SafeFileHandle device, int controlCode, String ipv6Address ) { uint bytesReturned = 0; // don't care about this in synchronous I/O bool result = Kernel32Import.DeviceIoControl(device, controlCode, ipv6Address, sizeof(char) * ipv6Address.Length, null, 0, ref bytesReturned, null ); // Close the driver handle Kernel32Import.CloseHandle(device); return(result); }
/// <summary> /// Helper method that actually sends the given IOCTL to the driver by /// calling the native DeviceIOControl() function. Called by AsyncControl(). /// </summary> private static unsafe void NativeAsyncControl( SafeFileHandle device, int controlCode, SafePinnedObject outBuffer, ref uint bytesReturned, NativeOverlapped *nativeOverlapped ) { bool succeeded = Kernel32Import.DeviceIoControl(device, controlCode, null, 0, outBuffer, outBuffer.Size, ref bytesReturned, nativeOverlapped ); // If DeviceIoControl returns TRUE, the operation completed // synchronously if (succeeded) { throw new InvalidOperationException($"Async call to DeviceIoControl completed synchronously."); } // DeviceIoControl is operating asynchronously; test the returned // error code to see if it is pending or not Int32 error = Marshal.GetLastWin32Error(); const Int32 cErrorIOPending = 997; // system-defined code for pending I/O if (error == cErrorIOPending) { return; } // Throw an exception if DeviceIoControl fails altogether throw new InvalidOperationException($"Control failed with error {error}"); }