whpx 0.1.0

Idiomatic Rust Bindings of Windows Hypervisor Platform
Documentation
// Windows Hypervisor Platform FFI Bindings

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;

// Binding helpers
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
		}
	};
}

// Export macro to self.
use whv_binding;

/// Initializes Bindings to Windows Hypervisor Platform APIs and Windows Hypervisor Instruction Emulation APIs.
/// 
/// This is the fundamental initialization routine that you must call before using any functionality of this crate.
pub fn init_bindings()
{
	winhvemulation::init_bindings();
	winhvplatform::init_bindings();
}