Safe way to call WSACleanup

This commit is contained in:
Andrew Golovashevich 2026-03-02 23:31:08 +03:00
parent d3c4e684ff
commit 5dc2ba2dca
3 changed files with 59 additions and 22 deletions

View File

@ -0,0 +1,56 @@
use super::errors::throw_from_windows_err_code;
use std::mem::uninitialized;
use windows::Win32::Networking::WinSock::{
SOCKET_ERROR, WSACleanup, WSADATA, WSAGetLastError, WSAStartup,
};
use bgtu_networks_2_network_abstract::NetworkScope;
struct WinSocksDefer {}
impl WinSocksDefer {
fn startup(expected_version: (u8, u8)) -> Self {
unsafe {
let mut data = uninitialized::<WSADATA>();
let expected_version_packed =
((expected_version.1 as u16) << 8) | (expected_version.0 as u16);
match WSAStartup(expected_version_packed, &mut data) {
0 => {}
errcode => throw_from_windows_err_code(errcode),
}
if data.wVersion != expected_version_packed {
panic!(
"WinSocks doesn't supports requested version {}.{}, maximum supported is {}.{}, current {}.{}",
expected_version.0,
expected_version.1,
data.wHighVersion & 0xFF,
data.wHighVersion >> 8,
data.wVersion & 0xFF,
data.wVersion >> 8
);
}
return Self {};
}
}
}
impl Drop for WinSocksDefer {
fn drop(&mut self) {
unsafe {
match WSACleanup() {
0 => {}
SOCKET_ERROR => throw_from_windows_err_code(WSAGetLastError()),
ret => panic!("Unexpected return value of `WSACleanup()`: {ret}"),
}
}
}
}
pub fn winsocks_scope_2_2<R>(scope: impl NetworkScope) -> R {
let ws = WinSocksDefer::startup((2,2));
scope.run(todo!());
let _ = ws;
}

View File

@ -3,4 +3,6 @@ mod errors;
mod task;
mod eventloop;
mod allocator;
mod winsocks_scope;
mod entry_point;
pub use entry_point::winsocks_scope_2_2;

View File

@ -1,21 +0,0 @@
use super::errors::throw_from_windows_err_code;
use std::mem::uninitialized;
use windows::Win32::Networking::WinSock::{WSACleanup, WSAStartup};
pub(in crate) fn winsocks_scope<R>(scope: impl FnOnce() -> R) -> R {
unsafe {
match WSAStartup(0x0202, &mut uninitialized()) {
0 => {}
errcode => throw_from_windows_err_code(errcode),
}
let result = scope();
match WSACleanup() {
0 => {}
errcode => throw_from_windows_err_code(errcode),
}
return result;
}
}