summaryrefslogtreecommitdiff
path: root/crates/windows-kernel-rs/src/driver.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/windows-kernel-rs/src/driver.rs')
-rw-r--r--crates/windows-kernel-rs/src/driver.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/crates/windows-kernel-rs/src/driver.rs b/crates/windows-kernel-rs/src/driver.rs
new file mode 100644
index 0000000..2bdac4e
--- /dev/null
+++ b/crates/windows-kernel-rs/src/driver.rs
@@ -0,0 +1,85 @@
+use alloc::boxed::Box;
+
+use widestring::U16CString;
+use windows_kernel_sys::{base::DRIVER_OBJECT, ntoskrnl::IoCreateDevice};
+
+use crate::{
+ device::{
+ Access,
+ Device,
+ DeviceDoFlags,
+ DeviceExtension,
+ DeviceFlags,
+ DeviceOperations,
+ DeviceOperationsVtable,
+ DeviceType,
+ },
+ error::{Error, IntoResult},
+ string::create_unicode_string,
+};
+
+pub struct Driver {
+ pub(crate) raw: *mut DRIVER_OBJECT,
+}
+
+impl Driver {
+ pub unsafe fn from_raw(raw: *mut DRIVER_OBJECT) -> Self {
+ Self {
+ raw,
+ }
+ }
+
+ pub unsafe fn as_raw(&self) -> *const DRIVER_OBJECT { self.raw as _ }
+
+ pub unsafe fn as_raw_mut(&mut self) -> *mut DRIVER_OBJECT { self.raw as _ }
+
+ pub fn create_device<T>(
+ &mut self,
+ name: &str,
+ device_type: DeviceType,
+ device_flags: DeviceFlags,
+ device_do_flags: DeviceDoFlags,
+ access: Access,
+ data: T,
+ ) -> Result<Device, Error>
+ where
+ T: DeviceOperations,
+ {
+ // Box the data.
+ let data = Box::new(data);
+
+ // Convert the name to UTF-16 and then create a UNICODE_STRING.
+ let name = U16CString::from_str(name).unwrap();
+ let mut name = create_unicode_string(name.as_slice());
+
+ // Create the device.
+ let mut device = core::ptr::null_mut();
+
+ unsafe {
+ IoCreateDevice(
+ self.raw,
+ core::mem::size_of::<DeviceExtension>() as u32,
+ &mut name,
+ device_type.into(),
+ device_flags.bits(),
+ access.is_exclusive() as _,
+ &mut device,
+ )
+ }
+ .into_result()?;
+
+ unsafe {
+ (*device).Flags |= device_do_flags.bits();
+ }
+
+ let device = unsafe { Device::from_raw(device) };
+
+ // Store the boxed data and vtable.
+ let extension = device.extension_mut();
+ extension.device_type = device_type;
+ extension.vtable = &DeviceOperationsVtable::<T>::VTABLE;
+ extension.data = Box::into_raw(data) as *mut cty::c_void;
+
+ Ok(device)
+ }
+}