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]
43macro_rules! query_info_data {
44 ($name:ident $($info_type:ident: $content:ty, )+) => {
45 paste::paste! {
46 #[allow(unused_imports)]
47 use binrw::prelude::*;
48 #[allow(unused_imports)]
49 use binrw::meta::WriteEndian;
50 #[binrw::binrw]
54 #[derive(Debug)]
55 #[brw(little)]
56 #[br(import(info_type: InfoType))]
57 pub enum $name {
58 $(
59 #[br(pre_assert(info_type == InfoType::$info_type))]
60 $info_type($content),
61 )+
62 }
63
64 impl $name {
65 $(
67 pub fn [<unwrap_ $info_type:lower>](self) -> $content {
68 match self {
69 $name::$info_type(data) => data,
70 _ => panic!("Expected $info_type, got {:?}", self),
71 }
72 }
73 pub fn [<as_ $info_type:lower>](self) -> Result<$content, $crate::SmbMsgError> {
74 match self {
75 $name::$info_type(data) => Ok(data),
76 _ => Err($crate::SmbMsgError::UnexpectedContent {
77 expected: stringify!($info_type),
78 actual: self.name(),
79 }),
80 }
81 }
82 )+
83
84 pub fn info_type(&self) -> InfoType {
86 match self {
87 $(
88 $name::$info_type(_) => InfoType::$info_type,
89 )+
90 }
91 }
92
93 pub fn name(&self) -> &'static str {
95 match self {
96 $(
97 $name::$info_type(_) => stringify!($info_type),
98 )+
99 }
100 }
101 }
102
103 $(
105 impl From<$content> for $name {
106 fn from(value: $content) -> Self {
107 $name::$info_type(value)
108 }
109 }
110 )+
111
112 #[binrw::binrw]
114 #[derive(Debug)]
115 pub struct [<Raw $name>]<T>
116 where
117 T: Sized,
118 {
119 #[br(parse_with = binrw::helpers::until_eof)]
120 data: Vec<u8>,
121
122 phantom: std::marker::PhantomData<T>,
123 }
124
125
126 impl<T> [<Raw $name>]<T>
127 where
128 T: Sized,
129 {
130 pub fn data(&self) -> &[u8] {
131 &self.data
132 }
133 }
134
135 impl<T> [<Raw $name>]<T>
136 where
137 T: Sized,
138 T: BinRead<Args<'static> = (T::Class,)> + FileInfoType,
139 {
140 pub fn parse(&self, class: T::Class) -> Result<T, $crate::SmbMsgError> {
142 let mut cursor = std::io::Cursor::new(&self.data);
143 let value = T::read_le_args(&mut cursor, (class,))?;
144 Ok(value)
145 }
146 }
147
148 impl<T> From<T> for [<Raw $name>]<T>
149 where
150 for<'a> T: BinWrite<Args<'a> = ()>,
151 {
152 fn from(value: T) -> Self {
153 let mut cursor = std::io::Cursor::new(Vec::new());
154 value.write_le(&mut cursor).unwrap();
155 Self {
156 data: cursor.into_inner(),
157 phantom: std::marker::PhantomData,
158 }
159 }
160 }
161 }
162 };
163}