ironrdp_pdu/gcc/
monitor_extended_data.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use ironrdp_core::{
    cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
    ReadCursor, WriteCursor,
};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};

const MONITOR_COUNT_MAX: usize = 16;
const MONITOR_ATTRIBUTE_SIZE: u32 = 20;

const FLAGS_SIZE: usize = 4;
const MONITOR_ATTRIBUTE_SIZE_FIELD_SIZE: usize = 4;
const MONITOR_COUNT: usize = 4;
const MONITOR_SIZE: usize = 20;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClientMonitorExtendedData {
    pub extended_monitors_info: Vec<ExtendedMonitorInfo>,
}

impl ClientMonitorExtendedData {
    const NAME: &'static str = "ClientMonitorExtendedData";

    const FIXED_PART_SIZE: usize = FLAGS_SIZE + MONITOR_ATTRIBUTE_SIZE_FIELD_SIZE + MONITOR_COUNT;
}

impl Encode for ClientMonitorExtendedData {
    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
        ensure_size!(in: dst, size: self.size());

        dst.write_u32(0); // flags
        dst.write_u32(MONITOR_ATTRIBUTE_SIZE); // flags
        dst.write_u32(cast_length!("nMonitors", self.extended_monitors_info.len())?);

        for extended_monitor_info in self.extended_monitors_info.iter().take(MONITOR_COUNT_MAX) {
            extended_monitor_info.encode(dst)?;
        }

        Ok(())
    }

    fn name(&self) -> &'static str {
        Self::NAME
    }

    fn size(&self) -> usize {
        Self::FIXED_PART_SIZE + self.extended_monitors_info.len() * MONITOR_SIZE
    }
}

impl<'de> Decode<'de> for ClientMonitorExtendedData {
    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
        ensure_fixed_part_size!(in: src);

        let _flags = src.read_u32(); // is unused

        let monitor_attribute_size = src.read_u32();
        if monitor_attribute_size != MONITOR_ATTRIBUTE_SIZE {
            return Err(invalid_field_err!("monitorAttributeSize", "invalid size"));
        }

        let monitor_count = cast_length!("monitorCount", src.read_u32())?;

        if monitor_count > MONITOR_COUNT_MAX {
            return Err(invalid_field_err!("monitorCount", "invalid monitor count"));
        }

        let mut extended_monitors_info = Vec::with_capacity(monitor_count);
        for _ in 0..monitor_count {
            extended_monitors_info.push(ExtendedMonitorInfo::decode(src)?);
        }

        Ok(Self { extended_monitors_info })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtendedMonitorInfo {
    pub physical_width: u32,
    pub physical_height: u32,
    pub orientation: MonitorOrientation,
    pub desktop_scale_factor: u32,
    pub device_scale_factor: u32,
}

impl ExtendedMonitorInfo {
    const NAME: &'static str = "ExtendedMonitorInfo";

    const FIXED_PART_SIZE: usize = MONITOR_SIZE;
}

impl Encode for ExtendedMonitorInfo {
    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
        ensure_fixed_part_size!(in: dst);

        dst.write_u32(self.physical_width);
        dst.write_u32(self.physical_height);
        dst.write_u32(self.orientation.to_u32().unwrap());
        dst.write_u32(self.desktop_scale_factor);
        dst.write_u32(self.device_scale_factor);

        Ok(())
    }

    fn name(&self) -> &'static str {
        Self::NAME
    }

    fn size(&self) -> usize {
        Self::FIXED_PART_SIZE
    }
}

impl<'de> Decode<'de> for ExtendedMonitorInfo {
    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
        ensure_fixed_part_size!(in: src);

        let physical_width = src.read_u32();
        let physical_height = src.read_u32();
        let orientation = MonitorOrientation::from_u32(src.read_u32())
            .ok_or_else(|| invalid_field_err!("orientation", "invalid monitor orientation"))?;
        let desktop_scale_factor = src.read_u32();
        let device_scale_factor = src.read_u32();

        Ok(Self {
            physical_width,
            physical_height,
            orientation,
            desktop_scale_factor,
            device_scale_factor,
        })
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MonitorOrientation {
    Landscape = 0,
    Portrait = 90,
    LandscapeFlipped = 180,
    PortraitFlipped = 270,
}