ironrdp_pdu/rdp/capability_sets/
general.rs1#[cfg(test)]
2mod tests;
3
4use std::fmt;
5
6use bitflags::bitflags;
7use ironrdp_core::{
8 ensure_fixed_part_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
9};
10
11const GENERAL_LENGTH: usize = 20;
12pub const PROTOCOL_VER: u16 = 0x0200;
13
14#[derive(Clone, Copy, PartialEq, Eq)]
15pub struct MajorPlatformType(u16);
16
17impl fmt::Debug for MajorPlatformType {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 let name = match *self {
20 Self::UNSPECIFIED => "UNSPECIFIED",
21 Self::WINDOWS => "WINDOWS",
22 Self::OS2 => "OS2",
23 Self::MACINTOSH => "MACINTOSH",
24 Self::UNIX => "UNIX",
25 Self::IOS => "IOS",
26 Self::OSX => "OSX",
27 Self::ANDROID => "ANDROID",
28 Self::CHROMEOS => "CHROMEOS",
29 _ => "UNKNOWN",
30 };
31
32 write!(f, "MajorPlatformType(0x{:02X}-{name})", self.0)
33 }
34}
35
36impl MajorPlatformType {
37 pub const UNSPECIFIED: Self = Self(0);
38 pub const WINDOWS: Self = Self(1);
39 pub const OS2: Self = Self(2);
40 pub const MACINTOSH: Self = Self(3);
41 pub const UNIX: Self = Self(4);
42 pub const IOS: Self = Self(5);
43 pub const OSX: Self = Self(6);
44 pub const ANDROID: Self = Self(7);
45 pub const CHROMEOS: Self = Self(8);
46}
47
48#[derive(Clone, Copy, PartialEq, Eq)]
49pub struct MinorPlatformType(u16);
50
51impl fmt::Debug for MinorPlatformType {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 let name = match *self {
54 Self::UNSPECIFIED => "UNSPECIFIED",
55 Self::WINDOWS_31X => "WINDOWS_31X",
56 Self::WINDOWS_95 => "WINDOWS_95",
57 Self::WINDOWS_NT => "WINDOWS_NT",
58 Self::OS2V21 => "OS2_V21",
59 Self::POWER_PC => "POWER_PC",
60 Self::MACINTOSH => "MACINTOSH",
61 Self::NATIVE_XSERVER => "NATIVE_XSERVER",
62 Self::PSEUDO_XSERVER => "PSEUDO_XSERVER",
63 Self::WINDOWS_RT => "WINDOWS_RT",
64 _ => "UNKNOWN",
65 };
66
67 write!(f, "MinorPlatformType(0x{:02X}-{name})", self.0)
68 }
69}
70
71impl MinorPlatformType {
72 pub const UNSPECIFIED: Self = Self(0);
73 pub const WINDOWS_31X: Self = Self(1);
74 pub const WINDOWS_95: Self = Self(2);
75 pub const WINDOWS_NT: Self = Self(3);
76 pub const OS2V21: Self = Self(4);
77 pub const POWER_PC: Self = Self(5);
78 pub const MACINTOSH: Self = Self(6);
79 pub const NATIVE_XSERVER: Self = Self(7);
80 pub const PSEUDO_XSERVER: Self = Self(8);
81 pub const WINDOWS_RT: Self = Self(9);
82}
83
84bitflags! {
85 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
86 pub struct GeneralExtraFlags: u16 {
87 const FASTPATH_OUTPUT_SUPPORTED = 0x0001;
88 const NO_BITMAP_COMPRESSION_HDR = 0x0400;
89 const LONG_CREDENTIALS_SUPPORTED = 0x0004;
90 const AUTORECONNECT_SUPPORTED = 0x0008;
91 const ENC_SALTED_CHECKSUM = 0x0010;
92 }
93}
94
95#[derive(Debug, PartialEq, Eq, Clone)]
96pub struct General {
97 pub major_platform_type: MajorPlatformType,
98 pub minor_platform_type: MinorPlatformType,
99 pub protocol_version: u16,
100 pub extra_flags: GeneralExtraFlags,
101 pub refresh_rect_support: bool,
102 pub suppress_output_support: bool,
103}
104
105impl General {
106 const NAME: &'static str = "General";
107
108 const FIXED_PART_SIZE: usize = GENERAL_LENGTH;
109}
110
111impl Default for General {
112 fn default() -> Self {
113 Self {
114 major_platform_type: MajorPlatformType::UNSPECIFIED,
115 minor_platform_type: MinorPlatformType::UNSPECIFIED,
116 protocol_version: PROTOCOL_VER,
117 extra_flags: GeneralExtraFlags::empty(),
118 refresh_rect_support: Default::default(),
119 suppress_output_support: Default::default(),
120 }
121 }
122}
123
124impl Encode for General {
125 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
126 ensure_fixed_part_size!(in: dst);
127
128 dst.write_u16(self.major_platform_type.0);
129 dst.write_u16(self.minor_platform_type.0);
130 dst.write_u16(PROTOCOL_VER);
131 dst.write_u16(0); dst.write_u16(0); dst.write_u16(self.extra_flags.bits());
134 dst.write_u16(0); dst.write_u16(0); dst.write_u16(0); dst.write_u8(u8::from(self.refresh_rect_support));
138 dst.write_u8(u8::from(self.suppress_output_support));
139
140 Ok(())
141 }
142
143 fn name(&self) -> &'static str {
144 Self::NAME
145 }
146
147 fn size(&self) -> usize {
148 Self::FIXED_PART_SIZE
149 }
150}
151
152impl<'de> Decode<'de> for General {
153 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
154 ensure_fixed_part_size!(in: src);
155
156 let major_platform_type = MajorPlatformType(src.read_u16());
157 let minor_platform_type = MinorPlatformType(src.read_u16());
158
159 let protocol_version = src.read_u16();
160
161 let _padding = src.read_u16();
162
163 let compression_types = src.read_u16();
164 if compression_types != 0 {
165 return Err(invalid_field_err!("compressionTypes", "invalid compression types"));
166 }
167
168 let extra_flags = GeneralExtraFlags::from_bits_truncate(src.read_u16());
169
170 let update_cap_flags = src.read_u16();
171 if update_cap_flags != 0 {
172 return Err(invalid_field_err!("updateCapFlags", "invalid update cap flags"));
173 }
174
175 let remote_unshare_flag = src.read_u16();
176 if remote_unshare_flag != 0 {
177 return Err(invalid_field_err!("remoteUnshareFlags", "invalid remote unshare flag"));
178 }
179
180 let compression_level = src.read_u16();
181 if compression_level != 0 {
182 return Err(invalid_field_err!("compressionLevel", "invalid compression level"));
183 }
184
185 let refresh_rect_support = src.read_u8() != 0;
186 let suppress_output_support = src.read_u8() != 0;
187
188 Ok(General {
189 major_platform_type,
190 minor_platform_type,
191 protocol_version,
192 extra_flags,
193 refresh_rect_support,
194 suppress_output_support,
195 })
196 }
197}