summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-09-29 12:51:17 +0200
committerDavid Lönnhager <david.l@mullvad.net>2025-10-03 16:42:48 +0200
commit13f2bab900c5fce9594f5351dbf2207e04ba8070 (patch)
tree044cedd906f9a9e7c99886e1547fd75a2b660c29
parent2d5bbb21f8531f0e180b3469912e32e3162bfc12 (diff)
downloadmullvadvpn-13f2bab900c5fce9594f5351dbf2207e04ba8070.tar.xz
mullvadvpn-13f2bab900c5fce9594f5351dbf2207e04ba8070.zip
Bump windows-sys version to latest
This also refactors and documents some code
-rw-r--r--Cargo.lock200
-rw-r--r--Cargo.toml3
-rw-r--r--desktop/packages/windows-utils/Cargo.toml2
-rw-r--r--installer-downloader/src/winapi_impl/delegate.rs4
-rw-r--r--installer-downloader/src/winapi_impl/ui.rs13
-rw-r--r--mullvad-daemon/Cargo.toml4
-rw-r--r--mullvad-daemon/src/migrations/mod.rs7
-rw-r--r--mullvad-paths/src/windows.rs143
-rw-r--r--talpid-core/src/dns/windows/dnsapi.rs5
-rw-r--r--talpid-core/src/dns/windows/iphlpapi.rs10
-rw-r--r--talpid-core/src/dns/windows/netsh.rs2
-rw-r--r--talpid-core/src/split_tunnel/windows/driver.rs20
-rw-r--r--talpid-core/src/split_tunnel/windows/mod.rs11
-rw-r--r--talpid-core/src/split_tunnel/windows/path_monitor.rs9
-rw-r--r--talpid-core/src/split_tunnel/windows/windows.rs3
-rw-r--r--talpid-core/src/window.rs8
-rw-r--r--talpid-openvpn/src/wintun.rs13
-rw-r--r--talpid-platform-metadata/src/windows.rs2
-rw-r--r--talpid-routing/src/windows/default_route_monitor.rs33
-rw-r--r--talpid-routing/src/windows/get_best_default_route.rs12
-rw-r--r--talpid-tunnel-config-client/Cargo.toml4
-rw-r--r--talpid-tunnel/src/windows.rs6
-rw-r--r--talpid-windows/src/fs.rs2
-rw-r--r--talpid-windows/src/io.rs6
-rw-r--r--talpid-windows/src/net.rs51
-rw-r--r--talpid-windows/src/process.rs54
-rw-r--r--talpid-windows/src/sync.rs47
-rw-r--r--talpid-wireguard/src/wireguard_nt/daita.rs20
-rw-r--r--talpid-wireguard/src/wireguard_nt/mod.rs41
-rw-r--r--test/Cargo.lock21
-rw-r--r--wireguard-go-rs/Cargo.toml2
31 files changed, 421 insertions, 337 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ba67067ff2..03de3831a9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1198,7 +1198,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -2402,7 +2402,7 @@ dependencies = [
"serde",
"talpid-platform-metadata",
"tokio",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winres",
]
@@ -3047,7 +3047,7 @@ dependencies = [
"talpid-types",
"thiserror 2.0.9",
"tokio",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winres",
]
@@ -3105,7 +3105,7 @@ dependencies = [
"tokio-stream",
"winapi",
"windows-service",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winres",
]
@@ -3202,7 +3202,7 @@ dependencies = [
"socket2 0.5.8",
"talpid-windows",
"tokio",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -3252,7 +3252,7 @@ dependencies = [
"thiserror 2.0.9",
"tokio",
"typed-builder 0.21.0",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -3272,7 +3272,7 @@ dependencies = [
"once_cell",
"thiserror 2.0.9",
"widestring",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -3293,7 +3293,7 @@ dependencies = [
"thiserror 2.0.9",
"tokio",
"uuid",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winres",
]
@@ -3352,7 +3352,7 @@ dependencies = [
"thiserror 2.0.9",
"tokio",
"windows-service",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -5574,7 +5574,7 @@ dependencies = [
"windows 0.58.0",
"windows-core 0.58.0",
"windows-service",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winreg 0.51.0",
"wmi",
]
@@ -5646,7 +5646,7 @@ dependencies = [
"uuid",
"widestring",
"winapi",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winreg 0.51.0",
]
@@ -5669,7 +5669,7 @@ dependencies = [
"tonic-build",
"tower",
"winapi",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"winres",
]
@@ -5680,7 +5680,7 @@ dependencies = [
"rs-release",
"talpid-dbus",
"talpid-windows",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -5704,7 +5704,7 @@ dependencies = [
"thiserror 2.0.9",
"tokio",
"widestring",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -5731,7 +5731,7 @@ dependencies = [
"tokio",
"tun 0.5.5",
"tun 0.7.13",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -5753,7 +5753,6 @@ dependencies = [
"tonic",
"tonic-build",
"tower",
- "windows-sys 0.52.0",
"zeroize",
]
@@ -5780,7 +5779,7 @@ dependencies = [
"socket2 0.5.8",
"talpid-types",
"thiserror 2.0.9",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -5826,7 +5825,7 @@ dependencies = [
"tun 0.7.13",
"tunnel-obfuscation",
"widestring",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"wireguard-go-rs",
"zeroize",
]
@@ -6749,12 +6748,24 @@ dependencies = [
[[package]]
name = "windows"
-version = "0.59.0"
+version = "0.61.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
+dependencies = [
+ "windows-collections",
+ "windows-core 0.61.2",
+ "windows-future",
+ "windows-link 0.1.3",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
- "windows-core 0.59.0",
- "windows-targets 0.53.0",
+ "windows-core 0.61.2",
]
[[package]]
@@ -6781,15 +6792,26 @@ dependencies = [
[[package]]
name = "windows-core"
-version = "0.59.0"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
+dependencies = [
+ "windows-implement 0.60.1",
+ "windows-interface 0.59.2",
+ "windows-link 0.1.3",
+ "windows-result 0.3.4",
+ "windows-strings 0.4.2",
+]
+
+[[package]]
+name = "windows-future"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
+checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
- "windows-implement 0.59.0",
- "windows-interface 0.59.0",
- "windows-result 0.3.0",
- "windows-strings 0.3.0",
- "windows-targets 0.53.0",
+ "windows-core 0.61.2",
+ "windows-link 0.1.3",
+ "windows-threading",
]
[[package]]
@@ -6805,9 +6827,9 @@ dependencies = [
[[package]]
name = "windows-implement"
-version = "0.59.0"
+version = "0.60.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
+checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
dependencies = [
"proc-macro2",
"quote",
@@ -6839,9 +6861,9 @@ dependencies = [
[[package]]
name = "windows-interface"
-version = "0.59.0"
+version = "0.59.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
+checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
dependencies = [
"proc-macro2",
"quote",
@@ -6849,6 +6871,28 @@ dependencies = [
]
[[package]]
+name = "windows-link"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+
+[[package]]
+name = "windows-link"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
+
+[[package]]
+name = "windows-numerics"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
+dependencies = [
+ "windows-core 0.61.2",
+ "windows-link 0.1.3",
+]
+
+[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6859,11 +6903,11 @@ dependencies = [
[[package]]
name = "windows-result"
-version = "0.3.0"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
- "windows-targets 0.53.0",
+ "windows-link 0.1.3",
]
[[package]]
@@ -6889,11 +6933,11 @@ dependencies = [
[[package]]
name = "windows-strings"
-version = "0.3.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
- "windows-targets 0.53.0",
+ "windows-link 0.1.3",
]
[[package]]
@@ -6946,6 +6990,15 @@ dependencies = [
]
[[package]]
+name = "windows-sys"
+version = "0.61.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
+dependencies = [
+ "windows-link 0.2.0",
+]
+
+[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6984,7 +7037,7 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm 0.52.6",
+ "windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
@@ -6992,19 +7045,12 @@ dependencies = [
]
[[package]]
-name = "windows-targets"
-version = "0.53.0"
+name = "windows-threading"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
+checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
dependencies = [
- "windows_aarch64_gnullvm 0.53.0",
- "windows_aarch64_msvc 0.53.0",
- "windows_i686_gnu 0.53.0",
- "windows_i686_gnullvm 0.53.0",
- "windows_i686_msvc 0.53.0",
- "windows_x86_64_gnu 0.53.0",
- "windows_x86_64_gnullvm 0.53.0",
- "windows_x86_64_msvc 0.53.0",
+ "windows-link 0.1.3",
]
[[package]]
@@ -7015,7 +7061,7 @@ dependencies = [
"talpid-types",
"talpid-windows",
"thiserror 2.0.9",
- "windows 0.59.0",
+ "windows 0.61.3",
]
[[package]]
@@ -7037,12 +7083,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
-
-[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7067,12 +7107,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
-name = "windows_aarch64_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
-
-[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7097,24 +7131,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
-name = "windows_i686_gnu"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
-
-[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
-name = "windows_i686_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
-
-[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7139,12 +7161,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
-name = "windows_i686_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
-
-[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7169,12 +7185,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
-name = "windows_x86_64_gnu"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
-
-[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7193,12 +7203,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
-
-[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7223,12 +7227,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
-name = "windows_x86_64_msvc"
-version = "0.53.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
-
-[[package]]
name = "winnow"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7301,7 +7299,7 @@ dependencies = [
"maybenot-ffi",
"talpid-types",
"thiserror 2.0.9",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
"zeroize",
]
diff --git a/Cargo.toml b/Cargo.toml
index 39d3603f46..2301179fcf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -95,7 +95,8 @@ clap = { version = "4.4.18", features = ["cargo", "derive"] }
once_cell = "1.16"
serde = "1.0.204"
serde_json = "1.0.122"
-windows-sys = "0.52.0"
+windows = "0.61.0"
+windows-sys = "0.61.0"
nix = "0.30.1"
strum = { version = "0.27" }
rand = "0.9"
diff --git a/desktop/packages/windows-utils/Cargo.toml b/desktop/packages/windows-utils/Cargo.toml
index f64ea99812..a52b025a58 100644
--- a/desktop/packages/windows-utils/Cargo.toml
+++ b/desktop/packages/windows-utils/Cargo.toml
@@ -17,7 +17,7 @@ path = "windows-utils-rs/lib.rs"
[target.'cfg(target_os = "windows")'.dependencies]
neon = "1"
-windows = { version = "0.59.0", features = ["Win32", "Win32_UI", "Win32_UI_Shell", "Win32_System", "Win32_System_Com", "Win32_Storage_FileSystem"] }
+windows = { workspace = true, features = ["Win32", "Win32_UI", "Win32_UI_Shell", "Win32_System", "Win32_System_Com", "Win32_Storage_FileSystem"] }
thiserror = { workspace = true }
talpid-types = { path = "../../../talpid-types" }
diff --git a/installer-downloader/src/winapi_impl/delegate.rs b/installer-downloader/src/winapi_impl/delegate.rs
index 1734642771..475fc58786 100644
--- a/installer-downloader/src/winapi_impl/delegate.rs
+++ b/installer-downloader/src/winapi_impl/delegate.rs
@@ -3,7 +3,7 @@
use installer_downloader::delegate::ErrorMessage;
use native_windows_gui::{self as nwg, Event};
-use windows_sys::Win32::UI::WindowsAndMessaging::PostMessageW;
+use windows_sys::Win32::{Foundation::HWND, UI::WindowsAndMessaging::PostMessageW};
use super::ui::{AppWindow, QUEUE_MESSAGE};
use crate::delegate::{AppDelegate, AppDelegateQueue};
@@ -247,6 +247,6 @@ impl AppDelegateQueue<AppWindow> for Queue {
};
let context_ptr = Box::into_raw(Box::new(context));
// SAFETY: This is safe since `callback` is Send
- unsafe { PostMessageW(hwnd as isize, QUEUE_MESSAGE, 0, context_ptr as isize) };
+ unsafe { PostMessageW(hwnd as HWND, QUEUE_MESSAGE, 0, context_ptr as isize) };
}
}
diff --git a/installer-downloader/src/winapi_impl/ui.rs b/installer-downloader/src/winapi_impl/ui.rs
index 6c44f36101..df9439ccb0 100644
--- a/installer-downloader/src/winapi_impl/ui.rs
+++ b/installer-downloader/src/winapi_impl/ui.rs
@@ -8,7 +8,8 @@ use native_windows_gui::{self as nwg, ControlHandle, ImageDecoder, WindowFlags};
use windows_sys::Win32::Foundation::COLORREF;
use windows_sys::Win32::Graphics::Gdi::{
- COLOR_WINDOW, CreateFontIndirectW, LOGFONTW, SetBkColor, SetBkMode, SetTextColor, TRANSPARENT,
+ COLOR_WINDOW, CreateFontIndirectW, HDC, LOGFONTW, SetBkColor, SetBkMode, SetTextColor,
+ TRANSPARENT,
};
use windows_sys::Win32::UI::WindowsAndMessaging::WM_CTLCOLORSTATIC;
@@ -392,8 +393,8 @@ fn handle_banner_label_colors(
if msg == WM_CTLCOLORSTATIC {
// SAFETY: `w` is a valid device context for WM_CTLCOLORSTATIC
unsafe {
- SetTextColor(w as isize, rgb([255, 255, 255]));
- SetBkColor(w as isize, rgb(BACKGROUND_COLOR));
+ SetTextColor(w as HDC, rgb([255, 255, 255]));
+ SetBkColor(w as HDC, rgb(BACKGROUND_COLOR));
}
}
None
@@ -411,8 +412,8 @@ fn handle_link_messages(
if msg == WM_CTLCOLORSTATIC && Some(p) == link_hwnd {
// SAFETY: `w` is a valid device context for WM_CTLCOLORSTATIC
unsafe {
- SetBkMode(w as isize, TRANSPARENT as _);
- SetTextColor(w as isize, rgb(LINK_COLOR));
+ SetBkMode(w as HDC, TRANSPARENT as _);
+ SetTextColor(w as HDC, rgb(LINK_COLOR));
}
// Out of bounds background
return Some(COLOR_WINDOW as isize);
@@ -488,7 +489,7 @@ fn create_link_font() -> Result<&'static nwg::Font, nwg::NwgError> {
// SAFETY: `logfont` is a valid font
let raw_font = unsafe { CreateFontIndirectW(&logfont) };
- if raw_font == 0 {
+ if raw_font.is_null() {
return Err(nwg::NwgError::Unknown);
}
diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml
index dfc1607467..5b1132fa10 100644
--- a/mullvad-daemon/Cargo.toml
+++ b/mullvad-daemon/Cargo.toml
@@ -104,9 +104,7 @@ mullvad-version = { path = "../mullvad-version" }
[target.'cfg(windows)'.build-dependencies.windows-sys]
workspace = true
-features = [
- "Win32_System_SystemServices",
-]
+features = ["Win32_System_SystemServices"]
[package.metadata.winres]
ProductName = "Mullvad VPN"
diff --git a/mullvad-daemon/src/migrations/mod.rs b/mullvad-daemon/src/migrations/mod.rs
index 284928073e..ea7d4523ee 100644
--- a/mullvad-daemon/src/migrations/mod.rs
+++ b/mullvad-daemon/src/migrations/mod.rs
@@ -243,11 +243,12 @@ mod windows {
use talpid_types::ErrorExt;
use tokio::fs;
use windows_sys::Win32::{
- Foundation::{ERROR_SUCCESS, LocalFree, PSID},
+ Foundation::{ERROR_SUCCESS, LocalFree},
Security::{
Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT, SE_OBJECT_TYPE},
- IsWellKnownSid, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR,
- SID, WELL_KNOWN_SID_TYPE, WinBuiltinAdministratorsSid, WinLocalSystemSid,
+ IsWellKnownSid, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, PSID,
+ SECURITY_DESCRIPTOR, SID, WELL_KNOWN_SID_TYPE, WinBuiltinAdministratorsSid,
+ WinLocalSystemSid,
},
};
diff --git a/mullvad-paths/src/windows.rs b/mullvad-paths/src/windows.rs
index a81cf3ae34..ae58891e3e 100644
--- a/mullvad-paths/src/windows.rs
+++ b/mullvad-paths/src/windows.rs
@@ -1,11 +1,15 @@
-#![allow(clippy::undocumented_unsafe_blocks)] // Remove me if you dare.
-
use crate::{Error, Result, UserPermissions};
use once_cell::sync::OnceCell;
use std::{
ffi::OsStr,
io, mem,
- os::windows::prelude::OsStrExt,
+ os::windows::{
+ io::{
+ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, HandleOrNull, IntoRawHandle,
+ OwnedHandle,
+ },
+ prelude::OsStrExt,
+ },
path::{Path, PathBuf},
ptr,
};
@@ -13,8 +17,8 @@ use widestring::{WideCStr, WideCString};
use windows_sys::{
Win32::{
Foundation::{
- CloseHandle, ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS, GENERIC_ALL, GENERIC_EXECUTE,
- GENERIC_READ, GENERIC_WRITE, HANDLE, INVALID_HANDLE_VALUE, LUID, LocalFree, S_OK,
+ ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS, GENERIC_ALL, GENERIC_EXECUTE, GENERIC_READ,
+ GENERIC_WRITE, HANDLE, LUID, LocalFree, S_OK,
},
Security::{
self, AdjustTokenPrivileges,
@@ -74,18 +78,6 @@ pub fn create_dir(path: PathBuf, user_permissions: Option<UserPermissions>) -> R
Ok(path)
}
-struct Handle(HANDLE);
-
-impl Drop for Handle {
- fn drop(&mut self) {
- if self.0 != 0 && self.0 != INVALID_HANDLE_VALUE {
- unsafe {
- CloseHandle(self.0);
- }
- }
- }
-}
-
fn get_wide_str<S: AsRef<OsStr>>(string: S) -> Vec<u16> {
let wide_string: Vec<u16> = string.as_ref()
.encode_wide()
@@ -178,6 +170,8 @@ fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> R
let mut admin_psid = [0u8; MAX_SID_SIZE as usize];
let mut admin_psid_len = u32::try_from(admin_psid.len()).unwrap();
+
+ // SAFETY: The pointer to the PSID is valid for writes of `admin_psid_len` bytes
if unsafe {
CreateWellKnownSid(
WinBuiltinAdministratorsSid,
@@ -210,6 +204,8 @@ fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> R
let mut au_psid = [0u8; MAX_SID_SIZE as usize];
let mut au_psid_len = u32::try_from(au_psid.len()).unwrap();
+
+ // SAFETY: The pointer to the PSID is valid for writes of `au_psid_len` bytes
if unsafe {
CreateWellKnownSid(
WinAuthenticatedUserSid,
@@ -243,6 +239,8 @@ fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> R
let ea_entries = [admin_ea, authenticated_users_ea];
let mut new_dacl = ptr::null_mut();
+ // SAFETY: `ea_entries` is valid for reads of `ea_entries.len()` elements
+ // `new_dacl` is a valid pointer to an ACL pointer
let result = unsafe {
SetEntriesInAclW(
u32::try_from(ea_entries.len()).unwrap(),
@@ -261,6 +259,7 @@ fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> R
}
// new_dacl is now allocated and must be freed with FreeLocal
+ // SAFETY: All pointers are valid
let result = unsafe {
SetNamedSecurityInfoW(
wide_path.as_ptr(),
@@ -273,6 +272,7 @@ fn set_security_permissions(path: &Path, user_permissions: UserPermissions) -> R
)
};
+ // SAFETY: `new_dacl` is a valid pointer since `SetEntriesInAclW` succeeded
unsafe { LocalFree(new_dacl.cast()) };
if result != ERROR_SUCCESS {
@@ -295,8 +295,15 @@ pub fn get_system_service_appdata() -> io::Result<PathBuf> {
.get_or_try_init(|| {
let join_handle = std::thread::spawn(|| {
impersonate_self(|| {
- let user_token = get_system_user_token()?;
- get_known_folder_path(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, user_token.0)
+ let user_token = OwnedHandle::try_from(get_system_user_token()?).ok();
+ // SAFETY: `FOLDERID_LocalAppData` is a valid known folder ID
+ unsafe {
+ get_known_folder_path(
+ &FOLDERID_LocalAppData,
+ KF_FLAG_DEFAULT,
+ user_token.as_ref().map(|t| t.as_handle()),
+ )
+ }
})
.or_else(|error| {
log::error!("Failed to get AppData path: {error}");
@@ -311,54 +318,60 @@ pub fn get_system_service_appdata() -> io::Result<PathBuf> {
/// Get user token for the system service user. Requires elevated privileges to work.
/// Useful for deducing the config path for the daemon on Windows when running as a user that
/// isn't the system service.
-/// If the current user is system, this function succeeds and returns a `NULL` handle;
-fn get_system_user_token() -> io::Result<Handle> {
+/// If the current user is system, this function succeeds and returns a NULL handle
+fn get_system_user_token() -> io::Result<HandleOrNull> {
let thread_token = get_current_thread_token()?;
- if is_local_system_user_token(thread_token.0)? {
- return Ok(Handle(0));
+ if is_local_system_user_token(&thread_token)? {
+ // SAFETY: It is safe to pass a null handle
+ return Ok(unsafe { HandleOrNull::from_raw_handle(ptr::null_mut()) });
}
let system_debug_priv = WideCString::from_str("SeDebugPrivilege").unwrap();
- adjust_token_privilege(thread_token.0, &system_debug_priv, true)?;
+ adjust_token_privilege(&thread_token, &system_debug_priv, true)?;
let find_result = find_process(|process_handle| {
let process_token = open_process_token(
- process_handle,
+ &process_handle,
GENERIC_READ | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
)
.ok()?;
- match is_local_system_user_token(process_token.0) {
+ match is_local_system_user_token(&process_token) {
Ok(true) => Some(process_token),
_ => None,
}
});
- if let Err(err) = adjust_token_privilege(thread_token.0, &system_debug_priv, false) {
+ if let Err(err) = adjust_token_privilege(&thread_token, &system_debug_priv, false) {
log::error!("Failed to drop SeDebugPrivilege: {}", err);
}
- find_result
+ // SAFETY: The handle is valid
+ find_result.map(|h| unsafe { HandleOrNull::from_raw_handle(h.into_raw_handle()) })
}
-fn open_process_token(process: HANDLE, access: u32) -> io::Result<Handle> {
- let mut process_token = 0;
- if unsafe { OpenProcessToken(process, access, &mut process_token) } == 0 {
+fn open_process_token(process: &impl AsRawHandle, access: u32) -> io::Result<OwnedHandle> {
+ let mut process_token = ptr::null_mut();
+ // SAFETY: `process` is a valid handle
+ if unsafe { OpenProcessToken(process.as_raw_handle(), access, &mut process_token) } == 0 {
return Err(io::Error::last_os_error());
}
- Ok(Handle(process_token))
+ // SAFETY: `process_token` is a valid handle since `OpenProcessToken` succeeded
+ Ok(unsafe { OwnedHandle::from_raw_handle(process_token) })
}
/// If all else fails, infer the AppData path from the system directory.
fn infer_appdata_from_system_directory() -> io::Result<PathBuf> {
- let mut sysdir = get_known_folder_path(&FOLDERID_System, KF_FLAG_DEFAULT, 0)?;
+ // SAFETY: `FOLDERID_System` is a valid known folder ID
+ let mut sysdir = unsafe { get_known_folder_path(&FOLDERID_System, KF_FLAG_DEFAULT, None) }?;
sysdir.extend(["config", "systemprofile", "AppData", "Local"]);
Ok(sysdir)
}
-fn get_current_thread_token() -> std::io::Result<Handle> {
- let mut token_handle: HANDLE = 0;
+fn get_current_thread_token() -> std::io::Result<OwnedHandle> {
+ let mut token_handle: HANDLE = ptr::null_mut();
+ // SAFETY: `GetCurrentThread` always returns a valid handle
if unsafe {
OpenThreadToken(
GetCurrentThread(),
@@ -370,16 +383,19 @@ fn get_current_thread_token() -> std::io::Result<Handle> {
{
return Err(std::io::Error::last_os_error());
}
- Ok(Handle(token_handle))
+ // SAFETY: `token_handle` is a valid handle since `OpenThreadToken` succeeded
+ Ok(unsafe { OwnedHandle::from_raw_handle(token_handle) })
}
fn impersonate_self<T>(func: impl FnOnce() -> io::Result<T>) -> io::Result<T> {
+ // SAFETY: Trivially safe
if unsafe { ImpersonateSelf(SecurityImpersonation) } == 0 {
return Err(std::io::Error::last_os_error());
}
let result = func();
+ // SAFETY: Trivially safe
if unsafe { RevertToSelf() } == 0 {
log::error!("RevertToSelf failed: {}", io::Error::last_os_error());
}
@@ -388,13 +404,13 @@ fn impersonate_self<T>(func: impl FnOnce() -> io::Result<T>) -> io::Result<T> {
}
fn adjust_token_privilege(
- token_handle: HANDLE,
+ token_handle: &impl AsRawHandle,
privilege: &WideCStr,
enable: bool,
) -> std::io::Result<()> {
- // SAFETY: LUID is a C struct and can safely be zeroed.
- let mut privilege_luid: LUID = unsafe { mem::zeroed() };
+ let mut privilege_luid = LUID::default();
+ // SAFETY: `privilege` is a valid null-terminated string, and `privilege_luid` points to a LUID
if unsafe { LookupPrivilegeValueW(ptr::null(), privilege.as_ptr(), &mut privilege_luid) } == 0 {
return Err(std::io::Error::last_os_error());
}
@@ -406,9 +422,10 @@ fn adjust_token_privilege(
Attributes: if enable { SE_PRIVILEGE_ENABLED } else { 0 },
}],
};
+ // SAFETY: All pointers are valid
let result = unsafe {
AdjustTokenPrivileges(
- token_handle,
+ token_handle.as_raw_handle(),
0,
&privileges,
0,
@@ -426,15 +443,30 @@ fn adjust_token_privilege(
Ok(())
}
-fn get_known_folder_path(
+/// Retrieve path to a known folder for a specific user token.
+///
+/// # Safety
+///
+/// `folder_id` must be a valid pointer to a known folder ID GUID.
+unsafe fn get_known_folder_path(
folder_id: *const GUID,
flags: i32,
- user_token: HANDLE,
+ user_token: Option<BorrowedHandle<'_>>,
) -> std::io::Result<PathBuf> {
let mut folder_path: PWSTR = ptr::null_mut();
- let status =
- unsafe { SHGetKnownFolderPath(folder_id, flags as u32, user_token, &mut folder_path) };
+ // SAFETY: All arguments are valid
+ let status = unsafe {
+ SHGetKnownFolderPath(
+ folder_id,
+ flags as u32,
+ user_token
+ .map(|h| h.as_raw_handle())
+ .unwrap_or(ptr::null_mut()),
+ &mut folder_path,
+ )
+ };
let result = if status == S_OK {
+ // SAFETY: `folder_path` is valid and null-terminated since `SHGetKnownFolderPath` succeeded
let path = unsafe { WideCStr::from_ptr_str(folder_path) };
Ok(PathBuf::from(path.to_os_string()))
} else {
@@ -444,18 +476,21 @@ fn get_known_folder_path(
))
};
+ // SAFETY: `folder_path` was allocated by `SHGetKnownFolderPath` and must be freed with `CoTaskMemFree
unsafe { CoTaskMemFree(folder_path as *mut _) };
result
}
/// Enumerate over all processes until `handle_process` returns a result or until there are
/// no more processes left. In the latter case, an error is returned.
-fn find_process<T>(handle_process: impl Fn(HANDLE) -> Option<T>) -> io::Result<T> {
+fn find_process<T>(handle_process: impl Fn(BorrowedHandle<'_>) -> Option<T>) -> io::Result<T> {
let mut pid_buffer = vec![0u32; 2048];
let mut num_procs: u32 = u32::try_from(pid_buffer.len()).unwrap();
let bytes_available = num_procs * (mem::size_of::<u32>() as u32);
let mut bytes_written = 0;
+
+ // SAFETY: `pid_buffer` is valid for writes of `bytes_available` bytes
if unsafe { EnumProcesses(pid_buffer.as_mut_ptr(), bytes_available, &mut bytes_written) } == 0 {
return Err(io::Error::last_os_error());
}
@@ -466,12 +501,14 @@ fn find_process<T>(handle_process: impl Fn(HANDLE) -> Option<T>) -> io::Result<T
pid_buffer
.into_iter()
.find_map(|process| {
- let process_handle =
- Handle(unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, 0, process) });
- if process_handle.0 == 0 {
+ // SAFETY: Trivially safe
+ let process_handle = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, 0, process) };
+ if process_handle.is_null() {
return None;
}
- handle_process(process_handle.0)
+ // SAFETY: `process_handle` is a valid handle since `OpenProcess` succeeded
+ let process_handle = unsafe { OwnedHandle::from_raw_handle(process_handle) };
+ handle_process(process_handle.as_handle())
})
.ok_or(io::Error::new(
io::ErrorKind::NotFound,
@@ -479,15 +516,17 @@ fn find_process<T>(handle_process: impl Fn(HANDLE) -> Option<T>) -> io::Result<T
))
}
-fn is_local_system_user_token(token: HANDLE) -> io::Result<bool> {
+fn is_local_system_user_token(token: &impl AsRawHandle) -> io::Result<bool> {
let mut token_info = vec![0u8; 1024];
loop {
let mut returned_info_len = 0;
+ // SAFETY: `token` is a valid handle, and `token_info` is valid for writes of
+ // `token_info.len()` bytes
let info_result = unsafe {
GetTokenInformation(
- token,
+ token.as_raw_handle(),
TokenUser,
token_info.as_mut_ptr() as _,
u32::try_from(token_info.len()).expect("len must fit in u32"),
@@ -517,6 +556,7 @@ fn is_local_system_user_token(token: HANDLE) -> io::Result<bool> {
let mut local_system_sid = [0u8; MAX_SID_SIZE as usize];
let mut local_system_size = u32::try_from(local_system_sid.len()).unwrap();
+ // SAFETY: `local_system_sid` is valid for writes of `local_system_size` bytes
if unsafe {
CreateWellKnownSid(
WinLocalSystemSid,
@@ -531,5 +571,6 @@ fn is_local_system_user_token(token: HANDLE) -> io::Result<bool> {
return Err(err);
}
+ // SAFETY: Both arguments point to valid security identifiers
Ok(unsafe { EqualSid(token_user.User.Sid, local_system_sid.as_ptr() as _) } != 0)
}
diff --git a/talpid-core/src/dns/windows/dnsapi.rs b/talpid-core/src/dns/windows/dnsapi.rs
index 6a71dd6ce4..0465b233e6 100644
--- a/talpid-core/src/dns/windows/dnsapi.rs
+++ b/talpid-core/src/dns/windows/dnsapi.rs
@@ -6,7 +6,6 @@ use std::{
},
time::{Duration, Instant},
};
-use windows_sys::Win32::Foundation::BOOL;
static FLUSH_TIMEOUT: Duration = Duration::from_secs(5);
static DNSAPI_HANDLE: OnceLock<DnsApi> = OnceLock::new();
@@ -64,7 +63,7 @@ impl DnsApi {
let begin = Instant::now();
// SAFETY: this function is trivially safe to call
- let result = if unsafe { (DnsFlushResolverCache)() } != 0 {
+ let result = if unsafe { (DnsFlushResolverCache)() } {
let elapsed = begin.elapsed();
if elapsed >= FLUSH_TIMEOUT {
log::warn!(
@@ -93,5 +92,5 @@ impl DnsApi {
#[link(name = "dnsapi")]
unsafe extern "system" {
// Flushes the DNS resolver cache
- pub fn DnsFlushResolverCache() -> BOOL;
+ pub fn DnsFlushResolverCache() -> bool;
}
diff --git a/talpid-core/src/dns/windows/iphlpapi.rs b/talpid-core/src/dns/windows/iphlpapi.rs
index d862e15036..cfb61d2771 100644
--- a/talpid-core/src/dns/windows/iphlpapi.rs
+++ b/talpid-core/src/dns/windows/iphlpapi.rs
@@ -72,8 +72,14 @@ static IPHLPAPI_HANDLE: OnceCell<IphlpApi> = OnceCell::new();
impl IphlpApi {
fn new() -> Result<Self, Error> {
- let module = unsafe { LoadLibraryExW(w!("iphlpapi.dll"), 0, LOAD_LIBRARY_SEARCH_SYSTEM32) };
- if module == 0 {
+ let module = unsafe {
+ LoadLibraryExW(
+ w!("iphlpapi.dll"),
+ ptr::null_mut(),
+ LOAD_LIBRARY_SEARCH_SYSTEM32,
+ )
+ };
+ if module.is_null() {
log::error!("Failed to load iphlpapi.dll");
return Err(Error::LoadDll(io::Error::last_os_error()));
}
diff --git a/talpid-core/src/dns/windows/netsh.rs b/talpid-core/src/dns/windows/netsh.rs
index 2f8a4d77d1..624fe34c69 100644
--- a/talpid-core/src/dns/windows/netsh.rs
+++ b/talpid-core/src/dns/windows/netsh.rs
@@ -170,7 +170,7 @@ fn wait_for_child(subproc: &mut Child, timeout: Duration) -> io::Result<Option<E
let dur_millis = u32::try_from(timeout.as_millis()).unwrap_or(INFINITE);
let subproc_handle = subproc.as_raw_handle();
- match unsafe { WaitForSingleObject(subproc_handle as isize, dur_millis) } {
+ match unsafe { WaitForSingleObject(subproc_handle, dur_millis) } {
WAIT_OBJECT_0 => subproc.try_wait(),
WAIT_TIMEOUT => Ok(None),
_error => Err(io::Error::last_os_error()),
diff --git a/talpid-core/src/split_tunnel/windows/driver.rs b/talpid-core/src/split_tunnel/windows/driver.rs
index 27f10d72dd..5cbd172266 100644
--- a/talpid-core/src/split_tunnel/windows/driver.rs
+++ b/talpid-core/src/split_tunnel/windows/driver.rs
@@ -28,7 +28,7 @@ use talpid_windows::{io::Overlapped, process::ProcessSnapshot, sync::Event};
use windows_sys::Win32::{
Foundation::{
ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND, ERROR_INVALID_PARAMETER, ERROR_IO_PENDING,
- HANDLE, NTSTATUS, WAIT_ABANDONED, WAIT_ABANDONED_0, WAIT_FAILED, WAIT_OBJECT_0,
+ NTSTATUS, WAIT_ABANDONED, WAIT_ABANDONED_0, WAIT_FAILED, WAIT_OBJECT_0,
},
Networking::WinSock::{IN_ADDR, IN6_ADDR},
Storage::FileSystem::FILE_FLAG_OVERLAPPED,
@@ -849,7 +849,7 @@ pub unsafe fn device_io_control_buffer_async(
let result = unsafe {
DeviceIoControl(
- device.as_raw_handle() as HANDLE,
+ device.as_raw_handle(),
ioctl_code,
input_ptr,
u32::try_from(input_len).map_err(|_error| {
@@ -888,13 +888,13 @@ 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_raw(), None) }?;
+ unsafe { wait_for_single_object(event, None) }?;
// SAFETY: The handle and overlapped object are valid.
let mut returned_bytes = 0u32;
let result = unsafe {
GetOverlappedResult(
- device.as_raw_handle() as HANDLE,
+ device.as_raw_handle(),
overlapped.as_mut_ptr(),
&mut returned_bytes,
0,
@@ -911,14 +911,17 @@ pub fn get_overlapped_result(
/// # Safety
///
/// * `object` must be a valid object that can be signaled, such as an event object.
-pub unsafe fn wait_for_single_object(object: HANDLE, timeout: Option<Duration>) -> io::Result<()> {
+pub unsafe fn wait_for_single_object(
+ object: &impl AsRawHandle,
+ timeout: Option<Duration>,
+) -> io::Result<()> {
let timeout = match timeout {
Some(timeout) => u32::try_from(timeout.as_millis()).map_err(|_error| {
io::Error::new(io::ErrorKind::InvalidInput, "the duration is too long")
})?,
None => INFINITE,
};
- let result = unsafe { WaitForSingleObject(object, timeout) };
+ let result = unsafe { WaitForSingleObject(object.as_raw_handle(), timeout) };
match result {
WAIT_OBJECT_0 => Ok(()),
WAIT_FAILED => Err(io::Error::last_os_error()),
@@ -933,7 +936,10 @@ pub unsafe fn wait_for_single_object(object: HANDLE, timeout: Option<Duration>)
/// # Safety
///
/// * `objects` must be a slice of valid objects that can be signaled, such as event objects.
-pub unsafe fn wait_for_multiple_objects(objects: &[HANDLE], wait_all: bool) -> io::Result<HANDLE> {
+pub unsafe fn wait_for_multiple_objects(
+ objects: &[RawHandle],
+ wait_all: bool,
+) -> io::Result<RawHandle> {
unsafe {
let objects_len = u32::try_from(objects.len())
.map_err(|_error| io::Error::new(io::ErrorKind::InvalidInput, "too many objects"))?;
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs
index 8b9db7843c..4c80c9e147 100644
--- a/talpid-core/src/split_tunnel/windows/mod.rs
+++ b/talpid-core/src/split_tunnel/windows/mod.rs
@@ -13,6 +13,7 @@ use std::{
ffi::{OsStr, OsString},
io,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
+ os::windows::io::AsRawHandle,
path::{Path, PathBuf},
sync::{
Arc, Mutex, MutexGuard, RwLock, Weak,
@@ -245,9 +246,7 @@ impl SplitTunnel {
overlapped: &mut Overlapped,
data_buffer: &mut Vec<u8>,
) -> io::Result<EventResult> {
- if unsafe { driver::wait_for_single_object(quit_event.as_raw(), Some(Duration::ZERO)) }
- .is_ok()
- {
+ if unsafe { driver::wait_for_single_object(quit_event, Some(Duration::ZERO)) }.is_ok() {
return Ok(EventResult::Quit);
}
@@ -271,8 +270,8 @@ impl SplitTunnel {
})?;
let event_objects = [
- overlapped.get_event().unwrap().as_raw(),
- quit_event.as_raw(),
+ overlapped.get_event().unwrap().as_raw_handle(),
+ quit_event.as_raw_handle(),
];
let signaled_object =
@@ -285,7 +284,7 @@ impl SplitTunnel {
},
)?;
- if signaled_object == quit_event.as_raw() {
+ if signaled_object == quit_event.as_raw_handle() {
// Quit event was signaled
return Ok(EventResult::Quit);
}
diff --git a/talpid-core/src/split_tunnel/windows/path_monitor.rs b/talpid-core/src/split_tunnel/windows/path_monitor.rs
index a4ea65ddde..b7fd5cc337 100644
--- a/talpid-core/src/split_tunnel/windows/path_monitor.rs
+++ b/talpid-core/src/split_tunnel/windows/path_monitor.rs
@@ -280,7 +280,7 @@ impl DirContext {
)
};
- if handle == 0 {
+ if handle.is_null() {
return Err(io::Error::last_os_error());
}
@@ -356,9 +356,10 @@ struct CompletionPort {
impl CompletionPort {
// `concurrent_threads`: 0 ==> number of processors
fn create(concurrent_threads: u32) -> io::Result<Self> {
- let handle =
- unsafe { CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, concurrent_threads) };
- if handle == 0 {
+ let handle = unsafe {
+ CreateIoCompletionPort(INVALID_HANDLE_VALUE, ptr::null_mut(), 0, concurrent_threads)
+ };
+ if handle.is_null() {
return Err(io::Error::last_os_error());
}
Ok(CompletionPort { handle })
diff --git a/talpid-core/src/split_tunnel/windows/windows.rs b/talpid-core/src/split_tunnel/windows/windows.rs
index 1d6c03d39c..fd042802f4 100644
--- a/talpid-core/src/split_tunnel/windows/windows.rs
+++ b/talpid-core/src/split_tunnel/windows/windows.rs
@@ -139,8 +139,7 @@ pub fn open_process(
pid: u32,
) -> Result<WinHandle, io::Error> {
let handle = unsafe { OpenProcess(access as u32, if inherit_handle { 1 } else { 0 }, pid) };
-
- if handle == 0 {
+ if handle.is_null() {
return Err(io::Error::last_os_error());
}
Ok(WinHandle(handle))
diff --git a/talpid-core/src/window.rs b/talpid-core/src/window.rs
index 69373991f2..b0615c8ed7 100644
--- a/talpid-core/src/window.rs
+++ b/talpid-core/src/window.rs
@@ -52,8 +52,8 @@ pub fn create_hidden_window<F: (Fn(HWND, u32, WPARAM, LPARAM) -> LRESULT) + Send
0,
0,
0,
- 0,
- 0,
+ ptr::null_mut(),
+ ptr::null_mut(),
GetModuleHandleW(ptr::null_mut()),
ptr::null_mut(),
)
@@ -77,7 +77,7 @@ pub fn create_hidden_window<F: (Fn(HWND, u32, WPARAM, LPARAM) -> LRESULT) + Send
let mut msg = unsafe { std::mem::zeroed() };
loop {
- let status = unsafe { GetMessageW(&mut msg, 0, 0, 0) };
+ let status = unsafe { GetMessageW(&mut msg, ptr::null_mut(), 0, 0) };
if status < 0 {
continue;
@@ -86,7 +86,7 @@ pub fn create_hidden_window<F: (Fn(HWND, u32, WPARAM, LPARAM) -> LRESULT) + Send
break;
}
- if msg.hwnd == 0 {
+ if msg.hwnd.is_null() {
if msg.message == REQUEST_THREAD_SHUTDOWN {
unsafe { DestroyWindow(dummy_window) };
}
diff --git a/talpid-openvpn/src/wintun.rs b/talpid-openvpn/src/wintun.rs
index 230675c54b..5e86fb3516 100644
--- a/talpid-openvpn/src/wintun.rs
+++ b/talpid-openvpn/src/wintun.rs
@@ -180,9 +180,14 @@ impl WintunDll {
fn new(resource_dir: &Path) -> io::Result<Self> {
let wintun_dll = U16CString::from_os_str_truncate(resource_dir.join("wintun.dll"));
- let handle =
- unsafe { LoadLibraryExW(wintun_dll.as_ptr(), 0, LOAD_WITH_ALTERED_SEARCH_PATH) };
- if handle == 0 {
+ let handle = unsafe {
+ LoadLibraryExW(
+ wintun_dll.as_ptr(),
+ ptr::null_mut(),
+ LOAD_WITH_ALTERED_SEARCH_PATH,
+ )
+ };
+ if handle.is_null() {
return Err(io::Error::last_os_error());
}
Self::new_inner(handle, Self::get_proc_address)
@@ -373,7 +378,7 @@ mod tests {
#[test]
fn test_wintun_imports() {
- WintunDll::new_inner(0, get_proc_fn).unwrap();
+ WintunDll::new_inner(ptr::null_mut(), get_proc_fn).unwrap();
}
#[test]
diff --git a/talpid-platform-metadata/src/windows.rs b/talpid-platform-metadata/src/windows.rs
index 6cb5599ceb..5841a54e45 100644
--- a/talpid-platform-metadata/src/windows.rs
+++ b/talpid-platform-metadata/src/windows.rs
@@ -66,7 +66,7 @@ impl WindowsVersion {
// SAFETY: module_name is a valid UTF-16/WTF-16 null-terminated string.
let ntdll = unsafe { GetModuleHandleW(module_name.as_ptr()) };
- if ntdll == 0 {
+ if ntdll.is_null() {
return Err(io::Error::last_os_error());
}
diff --git a/talpid-routing/src/windows/default_route_monitor.rs b/talpid-routing/src/windows/default_route_monitor.rs
index 6064a789b3..e67f2d4a50 100644
--- a/talpid-routing/src/windows/default_route_monitor.rs
+++ b/talpid-routing/src/windows/default_route_monitor.rs
@@ -6,26 +6,23 @@ use crate::debounce::BurstGuard;
use std::{
ffi::c_void,
+ os::windows::io::RawHandle,
+ ptr,
sync::{Arc, Mutex},
time::Duration,
};
use talpid_types::win32_err;
-use windows_sys::Win32::{
- Foundation::{BOOLEAN, HANDLE},
- NetworkManagement::{
- IpHelper::{
- CancelMibChangeNotify2, ConvertInterfaceLuidToIndex, MIB_IPFORWARD_ROW2,
- MIB_IPINTERFACE_ROW, MIB_NOTIFICATION_TYPE, MIB_UNICASTIPADDRESS_ROW,
- NotifyIpInterfaceChange, NotifyRouteChange2, NotifyUnicastIpAddressChange,
- },
- Ndis::NET_LUID_LH,
+use windows_sys::Win32::NetworkManagement::{
+ IpHelper::{
+ CancelMibChangeNotify2, ConvertInterfaceLuidToIndex, MIB_IPFORWARD_ROW2,
+ MIB_IPINTERFACE_ROW, MIB_NOTIFICATION_TYPE, MIB_UNICASTIPADDRESS_ROW,
+ NotifyIpInterfaceChange, NotifyRouteChange2, NotifyUnicastIpAddressChange,
},
+ Ndis::NET_LUID_LH,
};
use talpid_windows::net::AddressFamily;
-const WIN_FALSE: BOOLEAN = 0;
-
struct DefaultRouteMonitorContext {
callback: Box<dyn for<'a> Fn(EventType<'a>) + Send + 'static>,
refresh_current_route: bool,
@@ -128,7 +125,7 @@ impl Drop for DefaultRouteMonitor {
}
}
-struct NotifyChangeHandle(HANDLE);
+struct NotifyChangeHandle(RawHandle);
/// SAFETY: NotifyChangeHandle is `Send` since it holds sole ownership of a pointer provided by C
unsafe impl Send for NotifyChangeHandle {}
@@ -240,7 +237,7 @@ impl DefaultRouteMonitor {
// we cancel the callbacks. This will leak the weak pointer but the context state itself
// will be correctly dropped when DefaultRouteManager is dropped.
let context_ptr = context_and_burst;
- let mut handle_ptr = 0;
+ let mut handle_ptr = ptr::null_mut();
// SAFETY: No clear safety specifications, context_ptr must be valid for as long as handle
// has not been dropped.
win32_err!(unsafe {
@@ -248,14 +245,14 @@ impl DefaultRouteMonitor {
family,
Some(route_change_callback),
context_ptr as *const _,
- WIN_FALSE,
+ false,
&mut handle_ptr,
)
})
.map_err(Error::RegisterNotifyRouteCallback)?;
let notify_route_change_handle = NotifyChangeHandle(handle_ptr);
- let mut handle_ptr = 0;
+ let mut handle_ptr = ptr::null_mut();
// SAFETY: No clear safety specifications, context_ptr must be valid for as long as handle
// has not been dropped.
win32_err!(unsafe {
@@ -263,14 +260,14 @@ impl DefaultRouteMonitor {
family,
Some(interface_change_callback),
context_ptr as *const _,
- WIN_FALSE,
+ false,
&mut handle_ptr,
)
})
.map_err(Error::RegisterNotifyIpInterfaceCallback)?;
let notify_interface_change_handle = NotifyChangeHandle(handle_ptr);
- let mut handle_ptr = 0;
+ let mut handle_ptr = ptr::null_mut();
// SAFETY: No clear safety specifications, context_ptr must be valid for as long as handle
// has not been dropped.
win32_err!(unsafe {
@@ -278,7 +275,7 @@ impl DefaultRouteMonitor {
family,
Some(ip_address_change_callback),
context_ptr as *const _,
- WIN_FALSE,
+ false,
&mut handle_ptr,
)
})
diff --git a/talpid-routing/src/windows/get_best_default_route.rs b/talpid-routing/src/windows/get_best_default_route.rs
index 9ce5987dd7..0fc0af02a1 100644
--- a/talpid-routing/src/windows/get_best_default_route.rs
+++ b/talpid-routing/src/windows/get_best_default_route.rs
@@ -163,12 +163,8 @@ fn annotate_route(route: &MIB_IPFORWARD_ROW2) -> Option<AnnotatedRoute<'_>> {
)
.ok()?;
- if iface.Connected == 0 {
- None
- } else {
- Some(AnnotatedRoute {
- route,
- effective_metric: route.Metric + iface.Metric,
- })
- }
+ iface.Connected.then(|| AnnotatedRoute {
+ route,
+ effective_metric: route.Metric + iface.Metric,
+ })
}
diff --git a/talpid-tunnel-config-client/Cargo.toml b/talpid-tunnel-config-client/Cargo.toml
index a7290c3613..04c7968050 100644
--- a/talpid-tunnel-config-client/Cargo.toml
+++ b/talpid-tunnel-config-client/Cargo.toml
@@ -32,10 +32,6 @@ zeroize = "1.5.7"
[target.'cfg(unix)'.dependencies]
nix = { workspace = true, features = ["socket"] }
-[target.'cfg(windows)'.dependencies.windows-sys]
-workspace = true
-features = ["Win32_Networking_WinSock"]
-
[build-dependencies]
tonic-build = { workspace = true, default-features = false, features = [
"transport",
diff --git a/talpid-tunnel/src/windows.rs b/talpid-tunnel/src/windows.rs
index 21315d45ff..28759bda10 100644
--- a/talpid-tunnel/src/windows.rs
+++ b/talpid-tunnel/src/windows.rs
@@ -30,12 +30,12 @@ pub fn initialize_interfaces(
row.SitePrefixLength = 0;
row.RouterDiscoveryBehavior = RouterDiscoveryDisabled;
row.DadTransmits = 0;
- row.ManagedAddressConfigurationSupported = 0;
- row.OtherStatefulConfigurationSupported = 0;
+ row.ManagedAddressConfigurationSupported = false;
+ row.OtherStatefulConfigurationSupported = false;
// Ensure lowest interface metric
row.Metric = 1;
- row.UseAutomaticMetric = 0;
+ row.UseAutomaticMetric = false;
set_ip_interface_entry(&mut row)?;
}
diff --git a/talpid-windows/src/fs.rs b/talpid-windows/src/fs.rs
index fd716dddb1..8523cee918 100644
--- a/talpid-windows/src/fs.rs
+++ b/talpid-windows/src/fs.rs
@@ -20,7 +20,7 @@ pub fn is_admin_owned<T: AsRawHandle>(handle: T) -> io::Result<bool> {
// SAFETY: `handle` is a valid handle
let result = unsafe {
GetSecurityInfo(
- handle.as_raw_handle() as isize,
+ handle.as_raw_handle(),
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
(&mut owner) as *mut *mut SID as *mut *mut c_void,
diff --git a/talpid-windows/src/io.rs b/talpid-windows/src/io.rs
index 8a8966f620..cfb6a23ec3 100644
--- a/talpid-windows/src/io.rs
+++ b/talpid-windows/src/io.rs
@@ -1,4 +1,4 @@
-use std::{io, mem};
+use std::{io, mem, os::windows::io::AsRawHandle, ptr};
use windows_sys::Win32::System::IO::OVERLAPPED;
use crate::sync::Event;
@@ -41,11 +41,11 @@ impl Overlapped {
fn set_event(&mut self, event: Option<Event>) {
match event {
Some(event) => {
- self.overlapped.hEvent = event.as_raw();
+ self.overlapped.hEvent = event.as_raw_handle();
self.event = Some(event);
}
None => {
- self.overlapped.hEvent = 0;
+ self.overlapped.hEvent = ptr::null_mut();
self.event = None;
}
}
diff --git a/talpid-windows/src/net.rs b/talpid-windows/src/net.rs
index 557af9e961..5aa92fb089 100644
--- a/talpid-windows/src/net.rs
+++ b/talpid-windows/src/net.rs
@@ -4,9 +4,10 @@ use socket2::SockAddr;
use std::{
ffi::{OsStr, OsString},
fmt, io,
- mem::{self, MaybeUninit},
+ mem::MaybeUninit,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
os::windows::ffi::{OsStrExt, OsStringExt},
+ ptr,
sync::Mutex,
time::{Duration, Instant},
};
@@ -30,7 +31,6 @@ use windows_sys::{
AF_INET, AF_INET6, AF_UNSPEC, IN_ADDR, IN6_ADDR, IpDadStateDeprecated,
IpDadStateDuplicate, IpDadStateInvalid, IpDadStatePreferred, IpDadStateTentative,
NL_DAD_STATE, SOCKADDR_IN as sockaddr_in, SOCKADDR_IN6 as sockaddr_in6, SOCKADDR_INET,
- SOCKADDR_STORAGE as sockaddr_storage,
},
},
core::GUID,
@@ -174,7 +174,7 @@ pub fn notify_ip_interface_change<'a, T: FnMut(&MIB_IPINTERFACE_ROW, i32) + Send
) -> io::Result<Box<IpNotifierHandle<'a>>> {
let mut context = Box::new(IpNotifierHandle {
callback: Mutex::new(Box::new(callback)),
- handle: 0,
+ handle: ptr::null_mut(),
});
win32_err!(unsafe {
@@ -182,7 +182,7 @@ pub fn notify_ip_interface_change<'a, T: FnMut(&MIB_IPINTERFACE_ROW, i32) + Send
af_family_from_family(family),
Some(inner_callback),
&mut *context as *mut _ as *mut _,
- 0,
+ false,
(&mut context.handle) as *mut _,
)
})?;
@@ -194,9 +194,11 @@ pub fn get_ip_interface_entry(
family: AddressFamily,
luid: &NET_LUID_LH,
) -> io::Result<MIB_IPINTERFACE_ROW> {
- let mut row: MIB_IPINTERFACE_ROW = unsafe { mem::zeroed() };
- row.Family = family as u16;
- row.InterfaceLuid = *luid;
+ let mut row = MIB_IPINTERFACE_ROW {
+ Family: family as u16,
+ InterfaceLuid: *luid,
+ ..Default::default()
+ };
win32_err!(unsafe { GetIpInterfaceEntry(&mut row) })?;
Ok(row)
@@ -324,7 +326,7 @@ pub fn get_ip_address_for_interface(
/// Adds a unicast IP address for the given interface.
pub fn add_ip_address_for_interface(luid: NET_LUID_LH, address: IpAddr) -> Result<()> {
- let mut row = unsafe { mem::zeroed() };
+ let mut row = MIB_UNICASTIPADDRESS_ROW::default();
unsafe { InitializeUnicastIpAddressEntry(&mut row) };
row.InterfaceLuid = luid;
@@ -385,7 +387,7 @@ pub fn luid_from_alias<T: AsRef<OsStr>>(alias: T) -> io::Result<NET_LUID_LH> {
.encode_wide()
.chain(std::iter::once(0u16))
.collect();
- let mut luid: NET_LUID_LH = unsafe { std::mem::zeroed() };
+ let mut luid = NET_LUID_LH::default();
win32_err!(unsafe { ConvertInterfaceAliasToLuid(alias_wide.as_ptr(), &mut luid) })?;
Ok(luid)
}
@@ -427,7 +429,7 @@ pub fn ipaddr_from_in6addr(addr: IN6_ADDR) -> Ipv6Addr {
/// Converts a `SocketAddr` to `SOCKADDR_INET`
pub fn inet_sockaddr_from_socketaddr(addr: SocketAddr) -> SOCKADDR_INET {
// SAFETY: SOCKADDR_INET is a union of C structs, these can be safely zeroed.
- let mut sockaddr: SOCKADDR_INET = unsafe { mem::zeroed() };
+ let mut sockaddr = SOCKADDR_INET::default();
match addr {
// SAFETY: `*const sockaddr` may be treated as `*const sockaddr_in` since we know it's a v4
// address.
@@ -447,13 +449,30 @@ pub fn inet_sockaddr_from_socketaddr(addr: SocketAddr) -> SOCKADDR_INET {
pub fn try_socketaddr_from_inet_sockaddr(addr: SOCKADDR_INET) -> Result<SocketAddr> {
// SAFETY: si_family is always valid
let family = unsafe { addr.si_family };
- unsafe {
- let mut storage: sockaddr_storage = mem::zeroed();
- *(&mut storage as *mut _ as *mut SOCKADDR_INET) = addr;
- SockAddr::new(storage, mem::size_of_val(&addr) as i32)
+ match family {
+ AF_INET => {
+ // SAFETY: We know this is an IPv4 address based on the family
+ let ipv4_addr = unsafe { addr.Ipv4 };
+ // SAFETY: The IPv4 address is initialized
+ let ip = Ipv4Addr::from(u32::from_be(unsafe { ipv4_addr.sin_addr.S_un.S_addr }));
+ let port = u16::from_be(ipv4_addr.sin_port);
+ Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
+ }
+ AF_INET6 => {
+ // SAFETY: We know this is an IPv6 address based on the family
+ let ipv6_addr = unsafe { addr.Ipv6 };
+ // SAFETY: The IPv6 address is initialized
+ let ip = Ipv6Addr::from(unsafe { ipv6_addr.sin6_addr.u.Byte });
+ let port = u16::from_be(ipv6_addr.sin6_port);
+ let flowinfo = ipv6_addr.sin6_flowinfo;
+ // SAFETY: The scope ID is initialized
+ let scope_id = unsafe { ipv6_addr.Anonymous.sin6_scope_id };
+ Ok(SocketAddr::V6(SocketAddrV6::new(
+ ip, port, flowinfo, scope_id,
+ )))
+ }
+ _ => Err(Error::UnknownAddressFamily(family)),
}
- .as_socket()
- .ok_or(Error::UnknownAddressFamily(family))
}
/// Address family. These correspond to the `AF_*` constants.
diff --git a/talpid-windows/src/process.rs b/talpid-windows/src/process.rs
index b7c5d8b972..5dbd52f3c7 100644
--- a/talpid-windows/src/process.rs
+++ b/talpid-windows/src/process.rs
@@ -1,11 +1,12 @@
#![allow(clippy::undocumented_unsafe_blocks)] // Remove me if you dare
use std::{
- ffi::{CStr, c_char},
+ ffi::CStr,
io, mem,
+ os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle, RawHandle},
};
use windows_sys::Win32::{
- Foundation::{CloseHandle, ERROR_NO_MORE_FILES, HANDLE, INVALID_HANDLE_VALUE},
+ Foundation::{ERROR_NO_MORE_FILES, INVALID_HANDLE_VALUE},
System::Diagnostics::ToolHelp::{
CreateToolhelp32Snapshot, MODULEENTRY32, Module32First, Module32Next, PROCESSENTRY32W,
Process32FirstW, Process32NextW,
@@ -14,30 +15,31 @@ use windows_sys::Win32::{
/// A snapshot of process modules, threads, and heaps
pub struct ProcessSnapshot {
- handle: HANDLE,
+ handle: OwnedHandle,
}
impl ProcessSnapshot {
/// Create a new process snapshot using `CreateToolhelp32Snapshot`
pub fn new(flags: u32, process_id: u32) -> io::Result<ProcessSnapshot> {
+ // SAFETY: `CreateToolhelp32Snapshot` should handle invalid flags and process IDs
let snap = unsafe { CreateToolhelp32Snapshot(flags, process_id) };
if snap == INVALID_HANDLE_VALUE {
Err(io::Error::last_os_error())
} else {
- Ok(ProcessSnapshot { handle: snap })
+ Ok(ProcessSnapshot {
+ // SAFETY: `snap` is a valid handle since `CreateToolhelp32Snapshot` succeeded
+ handle: unsafe { OwnedHandle::from_raw_handle(snap) },
+ })
}
}
- /// Return the raw handle
- pub fn as_raw(&self) -> HANDLE {
- self.handle
- }
-
/// Return an iterator over the modules in the snapshot
pub fn modules(&self) -> ProcessSnapshotModules<'_> {
- let mut entry: MODULEENTRY32 = unsafe { mem::zeroed() };
- entry.dwSize = mem::size_of::<MODULEENTRY32>() as u32;
+ let entry = MODULEENTRY32 {
+ dwSize: mem::size_of::<MODULEENTRY32>() as u32,
+ ..Default::default()
+ };
ProcessSnapshotModules {
snapshot: self,
@@ -48,8 +50,10 @@ impl ProcessSnapshot {
/// Return an iterator over the processes in the snapshot
pub fn processes(&self) -> ProcessSnapshotEntries<'_> {
- let mut entry: PROCESSENTRY32W = unsafe { mem::zeroed() };
- entry.dwSize = mem::size_of::<PROCESSENTRY32W>() as u32;
+ let entry = PROCESSENTRY32W {
+ dwSize: mem::size_of::<PROCESSENTRY32W>() as u32,
+ ..Default::default()
+ };
ProcessSnapshotEntries {
snapshot: self,
@@ -59,11 +63,9 @@ impl ProcessSnapshot {
}
}
-impl Drop for ProcessSnapshot {
- fn drop(&mut self) {
- unsafe {
- CloseHandle(self.handle);
- }
+impl AsRawHandle for ProcessSnapshot {
+ fn as_raw_handle(&self) -> RawHandle {
+ self.handle.as_raw_handle()
}
}
@@ -89,7 +91,8 @@ impl Iterator for ProcessSnapshotModules<'_> {
fn next(&mut self) -> Option<io::Result<ModuleEntry>> {
if self.iter_started {
- if unsafe { Module32Next(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ // SAFETY: `self.snapshot` is a valid pointer, and `temp_entry` is a valid `MODULEENTRY32`
+ if unsafe { Module32Next(self.snapshot.as_raw_handle(), &mut self.temp_entry) } == 0 {
let last_error = io::Error::last_os_error();
return if last_error.raw_os_error().unwrap() as u32 == ERROR_NO_MORE_FILES {
@@ -99,14 +102,16 @@ impl Iterator for ProcessSnapshotModules<'_> {
};
}
} else {
- if unsafe { Module32First(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ // SAFETY: `self.snapshot` is a valid pointer, and `temp_entry` is a valid `MODULEENTRY32`
+ if unsafe { Module32First(self.snapshot.as_raw_handle(), &mut self.temp_entry) } == 0 {
return Some(Err(io::Error::last_os_error()));
}
self.iter_started = true;
}
let cstr_ref = &self.temp_entry.szModule[0];
- let cstr = unsafe { CStr::from_ptr(cstr_ref as *const u8 as *const c_char) };
+ // SAFETY: `szModule` is a null-terminated C string
+ let cstr = unsafe { CStr::from_ptr(cstr_ref) };
Some(Ok(ModuleEntry {
name: cstr.to_string_lossy().into_owned(),
base_address: self.temp_entry.modBaseAddr,
@@ -135,7 +140,8 @@ impl Iterator for ProcessSnapshotEntries<'_> {
fn next(&mut self) -> Option<io::Result<ProcessEntry>> {
if self.iter_started {
- if unsafe { Process32NextW(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ // SAFETY: `self.snapshot` is a valid pointer, and `temp_entry` is a valid `PROCESSENTRY32W`
+ if unsafe { Process32NextW(self.snapshot.as_raw_handle(), &mut self.temp_entry) } == 0 {
let last_error = io::Error::last_os_error();
return if last_error.raw_os_error().unwrap() as u32 == ERROR_NO_MORE_FILES {
@@ -145,7 +151,9 @@ impl Iterator for ProcessSnapshotEntries<'_> {
};
}
} else {
- if unsafe { Process32FirstW(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ // SAFETY: `self.snapshot` is a valid pointer, and `temp_entry` is a valid `PROCESSENTRY32W`
+ if unsafe { Process32FirstW(self.snapshot.as_raw_handle(), &mut self.temp_entry) } == 0
+ {
return Some(Err(io::Error::last_os_error()));
}
self.iter_started = true;
diff --git a/talpid-windows/src/sync.rs b/talpid-windows/src/sync.rs
index ddd97facdb..567f556a73 100644
--- a/talpid-windows/src/sync.rs
+++ b/talpid-windows/src/sync.rs
@@ -1,13 +1,17 @@
#![allow(clippy::undocumented_unsafe_blocks)] // Remove me if you dare.
-use std::{io, ptr};
+use std::{
+ io,
+ os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle, RawHandle},
+ ptr,
+};
use windows_sys::Win32::{
- Foundation::{BOOL, CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE},
+ Foundation::{DUPLICATE_SAME_ACCESS, DuplicateHandle},
System::Threading::{CreateEventW, GetCurrentProcess, SetEvent},
};
/// Windows event object
-pub struct Event(HANDLE);
+pub struct Event(OwnedHandle);
unsafe impl Send for Event {}
unsafe impl Sync for Event {}
@@ -18,37 +22,34 @@ impl Event {
let event = unsafe {
CreateEventW(
ptr::null_mut(),
- bool_to_winbool(manual_reset),
- bool_to_winbool(initial_state),
+ i32::from(manual_reset),
+ i32::from(initial_state),
ptr::null(),
)
};
- if event == 0 {
+ if event.is_null() {
return Err(io::Error::last_os_error());
}
- Ok(Self(event))
+ // SAFETY: `event` is a valid handle since `CreateEventW` succeeded
+ Ok(Self(unsafe { OwnedHandle::from_raw_handle(event) }))
}
/// Signal the event object
pub fn set(&self) -> io::Result<()> {
- if unsafe { SetEvent(self.0) } == 0 {
+ // SAFETY: `self.0` is a valid handle
+ if unsafe { SetEvent(self.0.as_raw_handle()) } == 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 mut new_event = ptr::null_mut();
let status = unsafe {
DuplicateHandle(
GetCurrentProcess(),
- self.0,
+ self.0.as_raw_handle(),
GetCurrentProcess(),
&mut new_event,
0,
@@ -59,19 +60,13 @@ impl Event {
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) };
+ // SAFETY: `new_event` is a valid handle since `DuplicateHandle` succeeded
+ Ok(Event(unsafe { OwnedHandle::from_raw_handle(new_event) }))
}
}
-const fn bool_to_winbool(val: bool) -> BOOL {
- match val {
- true => 1,
- false => 0,
+impl AsRawHandle for Event {
+ fn as_raw_handle(&self) -> RawHandle {
+ self.0.as_raw_handle()
}
}
diff --git a/talpid-wireguard/src/wireguard_nt/daita.rs b/talpid-wireguard/src/wireguard_nt/daita.rs
index a2c5d7e6c1..98e60eff30 100644
--- a/talpid-wireguard/src/wireguard_nt/daita.rs
+++ b/talpid-wireguard/src/wireguard_nt/daita.rs
@@ -6,13 +6,13 @@ use rand08::{
rngs::{OsRng, adapter::ReseedingRng},
};
use std::{
- collections::HashMap, fs, io, os::windows::prelude::RawHandle, path::Path, sync::Arc,
- time::Duration,
+ collections::HashMap, fs, io, os::windows::io::AsRawHandle, os::windows::prelude::RawHandle,
+ path::Path, sync::Arc, time::Duration,
};
use talpid_types::net::wireguard::PublicKey;
use tokio::task::JoinHandle;
use windows_sys::Win32::{
- Foundation::{BOOLEAN, ERROR_NO_MORE_ITEMS},
+ Foundation::ERROR_NO_MORE_ITEMS,
System::Threading::{INFINITE, WaitForMultipleObjects, WaitForSingleObject},
};
@@ -74,7 +74,7 @@ pub enum ActionType {
#[derive(Debug, Clone, Copy)]
pub struct PaddingAction {
pub byte_count: u16,
- pub replace: BOOLEAN,
+ pub replace: u8,
}
// See DAITA_ACTION:
@@ -99,19 +99,17 @@ const ACTIONS_CAPACITY: usize = 1000;
pub mod bindings {
use super::*;
- use windows_sys::Win32::Foundation::BOOL;
-
pub type WireGuardDaitaActivateFn = unsafe extern "stdcall" fn(
adapter: RawHandle,
events_capacity: usize,
actions_capacity: usize,
- ) -> BOOL;
+ ) -> bool;
pub type WireGuardDaitaEventDataAvailableEventFn =
unsafe extern "stdcall" fn(adapter: RawHandle) -> RawHandle;
pub type WireGuardDaitaReceiveEventsFn =
unsafe extern "stdcall" fn(adapter: RawHandle, events: *mut Event) -> usize;
pub type WireGuardDaitaSendActionFn =
- unsafe extern "stdcall" fn(adapter: RawHandle, action: *const Action) -> BOOL;
+ unsafe extern "stdcall" fn(adapter: RawHandle, action: *const Action) -> bool;
}
#[derive(Debug)]
@@ -293,7 +291,7 @@ impl Machinist {
use windows_sys::Win32::Foundation::WAIT_OBJECT_0;
loop {
- if unsafe { WaitForSingleObject(self.quit_event.as_raw(), 0) } == WAIT_OBJECT_0 {
+ if unsafe { WaitForSingleObject(self.quit_event.as_raw_handle(), 0) } == WAIT_OBJECT_0 {
break;
}
@@ -393,8 +391,8 @@ impl Machinist {
use windows_sys::Win32::Foundation::WAIT_OBJECT_0;
let wait_events = [
- self.quit_event.as_raw(),
- self.daita.event_data_available_event() as isize,
+ self.quit_event.as_raw_handle(),
+ self.daita.event_data_available_event(),
];
let mut event_buffer: [Event; EVENTS_CAPACITY] = unsafe { std::mem::zeroed() };
diff --git a/talpid-wireguard/src/wireguard_nt/mod.rs b/talpid-wireguard/src/wireguard_nt/mod.rs
index 0f650d3866..c51faf6d93 100644
--- a/talpid-wireguard/src/wireguard_nt/mod.rs
+++ b/talpid-wireguard/src/wireguard_nt/mod.rs
@@ -31,7 +31,7 @@ use talpid_windows::net;
use widestring::{U16CStr, U16CString};
use windows_sys::{
Win32::{
- Foundation::{BOOL, ERROR_MORE_DATA, FreeLibrary, HMODULE},
+ Foundation::{ERROR_MORE_DATA, FreeLibrary, HMODULE},
NetworkManagement::Ndis::NET_LUID_LH,
Networking::WinSock::{
ADDRESS_FAMILY, AF_INET, AF_INET6, IN_ADDR, IN6_ADDR, SOCKADDR_INET,
@@ -69,14 +69,14 @@ type WireGuardSetConfigurationFn = unsafe extern "stdcall" fn(
adapter: RawHandle,
config: *const MaybeUninit<u8>,
bytes: u32,
-) -> BOOL;
+) -> bool;
type WireGuardGetConfigurationFn = unsafe extern "stdcall" fn(
adapter: RawHandle,
config: *const MaybeUninit<u8>,
bytes: *mut u32,
-) -> BOOL;
+) -> bool;
type WireGuardSetStateFn =
- unsafe extern "stdcall" fn(adapter: RawHandle, state: WgAdapterState) -> BOOL;
+ unsafe extern "stdcall" fn(adapter: RawHandle, state: WgAdapterState) -> bool;
#[repr(C)]
#[allow(dead_code)]
@@ -108,7 +108,7 @@ enum WireGuardAdapterLogState {
}
type WireGuardSetAdapterLoggingFn =
- unsafe extern "stdcall" fn(adapter: RawHandle, state: WireGuardAdapterLogState) -> BOOL;
+ unsafe extern "stdcall" fn(adapter: RawHandle, state: WireGuardAdapterLogState) -> bool;
pub type Result<T> = std::result::Result<T, Error>;
@@ -707,9 +707,14 @@ impl WgNtDll {
let wg_nt_dll =
U16CString::from_os_str_truncate(resource_dir.join("mullvad-wireguard.dll"));
- let handle =
- unsafe { LoadLibraryExW(wg_nt_dll.as_ptr(), 0, LOAD_WITH_ALTERED_SEARCH_PATH) };
- if handle == 0 {
+ let handle = unsafe {
+ LoadLibraryExW(
+ wg_nt_dll.as_ptr(),
+ ptr::null_mut(),
+ LOAD_WITH_ALTERED_SEARCH_PATH,
+ )
+ };
+ if handle.is_null() {
return Err(io::Error::last_os_error());
}
Self::new_inner(handle, Self::get_proc_address)
@@ -808,10 +813,10 @@ impl WgNtDll {
config: *const MaybeUninit<u8>,
config_size: usize,
) -> io::Result<()> {
- let result = unsafe {
+ let succeeded = unsafe {
(self.func_set_configuration)(adapter, config, u32::try_from(config_size).unwrap())
};
- if result == 0 {
+ if !succeeded {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -821,10 +826,10 @@ impl WgNtDll {
let mut config_size = 0;
let mut config = vec![];
loop {
- let result = unsafe {
+ let succeeded = unsafe {
(self.func_get_configuration)(adapter, config.as_mut_ptr(), &mut config_size)
};
- if result == 0 {
+ if !succeeded {
let last_error = io::Error::last_os_error();
if last_error.raw_os_error() != Some(ERROR_MORE_DATA as i32) {
break Err(last_error);
@@ -841,8 +846,8 @@ impl WgNtDll {
adapter: RawHandle,
state: WgAdapterState,
) -> io::Result<()> {
- let result = unsafe { (self.func_set_adapter_state)(adapter, state) };
- if result == 0 {
+ let succeeded = unsafe { (self.func_set_adapter_state)(adapter, state) };
+ if !succeeded {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -857,7 +862,7 @@ impl WgNtDll {
adapter: RawHandle,
state: WireGuardAdapterLogState,
) -> io::Result<()> {
- if unsafe { (self.func_set_adapter_logging)(adapter, state) } == 0 {
+ if !unsafe { (self.func_set_adapter_logging)(adapter, state) } {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -870,7 +875,7 @@ impl WgNtDll {
events_capacity: usize,
actions_capacity: usize,
) -> io::Result<()> {
- if unsafe { (self.func_daita_activate)(adapter, events_capacity, actions_capacity) } == 0 {
+ if !unsafe { (self.func_daita_activate)(adapter, events_capacity, actions_capacity) } {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -907,7 +912,7 @@ impl WgNtDll {
adapter: RawHandle,
action: *const daita::Action,
) -> io::Result<()> {
- if unsafe { (self.func_daita_send_action)(adapter, action) } == 0 {
+ if !unsafe { (self.func_daita_send_action)(adapter, action) } {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -1235,7 +1240,7 @@ mod tests {
#[test]
fn test_dll_imports() {
- WgNtDll::new_inner(0, get_proc_fn).unwrap();
+ WgNtDll::new_inner(ptr::null_mut(), get_proc_fn).unwrap();
}
#[test]
diff --git a/test/Cargo.lock b/test/Cargo.lock
index ccdedcc77f..0e89ab61cf 100644
--- a/test/Cargo.lock
+++ b/test/Cargo.lock
@@ -2119,7 +2119,7 @@ dependencies = [
"once_cell",
"thiserror 2.0.3",
"widestring",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -3558,7 +3558,7 @@ version = "0.0.0"
dependencies = [
"rs-release",
"talpid-windows",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -3591,7 +3591,7 @@ dependencies = [
"socket2 0.5.8",
"talpid-types",
"thiserror 2.0.3",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -4508,6 +4508,12 @@ dependencies = [
]
[[package]]
+name = "windows-link"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
+
+[[package]]
name = "windows-service"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4568,6 +4574,15 @@ dependencies = [
]
[[package]]
+name = "windows-sys"
+version = "0.61.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/wireguard-go-rs/Cargo.toml b/wireguard-go-rs/Cargo.toml
index 415365e772..40d70623a5 100644
--- a/wireguard-go-rs/Cargo.toml
+++ b/wireguard-go-rs/Cargo.toml
@@ -25,7 +25,7 @@ talpid-types.path = "../talpid-types"
maybenot-ffi = "2.0.1"
[target.'cfg(target_os = "windows")'.dependencies]
-windows-sys = { version = "0.52.0", features = [
+windows-sys = { workspace = true, features = [
"Win32_Networking",
"Win32_NetworkManagement",
"Win32_NetworkManagement_Ndis",