use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
use crate::{ArchAdapter, WindowsError, WindowsOs, offset};
pub struct WindowsKeyIndex<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
vmi: VmiState<'a, WindowsOs<Driver>>,
va: Va,
}
impl<Driver> VmiVa for WindowsKeyIndex<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn va(&self) -> Va {
self.va
}
}
impl<'a, Driver> WindowsKeyIndex<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
pub const INDEX_LEAF_SIGNATURE: u16 = 0x696c;
pub const FAST_LEAF_SIGNATURE: u16 = 0x666c;
pub const HASH_LEAF_SIGNATURE: u16 = 0x686c;
pub const INDEX_ROOT_SIGNATURE: u16 = 0x6972;
pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
Self { vmi, va }
}
pub fn signature(&self) -> Result<u16, VmiError> {
let CM_KEY_INDEX = offset!(self.vmi, _CM_KEY_INDEX);
self.vmi.read_u16(self.va + CM_KEY_INDEX.Signature.offset())
}
pub fn count(&self) -> Result<u16, VmiError> {
let CM_KEY_INDEX = offset!(self.vmi, _CM_KEY_INDEX);
self.vmi.read_u16(self.va + CM_KEY_INDEX.Count.offset())
}
pub fn list(&self) -> Result<Va, VmiError> {
let CM_KEY_INDEX = offset!(self.vmi, _CM_KEY_INDEX);
Ok(self.va + CM_KEY_INDEX.List.offset())
}
pub fn entry_size(&self) -> Result<u64, VmiError> {
Self::entry_size_for(self.signature()?)
}
pub fn entry_size_for(signature: u16) -> Result<u64, VmiError> {
match signature {
Self::INDEX_LEAF_SIGNATURE | Self::INDEX_ROOT_SIGNATURE => Ok(4),
Self::FAST_LEAF_SIGNATURE | Self::HASH_LEAF_SIGNATURE => Ok(8),
_ => Err(WindowsError::CorruptedStruct("CM_KEY_INDEX.Signature").into()),
}
}
}