Windows adress wrapper and error formatter; allocator wrapper

This commit is contained in:
Andrew Golovashevich 2026-02-28 20:11:42 +03:00
parent 995bb2042d
commit 093b599882
9 changed files with 180 additions and 2 deletions

View File

@ -3,6 +3,9 @@ name = "bgtu-networks-2"
version = "0.0.0" version = "0.0.0"
edition = "2024" edition = "2024"
[lints]
rust = { nonstandard_style = "allow", unsafe_op_in_unsafe_fn = "allow" }
[dependencies] [dependencies]
eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] } eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] }
egui_extras = { version = "0.33.3" } egui_extras = { version = "0.33.3" }
@ -10,4 +13,10 @@ egui_extras = { version = "0.33.3" }
[dependencies.windows] [dependencies.windows]
version = ">=0.41.0, <=0.62.2" version = ">=0.41.0, <=0.62.2"
registry = "crates-io" registry = "crates-io"
features = ["Win32_System_SystemInformation", "Win32_System_Memory"] features = [
"Win32_System_IO",
"Win32_Networking",
"Win32_Networking_WinSock",
"Win32_System_Diagnostics",
"Win32_System_Diagnostics_Debug"
]

View File

@ -0,0 +1,5 @@
pub trait Address: Sized {
fn parse(raw: &str) -> Result<Self, String>;
fn to_string(self) -> String;
}

3
src/io/abstract/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod address;
pub use address::Address;

27
src/io/allocator.rs Normal file
View File

@ -0,0 +1,27 @@
use std::collections::HashMap;
use std::mem::uninitialized;
use std::pin::Pin;
use std::ptr;
pub struct Allocator<T> {
map: HashMap<usize, Pin<Box<T>>>,
}
impl<T> Allocator<T> {
pub fn new() -> Self {
return Self {
map: HashMap::new(),
};
}
pub unsafe fn alloc<'s>(&'s mut self) -> Pin<&'s mut T> {
let ptr = Box::pin(uninitialized::<T>());
let addr = ptr::from_ref(ptr.as_ref().get_ref()).addr();
self.map.insert(addr, ptr);
return self
.map
.get_mut(&addr)
.unwrap_or_else(|| unreachable!())
.as_mut();
}
}

3
src/io/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod windows;
mod allocator;
pub mod r#abstract;

49
src/io/windows/address.rs Normal file
View File

@ -0,0 +1,49 @@
use std::ffi::{c_char, c_void, OsString};
use crate::io::r#abstract::Address;
use crate::io::windows::errors::{format_windows_err_code_result, throw_from_windows_err_code};
use std::mem::zeroed;
use std::ptr;
use std::ptr::{copy_nonoverlapping, null, null_mut};
use windows::core::{PCWSTR, PWSTR};
use windows::Win32::Networking::WinSock::{FreeAddrInfoW, GetAddrInfoW, WSAAddressToStringW, WSAGetLastError, ADDRINFOW, SOCKADDR_STORAGE};
use std::mem::size_of;
use std::os::windows::ffi::OsStringExt;
pub struct WindowsAddress {
native: SOCKADDR_STORAGE,
}
impl Address for WindowsAddress {
fn parse(raw: &str) -> Result<Self, String> {
let encoded = raw.encode_utf16().collect::<Vec<_>>();
unsafe {
let mut p = null_mut::<ADDRINFOW>();
if (0 != GetAddrInfoW(PCWSTR(encoded.as_slice().as_ptr()), PCWSTR(null()), None, &mut p)) {
format_windows_err_code_result(WSAGetLastError())?;
}
let mut this = Self {
native: zeroed()
};
copy_nonoverlapping((*p).ai_addr.cast(), &mut this.native, (*p).ai_addrlen);
FreeAddrInfoW(Some(p));
return Result::Ok(this);
}
}
fn to_string(self) -> String {
let mut buffer = [0u16; 1024];
let mut buf_size = buffer.len() as u32;
unsafe {
if 0 != WSAAddressToStringW(ptr::from_ref(&self.native).cast(), size_of::<SOCKADDR_STORAGE>() as u32, None, PWSTR(buffer.as_mut_ptr()), &mut buf_size) {
throw_from_windows_err_code(WSAGetLastError());
}
}
return OsString::from_wide(&buffer).to_string_lossy().into_owned();
}
}

80
src/io/windows/errors.rs Normal file
View File

@ -0,0 +1,80 @@
use std::ffi::{CStr, CString, c_char};
use std::ptr;
use std::ptr::null_mut;
use std::slice::from_raw_parts_mut;
use windows::Win32::Foundation::{HLOCAL, LocalFree};
use windows::Win32::Networking::WinSock::WSA_ERROR;
use windows::Win32::System::Diagnostics::Debug::{
FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS,
FormatMessageA,
};
use windows::core::PSTR;
trait ErrCode {
fn to_dword(&self) -> u32;
}
impl ErrCode for WSA_ERROR {
fn to_dword(&self) -> u32 {
return 0u32
.checked_add_signed(self.0)
.unwrap_or_else(|| panic!("Cast i32 -> u32 overflow"));
}
}
impl ErrCode for u32 {
fn to_dword(&self) -> u32 {
return *self;
}
}
pub(super) fn throw_from_windows_err_code(code: impl ErrCode) -> ! {
panic!(
"Windows error [{:X}]: {}",
code.to_dword(),
format_windows_err_code(code)
)
}
pub(super) fn format_windows_err_code_result(code: impl ErrCode) -> Result<(), String> {
return Result::Err(format_windows_err_code(code));
}
pub(super) fn format_windows_err_code(code: impl ErrCode) -> String {
unsafe {
let mut msg = null_mut::<c_char>();
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
None,
code.to_dword(),
1 << 10,
PSTR(ptr::from_mut(&mut msg).cast()),
0,
None,
);
let mut trim_size = CStr::from_ptr(msg).count_bytes();
let msg = from_raw_parts_mut(msg, trim_size + 1);
while trim_size > 0 {
trim_size -= 1;
match msg[trim_size] {
0x0A | 0x0D => msg[trim_size] = 0x00,
_ => break,
}
}
let msg_owned = CStr::from_ptr(msg.as_ptr()).to_str().unwrap().to_owned();
LocalFree(Some(HLOCAL(msg.as_mut_ptr().cast())));
return msg_owned;
}
}
#[test]
fn _test_works() {
format_windows_err_code(0u32);
}

2
src/io/windows/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod address;
mod errors;

View File

@ -1,5 +1,5 @@
mod data2;
mod data; mod data;
mod io;
fn main() { fn main() {
println!("Hello, world!"); println!("Hello, world!");