moon-driver-utils 0.1.0

Windows Kernel Utils
pub mod npp;
pub mod npp_alloc;
pub mod pp;
pub mod utils;

use core::{
    alloc::Layout,
    fmt,
    ops::{Deref, DerefMut},
    ptr::NonNull,
};

use wdk_sys::{
    ntddk::{memset, ExAllocatePool, ExFreePool},
    POOL_TYPE,
};

#[derive(Debug)]
pub struct AllocationError;

impl fmt::Display for AllocationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Memory allocation failed")
    }
}

pub struct PoolMemory<T: ?Sized> {
    ptr: NonNull<T>,
}

unsafe impl<T: Send + ?Sized> Send for PoolMemory<T> {}
unsafe impl<T: Sync + ?Sized> Sync for PoolMemory<T> {}

// TODO: replace to Box with allocate
impl<T: Sized> PoolMemory<T> {
    pub fn new(value: T, pool_type: POOL_TYPE) -> Result<Self, AllocationError> {
        // let _ = Box::new_in(value, WDKAllocator);

        let layout = Layout::new::<T>();
        let ptr = unsafe { ExAllocatePool(pool_type, layout.size() as _) as *mut T };
        let data = NonNull::new(ptr).ok_or(AllocationError)?;
        unsafe {
            memset(ptr as *mut _, 0, layout.size() as _);
            core::ptr::write(ptr, value);
        }
        Ok(Self { ptr: data })
    }

    pub fn new_type(pool_type: POOL_TYPE) -> Result<Self, AllocationError> {
        let layout = Layout::new::<T>();
        let ptr = unsafe { ExAllocatePool(pool_type, layout.size() as _) as *mut T };
        let data = NonNull::new(ptr).ok_or(AllocationError)?;
        unsafe {
            memset(ptr as *mut _, 0, layout.size() as _);
        }
        Ok(Self { ptr: data })
    }

    pub fn new_bytes(pool_type: POOL_TYPE, len: u64) -> Result<Self, AllocationError> {
        let ptr = unsafe { ExAllocatePool(pool_type, len) as *mut T };
        let data = NonNull::new(ptr).ok_or(AllocationError)?;
        unsafe {
            memset(ptr as _, 0, len as _);
        }
        Ok(Self { ptr: data })
    }
}

impl<T: ?Sized> PoolMemory<T> {
    pub fn into_raw(self) -> *mut T {
        let ptr = self.ptr.as_ptr();
        core::mem::forget(self);
        ptr
    }

    pub unsafe fn from_raw(raw: *mut T) -> Result<Self, AllocationError> {
        let data = NonNull::new(raw).ok_or(AllocationError)?;
        Ok(Self { ptr: data })
    }

    pub fn as_ptr(&self) -> *mut T {
        self.ptr.as_ptr()
    }
}

impl<T: ?Sized> Deref for PoolMemory<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { self.ptr.as_ref() }
    }
}

impl<T: ?Sized> DerefMut for PoolMemory<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { self.ptr.as_mut() }
    }
}

impl<T: ?Sized> Drop for PoolMemory<T> {
    fn drop(&mut self) {
        unsafe {
            core::ptr::drop_in_place(self.ptr.as_ptr());
            ExFreePool(self.ptr.as_ptr() as *mut _);
        }
    }
}