#![no_std]
extern crate alloc;
pub mod device;
pub mod driver;
pub mod io_request;
pub mod ioctl;
pub mod symbolic_link;
use core::cell::UnsafeCell;
use device::{dispatch_device, Device, DeviceOperations};
use driver::Driver;
use symbolic_link::SymbolicLink;
use wdk_sys::{IRP_MJ_MAXIMUM_FUNCTION, _DRIVER_OBJECT};
struct Holder(UnsafeCell<Option<(Device, SymbolicLink)>>);
unsafe impl Sync for Holder {}
static CORE_HOLDER: Holder = Holder(UnsafeCell::new(None));
static mut CUSTOM_UNLOAD: Option<unsafe extern "C" fn(*mut wdk_sys::DRIVER_OBJECT)> = None;
pub unsafe extern "C" fn driver_unload(driver: *mut wdk_sys::DRIVER_OBJECT) {
let slot = &mut *CORE_HOLDER.0.get();
slot.take();
if let Some(f) = CUSTOM_UNLOAD {
f(driver);
}
}
pub unsafe fn init<T: DeviceOperations>(
driver_object: *mut _DRIVER_OBJECT,
device_name: &str,
symlink_name: &str,
data: T,
) -> Result<(), &'static str> {
if driver_object.is_null() {
return Err("driver_object is null");
}
let driver_object = &mut *driver_object;
let mut driver = Driver::from_raw(driver_object);
let device = driver.create_device(device_name, 0x22, 0, 0, data)?;
for i in 0..IRP_MJ_MAXIMUM_FUNCTION {
driver_object.MajorFunction[i as usize] = Some(dispatch_device);
}
let symlink = SymbolicLink::new(symlink_name, device_name)?;
driver_object.DriverUnload = Some(driver_unload);
let slot = &mut *CORE_HOLDER.0.get();
*slot = Some((device, symlink));
Ok(())
}
pub unsafe fn init_with_unload<T: DeviceOperations>(
driver_object: *mut _DRIVER_OBJECT,
device_name: &str,
symlink_name: &str,
data: T,
unload: Option<unsafe extern "C" fn(*mut wdk_sys::DRIVER_OBJECT)>,
) -> Result<(), &'static str> {
CUSTOM_UNLOAD = unload;
init(driver_object, device_name, symlink_name, data)
}