moon-driver-utils 0.1.0

Windows Kernel Utils
use core::cell::UnsafeCell;

use wdk_sys::{
    ntddk::{
        ExAcquireResourceSharedLite, ExEnterCriticalRegionAndAcquireResourceExclusive,
        ExInitializeResourceLite, ExReleaseResourceAndLeaveCriticalRegion, ExReleaseResourceLite,
    },
    ERESOURCE, NT_SUCCESS, _ERESOURCE,
};

extern crate alloc;

pub struct ExecutionBody<T> {
    resource: _ERESOURCE,
    data: UnsafeCell<T>,
}

unsafe impl<T: Send> Sync for ExecutionBody<T> {}

pub struct InitExecutionBodyError {}

impl<T> ExecutionBody<T> {
    pub fn new(data: T) -> Result<Self, InitExecutionBodyError> {
        let mut resource = ERESOURCE::default();
        let status = unsafe { ExInitializeResourceLite(&mut resource as *mut _) };
        if !NT_SUCCESS(status) {
            return Err(InitExecutionBodyError {});
        }

        let r = ExecutionBody {
            resource,
            data: UnsafeCell::new(data),
        };
        Ok(r)
    }

    pub fn read(&self) -> ExecutionBodyReadGuard<T> {
        unsafe { ExAcquireResourceSharedLite(&self.resource as *const _ as *mut _, 1) };
        ExecutionBodyReadGuard { lock: self }
    }

    pub fn write(&self) -> ExecutionBodyWriteGuard<T> {
        unsafe {
            ExEnterCriticalRegionAndAcquireResourceExclusive(&self.resource as *const _ as *mut _)
        };
        ExecutionBodyWriteGuard { lock: self }
    }
}

pub struct ExecutionBodyReadGuard<'a, T> {
    lock: &'a ExecutionBody<T>,
}

impl<'a, T> core::ops::Deref for ExecutionBodyReadGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { &*self.lock.data.get() }
    }
}

impl<'a, T> Drop for ExecutionBodyReadGuard<'a, T> {
    fn drop(&mut self) {
        unsafe { ExReleaseResourceLite(&self.lock.resource as *const _ as *mut _) };
    }
}

pub struct ExecutionBodyWriteGuard<'a, T> {
    lock: &'a ExecutionBody<T>,
}

impl<'a, T> core::ops::Deref for ExecutionBodyWriteGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { &*self.lock.data.get() }
    }
}

impl<'a, T> core::ops::DerefMut for ExecutionBodyWriteGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.lock.data.get() }
    }
}

impl<'a, T> Drop for ExecutionBodyWriteGuard<'a, T> {
    fn drop(&mut self) {
        unsafe {
            ExReleaseResourceAndLeaveCriticalRegion(&self.lock.resource as *const _ as *mut _)
        };
    }
}