1use std::iter::FusedIterator;
2
3use vmi_core::{Pa, Registers as _, Va, VmiError, VmiState, driver::VmiRead};
4
5use crate::{
6 WindowsOs, WindowsWow64Kind,
7 arch::{ArchAdapter, StructLayout, StructLayout32, StructLayout64},
8};
9
10pub trait ListEntry<Layout>
12where
13 Layout: StructLayout,
14{
15 const OFFSET_FLINK: u64;
17
18 const OFFSET_BLINK: u64;
20}
21
22pub struct ListEntryLayout;
24
25impl ListEntry<StructLayout32> for ListEntryLayout {
26 const OFFSET_FLINK: u64 = 0x00;
27 const OFFSET_BLINK: u64 = 0x04;
28}
29
30impl ListEntry<StructLayout64> for ListEntryLayout {
31 const OFFSET_FLINK: u64 = 0x00;
32 const OFFSET_BLINK: u64 = 0x08;
33}
34
35pub struct ListEntryIteratorBase<'a, Driver, Layout>
41where
42 Driver: VmiRead,
43 Driver::Architecture: ArchAdapter<Driver>,
44 Layout: StructLayout,
45 ListEntryLayout: ListEntry<Layout>,
46{
47 vmi: VmiState<'a, WindowsOs<Driver>>,
49
50 list_head: Va,
52
53 offset: u64,
59
60 root: Pa,
62
63 current: Option<Va>,
65
66 initialized: bool,
68
69 _marker: std::marker::PhantomData<Layout>,
70}
71
72impl<'a, Driver, Layout> ListEntryIteratorBase<'a, Driver, Layout>
73where
74 Driver: VmiRead,
75 Driver::Architecture: ArchAdapter<Driver>,
76 Layout: StructLayout,
77 ListEntryLayout: ListEntry<Layout>,
78{
79 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64, root: Pa) -> Self {
81 Self {
82 vmi,
83 list_head,
84 offset,
85 root,
86 current: None,
87 initialized: false,
88 _marker: std::marker::PhantomData,
89 }
90 }
91
92 fn next_entry(&self, entry: Va) -> Result<Va, VmiError> {
96 Layout::read_va(
97 self.vmi,
98 (
99 entry + <ListEntryLayout as ListEntry<Layout>>::OFFSET_FLINK,
100 self.root,
101 ),
102 )
103 }
104
105 fn previous_entry(&self, entry: Va) -> Result<Va, VmiError> {
109 Layout::read_va(
110 self.vmi,
111 (
112 entry + <ListEntryLayout as ListEntry<Layout>>::OFFSET_BLINK,
113 self.root,
114 ),
115 )
116 }
117
118 fn first_entry(&self) -> Result<Option<Va>, VmiError> {
122 if self.list_head.is_null() {
123 return Ok(None);
124 }
125
126 Ok(Some(self.next_entry(self.list_head)?))
127 }
128
129 fn last_entry(&self) -> Result<Option<Va>, VmiError> {
133 if self.list_head.is_null() {
134 return Ok(None);
135 }
136
137 Ok(Some(self.previous_entry(self.list_head)?))
138 }
139
140 fn walk_next(&mut self) -> Result<Option<Va>, VmiError> {
142 let entry = match self.current {
143 Some(entry) => entry,
144 None => {
145 if self.initialized {
150 return Ok(None);
151 }
152
153 self.initialized = true;
154
155 match self.first_entry() {
156 Ok(Some(first)) => first,
157 Ok(None) => return Ok(None),
158 Err(err) => return Err(err),
159 }
160 }
161 };
162
163 if entry == self.list_head {
164 return Ok(None);
165 }
166
167 match self.next_entry(entry) {
168 Ok(next) => self.current = Some(next),
169 Err(err) => {
170 self.current = None;
173 return Err(err);
174 }
175 }
176
177 Ok(Some(entry - self.offset))
178 }
179
180 fn walk_next_back(&mut self) -> Result<Option<Va>, VmiError> {
182 let entry = match self.current {
183 Some(entry) => entry,
184 None => {
185 if self.initialized {
190 return Ok(None);
191 }
192
193 self.initialized = true;
194
195 match self.last_entry() {
196 Ok(Some(last)) => last,
197 Ok(None) => return Ok(None),
198 Err(err) => return Err(err),
199 }
200 }
201 };
202
203 if entry == self.list_head {
204 return Ok(None);
205 }
206
207 match self.previous_entry(entry) {
208 Ok(prev) => self.current = Some(prev),
209 Err(err) => {
210 self.current = None;
211 return Err(err);
212 }
213 }
214
215 Ok(Some(entry - self.offset))
216 }
217}
218
219impl<Driver, Layout> Iterator for ListEntryIteratorBase<'_, Driver, Layout>
220where
221 Driver: VmiRead,
222 Driver::Architecture: ArchAdapter<Driver>,
223 Layout: StructLayout,
224 ListEntryLayout: ListEntry<Layout>,
225{
226 type Item = Result<Va, VmiError>;
227
228 fn next(&mut self) -> Option<Self::Item> {
229 self.walk_next().transpose()
230 }
231}
232
233impl<Driver, Layout> DoubleEndedIterator for ListEntryIteratorBase<'_, Driver, Layout>
234where
235 Driver: VmiRead,
236 Driver::Architecture: ArchAdapter<Driver>,
237 Layout: StructLayout,
238 ListEntryLayout: ListEntry<Layout>,
239{
240 fn next_back(&mut self) -> Option<Self::Item> {
241 self.walk_next_back().transpose()
242 }
243}
244
245impl<Driver, Layout> FusedIterator for ListEntryIteratorBase<'_, Driver, Layout>
246where
247 Driver: VmiRead,
248 Driver::Architecture: ArchAdapter<Driver>,
249 Layout: StructLayout,
250 ListEntryLayout: ListEntry<Layout>,
251{
252}
253
254enum ListEntryWrapper<'a, Driver>
255where
256 Driver: VmiRead,
257 Driver::Architecture: ArchAdapter<Driver>,
258{
259 W32(ListEntryIteratorBase<'a, Driver, StructLayout32>),
260 W64(ListEntryIteratorBase<'a, Driver, StructLayout64>),
261}
262
263impl<'a, Driver> ListEntryWrapper<'a, Driver>
264where
265 Driver: VmiRead,
266 Driver::Architecture: ArchAdapter<Driver>,
267{
268 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64, root: Pa) -> Self {
269 Self::W32(ListEntryIteratorBase::new(vmi, list_head, offset, root))
270 }
271
272 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64, root: Pa) -> Self {
273 Self::W64(ListEntryIteratorBase::new(vmi, list_head, offset, root))
274 }
275
276 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64, root: Pa) -> Self {
277 match vmi.registers().address_width() {
278 4 => Self::w32(vmi, list_head, offset, root),
279 8 => Self::w64(vmi, list_head, offset, root),
280 _ => panic!("Unsupported address width"),
281 }
282 }
283
284 fn walk_next(&mut self) -> Result<Option<Va>, VmiError> {
285 match self {
286 Self::W32(inner) => inner.walk_next(),
287 Self::W64(inner) => inner.walk_next(),
288 }
289 }
290
291 fn walk_next_back(&mut self) -> Result<Option<Va>, VmiError> {
292 match self {
293 Self::W32(inner) => inner.walk_next_back(),
294 Self::W64(inner) => inner.walk_next_back(),
295 }
296 }
297}
298
299pub struct ListEntryIterator<'a, Driver>
304where
305 Driver: VmiRead,
306 Driver::Architecture: ArchAdapter<Driver>,
307{
308 inner: ListEntryWrapper<'a, Driver>,
309}
310
311impl<'a, Driver> From<ListEntryIteratorBase<'a, Driver, StructLayout32>>
312 for ListEntryIterator<'a, Driver>
313where
314 Driver: VmiRead,
315 Driver::Architecture: ArchAdapter<Driver>,
316{
317 fn from(value: ListEntryIteratorBase<'a, Driver, StructLayout32>) -> Self {
318 Self {
319 inner: ListEntryWrapper::W32(value),
320 }
321 }
322}
323
324impl<'a, Driver> From<ListEntryIteratorBase<'a, Driver, StructLayout64>>
325 for ListEntryIterator<'a, Driver>
326where
327 Driver: VmiRead,
328 Driver::Architecture: ArchAdapter<Driver>,
329{
330 fn from(value: ListEntryIteratorBase<'a, Driver, StructLayout64>) -> Self {
331 Self {
332 inner: ListEntryWrapper::W64(value),
333 }
334 }
335}
336
337impl<'a, Driver> ListEntryIterator<'a, Driver>
338where
339 Driver: VmiRead,
340 Driver::Architecture: ArchAdapter<Driver>,
341{
342 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64) -> Self {
344 Self::with_kind(
345 vmi,
346 list_head,
347 offset,
348 vmi.translation_root(list_head),
349 WindowsWow64Kind::Native,
350 )
351 }
352
353 pub fn with_kind(
356 vmi: VmiState<'a, WindowsOs<Driver>>,
357 list_head: Va,
358 offset: u64,
359 root: Pa,
360 kind: WindowsWow64Kind,
361 ) -> Self {
362 let inner = match kind {
363 WindowsWow64Kind::Native => ListEntryWrapper::native(vmi, list_head, offset, root),
364 WindowsWow64Kind::X86 => ListEntryWrapper::w32(vmi, list_head, offset, root),
365 };
366
367 Self { inner }
368 }
369
370 fn walk_next(&mut self) -> Result<Option<Va>, VmiError> {
372 self.inner.walk_next()
373 }
374
375 fn walk_next_back(&mut self) -> Result<Option<Va>, VmiError> {
377 self.inner.walk_next_back()
378 }
379}
380
381impl<Driver> Iterator for ListEntryIterator<'_, Driver>
382where
383 Driver: VmiRead,
384 Driver::Architecture: ArchAdapter<Driver>,
385{
386 type Item = Result<Va, VmiError>;
387
388 fn next(&mut self) -> Option<Self::Item> {
389 self.walk_next().transpose()
390 }
391}
392
393impl<Driver> DoubleEndedIterator for ListEntryIterator<'_, Driver>
394where
395 Driver: VmiRead,
396 Driver::Architecture: ArchAdapter<Driver>,
397{
398 fn next_back(&mut self) -> Option<Self::Item> {
399 self.walk_next_back().transpose()
400 }
401}
402
403impl<Driver> FusedIterator for ListEntryIterator<'_, Driver>
404where
405 Driver: VmiRead,
406 Driver::Architecture: ArchAdapter<Driver>,
407{
408}