nt_hive/
subkeys_list.rs

1// Copyright 2020-2025 Colin Finck <colin@reactos.org>
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4use core::iter::FusedIterator;
5use core::mem;
6use core::ops::Range;
7
8use zerocopy::byteorder::LittleEndian;
9use zerocopy::{
10    FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut,
11    Unaligned, U16,
12};
13
14use crate::error::{NtHiveError, Result};
15use crate::helpers::byte_subrange;
16use crate::hive::Hive;
17use crate::index_root::{IndexRootKeyNodes, IndexRootKeyNodesMut};
18use crate::key_node::{KeyNode, KeyNodeMut};
19use crate::leaf::{LeafKeyNodes, LeafKeyNodesMut, LeafType};
20
21/// On-Disk Structure of a Subkeys List header.
22/// This is common for all subkey types (Fast Leaf, Hash Leaf, Index Leaf, Index Root).
23#[derive(FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned)]
24#[repr(packed)]
25pub(crate) struct SubkeysListHeader {
26    pub(crate) signature: [u8; 2],
27    pub(crate) count: U16<LittleEndian>,
28}
29
30/// Subkeys of a single [`KeyNode`].
31///
32/// A Subkeys List generalizes over all structures used to manage subkeys.
33/// These are: Fast Leaf (`lf`), Hash Leaf (`lh`), Index Leaf (`li`), Index Root (`ri`).
34pub(crate) struct SubkeysList<'h, B: SplitByteSlice> {
35    hive: &'h Hive<B>,
36    header_range: Range<usize>,
37    pub(crate) data_range: Range<usize>,
38}
39
40impl<'h, B> SubkeysList<'h, B>
41where
42    B: SplitByteSlice,
43{
44    pub(crate) fn new(hive: &'h Hive<B>, cell_range: Range<usize>) -> Result<Self> {
45        Self::new_internal(hive, cell_range, true)
46    }
47
48    pub(crate) fn new_without_index_root(
49        hive: &'h Hive<B>,
50        cell_range: Range<usize>,
51    ) -> Result<Self> {
52        // This function only exists to share validation code with `LeafItemRanges`.
53        Self::new_internal(hive, cell_range, false)
54    }
55
56    fn new_internal(
57        hive: &'h Hive<B>,
58        cell_range: Range<usize>,
59        index_root_supported: bool,
60    ) -> Result<Self> {
61        let header_range = byte_subrange(&cell_range, mem::size_of::<SubkeysListHeader>())
62            .ok_or_else(|| NtHiveError::InvalidHeaderSize {
63                offset: hive.offset_of_data_offset(cell_range.start),
64                expected: mem::size_of::<SubkeysListHeader>(),
65                actual: cell_range.len(),
66            })?;
67        let data_range = header_range.end..cell_range.end;
68
69        let subkeys_list = Self {
70            hive,
71            header_range,
72            data_range,
73        };
74        subkeys_list.validate_signature(index_root_supported)?;
75
76        Ok(subkeys_list)
77    }
78
79    pub(crate) fn header(&self) -> Ref<&[u8], SubkeysListHeader> {
80        Ref::from_bytes(&self.hive.data[self.header_range.clone()]).unwrap()
81    }
82
83    fn validate_signature(&self, index_root_supported: bool) -> Result<()> {
84        let header = self.header();
85
86        match &header.signature {
87            // Index Leaf / Fast Leaf / Hash Leaf
88            b"lf" | b"lh" | b"li" => return Ok(()),
89
90            // Index Root
91            b"ri" => {
92                if index_root_supported {
93                    return Ok(());
94                }
95            }
96
97            // Anything else
98            _ => (),
99        }
100
101        let expected_signature: &[u8] = if index_root_supported {
102            b"lf|lh|li|ri"
103        } else {
104            b"lf|lh|li"
105        };
106
107        Err(NtHiveError::InvalidTwoByteSignature {
108            offset: self.hive.offset_of_field(&header.signature),
109            expected: expected_signature,
110            actual: header.signature,
111        })
112    }
113}
114
115/// Iterator over
116///   all subkeys of a [`KeyNode`],
117///   returning a constant [`KeyNode`] for each subkey.
118///
119/// This iterator combines [`IndexRootKeyNodes`] and [`LeafKeyNodes`].
120/// Refer to them for a more technical documentation.
121///
122/// On-Disk Signatures: `lf`, `lh`, `li`, `ri`
123#[derive(Clone)]
124pub enum SubKeyNodes<'h, B: SplitByteSlice> {
125    IndexRoot(IndexRootKeyNodes<'h, B>),
126    Leaf(LeafKeyNodes<'h, B>),
127}
128
129impl<'h, B> SubKeyNodes<'h, B>
130where
131    B: SplitByteSlice,
132{
133    pub(crate) fn new(hive: &'h Hive<B>, cell_range: Range<usize>) -> Result<Self> {
134        let subkeys_list = SubkeysList::new(hive, cell_range)?;
135        let header = subkeys_list.header();
136        let signature = header.signature;
137        let count = header.count.get();
138        let count_field_offset = subkeys_list.hive.offset_of_field(&header.count);
139        let data_range = subkeys_list.data_range;
140
141        match &signature {
142            b"lf" | b"lh" | b"li" => {
143                // Fast Leaf, Hash Leaf or Index Leaf
144                let leaf_type = LeafType::from_signature(&signature).unwrap();
145                let iter =
146                    LeafKeyNodes::new(hive, count, count_field_offset, data_range, leaf_type)?;
147                Ok(Self::Leaf(iter))
148            }
149            b"ri" => {
150                // Index Root
151                let iter = IndexRootKeyNodes::new(hive, count, count_field_offset, data_range)?;
152                Ok(Self::IndexRoot(iter))
153            }
154            _ => unreachable!(),
155        }
156    }
157}
158
159impl<'h, B> Iterator for SubKeyNodes<'h, B>
160where
161    B: SplitByteSlice,
162{
163    type Item = Result<KeyNode<'h, B>>;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        match self {
167            Self::IndexRoot(iter) => iter.next(),
168            Self::Leaf(iter) => iter.next(),
169        }
170    }
171
172    fn count(self) -> usize {
173        match self {
174            Self::IndexRoot(iter) => iter.count(),
175            Self::Leaf(iter) => iter.count(),
176        }
177    }
178
179    fn last(self) -> Option<Self::Item> {
180        match self {
181            Self::IndexRoot(iter) => iter.last(),
182            Self::Leaf(iter) => iter.last(),
183        }
184    }
185
186    fn nth(&mut self, n: usize) -> Option<Self::Item> {
187        match self {
188            Self::IndexRoot(iter) => iter.nth(n),
189            Self::Leaf(iter) => iter.nth(n),
190        }
191    }
192
193    fn size_hint(&self) -> (usize, Option<usize>) {
194        match self {
195            Self::IndexRoot(iter) => iter.size_hint(),
196            Self::Leaf(iter) => iter.size_hint(),
197        }
198    }
199}
200
201impl<B> FusedIterator for SubKeyNodes<'_, B> where B: SplitByteSlice {}
202
203/// Iterator over
204///   all subkeys of a [`KeyNode`],
205///   returning a mutable [`KeyNode`] for each subkey.
206///
207/// This iterator combines [`IndexRootKeyNodesMut`] and [`LeafKeyNodesMut`].
208/// Refer to them for a more technical documentation.
209///
210/// On-Disk Signatures: `lf`, `lh`, `li`, `ri`
211pub(crate) enum SubKeyNodesMut<'h, B: SplitByteSliceMut> {
212    IndexRoot(IndexRootKeyNodesMut<'h, B>),
213    Leaf(LeafKeyNodesMut<'h, B>),
214}
215
216impl<'h, B> SubKeyNodesMut<'h, B>
217where
218    B: SplitByteSliceMut,
219{
220    pub(crate) fn new(hive: &'h mut Hive<B>, cell_range: Range<usize>) -> Result<Self> {
221        let subkeys_list = SubkeysList::new(&*hive, cell_range)?;
222        let header = subkeys_list.header();
223        let signature = header.signature;
224        let count = header.count.get();
225        let count_field_offset = subkeys_list.hive.offset_of_field(&header.count);
226        let data_range = subkeys_list.data_range;
227
228        match &signature {
229            b"lf" | b"lh" | b"li" => {
230                // Fast Leaf, Hash Leaf or Index Leaf
231                let leaf_type = LeafType::from_signature(&signature).unwrap();
232                let iter =
233                    LeafKeyNodesMut::new(hive, count, count_field_offset, data_range, leaf_type)?;
234                Ok(Self::Leaf(iter))
235            }
236            b"ri" => {
237                // Index Root
238                let iter = IndexRootKeyNodesMut::new(hive, count, count_field_offset, data_range)?;
239                Ok(Self::IndexRoot(iter))
240            }
241            _ => unreachable!(),
242        }
243    }
244
245    pub fn next(&mut self) -> Option<Result<KeyNodeMut<B>>> {
246        match self {
247            Self::IndexRoot(iter) => iter.next(),
248            Self::Leaf(iter) => iter.next(),
249        }
250    }
251}