ironrdp_pdu/rdp/capability_sets/
input.rs

1#[cfg(test)]
2mod tests;
3
4use bitflags::bitflags;
5use ironrdp_core::{
6    ensure_fixed_part_size, read_padding, write_padding, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
7    WriteCursor,
8};
9use num_traits::{FromPrimitive as _, ToPrimitive as _};
10
11use crate::gcc::{KeyboardType, IME_FILE_NAME_SIZE};
12use crate::utils;
13
14const INPUT_LENGTH: usize = 84;
15
16bitflags! {
17    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18    pub struct InputFlags: u16 {
19        const SCANCODES = 0x0001;
20        const MOUSEX = 0x0004;
21        const FASTPATH_INPUT = 0x0008;
22        const UNICODE = 0x0010;
23        const FASTPATH_INPUT_2 = 0x0020;
24        const UNUSED_1 = 0x0040;
25        const MOUSE_RELATIVE = 0x0080;
26        const TS_MOUSE_HWHEEL = 0x0100;
27        const TS_QOE_TIMESTAMPS = 0x0200;
28    }
29}
30
31#[derive(Debug, PartialEq, Eq, Clone)]
32pub struct Input {
33    pub input_flags: InputFlags,
34    pub keyboard_layout: u32,
35    pub keyboard_type: Option<KeyboardType>,
36    pub keyboard_subtype: u32,
37    pub keyboard_function_key: u32,
38    pub keyboard_ime_filename: String,
39}
40
41impl Input {
42    const NAME: &'static str = "Input";
43
44    const FIXED_PART_SIZE: usize = INPUT_LENGTH;
45}
46
47impl Encode for Input {
48    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
49        ensure_fixed_part_size!(in: dst);
50
51        dst.write_u16(self.input_flags.bits());
52        write_padding!(dst, 2);
53        dst.write_u32(self.keyboard_layout);
54
55        let type_buffer = match self.keyboard_type.as_ref() {
56            Some(value) => value.to_u32().unwrap_or(0),
57            None => 0,
58        };
59        dst.write_u32(type_buffer);
60
61        dst.write_u32(self.keyboard_subtype);
62        dst.write_u32(self.keyboard_function_key);
63
64        utils::encode_string(
65            dst.remaining_mut(),
66            &self.keyboard_ime_filename,
67            utils::CharacterSet::Unicode,
68            true,
69        )?;
70        dst.advance(IME_FILE_NAME_SIZE);
71
72        Ok(())
73    }
74
75    fn name(&self) -> &'static str {
76        Self::NAME
77    }
78
79    fn size(&self) -> usize {
80        Self::FIXED_PART_SIZE
81    }
82}
83
84impl<'de> Decode<'de> for Input {
85    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
86        ensure_fixed_part_size!(in: src);
87
88        let input_flags = InputFlags::from_bits_truncate(src.read_u16());
89        read_padding!(src, 2);
90        let keyboard_layout = src.read_u32();
91
92        let keyboard_type = KeyboardType::from_u32(src.read_u32());
93
94        let keyboard_subtype = src.read_u32();
95        let keyboard_function_key = src.read_u32();
96
97        let keyboard_ime_filename =
98            utils::decode_string(src.read_slice(IME_FILE_NAME_SIZE), utils::CharacterSet::Unicode, false)?;
99
100        Ok(Input {
101            input_flags,
102            keyboard_layout,
103            keyboard_type,
104            keyboard_subtype,
105            keyboard_function_key,
106            keyboard_ime_filename,
107        })
108    }
109}