summaryrefslogtreecommitdiffhomepage
path: root/talpid-windows/src
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 /talpid-windows/src
parent5f5e7b3c0e4b14cd8cbd4e53919e3555e24319ed (diff)
downloadmullvadvpn-b3cc38c2bea1869e495206ec1febc6a92bb300bc.tar.xz
mullvadvpn-b3cc38c2bea1869e495206ec1febc6a92bb300bc.zip
Move Event and Overlapped to talpid-windows crate
Diffstat (limited to 'talpid-windows/src')
-rw-r--r--talpid-windows/src/io.rs49
-rw-r--r--talpid-windows/src/lib.rs12
-rw-r--r--talpid-windows/src/sync.rs75
3 files changed, 136 insertions, 0 deletions
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,
+ }
+}