use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
use super::WindowsObject;
use crate::{ArchAdapter, WindowsOs, WindowsOsExt as _, offset};
pub struct WindowsObjectHeaderNameInfo<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi: VmiState<'a, WindowsOs<Driver>>,
va: Va,
}
impl<Driver> VmiVa for WindowsObjectHeaderNameInfo<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn va(&self) -> Va {
self.va
}
}
impl<Driver> std::fmt::Debug for WindowsObjectHeaderNameInfo<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let directory = self.directory();
let name = self.name();
f.debug_struct("WindowsObjectHeaderNameInfo")
.field("directory", &directory)
.field("name", &name)
.finish()
}
}
impl<'a, Driver> WindowsObjectHeaderNameInfo<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
Self { vmi, va }
}
pub fn directory(&self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
let OBJECT_HEADER_NAME_INFO = offset!(self.vmi, _OBJECT_HEADER_NAME_INFO);
let directory = self
.vmi
.read_va_native(self.va + OBJECT_HEADER_NAME_INFO.Directory.offset())?;
if directory.is_null() {
return Ok(None);
}
Ok(Some(WindowsObject::new(self.vmi, directory)))
}
pub fn name(&self) -> Result<String, VmiError> {
let OBJECT_HEADER_NAME_INFO = offset!(self.vmi, _OBJECT_HEADER_NAME_INFO);
self.vmi
.os()
.read_unicode_string(self.va + OBJECT_HEADER_NAME_INFO.Name.offset())
}
pub fn full_path(&self) -> Result<String, VmiError> {
let mut path = String::new();
if let Some(directory) = self.directory()? {
if let Some(directory_path) = directory.full_path()? {
path.push_str(&directory_path);
}
if directory.va() != self.vmi.os().object_root_directory()?.va() {
path.push('\\');
}
}
path.push_str(&self.name()?);
Ok(path)
}
}