50 lines
1.7 KiB
Rust
50 lines
1.7 KiB
Rust
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();
|
|
}
|
|
}
|