vmi_os_windows/iter/
directory.rs1use std::iter::FusedIterator;
2
3use vmi_core::{Registers as _, Va, VmiError, VmiState, driver::VmiRead};
4
5use crate::{ArchAdapter, WindowsObject, WindowsOs};
6
7pub struct DirectoryObjectIterator<'a, Driver>
13where
14 Driver: VmiRead,
15 Driver::Architecture: ArchAdapter<Driver>,
16{
17 vmi: VmiState<'a, WindowsOs<Driver>>,
19
20 directory_va: Va,
22
23 hash_buckets_offset: u64,
25
26 chain_link_offset: u64,
28
29 object_offset: u64,
31
32 bucket: u64,
34
35 entry: Option<Va>,
38}
39
40impl<'a, Driver> DirectoryObjectIterator<'a, Driver>
41where
42 Driver: VmiRead,
43 Driver::Architecture: ArchAdapter<Driver>,
44{
45 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, directory_va: Va) -> Self {
47 let offsets = &vmi.underlying_os().offsets;
48 let OBJECT_DIRECTORY = &offsets._OBJECT_DIRECTORY;
49 let OBJECT_DIRECTORY_ENTRY = &offsets._OBJECT_DIRECTORY_ENTRY;
50
51 let hash_buckets_offset = OBJECT_DIRECTORY.HashBuckets.offset();
52 let chain_link_offset = OBJECT_DIRECTORY_ENTRY.ChainLink.offset();
53 let object_offset = OBJECT_DIRECTORY_ENTRY.Object.offset();
54
55 Self {
56 vmi,
57 directory_va,
58 hash_buckets_offset,
59 chain_link_offset,
60 object_offset,
61 bucket: 0,
62 entry: None,
63 }
64 }
65
66 fn walk_next(&mut self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
68 const BUCKET_COUNT: u64 = 37;
69
70 let address_width = self.vmi.registers().address_width() as u64;
71
72 loop {
73 let entry = match self.entry.take() {
74 Some(entry) => entry,
75 None => {
76 if self.bucket >= BUCKET_COUNT {
77 return Ok(None);
78 }
79
80 let hash_bucket = self.vmi.read_va_native(
81 self.directory_va + self.hash_buckets_offset + self.bucket * address_width,
82 )?;
83 self.bucket += 1;
84
85 if hash_bucket.is_null() {
86 continue;
87 }
88
89 hash_bucket
90 }
91 };
92
93 let object = self.vmi.read_va_native(entry + self.object_offset)?;
94 let next = self.vmi.read_va_native(entry + self.chain_link_offset)?;
95
96 self.entry = if next.is_null() { None } else { Some(next) };
97
98 return Ok(Some(WindowsObject::new(self.vmi, object)));
99 }
100 }
101}
102
103impl<'a, Driver> Iterator for DirectoryObjectIterator<'a, Driver>
104where
105 Driver: VmiRead,
106 Driver::Architecture: ArchAdapter<Driver>,
107{
108 type Item = Result<WindowsObject<'a, Driver>, VmiError>;
109
110 fn next(&mut self) -> Option<Self::Item> {
111 self.walk_next().transpose()
112 }
113}
114
115impl<Driver> FusedIterator for DirectoryObjectIterator<'_, Driver>
116where
117 Driver: VmiRead,
118 Driver::Architecture: ArchAdapter<Driver>,
119{
120}