smb_fscc/
query_file_info.rs

1//! File Information Classes for getting file information.
2//!
3//! This module mostly exports [QueryFileInfo] enum, and all structs that can be used with it.
4//!
5//! [MS-FSCC 2.4](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/4718fc40-e539-4014-8e33-b675af74e3e1>)
6
7use std::ops::Deref;
8
9use binrw::{NullString, io::TakeSeekExt, prelude::*};
10
11use super::{
12    ChainedItemList, FileAccessMask, FileAttributes, FileBasicInformation, FileFullEaInformation,
13    FileModeInformation, FileNameInformation, FilePipeInformation, FilePositionInformation,
14};
15use crate::{ReparseTag, file_info_classes};
16use smb_dtyp::binrw_util::prelude::*;
17
18file_info_classes! {
19    /// Query file information classes.
20    pub QueryFileInfo {
21        pub Access = 8,
22        pub Alignment = 17,
23        pub All = 18,
24        pub AlternateName = 21,
25        pub AttributeTag = 35,
26        pub Basic = 4,
27        pub Compression = 28,
28        pub Ea = 7,
29        pub FullEa = 15,
30        pub Id = 59,
31        pub Internal = 6,
32        pub Mode = 16,
33        pub NetworkOpen = 34,
34        pub NormalizedName = 48,
35        pub Pipe = 23,
36        pub PipeLocal = 24,
37        pub PipeRemote  = 25,
38        pub Position = 14,
39        pub Standard = 5,
40        pub Stream = 22,
41    }
42}
43
44pub type QueryFileFullEaInformation = FileFullEaInformation;
45
46pub type FileStreamInformation = ChainedItemList<FileStreamInformationInner, 8>;
47
48/// Query the access rights of a file that were granted when the file was opened.
49///
50/// [MS-FSCC 2.4.1](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/01cf43d2-deb3-40d3-a39b-9e68693d7c90>)
51#[binrw::binrw]
52#[derive(Debug, PartialEq, Eq)]
53pub struct FileAccessInformation {
54    /// Contains values that specify the access rights that were granted when the file was opened.
55    pub access_flags: FileAccessMask,
56}
57
58/// Query a collection of file information structures.
59///
60/// [MS-FSCC 2.4.2](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/95f3056a-ebc1-4f5d-b938-3f68a44677a6>)
61#[binrw::binrw]
62#[derive(Debug, PartialEq, Eq)]
63pub struct FileAllInformation {
64    /// Basic file information including timestamps and attributes.
65    pub basic: FileBasicInformation,
66    /// Standard file information about allocation size and file size.
67    pub standard: FileStandardInformation,
68    /// Internal file information including the file index number.
69    pub internal: FileInternalInformation,
70    /// Extended attribute information for the file.
71    pub ea: FileEaInformation,
72    /// Access rights information for the file.
73    pub access: FileAccessInformation,
74    /// Current file position information.
75    pub position: FilePositionInformation,
76    /// File mode information.
77    pub mode: FileModeInformation,
78    /// Buffer alignment requirements for the underlying device.
79    pub alignment: FileAlignmentInformation,
80    /// File name information.
81    pub name: FileNameInformation,
82}
83
84/// Query the buffer alignment required by the underlying device.
85///
86/// [MS-FSCC 2.4.3](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/9b0b9971-85aa-4651-8438-f1c4298bcb0d>)
87#[binrw::binrw]
88#[derive(Debug, PartialEq, Eq)]
89#[brw(repr(u32))]
90pub enum FileAlignmentInformation {
91    /// Specifies that there are no alignment requirements for the device.
92    Byte = 0,
93    /// Specifies that data must be aligned on a 2-byte boundary.
94    Word = 1,
95    /// Specifies that data must be aligned on a 4-byte boundary.
96    Long = 3,
97    /// Specifies that data must be aligned on an 8-byte boundary.
98    Quad = 7,
99    /// Specifies that data must be aligned on a 16-byte boundary.
100    Octa = 0xf,
101    /// Specifies that data must be aligned on a 32-byte boundary.
102    _32Byte = 0x1f,
103    /// Specifies that data must be aligned on a 64-byte boundary.
104    _64Byte = 0x3f,
105    /// Specifies that data must be aligned on a 128-byte boundary.
106    _128Byte = 0x7f,
107    /// Specifies that data must be aligned on a 256-byte boundary.
108    _256Byte = 0xff,
109    /// Specifies that data must be aligned on a 512-byte boundary.
110    _512Byte = 0x1ff,
111}
112
113/// Query the alternate name (8.3 short name) of a file.
114///
115/// [MS-FSCC 2.4.5](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/cb90d9e0-695d-4418-8d89-a29e2ba9faf8>)
116#[binrw::binrw]
117#[derive(Debug, PartialEq, Eq)]
118pub struct FileAlternateNameInformation {
119    /// The alternate name information, following the same structure as FileNameInformation.
120    inner: FileNameInformation,
121}
122
123impl Deref for FileAlternateNameInformation {
124    type Target = FileNameInformation;
125
126    fn deref(&self) -> &Self::Target {
127        &self.inner
128    }
129}
130
131impl From<&str> for FileAlternateNameInformation {
132    fn from(value: &str) -> Self {
133        Self {
134            inner: FileNameInformation::from(value),
135        }
136    }
137}
138
139/// Query file attribute and reparse tag information for a file.
140///
141/// [MS-FSCC 2.4.6](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/d295752f-ce89-4b98-8553-266d37c84f0e>)
142#[binrw::binrw]
143#[derive(Debug, PartialEq, Eq)]
144pub struct FileAttributeTagInformation {
145    /// File attributes as a bitmask of flags.
146    pub file_attributes: FileAttributes,
147    /// The reparse point tag value. If the file is not a reparse point, this value is undefined and should not be used.
148    pub reparse_tag: ReparseTag,
149}
150
151/// Query compression information for a file.
152///
153/// [MS-FSCC 2.4.9](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/0a7e50c4-2839-438e-aa6c-0da7d681a5a7>)
154#[binrw::binrw]
155#[derive(Debug, PartialEq, Eq)]
156pub struct FileCompressionInformation {
157    /// The size of the compressed file in bytes.
158    pub compressed_file_size: u64,
159    /// The compression format used for the file.
160    pub compression_format: FileCompressionFormat,
161    /// The compression unit size in bytes as a power of 2.
162    pub compression_unit: u8,
163    /// The compression chunk size in bytes as a power of 2.
164    pub chunk_shift: u8,
165    /// The cluster size in bytes as a power of 2.
166    pub cluster_shift: u8,
167
168    #[bw(calc = [0; 3])]
169    #[br(temp)]
170    _reserved: [u8; 3],
171}
172
173/// Compression format values for file compression.
174#[binrw::binrw]
175#[derive(Debug, PartialEq, Eq)]
176#[brw(repr(u16))]
177pub enum FileCompressionFormat {
178    /// The file is not compressed.
179    None = 0,
180    /// The file is compressed using the LZNT1 compression algorithm.
181    Lznt1 = 2,
182}
183
184/// Query the size of the extended attributes (EA) for a file.
185///
186/// [MS-FSCC 2.4.13](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/db6cf109-ead8-441a-b29e-cb2032778b0f>)
187#[binrw::binrw]
188#[derive(Debug, PartialEq, Eq)]
189pub struct FileEaInformation {
190    /// The size in bytes of the extended attributes for the file.
191    pub ea_size: u32,
192}
193
194/// Query the file system's 8-byte file reference number for a file.
195///
196/// [MS-FSCC 2.4.26](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/e4185a8a-ed8d-4f98-ab55-ca34dc8916e6>)
197#[binrw::binrw]
198#[derive(Debug, PartialEq, Eq)]
199pub struct FileIdInformation {
200    /// The serial number of the volume containing the file.
201    pub volume_serial_number: u64,
202    /// A 128-bit file identifier that uniquely identifies a file within the file system.
203    pub file_id: u128,
204}
205
206/// Query the file system's 8-byte file reference number for a file.
207///
208/// [MS-FSCC 2.4.27](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/7d796611-2fa5-41ac-8178-b6fea3a017b3>)
209#[binrw::binrw]
210#[derive(Debug, PartialEq, Eq)]
211pub struct FileInternalInformation {
212    /// An 8-byte file reference number for the file. This number is generated and assigned to the file by the file system.
213    pub index_number: u64,
214}
215
216/// Query network file open information for a file.
217///
218/// [MS-FSCC 2.4.34](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/26d261db-58d1-4513-a548-074448cbb146>)
219#[binrw::binrw]
220#[derive(Debug, PartialEq, Eq)]
221pub struct FileNetworkOpenInformation {
222    /// The time when the file was created.
223    pub creation_time: FileTime,
224    /// The time when the file was last accessed.
225    pub last_access_time: FileTime,
226    /// The time when data was last written to the file.
227    pub last_write_time: FileTime,
228    /// The time when the file was last changed.
229    pub change_time: FileTime,
230    /// The number of bytes that are allocated for the file.
231    pub allocation_size: u64,
232    /// The end of file location as a byte offset from the start of the file.
233    pub end_of_file: u64,
234    /// The file attributes.
235    pub file_attributes: FileAttributes,
236    #[bw(calc = 0)]
237    #[br(temp)]
238    _reserved: u32,
239}
240
241/// Query the normalized name of a file.
242///
243/// A normalized name is an absolute pathname where each short name component has been replaced with the corresponding long name component,
244/// and each name component uses the exact letter casing stored on disk
245///
246/// [MS-FSCC 2.4.36](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/20bcadba-808c-4880-b757-4af93e41edf6>)
247#[binrw::binrw]
248#[derive(Debug, PartialEq, Eq)]
249pub struct FileNormalizedNameInformation {
250    /// The normalized name information, following the same structure as FileNameInformation.
251    inner: FileNameInformation,
252}
253
254impl Deref for FileNormalizedNameInformation {
255    type Target = FileNameInformation;
256
257    fn deref(&self) -> &Self::Target {
258        &self.inner
259    }
260}
261
262impl From<&str> for FileNormalizedNameInformation {
263    fn from(value: &str) -> Self {
264        Self {
265            inner: FileNameInformation::from(value),
266        }
267    }
268}
269
270/// Query information associated with a named pipe that is not specific to one end of the pipe or another.
271///
272/// [MS-FSCC 2.4.38](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/de9abdc7-b974-4ec3-a4dc-42853777f412>)
273#[binrw::binrw]
274#[derive(Debug, PartialEq, Eq)]
275pub struct FilePipeLocalInformation {
276    /// The type of named pipe.
277    pub named_pipe_type: NamedPipeType,
278    /// The named pipe configuration.
279    pub named_pipe_configuration: NamedPipeConfiguration,
280    /// The maximum number of instances that can be created for this pipe.
281    pub maximum_instances: u32,
282    /// The number of current named pipe instances.
283    pub current_instances: u32,
284    /// The inbound quota in bytes.
285    pub inbound_quota: u32,
286    /// Bytes of data available to be read from the named pipe.
287    pub read_data_available: u32,
288    /// The outbound quota in bytes.
289    pub outbound_quota: u32,
290    /// The write quota in bytes.
291    pub write_quota_available: u32,
292    /// The named pipe state.
293    pub named_pipe_state: NamedPipeState,
294    /// Specifies whether the named pipe handle is for the client or server end of a named pipe.
295    pub named_pipe_end: NamedPipeEnd,
296}
297
298/// Named pipe type values.
299#[binrw::binrw]
300#[derive(Debug, PartialEq, Eq)]
301#[brw(repr(u32))]
302pub enum NamedPipeType {
303    /// The pipe is a byte-stream pipe.
304    ByteStream = 0,
305    /// The pipe is a message pipe.
306    Message = 1,
307}
308
309/// Named pipe configuration values.
310#[binrw::binrw]
311#[derive(Debug, PartialEq, Eq)]
312#[brw(repr(u32))]
313pub enum NamedPipeConfiguration {
314    /// The flow of data in the pipe goes from client to server only.
315    Inbound = 0,
316    /// The flow of data in the pipe goes from server to client only.
317    Outbound = 1,
318    /// The pipe is bidirectional; both server and client can read from and write to the pipe.
319    FullDuplex = 2,
320}
321
322/// Named pipe state values.
323#[binrw::binrw]
324#[derive(Debug, PartialEq, Eq)]
325#[brw(repr(u32))]
326pub enum NamedPipeState {
327    /// The pipe is disconnected.
328    Disconnected = 1,
329    /// The pipe is waiting for a client to connect.
330    Listening = 2,
331    /// The pipe is connected to a client.
332    Connected = 3,
333    /// The pipe is in the process of being closed.
334    Closing = 4,
335}
336
337/// Named pipe end values.
338#[binrw::binrw]
339#[derive(Debug, PartialEq, Eq)]
340#[brw(repr(u32))]
341pub enum NamedPipeEnd {
342    /// The handle is for the client end of the named pipe.
343    Client = 0,
344    /// The handle is for the server end of the named pipe.
345    Server = 1,
346}
347
348/// Query information that is associated with the remote end of a named pipe.
349///
350/// [MS-FSCC 2.4.39](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/4319b135-4472-482f-a0a3-6cc3a856c6b6>)
351#[binrw::binrw]
352#[derive(Debug, PartialEq, Eq)]
353pub struct FilePipeRemoteInformation {
354    /// The time at which the data is collected.
355    pub collect_data_time: FileTime,
356    /// The maximum size, in bytes, of data that will be collected before transmission to the remote end of the named pipe.
357    pub maximum_collection_count: u32,
358}
359
360/// Query standard information for a file.
361///
362/// [MS-FSCC 2.4.47](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/5afa7f66-619c-48f3-955f-68c4ece704ae>)
363#[binrw::binrw]
364#[derive(Debug, PartialEq, Eq)]
365pub struct FileStandardInformation {
366    /// The number of bytes that are allocated for the file.
367    pub allocation_size: u64,
368    /// The end of file location as a byte offset from the start of the file.
369    pub end_of_file: u64,
370    /// The number of non-deleted hard links to this file.
371    pub number_of_links: u32,
372    /// Set to TRUE if the file has been marked for deletion.
373    pub delete_pending: Boolean,
374    /// Set to TRUE if the file is a directory.
375    pub directory: Boolean,
376    #[bw(calc = 0)]
377    #[br(temp)]
378    _reserved: u16,
379}
380
381/// Enumerate the data streams for a file.
382///
383/// [MS-FSCC 2.4.49](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/f8762be6-3ab9-411e-a7d6-5cc68f70c78d>)
384#[binrw::binrw]
385#[derive(Debug, PartialEq, Eq)]
386pub struct FileStreamInformationInner {
387    #[bw(try_calc = stream_name.size().try_into())]
388    stream_name_length: u32,
389    /// The size, in bytes, of the stream.
390    pub stream_size: u64,
391    /// The number of bytes that are allocated for the stream.
392    pub stream_allocation_size: u64,
393    /// The name of the stream in Unicode.
394    #[br(args { size: SizedStringSize::bytes(stream_name_length)})]
395    pub stream_name: SizedWideString,
396}
397
398/// Query extended attributes for a file.
399#[binrw::binrw]
400#[derive(Debug, PartialEq, Eq)]
401#[bw(import(has_next: bool))]
402pub struct FileGetEaInformation {
403    // Length does NOT include the null terminator.
404    #[bw(try_calc = ea_name.len().try_into())]
405    ea_name_length: u8,
406    /// The name of the extended attribute.
407    #[br(map_stream = |s| s.take_seek(ea_name_length as u64 + 1))]
408    pub ea_name: NullString,
409}
410
411impl FileGetEaInformation {
412    pub fn new<S: Into<String>>(name: S) -> Self {
413        Self {
414            ea_name: NullString::from(name.into()),
415        }
416    }
417}
418
419#[cfg(test)]
420mod tests {
421    use super::*;
422    use smb_tests::*;
423    use time::macros::datetime;
424
425    fn get_file_access_information_for_test() -> FileAccessInformation {
426        FileAccessInformation {
427            access_flags: FileAccessMask::new()
428                .with_file_read_data(true)
429                .with_file_write_data(true)
430                .with_file_append_data(true)
431                .with_file_read_ea(true)
432                .with_file_write_ea(true)
433                .with_file_execute(true)
434                .with_file_delete_child(true)
435                .with_file_read_attributes(true)
436                .with_file_write_attributes(true)
437                .with_delete(true)
438                .with_read_control(true)
439                .with_write_dacl(true)
440                .with_write_owner(true)
441                .with_synchronize(true),
442        }
443    }
444    const FILE_ACCESS_INFORMATION_FOR_TEST_STRING: &str = "ff011f00";
445    test_binrw! {
446        FileAccessInformation: get_file_access_information_for_test() => FILE_ACCESS_INFORMATION_FOR_TEST_STRING
447    }
448
449    fn get_file_alignment_information_for_test() -> FileAlignmentInformation {
450        FileAlignmentInformation::Byte
451    }
452    const FILE_ALIGNMENT_INFORMATION_FOR_TEST_STRING: &str = "00000000";
453    test_binrw! {
454        FileAlignmentInformation: get_file_alignment_information_for_test() => FILE_ALIGNMENT_INFORMATION_FOR_TEST_STRING
455    }
456
457    test_binrw! {
458        FileAlternateNameInformation: FileAlternateNameInformation::from("query_info_o") => "18000000710075006500720079005f0069006e0066006f005f006f00"
459    }
460
461    test_binrw! {
462        // TODO: DFS reparse tag here can be cool
463        struct FileAttributeTagInformation {
464            file_attributes: FileAttributes::new()
465                .with_archive(true),
466            reparse_tag: ReparseTag::ReservedZero,
467        } => "2000000000000000"
468    }
469
470    fn get_file_basic_information_for_test() -> FileBasicInformation {
471        FileBasicInformation {
472            creation_time: datetime!(2025-10-17 10:35:07.801764000).into(),
473            last_access_time: datetime!(2025-10-17 10:35:07.801764000).into(),
474            last_write_time: datetime!(2025-10-17 10:35:07.801764000).into(),
475            change_time: datetime!(2025-10-17 10:35:07.801764000).into(),
476            file_attributes: FileAttributes::new().with_archive(true),
477        }
478    }
479    const FILE_BASIC_INFORMATION_FOR_TEST_STRING: &str =
480        "681621b5513fdc01681621b5513fdc01681621b5513fdc01681621b5513fdc012000000000000000";
481
482    test_binrw! {
483        FileBasicInformation: get_file_basic_information_for_test() => FILE_BASIC_INFORMATION_FOR_TEST_STRING
484    }
485
486    test_binrw! {
487        // TODO: something with actual compression
488        struct FileCompressionInformation => no {
489            compressed_file_size: 13,
490            compression_format: FileCompressionFormat::None,
491            compression_unit: 0,
492            chunk_shift: 0,
493            cluster_shift: 0,
494        } => "0d000000000000000000000000000000"
495    }
496
497    fn get_internal_information_for_test() -> FileInternalInformation {
498        FileInternalInformation {
499            index_number: 0x33b16,
500        }
501    }
502    const FILE_INTERNAL_INFORMATION_FOR_TEST_STRING: &str = "163b030000000000";
503
504    test_binrw! {
505         FileInternalInformation: get_internal_information_for_test() => FILE_INTERNAL_INFORMATION_FOR_TEST_STRING
506    }
507
508    fn get_file_mode_information_for_test() -> FileModeInformation {
509        FileModeInformation::new().with_synchronous_io_non_alert(true)
510    }
511
512    const FILE_MODE_INFORMATION_FOR_TEST_STRING: &str = "20000000";
513
514    test_binrw! {
515        FileModeInformation: get_file_mode_information_for_test() => FILE_MODE_INFORMATION_FOR_TEST_STRING
516    }
517
518    test_binrw! {
519        struct FileNetworkOpenInformation {
520            creation_time: datetime!(2025-10-17 12:44:04.747034).into(),
521            last_access_time: datetime!(2025-10-17 12:44:04.747034).into(),
522            last_write_time: datetime!(2025-10-17 12:44:04.747034).into(),
523            change_time: datetime!(2025-10-17 12:44:04.747034).into(),
524            allocation_size: 4096,
525            end_of_file: 13,
526            file_attributes: FileAttributes::new().with_archive(true),
527        } => "043fb5b8633fdc01043fb5b8633fdc01043fb5b8633fdc01043fb5b8633fdc0100100000000000000d000000000000002000000000000000"
528    }
529
530    test_binrw! {
531        FileNormalizedNameInformation: FileNormalizedNameInformation::from("query_info_on.txt") => "22000000710075006500720079005f0069006e0066006f005f006f006e002e00740078007400"
532    }
533
534    fn get_file_position_information_for_test() -> FilePositionInformation {
535        FilePositionInformation {
536            current_byte_offset: 1024,
537        }
538    }
539    const FILE_POSITION_INFORMATION_FOR_TEST_STRING: &str = "0004000000000000";
540
541    test_binrw! {
542        FilePositionInformation: get_file_position_information_for_test() => FILE_POSITION_INFORMATION_FOR_TEST_STRING
543    }
544
545    fn get_standard_information_for_test() -> FileStandardInformation {
546        FileStandardInformation {
547            allocation_size: 4096,
548            end_of_file: 13,
549            number_of_links: 0,
550            delete_pending: true.into(),
551            directory: false.into(),
552        }
553    }
554    const FILE_STANDARD_INFORMATION_FOR_TEST_STRING: &str =
555        "00100000000000000d000000000000000000000001000000";
556
557    test_binrw! {FileStandardInformation: get_standard_information_for_test() => FILE_STANDARD_INFORMATION_FOR_TEST_STRING}
558
559    fn get_file_name_information_for_test() -> FileNameInformation {
560        FileNameInformation::from("File_Name.txt")
561    }
562    const FILE_NAME_INFORMATION_FOR_TEST_STRING: &str =
563        "1a000000460069006c0065005f004e0061006d0065002e00740078007400";
564    test_binrw!(
565        FileNameInformation: get_file_name_information_for_test() =>
566        FILE_NAME_INFORMATION_FOR_TEST_STRING
567    );
568
569    fn get_file_ea_information_for_test() -> FileEaInformation {
570        FileEaInformation { ea_size: 208 }
571    }
572    const FILE_EA_INFORMATION_FOR_TEST_STRING: &str = "d0000000";
573    test_binrw!(
574        FileEaInformation: get_file_ea_information_for_test() =>
575        FILE_EA_INFORMATION_FOR_TEST_STRING
576    );
577
578    const FILE_ALL_INFORMATION_FOR_TEST_STRING: &str = const_format::concatcp!(
579        FILE_BASIC_INFORMATION_FOR_TEST_STRING,
580        FILE_STANDARD_INFORMATION_FOR_TEST_STRING,
581        FILE_INTERNAL_INFORMATION_FOR_TEST_STRING,
582        FILE_EA_INFORMATION_FOR_TEST_STRING,
583        FILE_ACCESS_INFORMATION_FOR_TEST_STRING,
584        FILE_POSITION_INFORMATION_FOR_TEST_STRING,
585        FILE_MODE_INFORMATION_FOR_TEST_STRING,
586        FILE_ALIGNMENT_INFORMATION_FOR_TEST_STRING,
587        FILE_NAME_INFORMATION_FOR_TEST_STRING
588    );
589    test_binrw! {
590        FileAllInformation: FileAllInformation {basic:get_file_basic_information_for_test(),
591            standard:get_standard_information_for_test(),
592            internal: get_internal_information_for_test(),
593            ea: get_file_ea_information_for_test(),
594            access: get_file_access_information_for_test(),
595            position: get_file_position_information_for_test(),
596            mode: get_file_mode_information_for_test(),
597            alignment: get_file_alignment_information_for_test(),
598            name: get_file_name_information_for_test(),
599        }
600        => FILE_ALL_INFORMATION_FOR_TEST_STRING
601    }
602
603    test_binrw! {
604        FileStreamInformation: FileStreamInformation::from(
605            vec![
606                FileStreamInformationInner { stream_size: 1096224, stream_allocation_size: 720896, stream_name: "::$DATA".into() },
607                FileStreamInformationInner { stream_size: 7, stream_allocation_size: 8, stream_name: ":SmartScreen:$DATA".into() },
608                FileStreamInformationInner { stream_size: 63, stream_allocation_size: 64, stream_name: ":Zone.Identifier:$DATA".into() },
609            ]
610        ) => "280000000e00000020ba10000000000000000b00000000003a003a002400440041005400410000004000000024000000070000000000000008000000000000003a0053006d00610072007400530063007200650065006e003a002400440041005400410000000000000000002c0000003f0000000000000040000000000000003a005a006f006e0065002e004900640065006e007400690066006900650072003a0024004400410054004100"
611    }
612
613    test_binrw! {
614        struct FileIdInformation {
615            volume_serial_number: 0xc86ef7996ef77f0e,
616            file_id: 0x0000000000000000006a00000000cd5a,
617        } => "0e7ff76e99f76ec85acd000000006a000000000000000000"
618    }
619
620    test_binrw! {
621        struct FilePipeLocalInformation {
622            named_pipe_type: NamedPipeType::Message,
623            named_pipe_configuration: NamedPipeConfiguration::FullDuplex,
624            maximum_instances: 0xffffffff,
625            current_instances: 4,
626            inbound_quota: 2048,
627            read_data_available: 0,
628            outbound_quota: 2048,
629            write_quota_available: 1024,
630            named_pipe_state: NamedPipeState::Connected,
631            named_pipe_end: NamedPipeEnd::Client,
632        } => "0100000002000000ffffffff04000000000800000000000000080000000400000300000000000000"
633    }
634
635    // Querying this is both no trivial, and also probably passes tests.
636    // test_binrw! {
637    //     struct FilePipeRemoteInformation {
638    //     } => ""
639    // }
640}