summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-10-27 13:40:17 +0100
committerDavid Lönnhager <david.l@mullvad.net>2021-07-02 09:54:19 +0200
commit5cd1b8f33eb9118f457518c25ef50fef97473c0a (patch)
tree9ea5ac3573e445b5135632daaf50b2899786155c
parent80020b12dd8ad57269164e33cd8b0012b7ed91c8 (diff)
downloadmullvadvpn-5cd1b8f33eb9118f457518c25ef50fef97473c0a.tar.xz
mullvadvpn-5cd1b8f33eb9118f457518c25ef50fef97473c0a.zip
Add device_io_control_buffer_async
-rw-r--r--talpid-core/src/split_tunnel/windows/driver.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/talpid-core/src/split_tunnel/windows/driver.rs b/talpid-core/src/split_tunnel/windows/driver.rs
index 97fd9181c8..2fc60ff2bd 100644
--- a/talpid-core/src/split_tunnel/windows/driver.rs
+++ b/talpid-core/src/split_tunnel/windows/driver.rs
@@ -747,6 +747,60 @@ pub fn device_io_control_buffer(
Ok(())
}
+/// Send an IOCTL code to the given device handle.
+/// `input` specifies an optional buffer to send.
+/// The result must be obtained using `GetOverlappedResultEx`.
+pub unsafe fn device_io_control_buffer_async(
+ device: RawHandle,
+ ioctl_code: u32,
+ mut output: Option<&mut Vec<u8>>,
+ input: Option<&[u8]>,
+ overlapped: &OVERLAPPED,
+) -> Result<(), io::Error> {
+ let input_ptr = match input {
+ Some(input) => input as *const _ as *mut _,
+ None => ptr::null_mut(),
+ };
+ let input_len = input.map(|input| input.len()).unwrap_or(0);
+
+ let out_ptr = match output {
+ Some(ref mut output) => output.as_mut_ptr() as *mut _,
+ None => ptr::null_mut(),
+ };
+ let output_size = if let Some(ref output) = output {
+ output.capacity()
+ } else {
+ 0
+ };
+
+ let overlapped = overlapped as *const _ as *mut _;
+
+ let result = DeviceIoControl(
+ device as *mut _,
+ ioctl_code,
+ input_ptr,
+ input_len as u32,
+ out_ptr,
+ output_size as u32,
+ ptr::null_mut(),
+ overlapped,
+ );
+
+ if result != 0 {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "Expected pending operation",
+ ));
+ }
+
+ let last_error = io::Error::last_os_error();
+ if last_error.raw_os_error() != Some(ERROR_IO_PENDING as i32) {
+ return Err(last_error);
+ }
+
+ Ok(())
+}
+
/// Creates a new instance of an arbitrary type from a byte buffer.
pub unsafe fn deserialize_buffer<T: Sized>(buffer: &Vec<u8>) -> T {
let mut instance: T = mem::zeroed();