smb_fscc/
directory_info.rs

1use binrw::prelude::*;
2
3use crate::file_info_classes;
4use smb_dtyp::binrw_util::prelude::*;
5
6use super::{ChainedItem, FileAttributes, ReparseTag};
7
8file_info_classes! {
9    pub QueryDirectoryInfo {
10        pub Directory = 0x01,
11        pub FullDirectory = 0x02,
12        pub IdFullDirectory = 0x26,
13        pub BothDirectory = 0x03,
14        pub IdBothDirectory = 0x25,
15        pub Names = 0x0c,
16        pub IdExtdDirectory = 0x3c,
17
18        pub Id64ExtdDirectory = 0x4e,
19        pub Id64ExtdBothDirectory = 0x4f,
20        pub IdAllExtdDirectory = 0x50,
21        pub IdAllExtdBothDirectory = 0x51,
22    }, Read
23}
24
25macro_rules! query_dir_type {
26    (
27        $svis:vis struct $name:ident {
28            $(
29                $(#[$field_meta:meta])*
30                $vis:vis $field_name:ident : $field_ty:ty,
31            )*
32        }
33    ) => {
34        paste::paste! {
35            #[binrw::binrw]
36            #[derive(Debug, PartialEq, Eq)]
37            $svis struct [<$name Inner>] {
38                pub file_index: u32,
39                pub creation_time: FileTime,
40                pub last_access_time: FileTime,
41                pub last_write_time: FileTime,
42                pub change_time: FileTime,
43                pub end_of_file: u64,
44                pub allocation_size: u64,
45                pub file_attributes: FileAttributes,
46                #[bw(try_calc = file_name.size().try_into())]
47                _file_name_length: u32, // bytes
48
49                #[br(if(!file_attributes.reparse_point()))]
50                // ea_size and reparse_tag are the same field, parsed differently, based on attributes.
51                #[bw(assert(reparse_tag.is_some() != ea_size.is_some()))]
52                pub ea_size: Option<u32>,
53                #[br(if(file_attributes.reparse_point()))]
54                // Must set file_attributes.reparse_point() to true for this to be some.
55                #[bw(assert(reparse_tag.is_some() == file_attributes.reparse_point()))]
56                pub reparse_tag: Option<ReparseTag>,
57
58                $(
59                    $(#[$field_meta])*
60                    $vis $field_name: $field_ty,
61                )*
62
63                #[br(args(_file_name_length as u64))]
64                pub file_name: SizedWideString,
65            }
66
67            $svis type $name = ChainedItem<[<$name Inner>]>;
68        }
69    };
70}
71
72#[binrw::binrw]
73#[derive(Debug, PartialEq, Eq)]
74pub struct FileDirectoryInformationInner {
75    pub file_index: u32,
76    pub creation_time: FileTime,
77    pub last_access_time: FileTime,
78    pub last_write_time: FileTime,
79    pub change_time: FileTime,
80    pub end_of_file: u64,
81    pub allocation_size: u64,
82    pub file_attributes: FileAttributes,
83    #[bw(try_calc = file_name.size().try_into())]
84    _file_name_length: u32,
85    #[br(args(_file_name_length as u64))]
86    pub file_name: SizedWideString,
87}
88pub type FileDirectoryInformation = ChainedItem<FileDirectoryInformationInner>;
89
90query_dir_type! {
91    pub struct FileFullDirectoryInformation {}
92}
93
94query_dir_type! {
95    pub struct FileId64ExtdBothDirectoryInformation {
96        pub reparse_point_tag: u32,
97        pub file_id: u64,
98        pub short_name_length: u8,
99        #[bw(calc = 0)]
100        _reserved1: u8,
101        pub short_name: [u16; 24], // 8.3
102        #[bw(calc = 0)]
103        _reserved2: u16,
104    }
105}
106
107query_dir_type! {
108    pub struct FileId64ExtdDirectoryInformation {
109        pub reparse_point_tag: u32,
110        pub file_id: u64,
111    }
112}
113
114query_dir_type! {
115    pub struct FileIdAllExtdBothDirectoryInformation {
116        pub reparse_point_tag: u32,
117        pub file_id: u64,
118        pub file_id_128: u128,
119        pub short_name_length: u8,
120        #[bw(calc = 0)]
121        _reserved1: u8,
122        pub short_name: [u16; 24], // 8.3
123    }
124}
125
126query_dir_type! {
127    pub struct FileIdAllExtdDirectoryInformation {
128        pub reparse_point_tag: u32,
129        pub file_id: u64,
130        pub file_id_128: u128,
131    }
132}
133
134query_dir_type! {
135    pub struct FileIdBothDirectoryInformation {
136        pub short_name_length: u8,
137        #[bw(calc = 0)]
138        _reserved1: u8,
139        pub short_name: [u16; 12], // 8.3
140        #[bw(calc = 0)]
141        _reserved2: u16,
142        pub fild_id: u64,
143    }
144}
145
146query_dir_type! {
147    pub struct FileIdExtdDirectoryInformation {
148        pub reparse_point_tag: u32,
149        pub file_id: u128,
150    }
151}
152
153query_dir_type! {
154    pub struct FileIdFullDirectoryInformation {
155        #[bw(calc = 0)]
156        _reserved: u32,
157        pub file_id: u64,
158    }
159}
160
161#[binrw::binrw]
162#[derive(Debug, PartialEq, Eq)]
163pub struct FileNamesInformationInner {
164    pub file_index: u32,
165    #[bw(try_calc = file_name.size().try_into())]
166    pub file_name_length: u32,
167    #[br(args(file_name_length as u64))]
168    pub file_name: SizedWideString,
169}
170
171query_dir_type! {
172    pub struct FileBothDirectoryInformation {
173        pub short_name_length: u8,
174        #[bw(calc = 0)]
175        _reserved1: u8,
176        pub short_name: [u16; 24], // 8.3
177    }
178}
179
180pub type FileNamesInformation = ChainedItem<FileNamesInformationInner>;