use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
use super::{FromWindowsObject, WindowsObject, WindowsObjectTypeKind};
use crate::{ArchAdapter, WindowsOs, WindowsOsExt as _, offset};
pub struct WindowsFileObject<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi: VmiState<'a, WindowsOs<Driver>>,
va: Va,
}
impl<'a, Driver> From<WindowsFileObject<'a, Driver>> for WindowsObject<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn from(value: WindowsFileObject<'a, Driver>) -> Self {
Self::new(value.vmi, value.va)
}
}
impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsFileObject<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn from_object(object: WindowsObject<'a, Driver>) -> Result<Option<Self>, VmiError> {
match object.type_kind()? {
Some(WindowsObjectTypeKind::File) => Ok(Some(Self::new(object.vmi, object.va))),
_ => Ok(None),
}
}
}
impl<Driver> VmiVa for WindowsFileObject<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn va(&self) -> Va {
self.va
}
}
impl<'a, Driver> WindowsFileObject<'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 device_object(&self) -> Result<WindowsObject<'a, Driver>, VmiError> {
let FILE_OBJECT = offset!(self.vmi, _FILE_OBJECT);
let device_object = self
.vmi
.read_va_native(self.va + FILE_OBJECT.DeviceObject.offset())?;
Ok(WindowsObject::new(self.vmi, device_object))
}
pub fn filename(&self) -> Result<String, VmiError> {
let FILE_OBJECT = offset!(self.vmi, _FILE_OBJECT);
self.vmi
.os()
.read_unicode_string(self.va + FILE_OBJECT.FileName.offset())
}
pub fn full_path(&self) -> Result<String, VmiError> {
let device = self.device_object()?.name_info()?;
let directory = match &device {
Some(device) => match device.directory()? {
Some(directory) => directory.name_info()?,
None => None,
},
None => None,
};
let mut result = String::new();
if let Some(directory) = directory {
result.push('\\');
result.push_str(&directory.name()?);
}
if let Some(device) = device {
result.push('\\');
result.push_str(&device.name()?);
}
result.push_str(&self.filename()?);
Ok(result)
}
}