Skip to content

Commit

Permalink
Upgrade to windows-sys crate (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssrlive authored Jul 18, 2024
1 parent 5904813 commit 5c801d0
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 102 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ jobs:
name: Test
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
rust: [stable, beta, nightly]
steps:
- uses: actions/checkout@master
- name: Build & Test
if: ${{ !cancelled() }}
run: |
rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
cargo test
- name: Abort on error
if: ${{ failure() }}
run: echo "Some of jobs failed" && false

rustfmt:
name: Rustfmt
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.vscode/
.VSCodeCounter/
.env
tmp/
build/
out.pcap
Expand Down
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wintun"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
authors = [
"null.black Inc. <[email protected]>",
Expand Down Expand Up @@ -29,8 +29,8 @@ panic_on_unsent_packets = []
c2rust-bitfields = "0.18"
libloading = "0.8"
log = "0.4"
thiserror = "1.0"
windows = { version = "0.52", features = [
thiserror = "1"
windows-sys = { version = "0.52", features = [
"Win32_System_Diagnostics_Debug",
"Win32_System_SystemServices",
"Win32_Security_Cryptography",
Expand All @@ -39,14 +39,16 @@ windows = { version = "0.52", features = [
"Win32_Networking_WinSock",
"Win32_System_Threading",
"Win32_System_Com",
"Win32_System_Rpc",
"Win32_Security",
"Win32_Foundation",
"Win32_System_Ioctl",
"Win32_System_IO",
] }

[dev-dependencies]
env_logger = "0.10"
dotenvy = "0.15"
env_logger = "0.11"
packet = "0.1"
pcap-file = "2.0"
pcap-file = "2"
subprocess = "0.2"
1 change: 1 addition & 0 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod misc;
static RUNNING: AtomicBool = AtomicBool::new(true);

fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenvy::dotenv().ok();
env_logger::init();
let dll_path = misc::get_wintun_bin_relative_path()?;
let wintun = unsafe { wintun::load_from_path(dll_path)? };
Expand Down
23 changes: 15 additions & 8 deletions examples/udp-echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use std::{
Arc,
},
};
use windows::{
core::PCWSTR,
Win32::Security::Cryptography::{CryptAcquireContextW, CryptGenRandom, CryptReleaseContext, PROV_RSA_FULL},
use windows_sys::Win32::{
Foundation::FALSE,
Security::Cryptography::{CryptAcquireContextW, CryptGenRandom, CryptReleaseContext, PROV_RSA_FULL},
};
mod misc;

Expand Down Expand Up @@ -47,6 +47,7 @@ impl std::fmt::Display for NaiveUdpPacket {
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenvy::dotenv().ok();
env_logger::init();
// Loading wintun
let dll_path = misc::get_wintun_bin_relative_path()?;
Expand Down Expand Up @@ -256,14 +257,20 @@ fn extract_udp_packet(packet: &[u8]) -> Result<NaiveUdpPacket, wintun::Error> {
Err(info.into())
}

fn generate_random_bytes(len: usize) -> Result<Vec<u8>, windows::core::Error> {
fn generate_random_bytes(len: usize) -> std::io::Result<Vec<u8>> {
let mut buf = vec![0u8; len];
unsafe {
let mut h_prov = 0_usize;
let null = PCWSTR::null();
CryptAcquireContextW(&mut h_prov, null, null, PROV_RSA_FULL, 0)?;
CryptGenRandom(h_prov, &mut buf)?;
CryptReleaseContext(h_prov, 0)?;
let null = std::ptr::null_mut();
if FALSE == CryptAcquireContextW(&mut h_prov, null, null, PROV_RSA_FULL, 0) {
return Err(std::io::Error::last_os_error());
}
if FALSE == CryptGenRandom(h_prov, buf.len() as _, buf.as_mut_ptr()) {
return Err(std::io::Error::last_os_error());
}
if FALSE == CryptReleaseContext(h_prov, 0) {
return Err(std::io::Error::last_os_error());
}
};
Ok(buf)
}
9 changes: 5 additions & 4 deletions examples/wireshark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};
use subprocess::{Popen, PopenConfig, Redirection};
use windows::Win32::{
use windows_sys::Win32::{
Foundation::NO_ERROR,
NetworkManagement::IpHelper::{GetBestRoute, MIB_IPFORWARDROW},
Networking::WinSock::{AF_INET, AF_INET6, SOCKADDR_INET},
Expand All @@ -29,11 +29,11 @@ fn _ip_addr_to_win_addr(addr: IpAddr) -> SOCKADDR_INET {
match addr {
IpAddr::V4(v4) => {
result.si_family = AF_INET;
result.Ipv4.sin_addr = v4.into();
result.Ipv4.sin_addr.S_un.S_addr = u32::from_ne_bytes(v4.octets());
}
IpAddr::V6(v6) => {
result.si_family = AF_INET6;
result.Ipv6.sin6_addr = v6.into();
result.Ipv6.sin6_addr.u.Byte = v6.octets();
}
}

Expand Down Expand Up @@ -67,6 +67,7 @@ impl RouteCmd {
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenvy::dotenv().ok();
env_logger::init();

let dll_path = misc::get_wintun_bin_relative_path()?;
Expand All @@ -92,7 +93,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let gateway = unsafe {
let mut row: MIB_IPFORWARDROW = std::mem::zeroed();
let result = GetBestRoute(u32::from_be_bytes([1, 1, 1, 1]), 0, &mut row as *mut MIB_IPFORWARDROW);
if result != NO_ERROR.0 {
if result != NO_ERROR {
log::error!("Failed to get best route: {}", format_message(result)?);
return Err("Failed to get best route".into());
}
Expand Down
47 changes: 29 additions & 18 deletions src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use std::{
sync::Arc,
sync::OnceLock,
};
use windows::{
core::{GUID, PCSTR, PCWSTR},
use windows_sys::{
core::GUID,
Win32::{
Foundation::FALSE,
NetworkManagement::{
Expand Down Expand Up @@ -51,9 +51,9 @@ impl Adapter {
let mut friendly_name = None;

util::get_adapters_addresses(|address| {
let name_iter = unsafe { address.AdapterName.to_string()? };
let name_iter = unsafe { util::win_pstr_to_string(address.AdapterName) }?;
if name_iter == name {
friendly_name = unsafe { Some(address.FriendlyName.to_string()?) };
friendly_name = Some(unsafe { util::win_pwstr_to_string(address.FriendlyName)? });
}
Ok(())
})?;
Expand Down Expand Up @@ -94,7 +94,11 @@ impl Adapter {

let guid = match guid {
Some(guid) => guid,
None => GUID::new()?.to_u128(),
None => {
let mut guid: GUID = unsafe { std::mem::zeroed() };
unsafe { windows_sys::Win32::System::Rpc::UuidCreate(&mut guid as *mut GUID) };
util::win_guid_to_u128(&guid)
}
};

crate::log::set_default_logger_if_unset(wintun);
Expand Down Expand Up @@ -135,18 +139,18 @@ impl Adapter {
} else {
let mut guid = None;
util::get_adapters_addresses(|address: IP_ADAPTER_ADDRESSES_LH| {
let frindly_name = PCWSTR(address.FriendlyName.0 as *const u16);
let frindly_name = unsafe { frindly_name.to_string()? };
let frindly_name = unsafe { util::win_pwstr_to_string(address.FriendlyName)? };
if frindly_name == name {
let adapter_name = unsafe { address.AdapterName.to_string()? };
let adapter_name = unsafe { util::win_pstr_to_string(address.AdapterName) }?;
let adapter_name_utf16: Vec<u16> = adapter_name.encode_utf16().chain(std::iter::once(0)).collect();
let adapter_name_ptr: *const u16 = adapter_name_utf16.as_ptr();
let adapter = unsafe { CLSIDFromString(PCWSTR(adapter_name_ptr))? };
let mut adapter: GUID = unsafe { std::mem::zeroed() };
unsafe { CLSIDFromString(adapter_name_ptr, &mut adapter as *mut GUID) };
guid = Some(adapter);
}
Ok(())
})?;
let guid = guid.ok_or("Unable to find matching GUID")?.to_u128();
let guid = util::win_guid_to_u128(&guid.ok_or("Unable to find matching GUID")?);
Ok(Arc::new(Adapter {
adapter: UnsafeHandle(result),
wintun: wintun.clone(),
Expand Down Expand Up @@ -182,7 +186,7 @@ impl Adapter {
if result.is_null() {
Err("WintunStartSession failed".into())
} else {
let shutdown_event = unsafe { CreateEventA(None, FALSE, FALSE, PCSTR::null())? };
let shutdown_event = unsafe { CreateEventA(std::ptr::null_mut(), FALSE, FALSE, std::ptr::null_mut()) };
Ok(session::Session {
session: UnsafeHandle(result),
wintun: self.wintun.clone(),
Expand Down Expand Up @@ -217,7 +221,7 @@ impl Adapter {
let mut adapter_index = None;

util::get_adapters_addresses(|address| {
let name_iter = unsafe { address.AdapterName.to_string()? };
let name_iter = unsafe { util::win_pstr_to_string(address.AdapterName) }?;
if name_iter == name {
adapter_index = unsafe { Some(address.Anonymous1.Anonymous.IfIndex) };
// adapter_index = Some(address.Ipv6IfIndex);
Expand Down Expand Up @@ -277,8 +281,12 @@ impl Adapter {

/// Sets the DNS servers for this adapter
pub fn set_dns_servers(&self, dns_servers: &[IpAddr]) -> Result<(), Error> {
let interface = GUID::from(self.get_guid());
Ok(util::set_interface_dns_servers(interface, dns_servers)?)
let interface = GUID::from_u128(self.get_guid());
if let Err(err) = util::set_interface_dns_servers(interface, dns_servers) {
log::error!("Failed to set DNS servers in first attempt: {}", err);
util::set_adapter_dns_servers(&self.get_name()?, dns_servers)?;
}
Ok(())
}

/// Sets the network addresses of this adapter, including network address, subnet mask, and gateway
Expand Down Expand Up @@ -319,7 +327,7 @@ impl Adapter {
let mut adapter_addresses = vec![];

util::get_adapters_addresses(|adapter| {
let name_iter = unsafe { adapter.AdapterName.to_string()? };
let name_iter = unsafe { util::win_pstr_to_string(adapter.AdapterName) }?;
if name_iter == name {
let mut current_address = adapter.FirstUnicastAddress;
while !current_address.is_null() {
Expand All @@ -346,7 +354,7 @@ impl Adapter {
let name = util::guid_to_win_style_string(&GUID::from_u128(self.guid))?;
let mut gateways = vec![];
util::get_adapters_addresses(|adapter| {
let name_iter = unsafe { adapter.AdapterName.to_string()? };
let name_iter = unsafe { util::win_pstr_to_string(adapter.AdapterName) }?;
if name_iter == name {
let mut current_gateway = adapter.FirstGatewayAddress;
while !current_gateway.is_null() {
Expand All @@ -372,7 +380,7 @@ impl Adapter {
let name = util::guid_to_win_style_string(&GUID::from_u128(self.guid))?;
let mut subnet_mask = None;
util::get_adapters_addresses(|adapter| {
let name_iter = unsafe { adapter.AdapterName.to_string()? };
let name_iter = unsafe { util::win_pstr_to_string(adapter.AdapterName) }?;
if name_iter == name {
let mut current_address = adapter.FirstUnicastAddress;
while !current_address.is_null() {
Expand All @@ -387,7 +395,10 @@ impl Adapter {
match address {
IpAddr::V4(_) => {
let mut mask = 0_u32;
unsafe { ConvertLengthToIpv4Mask(masklength as u32, &mut mask as *mut u32)? };
match unsafe { ConvertLengthToIpv4Mask(masklength as u32, &mut mask as *mut u32) } {
0 => {}
err => return Err(std::io::Error::from_raw_os_error(err as i32).into()),
}
subnet_mask = Some(IpAddr::V4(Ipv4Addr::from(mask.to_le_bytes())));
}
IpAddr::V6(_) => {
Expand Down
3 changes: 0 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ pub enum Error {
#[error(transparent)]
LibLoading(#[from] libloading::Error),

#[error(transparent)]
WindowsCore(#[from] windows::core::Error),

#[error(transparent)]
FromUtf16Error(#[from] std::string::FromUtf16Error),

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub use crate::{
session::Session,
util::{format_message, get_active_network_interface_gateways, run_command},
};
pub use windows::Win32::{Foundation::HANDLE, NetworkManagement::Ndis::NET_LUID_LH};
pub use windows_sys::Win32::{Foundation::HANDLE, NetworkManagement::Ndis::NET_LUID_LH};

// TODO: Get bindgen to scrape these from the `wintun.h`
// We need to make sure these stay up to date
Expand Down Expand Up @@ -188,7 +188,7 @@ impl std::fmt::Display for Version {
pub fn get_running_driver_version(wintun: &Wintun) -> Result<Version> {
let version = unsafe { wintun.WintunGetRunningDriverVersion() };
if version == 0 {
Err(Error::from(util::get_last_error()))
Err(util::get_last_error()?.into())
} else {
let v = version.to_be_bytes();
Ok(Version {
Expand Down
5 changes: 2 additions & 3 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{wintun_raw, Wintun};
use crate::{util, wintun_raw, Wintun};
use std::sync::atomic::{AtomicBool, Ordering};
use windows::core::PWSTR;

/// Sets the logger wintun will use when logging. Maps to the WintunSetLogger C function
pub fn set_logger(wintun: &Wintun, f: wintun_raw::WINTUN_LOGGER_CALLBACK) {
Expand All @@ -23,7 +22,7 @@ pub unsafe extern "stdcall" fn default_logger(
message: *const wintun_raw::WCHAR,
) {
//Wintun will always give us a valid UTF16 null termineted string
let utf8_msg = PWSTR(message as *mut u16).to_string().unwrap_or_else(|e| e.to_string());
let utf8_msg = util::win_pwstr_to_string(message as *mut u16).unwrap_or_else(|e| e.to_string());
match level {
wintun_raw::WINTUN_LOGGER_LEVEL_WINTUN_LOG_INFO => log::info!("WinTun: {}", utf8_msg),
wintun_raw::WINTUN_LOGGER_LEVEL_WINTUN_LOG_WARN => log::warn!("WinTun: {}", utf8_msg),
Expand Down
Loading

0 comments on commit 5c801d0

Please sign in to comment.