ironrdp_cliprdr/pdu/format_data/
metafile.rs

1use std::borrow::Cow;
2
3use bitflags::bitflags;
4use ironrdp_core::{
5    ensure_fixed_part_size, ensure_size, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
6};
7
8bitflags! {
9    /// Represents `mappingMode` fields of `CLIPRDR_MFPICT` structure.
10    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11    pub struct PackedMetafileMappingMode: u32 {
12        /// Each logical unit is mapped to one device pixel. Positive x is to the right; positive
13        /// y is down.
14        const TEXT = 0x0000_0001;
15        /// Each logical unit is mapped to 0.1 millimeter. Positive x is to the right; positive
16        /// y is up.
17        const LO_METRIC = 0x0000_0002;
18        /// Each logical unit is mapped to 0.01 millimeter. Positive x is to the right; positive
19        /// y is up.
20        const HI_METRIC = 0x0000_0003;
21        /// Each logical unit is mapped to 0.01 inch. Positive x is to the right; positive y is up.
22        const LO_ENGLISH = 0x0000_0004;
23        /// Each logical unit is mapped to 0.001 inch. Positive x is to the right; positive y is up.
24        const HI_ENGLISH = 0x0000_0005;
25        /// Each logical unit is mapped to 1/20 of a printer's point (1/1440 of an inch), also
26        /// called a twip. Positive x is to the right; positive y is up.
27        const TWIPS = 0x0000_0006;
28        /// Logical units are mapped to arbitrary units with equally scaled axes; one unit along
29        /// the x-axis is equal to one unit along the y-axis.
30        const ISOTROPIC = 0x0000_0007;
31        /// Logical units are mapped to arbitrary units with arbitrarily scaled axes.
32        const ANISOTROPIC = 0x0000_0008;
33    }
34}
35
36/// Represents `CLIPRDR_MFPICT`
37///
38/// NOTE: `Decode` implementation will read all remaining data in cursor as metafile contents.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct PackedMetafile<'a> {
41    pub mapping_mode: PackedMetafileMappingMode,
42    pub x_ext: u32,
43    pub y_ext: u32,
44    /// The variable sized contents of the metafile as specified in [MS-WMF] section 2
45    data: Cow<'a, [u8]>,
46}
47
48impl PackedMetafile<'_> {
49    const NAME: &'static str = "CLIPRDR_MFPICT";
50    const FIXED_PART_SIZE: usize = 4 /* mode */ + 4 /* xExt */ + 4 /* yExt */;
51
52    pub fn new(
53        mapping_mode: PackedMetafileMappingMode,
54        x_ext: u32,
55        y_ext: u32,
56        data: impl Into<Cow<'static, [u8]>>,
57    ) -> Self {
58        Self {
59            mapping_mode,
60            x_ext,
61            y_ext,
62            data: data.into(),
63        }
64    }
65
66    pub fn data(&self) -> &[u8] {
67        &self.data
68    }
69}
70
71impl Encode for PackedMetafile<'_> {
72    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
73        ensure_size!(in: dst, size: self.size());
74
75        dst.write_u32(self.mapping_mode.bits());
76        dst.write_u32(self.x_ext);
77        dst.write_u32(self.y_ext);
78        dst.write_slice(&self.data);
79
80        Ok(())
81    }
82
83    fn name(&self) -> &'static str {
84        Self::NAME
85    }
86
87    fn size(&self) -> usize {
88        Self::FIXED_PART_SIZE + self.data.len()
89    }
90}
91
92impl<'de> Decode<'de> for PackedMetafile<'de> {
93    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
94        ensure_fixed_part_size!(in: src);
95
96        let mapping_mode = PackedMetafileMappingMode::from_bits_truncate(src.read_u32());
97        let x_ext = src.read_u32();
98        let y_ext = src.read_u32();
99
100        let data_len = src.len();
101
102        let data = src.read_slice(data_len);
103
104        Ok(Self {
105            mapping_mode,
106            x_ext,
107            y_ext,
108            data: Cow::Borrowed(data),
109        })
110    }
111}