moon-driver-core 0.1.3

Windows WDK driver core helpers: device, IOCTL, IRP, symlink
use alloc::vec::Vec;
use wdk_sys::{
    ntddk::{IoCreateSymbolicLink, IoDeleteSymbolicLink, RtlInitUnicodeString},
    NT_SUCCESS, UNICODE_STRING,
};

pub struct SymbolicLink {
    name: Vec<u16>,
}

impl SymbolicLink {
    pub fn new(name: &str, target: &str) -> Result<Self, &'static str> {
        let name_utf16: Vec<u16> = name.encode_utf16().chain(core::iter::once(0)).collect();
        Self::create(&name_utf16, target)?;
        Ok(Self { name: name_utf16 })
    }
    pub fn create(name: &Vec<u16>, target: &str) -> Result<(), &'static str> {
        let mut name_us: UNICODE_STRING = unsafe { core::mem::zeroed() };
        let mut target_us: UNICODE_STRING = unsafe { core::mem::zeroed() };
        let target_utf16: Vec<u16> = target.encode_utf16().chain(core::iter::once(0)).collect();
        unsafe {
            RtlInitUnicodeString(&mut name_us, name.as_ptr());
            RtlInitUnicodeString(&mut target_us, target_utf16.as_ptr());
        }
        let status = unsafe { IoCreateSymbolicLink(&mut name_us, &mut target_us) };
        if !NT_SUCCESS(status) {
            return Err("CreateSymbolicLink error");
        }
        Ok(())
    }
    fn delete(name: &Vec<u16>) {
        let mut name_us: UNICODE_STRING = unsafe { core::mem::zeroed() };
        unsafe {
            RtlInitUnicodeString(&mut name_us, name.as_ptr());
            let _ = IoDeleteSymbolicLink(&mut name_us);
        }
    }
}

impl Drop for SymbolicLink {
    fn drop(&mut self) {
        Self::delete(&self.name);
    }
}