summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-10-17 11:24:08 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-10-20 18:17:06 +0200
commitb3cc38c2bea1869e495206ec1febc6a92bb300bc (patch)
tree6c9663ef925b5699db8c2befcb5fa910b0e28deb
parent5f5e7b3c0e4b14cd8cbd4e53919e3555e24319ed (diff)
downloadmullvadvpn-b3cc38c2bea1869e495206ec1febc6a92bb300bc.tar.xz
mullvadvpn-b3cc38c2bea1869e495206ec1febc6a92bb300bc.zip
Move Event and Overlapped to talpid-windows crate
-rw-r--r--Cargo.lock8
-rw-r--r--talpid-core/Cargo.toml1
-rw-r--r--talpid-core/src/split_tunnel/windows/driver.rs7
-rw-r--r--talpid-core/src/split_tunnel/windows/mod.rs31
-rw-r--r--talpid-core/src/split_tunnel/windows/windows.rs99
-rw-r--r--talpid-windows/Cargo.toml21
-rw-r--r--talpid-windows/src/io.rs49
-rw-r--r--talpid-windows/src/lib.rs12
-rw-r--r--talpid-windows/src/sync.rs75
9 files changed, 191 insertions, 112 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c929ce5754..63031c21c6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3456,6 +3456,7 @@ dependencies = [
"talpid-tunnel",
"talpid-tunnel-config-client",
"talpid-types",
+ "talpid-windows",
"talpid-windows-net",
"talpid-wireguard",
"tokio",
@@ -3622,6 +3623,13 @@ dependencies = [
]
[[package]]
+name = "talpid-windows"
+version = "0.0.0"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "talpid-windows-net"
version = "0.0.0"
dependencies = [
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index e39b07f244..40dae6b27b 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -61,6 +61,7 @@ winreg = { version = "0.51", features = ["transactions"] }
memoffset = "0.6"
windows-service = "0.6.0"
talpid-windows-net = { path = "../talpid-windows-net" }
+talpid-windows = { path = "../talpid-windows" }
[target.'cfg(windows)'.dependencies.windows-sys]
workspace = true
diff --git a/talpid-core/src/split_tunnel/windows/driver.rs b/talpid-core/src/split_tunnel/windows/driver.rs
index c868834518..eea79f188f 100644
--- a/talpid-core/src/split_tunnel/windows/driver.rs
+++ b/talpid-core/src/split_tunnel/windows/driver.rs
@@ -1,6 +1,6 @@
use super::windows::{
- get_device_path, get_process_creation_time, get_process_device_path, open_process, Event,
- Overlapped, ProcessAccess, ProcessSnapshot,
+ get_device_path, get_process_creation_time, get_process_device_path, open_process,
+ ProcessAccess, ProcessSnapshot,
};
use bitflags::bitflags;
use memoffset::offset_of;
@@ -22,6 +22,7 @@ use std::{
time::Duration,
};
use talpid_types::ErrorExt;
+use talpid_windows::{io::Overlapped, sync::Event};
use windows_sys::Win32::{
Foundation::{
ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND, ERROR_INVALID_PARAMETER, ERROR_IO_PENDING,
@@ -877,7 +878,7 @@ pub fn get_overlapped_result(
let event = overlapped.get_event().unwrap();
// SAFETY: This is a valid event object.
- unsafe { wait_for_single_object(event.as_handle(), None) }?;
+ unsafe { wait_for_single_object(event.as_raw(), None) }?;
// SAFETY: The handle and overlapped object are valid.
let mut returned_bytes = 0u32;
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs
index 40d7c340ad..dcabda7c8e 100644
--- a/talpid-core/src/split_tunnel/windows/mod.rs
+++ b/talpid-core/src/split_tunnel/windows/mod.rs
@@ -105,7 +105,7 @@ pub struct SplitTunnel {
runtime: tokio::runtime::Handle,
request_tx: RequestTx,
event_thread: Option<std::thread::JoinHandle<()>>,
- quit_event: Arc<windows::Event>,
+ quit_event: Arc<talpid_windows::sync::Event>,
excluded_processes: Arc<RwLock<HashMap<usize, ExcludedProcess>>>,
_route_change_callback: Option<CallbackHandle>,
daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
@@ -191,14 +191,21 @@ impl SplitTunnel {
fn spawn_event_listener(
handle: Arc<driver::DeviceHandle>,
excluded_processes: Arc<RwLock<HashMap<usize, ExcludedProcess>>>,
- ) -> Result<(std::thread::JoinHandle<()>, Arc<windows::Event>), Error> {
- let mut event_overlapped = windows::Overlapped::new(Some(
- windows::Event::new(true, false).map_err(Error::EventThreadError)?,
+ ) -> Result<
+ (
+ std::thread::JoinHandle<()>,
+ Arc<talpid_windows::sync::Event>,
+ ),
+ Error,
+ > {
+ let mut event_overlapped = talpid_windows::io::Overlapped::new(Some(
+ talpid_windows::sync::Event::new(true, false).map_err(Error::EventThreadError)?,
))
.map_err(Error::EventThreadError)?;
- let quit_event =
- Arc::new(windows::Event::new(true, false).map_err(Error::EventThreadError)?);
+ let quit_event = Arc::new(
+ talpid_windows::sync::Event::new(true, false).map_err(Error::EventThreadError)?,
+ );
let quit_event_copy = quit_event.clone();
let event_thread = std::thread::spawn(move || {
@@ -237,11 +244,11 @@ impl SplitTunnel {
fn fetch_next_event(
device: &Arc<driver::DeviceHandle>,
- quit_event: &windows::Event,
- overlapped: &mut windows::Overlapped,
+ quit_event: &talpid_windows::sync::Event,
+ overlapped: &mut talpid_windows::io::Overlapped,
data_buffer: &mut Vec<u8>,
) -> io::Result<EventResult> {
- if unsafe { driver::wait_for_single_object(quit_event.as_handle(), Some(Duration::ZERO)) }
+ if unsafe { driver::wait_for_single_object(quit_event.as_raw(), Some(Duration::ZERO)) }
.is_ok()
{
return Ok(EventResult::Quit);
@@ -268,8 +275,8 @@ impl SplitTunnel {
})?;
let event_objects = [
- overlapped.get_event().unwrap().as_handle(),
- quit_event.as_handle(),
+ overlapped.get_event().unwrap().as_raw(),
+ quit_event.as_raw(),
];
let signaled_object =
@@ -283,7 +290,7 @@ impl SplitTunnel {
},
)?;
- if signaled_object == quit_event.as_handle() {
+ if signaled_object == quit_event.as_raw() {
// Quit event was signaled
return Ok(EventResult::Quit);
}
diff --git a/talpid-core/src/split_tunnel/windows/windows.rs b/talpid-core/src/split_tunnel/windows/windows.rs
index 77fafdc199..423426c385 100644
--- a/talpid-core/src/split_tunnel/windows/windows.rs
+++ b/talpid-core/src/split_tunnel/windows/windows.rs
@@ -13,7 +13,7 @@ use std::{
};
use windows_sys::Win32::{
Foundation::{
- CloseHandle, BOOL, ERROR_INSUFFICIENT_BUFFER, ERROR_NO_MORE_FILES, FILETIME, HANDLE,
+ CloseHandle, ERROR_INSUFFICIENT_BUFFER, ERROR_NO_MORE_FILES, FILETIME, HANDLE,
INVALID_HANDLE_VALUE,
},
Storage::FileSystem::{GetFinalPathNameByHandleW, QueryDosDeviceW},
@@ -22,11 +22,8 @@ use windows_sys::Win32::{
CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W,
},
ProcessStatus::GetProcessImageFileNameW,
- Threading::{
- CreateEventW, GetProcessTimes, OpenProcess, SetEvent, PROCESS_QUERY_LIMITED_INFORMATION,
- },
+ Threading::{GetProcessTimes, OpenProcess, PROCESS_QUERY_LIMITED_INFORMATION},
WindowsProgramming::VOLUME_NAME_NT,
- IO::OVERLAPPED,
},
};
@@ -299,95 +296,3 @@ fn get_process_device_path_inner(
Ok(OsStringExt::from_wide(&buffer))
}
-
-/// Abstraction over `OVERLAPPED`, which is used for async I/O.
-pub struct Overlapped {
- overlapped: OVERLAPPED,
- event: Option<Event>,
-}
-
-unsafe impl Send for Overlapped {}
-unsafe impl Sync for Overlapped {}
-
-impl Overlapped {
- /// Creates an `OVERLAPPED` object with `hEvent` set.
- pub fn new(event: Option<Event>) -> io::Result<Self> {
- let mut overlapped = Overlapped {
- overlapped: unsafe { mem::zeroed() },
- event: None,
- };
- overlapped.set_event(event);
- Ok(overlapped)
- }
-
- /// Borrows the underlying `OVERLAPPED` object.
- pub fn as_mut_ptr(&mut self) -> *mut OVERLAPPED {
- &mut self.overlapped
- }
-
- /// Returns a reference to the associated event.
- pub fn get_event(&self) -> Option<&Event> {
- self.event.as_ref()
- }
-
- /// Sets the event object for the underlying `OVERLAPPED` object (i.e., `hEvent`)
- fn set_event(&mut self, event: Option<Event>) {
- match event {
- Some(event) => {
- self.overlapped.hEvent = event.0;
- self.event = Some(event);
- }
- None => {
- self.overlapped.hEvent = 0;
- self.event = None;
- }
- }
- }
-}
-
-/// Abstraction over a Windows event object.
-pub struct Event(HANDLE);
-
-unsafe impl Send for Event {}
-unsafe impl Sync for Event {}
-
-impl Event {
- pub fn new(manual_reset: bool, initial_state: bool) -> io::Result<Self> {
- let event = unsafe {
- CreateEventW(
- ptr::null_mut(),
- bool_to_winbool(manual_reset),
- bool_to_winbool(initial_state),
- ptr::null(),
- )
- };
- if event == 0 {
- return Err(io::Error::last_os_error());
- }
- Ok(Self(event))
- }
-
- pub fn set(&self) -> io::Result<()> {
- if unsafe { SetEvent(self.0) } == 0 {
- return Err(io::Error::last_os_error());
- }
- Ok(())
- }
-
- pub fn as_handle(&self) -> HANDLE {
- self.0
- }
-}
-
-impl Drop for Event {
- fn drop(&mut self) {
- unsafe { CloseHandle(self.0) };
- }
-}
-
-const fn bool_to_winbool(val: bool) -> BOOL {
- match val {
- true => 1,
- false => 0,
- }
-}
diff --git a/talpid-windows/Cargo.toml b/talpid-windows/Cargo.toml
new file mode 100644
index 0000000000..20a4d1ae3e
--- /dev/null
+++ b/talpid-windows/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "talpid-windows"
+description = "Nice abstractions for Windows"
+version.workspace = true
+authors.workspace = true
+repository.workspace = true
+license.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[target.'cfg(windows)'.dependencies.windows-sys]
+workspace = true
+features = [
+ "Win32_Foundation",
+ "Win32_Globalization",
+ "Win32_System_Com",
+ "Win32_System_IO",
+ "Win32_Networking_WinSock",
+ "Win32_NetworkManagement_IpHelper",
+ "Win32_NetworkManagement_Ndis",
+]
diff --git a/talpid-windows/src/io.rs b/talpid-windows/src/io.rs
new file mode 100644
index 0000000000..1bcffb30d3
--- /dev/null
+++ b/talpid-windows/src/io.rs
@@ -0,0 +1,49 @@
+use std::{io, mem};
+use windows_sys::Win32::System::IO::OVERLAPPED;
+
+use crate::sync::Event;
+
+/// Abstraction over `OVERLAPPED`.
+pub struct Overlapped {
+ overlapped: OVERLAPPED,
+ event: Option<Event>,
+}
+
+unsafe impl Send for Overlapped {}
+unsafe impl Sync for Overlapped {}
+
+impl Overlapped {
+ /// Creates an `OVERLAPPED` object with `hEvent` set.
+ pub fn new(event: Option<Event>) -> io::Result<Self> {
+ let mut overlapped = Overlapped {
+ overlapped: unsafe { mem::zeroed() },
+ event: None,
+ };
+ overlapped.set_event(event);
+ Ok(overlapped)
+ }
+
+ /// Borrows the underlying `OVERLAPPED` object.
+ pub fn as_mut_ptr(&mut self) -> *mut OVERLAPPED {
+ &mut self.overlapped
+ }
+
+ /// Returns a reference to the associated event.
+ pub fn get_event(&self) -> Option<&Event> {
+ self.event.as_ref()
+ }
+
+ /// Sets the event object for the underlying `OVERLAPPED` object (i.e., `hEvent`)
+ fn set_event(&mut self, event: Option<Event>) {
+ match event {
+ Some(event) => {
+ self.overlapped.hEvent = event.as_raw();
+ self.event = Some(event);
+ }
+ None => {
+ self.overlapped.hEvent = 0;
+ self.event = None;
+ }
+ }
+ }
+}
diff --git a/talpid-windows/src/lib.rs b/talpid-windows/src/lib.rs
new file mode 100644
index 0000000000..edc471aa33
--- /dev/null
+++ b/talpid-windows/src/lib.rs
@@ -0,0 +1,12 @@
+//! Interface with low-level windows specific bits.
+
+#![deny(missing_docs)]
+#![deny(rust_2018_idioms)]
+
+/// Windows I/O
+#[cfg(windows)]
+pub mod io;
+
+/// Synchronization (event objects, etc.)
+#[cfg(windows)]
+pub mod sync;
diff --git a/talpid-windows/src/sync.rs b/talpid-windows/src/sync.rs
new file mode 100644
index 0000000000..7b4ed59be3
--- /dev/null
+++ b/talpid-windows/src/sync.rs
@@ -0,0 +1,75 @@
+use std::{io, ptr};
+use windows_sys::Win32::{
+ Foundation::{CloseHandle, DuplicateHandle, BOOL, DUPLICATE_SAME_ACCESS, HANDLE},
+ System::Threading::{CreateEventW, GetCurrentProcess, SetEvent},
+};
+
+/// Windows event object
+pub struct Event(HANDLE);
+
+unsafe impl Send for Event {}
+unsafe impl Sync for Event {}
+
+impl Event {
+ /// Create a new event object using `CreateEventW`
+ pub fn new(manual_reset: bool, initial_state: bool) -> io::Result<Self> {
+ let event = unsafe {
+ CreateEventW(
+ ptr::null_mut(),
+ bool_to_winbool(manual_reset),
+ bool_to_winbool(initial_state),
+ ptr::null(),
+ )
+ };
+ if event == 0 {
+ return Err(io::Error::last_os_error());
+ }
+ Ok(Self(event))
+ }
+
+ /// Signal the event object
+ pub fn set(&self) -> io::Result<()> {
+ if unsafe { SetEvent(self.0) } == 0 {
+ return Err(io::Error::last_os_error());
+ }
+ Ok(())
+ }
+
+ /// Return raw event object
+ pub fn as_raw(&self) -> HANDLE {
+ self.0
+ }
+
+ /// Duplicate the event object with `DuplicateHandle()`
+ pub fn duplicate(&self) -> io::Result<Event> {
+ let mut new_event = 0;
+ let status = unsafe {
+ DuplicateHandle(
+ GetCurrentProcess(),
+ self.0,
+ GetCurrentProcess(),
+ &mut new_event,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS,
+ )
+ };
+ if status == 0 {
+ return Err(io::Error::last_os_error());
+ }
+ Ok(Event(new_event))
+ }
+}
+
+impl Drop for Event {
+ fn drop(&mut self) {
+ unsafe { CloseHandle(self.0) };
+ }
+}
+
+const fn bool_to_winbool(val: bool) -> BOOL {
+ match val {
+ true => 1,
+ false => 0,
+ }
+}