1use std::ops::Deref;
2
3use binrw::{NullString, io::TakeSeekExt, prelude::*};
4
5use super::{
6 ChainedItemList, FileAccessMask, FileAttributes, FileBasicInformation, FileFullEaInformation,
7 FileModeInformation, FileNameInformation, FilePipeInformation, FilePositionInformation,
8};
9use crate::file_info_classes;
10use smb_dtyp::binrw_util::prelude::{Boolean, FileTime, SizedWideString};
11
12file_info_classes! {
13 pub QueryFileInfo {
14 pub Access = 8,
15 pub Alignment = 17,
16 pub All = 18,
17 pub AlternateName = 21,
18 pub AttributeTag = 35,
19 pub Basic = 4,
20 pub Compression = 28,
21 pub Ea = 7,
22 pub FullEa = 15,
23 pub Id = 59,
24 pub Internal = 6,
25 pub Mode = 16,
26 pub NetworkOpen = 34,
27 pub NormalizedName = 48,
28 pub Pipe = 23,
29 pub PipeLocal = 24,
30 pub PipeRemote = 25,
31 pub Position = 14,
32 pub Standard = 5,
33 pub Stream = 22,
34 }, Read
35}
36
37pub type QueryFileFullEaInformation = FileFullEaInformation;
40
41pub type FileStreamInformation = ChainedItemList<FileStreamInformationInner>;
42
43#[binrw::binrw]
44#[derive(Debug, PartialEq, Eq)]
45pub struct FileAccessInformation {
46 pub access_flags: FileAccessMask,
47}
48
49#[binrw::binrw]
50#[derive(Debug, PartialEq, Eq)]
51pub struct FileAllInformation {
52 pub basic: FileBasicInformation,
53 pub standard: FileStandardInformation,
54 pub internal: FileInternalInformation,
55 pub ea: FileEaInformation,
56 pub access: FileAccessInformation,
57 pub position: FilePositionInformation,
58 pub mode: FileModeInformation,
59 pub alignment: FileAlignmentInformation,
60 pub name: FileNameInformation,
61}
62
63#[binrw::binrw]
64#[derive(Debug, PartialEq, Eq)]
65#[brw(repr(u32))]
66pub enum FileAlignmentInformation {
67 Byte = 0,
68 Word = 1,
69 Long = 3,
70 Quad = 7,
71 Octa = 0xf,
72 _32Byte = 0x1f,
73 _64Byte = 0x3f,
74 _128Byte = 0x7f,
75 _256Byte = 0xff,
76 _512Byte = 0x1ff,
77}
78
79#[binrw::binrw]
80#[derive(Debug, PartialEq, Eq)]
81pub struct FileAlternateNameInformation {
82 inner: FileNameInformation,
83}
84
85impl Deref for FileAlternateNameInformation {
86 type Target = FileNameInformation;
87
88 fn deref(&self) -> &Self::Target {
89 &self.inner
90 }
91}
92
93#[binrw::binrw]
94#[derive(Debug, PartialEq, Eq)]
95pub struct FileAttributeTagInformation {
96 pub file_attributes: u32,
97 pub reparse_tag: u32,
98}
99
100#[binrw::binrw]
101#[derive(Debug, PartialEq, Eq)]
102pub struct FileCompressionInformation {
103 pub compressed_file_size: u64,
104 pub compression_format: FileCompressionFormat,
105 pub compression_unit: u8,
106 pub chunk_shift: u8,
107 pub cluster_shift: u8,
108
109 #[bw(calc = [0; 3])]
110 _reserved: [u8; 3],
111}
112
113#[binrw::binrw]
114#[derive(Debug, PartialEq, Eq)]
115#[brw(repr(u16))]
116pub enum FileCompressionFormat {
117 None = 0,
118 Lznt1 = 2,
119}
120
121#[binrw::binrw]
122#[derive(Debug, PartialEq, Eq)]
123pub struct FileEaInformation {
124 pub ea_size: u32,
125}
126
127#[binrw::binrw]
128#[derive(Debug, PartialEq, Eq)]
129pub struct FileIdInformation {
130 pub volume_serial_number: u64,
131 pub file_id: u128,
132}
133
134#[binrw::binrw]
135#[derive(Debug, PartialEq, Eq)]
136pub struct FileInternalInformation {
137 pub index_number: u64,
138}
139
140#[binrw::binrw]
141#[derive(Debug, PartialEq, Eq)]
142pub struct FileNetworkOpenInformation {
143 pub creation_time: FileTime,
144 pub last_access_time: FileTime,
145 pub last_write_time: FileTime,
146 pub change_time: FileTime,
147 pub allocation_size: u64,
148 pub end_of_file: u64,
149 pub file_attributes: FileAttributes,
150 #[bw(calc = 0)]
151 _reserved: u32,
152}
153
154#[binrw::binrw]
155#[derive(Debug, PartialEq, Eq)]
156pub struct FileNormalizedNameInformation {
157 inner: FileNameInformation,
158}
159
160impl Deref for FileNormalizedNameInformation {
161 type Target = FileNameInformation;
162
163 fn deref(&self) -> &Self::Target {
164 &self.inner
165 }
166}
167
168#[binrw::binrw]
169#[derive(Debug, PartialEq, Eq)]
170pub struct FilePipeLocalInformation {
171 pub named_pipe_type: NamedPipeType,
172 pub named_pipe_configuration: NamedPipeConfiguration,
173 pub maximum_instances: u32,
174 pub current_instances: u32,
175 pub inbound_quota: u32,
176 pub outbound_quota: u32,
177 pub write_quota: u32,
178 pub named_pipe_state: NamedPipeState,
179 pub named_pipe_end: NamedPipeEnd,
180}
181
182#[binrw::binrw]
183#[derive(Debug, PartialEq, Eq)]
184#[brw(repr(u32))]
185pub enum NamedPipeType {
186 ByteStream = 0,
187 Message = 1,
188}
189
190#[binrw::binrw]
191#[derive(Debug, PartialEq, Eq)]
192#[brw(repr(u32))]
193pub enum NamedPipeConfiguration {
194 Inbound = 0,
195 Outbound = 1,
196 FullDuplex = 2,
197}
198
199#[binrw::binrw]
200#[derive(Debug, PartialEq, Eq)]
201#[brw(repr(u32))]
202pub enum NamedPipeState {
203 Disconnected = 1,
204 Listening = 2,
205 Connected = 3,
206 Closing = 4,
207}
208
209#[binrw::binrw]
210#[derive(Debug, PartialEq, Eq)]
211#[brw(repr(u32))]
212pub enum NamedPipeEnd {
213 Client = 0,
214 Server = 1,
215}
216
217#[binrw::binrw]
218#[derive(Debug, PartialEq, Eq)]
219pub struct FilePipeRemoteInformation {
220 pub collect_data_time: FileTime,
221 pub maximum_collection_count: u32,
222}
223
224#[binrw::binrw]
225#[derive(Debug, PartialEq, Eq)]
226pub struct FileStandardInformation {
227 pub allocation_size: u64,
228 pub end_of_file: u64,
229 pub number_of_links: u32,
230 pub delete_pending: Boolean,
231 pub directory: Boolean,
232 #[bw(calc = 0)]
233 #[br(assert(reserved == 0))]
234 reserved: u16,
235}
236
237#[binrw::binrw]
238#[derive(Debug, PartialEq, Eq)]
239pub struct FileStreamInformationInner {
240 #[bw(try_calc = stream_name.size().try_into())]
241 stream_name_length: u32,
242 pub stream_size: u64,
243 pub stream_allocation_size: u64,
244 #[br(args(stream_name_length as u64))]
245 pub stream_name: SizedWideString,
246}
247
248#[binrw::binrw]
249#[derive(Debug, PartialEq, Eq)]
250#[bw(import(has_next: bool))]
251pub struct FileGetEaInformation {
252 #[bw(try_calc = ea_name.len().try_into())]
253 ea_name_length: u8,
254 #[br(map_stream = |s| s.take_seek(ea_name_length as u64))]
255 pub ea_name: NullString,
256}
257
258impl FileGetEaInformation {
259 pub fn new<S: Into<String>>(name: S) -> Self {
260 Self {
261 ea_name: NullString::from(name.into()),
262 }
263 }
264}