use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead, os::ProcessObject};
use super::WindowsProcess;
use crate::{ArchAdapter, ListEntryIterator, WindowsOs, offset};
struct Field {
offset: u64,
}
impl Field {
const fn offset(&self) -> u64 {
self.offset
}
}
#[expect(non_camel_case_types)]
struct _MM_SESSION_SPACE {
SessionId: Field, ProcessList: Field, }
const MM_SESSION_SPACE: _MM_SESSION_SPACE = _MM_SESSION_SPACE {
SessionId: Field { offset: 0x0008 },
ProcessList: Field { offset: 0x0010 },
};
pub struct WindowsSession<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi: VmiState<'a, WindowsOs<Driver>>,
va: Va,
}
impl<Driver> VmiVa for WindowsSession<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn va(&self) -> Va {
self.va
}
}
impl<'a, Driver> WindowsSession<'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 id(&self) -> Result<u32, VmiError> {
self.vmi
.read_u32(self.va + MM_SESSION_SPACE.SessionId.offset())
}
pub fn processes(
&self,
) -> Result<
impl Iterator<Item = Result<WindowsProcess<'a, Driver>, VmiError>> + use<'a, Driver>,
VmiError,
> {
let EPROCESS = offset!(self.vmi, _EPROCESS);
let vmi = self.vmi;
Ok(ListEntryIterator::new(
vmi,
self.va + MM_SESSION_SPACE.ProcessList.offset(),
EPROCESS.SessionProcessLinks.offset(),
)
.map(move |result| result.map(|entry| WindowsProcess::new(vmi, ProcessObject(entry)))))
}
}