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> {}
impl<T: Sized> PoolMemory<T> {
pub fn new(value: T, 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 _);
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 _);
}
}
}