1use binrw::prelude::*;
4use modular_bitfield::prelude::*;
5
6#[binrw::binrw]
7#[derive(Debug, PartialEq, Eq, Copy, Clone)]
8#[brw(repr(u8))]
9pub enum InfoType {
10 File = 0x1,
11 FileSystem = 0x2,
12 Security = 0x3,
13 Quota = 0x4,
14}
15
16#[bitfield]
17#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
18#[bw(map = |&x| Self::into_bytes(x))]
19#[br(map = Self::from_bytes)]
20pub struct AdditionalInfo {
21 pub owner_security_information: bool,
22 pub group_security_information: bool,
23 pub dacl_security_information: bool,
24 pub sacl_security_information: bool,
25
26 pub label_security_information: bool,
27 pub attribute_security_information: bool,
28 pub scope_security_information: bool,
29
30 #[skip]
31 __: B9,
32 pub backup_security_information: bool,
33 #[skip]
34 __: B15,
35}
36
37#[macro_export]
47macro_rules! query_info_data {
48 ($name:ident $($info_type:ident: $content:ty, )+) => {
49 pastey::paste! {
50 #[allow(unused_imports)]
51 use binrw::prelude::*;
52 #[allow(unused_imports)]
53 use binrw::meta::WriteEndian;
54
55 #[doc = concat!("Enum to hold the different info types for ", stringify!($name),
56 ", that are used within SMB requests for querying or setting information.")]
57 #[binrw::binrw]
58 #[derive(Debug, PartialEq, Eq)]
59 #[brw(little)]
60 #[br(import(info_type: InfoType))]
61 pub enum $name {
62 $(
63 #[br(pre_assert(info_type == InfoType::$info_type))]
64 $info_type($content),
65 )+
66 }
67
68 impl $name {
69 $(
71 #[doc = concat!("Get the inner content as [`", stringify!($content), "`].")]
72 pub fn [<as_ $info_type:lower>](self) -> Result<$content, $crate::SmbMsgError> {
73 match self {
74 $name::$info_type(data) => Ok(data),
75 _ => Err($crate::SmbMsgError::UnexpectedContent {
76 expected: stringify!($info_type),
77 actual: self.name(),
78 }),
79 }
80 }
81 )+
82
83 pub fn info_type(&self) -> InfoType {
85 match self {
86 $(
87 $name::$info_type(_) => InfoType::$info_type,
88 )+
89 }
90 }
91
92 pub fn name(&self) -> &'static str {
94 match self {
95 $(
96 $name::$info_type(_) => stringify!($info_type),
97 )+
98 }
99 }
100 }
101
102 $(
104 impl From<$content> for $name {
105 fn from(value: $content) -> Self {
106 $name::$info_type(value)
107 }
108 }
109 )+
110
111 #[binrw::binrw]
112 #[derive(Debug, PartialEq, Eq)]
113 pub struct [<Raw $name>]<T>
114 where
115 T: Sized,
116 {
117 #[br(parse_with = binrw::helpers::until_eof)]
118 data: Vec<u8>,
119
120 phantom: std::marker::PhantomData<T>,
121 }
122
123
124 impl<T> [<Raw $name>]<T>
125 where
126 T: Sized,
127 {
128 pub fn data(&self) -> &[u8] {
129 &self.data
130 }
131 }
132
133 impl<T> [<Raw $name>]<T>
134 where
135 T: Sized,
136 T: BinRead<Args<'static> = (T::Class,)> + FileInfoType,
137 {
138 pub fn parse(&self, class: T::Class) -> Result<T, $crate::SmbMsgError> {
140 let mut cursor = std::io::Cursor::new(&self.data);
141 let value = T::read_le_args(&mut cursor, (class,))?;
142 Ok(value)
143 }
144 }
145
146 impl<T> From<T> for [<Raw $name>]<T>
147 where
148 for<'a> T: BinWrite<Args<'a> = ()>,
149 {
150 fn from(value: T) -> Self {
151 let mut cursor = std::io::Cursor::new(Vec::new());
152 value.write_le(&mut cursor).unwrap();
153 Self {
154 data: cursor.into_inner(),
155 phantom: std::marker::PhantomData,
156 }
157 }
158 }
159 }
160 };
161}