nt_apiset/
namespace_entry.rs1use core::iter::FusedIterator;
5use core::mem;
6use core::ops::Range;
7
8use bitflags::bitflags;
9use nt_string::u16strle::U16StrLe;
10use zerocopy::{FromBytes, LayoutVerified, LittleEndian, Unaligned, U32};
11
12use crate::error::{NtApiSetError, Result};
13use crate::value_entry::{ApiSetValueEntries, ApiSetValueEntryHeader};
14
15#[allow(dead_code)]
16#[derive(Debug, FromBytes, Unaligned)]
17#[repr(packed)]
18pub(crate) struct ApiSetNamespaceEntryHeader {
19 flags: U32<LittleEndian>,
21 name_offset: U32<LittleEndian>,
22 name_length: U32<LittleEndian>,
23 hashed_length: U32<LittleEndian>,
24 array_offset: U32<LittleEndian>,
25 array_count: U32<LittleEndian>,
26}
27
28bitflags! {
29 pub struct ApiSetNamespaceEntryFlags: u32 {
31 const SEALED = 1 << 0;
33 const IS_EXTENSION = 1 << 1;
35 }
36}
37
38#[derive(Clone, Debug)]
47pub struct ApiSetNamespaceEntries<'a> {
48 section_bytes: &'a [u8],
49 range: Range<usize>,
50}
51
52impl<'a> ApiSetNamespaceEntries<'a> {
53 pub(crate) const fn new(section_bytes: &'a [u8], range: Range<usize>) -> Self {
54 Self {
55 section_bytes,
56 range,
57 }
58 }
59}
60
61impl<'a> Iterator for ApiSetNamespaceEntries<'a> {
62 type Item = ApiSetNamespaceEntry<'a>;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 let (header, _) =
66 LayoutVerified::<_, ApiSetNamespaceEntryHeader>::new_unaligned_from_prefix(
67 self.section_bytes.get(self.range.clone())?,
68 )?;
69 let entry = ApiSetNamespaceEntry {
70 section_bytes: self.section_bytes,
71 position: self.range.start,
72 header,
73 };
74 self.range.start += mem::size_of::<ApiSetNamespaceEntryHeader>();
75
76 Some(entry)
77 }
78
79 fn size_hint(&self) -> (usize, Option<usize>) {
80 let size = self.range.len() / mem::size_of::<ApiSetNamespaceEntryHeader>();
81 (size, Some(size))
82 }
83
84 fn nth(&mut self, n: usize) -> Option<Self::Item> {
85 let bytes_to_skip = n.checked_mul(mem::size_of::<ApiSetNamespaceEntryHeader>())?;
87 self.range.start = self.range.start.checked_add(bytes_to_skip)?;
88 self.next()
89 }
90}
91
92impl<'a> ExactSizeIterator for ApiSetNamespaceEntries<'a> {}
93impl<'a> FusedIterator for ApiSetNamespaceEntries<'a> {}
94
95#[derive(Debug)]
102pub struct ApiSetNamespaceEntry<'a> {
103 section_bytes: &'a [u8],
104 position: usize,
105 header: LayoutVerified<&'a [u8], ApiSetNamespaceEntryHeader>,
106}
107
108impl<'a> ApiSetNamespaceEntry<'a> {
109 pub fn flags(&self) -> ApiSetNamespaceEntryFlags {
111 ApiSetNamespaceEntryFlags::from_bits_truncate(self.header.flags.get())
112 }
113
114 pub fn name(&self) -> Result<U16StrLe<'a>> {
119 let start = self.header.name_offset.get() as usize;
120 let length = self.header.name_length.get() as usize;
121 let end = start + length;
122 let range = start..end;
123
124 let name_bytes =
125 self.section_bytes
126 .get(range.clone())
127 .ok_or(NtApiSetError::EntryNameOutOfBounds {
128 name_range: range,
129 entry_offset: self.position,
130 actual: self.section_bytes.len(),
131 })?;
132
133 Ok(U16StrLe(name_bytes))
134 }
135
136 pub fn value_entries(&self) -> Result<ApiSetValueEntries<'a>> {
142 let start = self.header.array_offset.get() as usize;
143 let count = self.header.array_count.get() as usize;
144 let end = start + mem::size_of::<ApiSetValueEntryHeader>() * count;
145 let range = start..end;
146
147 self.section_bytes
148 .get(range.clone())
149 .ok_or(NtApiSetError::ValueEntriesOutOfBounds {
150 range: start..end,
151 actual: self.section_bytes.len(),
152 })?;
153
154 Ok(ApiSetValueEntries::new(self.section_bytes, range))
155 }
156}