ironrdp_pdu/gcc/
monitor_extended_data.rs

1use ironrdp_core::{
2    cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
3    ReadCursor, WriteCursor,
4};
5use num_derive::{FromPrimitive, ToPrimitive};
6use num_traits::{FromPrimitive as _, ToPrimitive as _};
7
8const MONITOR_COUNT_MAX: usize = 16;
9const MONITOR_ATTRIBUTE_SIZE: u32 = 20;
10
11const FLAGS_SIZE: usize = 4;
12const MONITOR_ATTRIBUTE_SIZE_FIELD_SIZE: usize = 4;
13const MONITOR_COUNT: usize = 4;
14const MONITOR_SIZE: usize = 20;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ClientMonitorExtendedData {
18    pub extended_monitors_info: Vec<ExtendedMonitorInfo>,
19}
20
21impl ClientMonitorExtendedData {
22    const NAME: &'static str = "ClientMonitorExtendedData";
23
24    const FIXED_PART_SIZE: usize = FLAGS_SIZE + MONITOR_ATTRIBUTE_SIZE_FIELD_SIZE + MONITOR_COUNT;
25}
26
27impl Encode for ClientMonitorExtendedData {
28    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
29        ensure_size!(in: dst, size: self.size());
30
31        dst.write_u32(0); // flags
32        dst.write_u32(MONITOR_ATTRIBUTE_SIZE); // flags
33        dst.write_u32(cast_length!("nMonitors", self.extended_monitors_info.len())?);
34
35        for extended_monitor_info in self.extended_monitors_info.iter().take(MONITOR_COUNT_MAX) {
36            extended_monitor_info.encode(dst)?;
37        }
38
39        Ok(())
40    }
41
42    fn name(&self) -> &'static str {
43        Self::NAME
44    }
45
46    fn size(&self) -> usize {
47        Self::FIXED_PART_SIZE + self.extended_monitors_info.len() * MONITOR_SIZE
48    }
49}
50
51impl<'de> Decode<'de> for ClientMonitorExtendedData {
52    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
53        ensure_fixed_part_size!(in: src);
54
55        let _flags = src.read_u32(); // is unused
56
57        let monitor_attribute_size = src.read_u32();
58        if monitor_attribute_size != MONITOR_ATTRIBUTE_SIZE {
59            return Err(invalid_field_err!("monitorAttributeSize", "invalid size"));
60        }
61
62        let monitor_count = cast_length!("monitorCount", src.read_u32())?;
63
64        if monitor_count > MONITOR_COUNT_MAX {
65            return Err(invalid_field_err!("monitorCount", "invalid monitor count"));
66        }
67
68        let mut extended_monitors_info = Vec::with_capacity(monitor_count);
69        for _ in 0..monitor_count {
70            extended_monitors_info.push(ExtendedMonitorInfo::decode(src)?);
71        }
72
73        Ok(Self { extended_monitors_info })
74    }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct ExtendedMonitorInfo {
79    pub physical_width: u32,
80    pub physical_height: u32,
81    pub orientation: MonitorOrientation,
82    pub desktop_scale_factor: u32,
83    pub device_scale_factor: u32,
84}
85
86impl ExtendedMonitorInfo {
87    const NAME: &'static str = "ExtendedMonitorInfo";
88
89    const FIXED_PART_SIZE: usize = MONITOR_SIZE;
90}
91
92impl Encode for ExtendedMonitorInfo {
93    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
94        ensure_fixed_part_size!(in: dst);
95
96        dst.write_u32(self.physical_width);
97        dst.write_u32(self.physical_height);
98        dst.write_u32(self.orientation.to_u32().unwrap());
99        dst.write_u32(self.desktop_scale_factor);
100        dst.write_u32(self.device_scale_factor);
101
102        Ok(())
103    }
104
105    fn name(&self) -> &'static str {
106        Self::NAME
107    }
108
109    fn size(&self) -> usize {
110        Self::FIXED_PART_SIZE
111    }
112}
113
114impl<'de> Decode<'de> for ExtendedMonitorInfo {
115    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
116        ensure_fixed_part_size!(in: src);
117
118        let physical_width = src.read_u32();
119        let physical_height = src.read_u32();
120        let orientation = MonitorOrientation::from_u32(src.read_u32())
121            .ok_or_else(|| invalid_field_err!("orientation", "invalid monitor orientation"))?;
122        let desktop_scale_factor = src.read_u32();
123        let device_scale_factor = src.read_u32();
124
125        Ok(Self {
126            physical_width,
127            physical_height,
128            orientation,
129            desktop_scale_factor,
130            device_scale_factor,
131        })
132    }
133}
134
135#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
136pub enum MonitorOrientation {
137    Landscape = 0,
138    Portrait = 90,
139    LandscapeFlipped = 180,
140    PortraitFlipped = 270,
141}