diff --git a/Cargo.toml b/Cargo.toml index e115a77..7a3e045 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ name = "bgtu-networks-2" version = "0.0.0" edition = "2024" +[lints] +rust = { nonstandard_style = "allow", unsafe_op_in_unsafe_fn = "allow" } + [dependencies] eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] } egui_extras = { version = "0.33.3" } @@ -10,4 +13,10 @@ egui_extras = { version = "0.33.3" } [dependencies.windows] version = ">=0.41.0, <=0.62.2" registry = "crates-io" -features = ["Win32_System_SystemInformation", "Win32_System_Memory"] \ No newline at end of file +features = [ + "Win32_System_IO", + "Win32_Networking", + "Win32_Networking_WinSock", + "Win32_System_Diagnostics", + "Win32_System_Diagnostics_Debug" +] \ No newline at end of file diff --git a/src/io/abstract/address.rs b/src/io/abstract/address.rs new file mode 100644 index 0000000..d96110a --- /dev/null +++ b/src/io/abstract/address.rs @@ -0,0 +1,5 @@ +pub trait Address: Sized { + fn parse(raw: &str) -> Result; + + fn to_string(self) -> String; +} diff --git a/src/io/abstract/mod.rs b/src/io/abstract/mod.rs new file mode 100644 index 0000000..a64e967 --- /dev/null +++ b/src/io/abstract/mod.rs @@ -0,0 +1,3 @@ +mod address; + +pub use address::Address; \ No newline at end of file diff --git a/src/io/allocator.rs b/src/io/allocator.rs new file mode 100644 index 0000000..7c51b1b --- /dev/null +++ b/src/io/allocator.rs @@ -0,0 +1,27 @@ +use std::collections::HashMap; +use std::mem::uninitialized; +use std::pin::Pin; +use std::ptr; + +pub struct Allocator { + map: HashMap>>, +} + +impl Allocator { + 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::()); + 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(); + } +} diff --git a/src/io/mod.rs b/src/io/mod.rs new file mode 100644 index 0000000..15b2dac --- /dev/null +++ b/src/io/mod.rs @@ -0,0 +1,3 @@ +mod windows; +mod allocator; +pub mod r#abstract; \ No newline at end of file diff --git a/src/io/windows/address.rs b/src/io/windows/address.rs new file mode 100644 index 0000000..246d049 --- /dev/null +++ b/src/io/windows/address.rs @@ -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 { + let encoded = raw.encode_utf16().collect::>(); + unsafe { + let mut p = null_mut::(); + + 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::() 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(); + } +} diff --git a/src/io/windows/errors.rs b/src/io/windows/errors.rs new file mode 100644 index 0000000..f39cb31 --- /dev/null +++ b/src/io/windows/errors.rs @@ -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::(); + 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); +} diff --git a/src/io/windows/mod.rs b/src/io/windows/mod.rs new file mode 100644 index 0000000..1250081 --- /dev/null +++ b/src/io/windows/mod.rs @@ -0,0 +1,2 @@ +mod address; +mod errors; diff --git a/src/main.rs b/src/main.rs index 3566ed6..a7907da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -mod data2; mod data; +mod io; fn main() { println!("Hello, world!");