use core::{ffi::c_void, fmt::{self, Write}, ptr::{null, null_mut}, slice};
pub mod winhvplatformdefs;
pub mod winhvplatform;
pub mod winhvemulation;
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)] pub struct HResult(pub u32);
struct ResultBuffer<'a>(&'a mut [u16]);
impl ResultBuffer<'_>
{
fn format_result(result:u32)->Result<Self,Win32Error>
{
let mut text_raw:*mut u16=null_mut();
let chars=unsafe{FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,null(),result,0,&raw mut text_raw,0,null())};
if chars>0
{
Ok(Self(unsafe{slice::from_raw_parts_mut(text_raw.cast(),chars as usize)}))
}
else
{
Err(unsafe{GetLastError()})
}
}
}
impl Drop for ResultBuffer<'_>
{
fn drop(&mut self)
{
unsafe
{
LocalFree(self.0.as_mut_ptr().cast());
}
}
}
impl HResult
{
pub const S_OK:Self=Self(0x00000000);
pub const E_NOTIMPL:Self=Self(0x80004001);
pub const E_FAIL:Self=Self(0x80004005);
}
impl fmt::Display for HResult
{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result
{
match ResultBuffer::format_result(self.0)
{
Ok(buff)=>
{
for result in char::decode_utf16(buff.0.iter().copied())
{
match result
{
Ok(c)=>f.write_char(c)?,
Err(_)=>return Err(fmt::Error)
}
}
Ok(())
}
Err(e)=>writeln!(f,"FormatMessageW cannot display HRESULT 0x{:X}! Error-Code: {e}",self.0)
}
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)] pub struct Win32Error(pub u32);
impl fmt::Display for Win32Error
{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result
{
match ResultBuffer::format_result(self.0)
{
Ok(buff)=>
{
for result in char::decode_utf16(buff.0.iter().copied())
{
match result
{
Ok(c)=>f.write_char(c)?,
Err(_)=>return Err(fmt::Error)
}
}
Ok(())
}
Err(e)=>writeln!(f,"FormatMessageW cannot display Error-Code {}! Error-Code: {e}",self.0)
}
}
}
unsafe extern "system"
{
fn LoadLibraryA(image_name:*const i8)->*mut c_void;
fn GetProcAddress(image_base:*mut c_void,procedure_name:*const i8)->*const c_void;
fn FormatMessageW(flags:u32,source:*const c_void,message_id:u32,language_id:u32,buffer:*mut *mut u16,size:u32,args:*const *const i8)->u32;
fn LocalFree(mem:*mut c_void)->*mut c_void;
pub(super) fn GetLastError()->Win32Error;
pub(super) fn VirtualAlloc(address:*mut c_void,size:usize,allocation_type:u32,protect:u32)->*mut c_void;
pub(super) fn VirtualFree(address:*mut c_void,size:usize,free_type:u32)->bool;
}
pub(super) const MEM_COMMIT:u32=0x1000;
pub(super) const MEM_RELEASE:u32=0x8000;
pub(super) const PAGE_READWRITE:u32=0x4;
const FORMAT_MESSAGE_ALLOCATE_BUFFER:u32=0x100;
const FORMAT_MESSAGE_FROM_SYSTEM:u32=0x1000;
macro_rules! whv_binding
{
($static_name:ident,$type_name:ident,$default_name:ident,$sig:tt) =>
{
pub type $type_name=unsafe extern "system" fn $sig->HResult;
pub(super) static mut $static_name:$type_name=$default_name;
#[allow(unused_variables)]
unsafe extern "system" fn $default_name $sig -> HResult
{
HResult::E_NOTIMPL
}
};
}
use whv_binding;
pub fn init_bindings()
{
winhvemulation::init_bindings();
winhvplatform::init_bindings();
}