ironrdp_pdu/rdp/capability_sets/
order.rs

1#[cfg(test)]
2mod tests;
3
4use bitflags::bitflags;
5use ironrdp_core::{ensure_fixed_part_size, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor};
6
7const ORDER_LENGTH: usize = 84;
8const ORD_LEVEL_1_ORDERS: u16 = 1;
9const SUPPORT_ARRAY_LEN: usize = 32;
10const DESKTOP_SAVE_Y_GRAN_VAL: u16 = 20;
11
12#[derive(Copy, Clone)]
13pub enum OrderSupportIndex {
14    DstBlt = 0x00,
15    PatBlt = 0x01,
16    ScrBlt = 0x02,
17    MemBlt = 0x03,
18    Mem3Blt = 0x04,
19    DrawnInEGrid = 0x07,
20    LineTo = 0x08,
21    MultiDrawnInEGrid = 0x09,
22    SaveBitmap = 0x0B,
23    MultiDstBlt = 0x0F,
24    MultiPatBlt = 0x10,
25    MultiScrBlt = 0x11,
26    MultiOpaqueRect = 0x12,
27    Fast = 0x13,
28    PolygonSC = 0x14,
29    PolygonCB = 0x15,
30    Polyline = 0x16,
31    FastGlyph = 0x18,
32    EllipseSC = 0x19,
33    EllipseCB = 0x1A,
34    Index = 0x1B,
35}
36
37bitflags! {
38    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
39    pub struct OrderFlags: u16 {
40        const NEGOTIATE_ORDER_SUPPORT = 0x0002;
41        const ZERO_BOUNDS_DELTAS_SUPPORT = 0x0008;
42        const COLOR_INDEX_SUPPORT = 0x0020;
43        const SOLID_PATTERN_BRUSH_ONLY = 0x0040;
44        const ORDER_FLAGS_EXTRA_FLAGS = 0x0080;
45    }
46}
47
48bitflags! {
49    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
50    pub struct OrderSupportExFlags: u16 {
51        const CACHE_BITMAP_REV3_SUPPORT = 2;
52        const ALTSEC_FRAME_MARKER_SUPPORT = 4;
53    }
54}
55
56#[derive(Debug, PartialEq, Eq, Clone)]
57pub struct Order {
58    pub order_flags: OrderFlags,
59    order_support: [u8; SUPPORT_ARRAY_LEN],
60    pub order_support_ex_flags: OrderSupportExFlags,
61    pub desktop_save_size: u32,
62    pub text_ansi_code_page: u16,
63}
64
65impl Order {
66    const NAME: &'static str = "Order";
67
68    const FIXED_PART_SIZE: usize = ORDER_LENGTH;
69
70    pub fn new(
71        order_flags: OrderFlags,
72        order_support_ex_flags: OrderSupportExFlags,
73        desktop_save_size: u32,
74        text_ansi_code_page: u16,
75    ) -> Self {
76        Self {
77            order_flags,
78            order_support: [0; SUPPORT_ARRAY_LEN],
79            order_support_ex_flags,
80            desktop_save_size,
81            text_ansi_code_page,
82        }
83    }
84
85    pub fn set_support_flag(&mut self, flag: OrderSupportIndex, value: bool) {
86        self.order_support[flag as usize] = u8::from(value)
87    }
88
89    pub fn get_support_flag(&mut self, flag: OrderSupportIndex) -> bool {
90        self.order_support[flag as usize] == 1
91    }
92}
93
94impl Encode for Order {
95    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
96        ensure_fixed_part_size!(in: dst);
97
98        dst.write_u128(0);
99
100        dst.write_u32(0); // padding
101        dst.write_u16(1); // desktopSaveXGranularity
102        dst.write_u16(DESKTOP_SAVE_Y_GRAN_VAL);
103        dst.write_u16(0); // padding
104        dst.write_u16(ORD_LEVEL_1_ORDERS); // maximumOrderLevel
105        dst.write_u16(0); // numberFonts
106        dst.write_u16(self.order_flags.bits());
107        dst.write_slice(&self.order_support);
108        dst.write_u16(0); // textFlags
109        dst.write_u16(self.order_support_ex_flags.bits());
110        dst.write_u32(0); // padding
111        dst.write_u32(self.desktop_save_size);
112        dst.write_u16(0); // padding
113        dst.write_u16(0); // padding
114        dst.write_u16(self.text_ansi_code_page);
115        dst.write_u16(0); // padding
116
117        Ok(())
118    }
119
120    fn name(&self) -> &'static str {
121        Self::NAME
122    }
123
124    fn size(&self) -> usize {
125        Self::FIXED_PART_SIZE
126    }
127}
128
129impl<'de> Decode<'de> for Order {
130    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
131        ensure_fixed_part_size!(in: src);
132
133        let _terminal_descriptor = src.read_u128();
134        let _padding = src.read_u32();
135        let _desktop_save_x_granularity = src.read_u16();
136        let _desktop_save_y_granularity = src.read_u16();
137        let _padding = src.read_u16();
138        let _max_order_level = src.read_u16();
139        let _num_fonts = src.read_u16();
140
141        let order_flags = OrderFlags::from_bits_truncate(src.read_u16());
142        let order_support = src.read_array();
143
144        let _text_flags = src.read_u16();
145
146        let order_support_ex_flags = OrderSupportExFlags::from_bits_truncate(src.read_u16());
147
148        let _padding = src.read_u32();
149        let desktop_save_size = src.read_u32();
150        let _padding = src.read_u16();
151        let _padding = src.read_u16();
152        let text_ansi_code_page = src.read_u16();
153        let _padding = src.read_u16();
154
155        Ok(Order {
156            order_flags,
157            order_support,
158            order_support_ex_flags,
159            desktop_save_size,
160            text_ansi_code_page,
161        })
162    }
163}