ironrdp_pdu/basic_output/
bitmap.rs1#[cfg(test)]
2mod tests;
3
4pub mod rdp6;
5
6use core::fmt::{self, Debug};
7
8use bitflags::bitflags;
9use ironrdp_core::{
10 ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
11 WriteCursor,
12};
13
14use crate::geometry::InclusiveRectangle;
15
16const FIRST_ROW_SIZE_VALUE: u16 = 0;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct BitmapUpdateData<'a> {
21 pub rectangles: Vec<BitmapData<'a>>,
22}
23
24impl BitmapUpdateData<'_> {
25 const NAME: &'static str = "TS_UPDATE_BITMAP_DATA";
26 const FIXED_PART_SIZE: usize = 2 + 2 ;
27}
28
29impl BitmapUpdateData<'_> {
30 pub fn encode_header(rectangles: u16, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
31 ensure_size!(in: dst, size: 2);
32
33 dst.write_u16(BitmapFlags::BITMAP_UPDATE_TYPE.bits());
34 dst.write_u16(rectangles);
35
36 Ok(())
37 }
38}
39
40impl Encode for BitmapUpdateData<'_> {
41 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
42 ensure_size!(in: dst, size: self.size());
43
44 if self.rectangles.len() > u16::MAX as usize {
45 return Err(invalid_field_err!("numberRectangles", "rectangle count is too big"));
46 }
47
48 Self::encode_header(self.rectangles.len() as u16, dst)?;
49
50 for bitmap_data in self.rectangles.iter() {
51 bitmap_data.encode(dst)?;
52 }
53
54 Ok(())
55 }
56
57 fn name(&self) -> &'static str {
58 Self::NAME
59 }
60
61 fn size(&self) -> usize {
62 self.rectangles
63 .iter()
64 .fold(Self::FIXED_PART_SIZE, |size, new| size + new.size())
65 }
66}
67
68impl<'de> Decode<'de> for BitmapUpdateData<'de> {
69 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
70 ensure_fixed_part_size!(in: src);
71
72 let update_type = BitmapFlags::from_bits_truncate(src.read_u16());
73 if !update_type.contains(BitmapFlags::BITMAP_UPDATE_TYPE) {
74 return Err(invalid_field_err!("updateType", "invalid update type"));
75 }
76
77 let rectangles_number = src.read_u16() as usize;
78 let mut rectangles = Vec::with_capacity(rectangles_number);
79
80 for _ in 0..rectangles_number {
81 rectangles.push(BitmapData::decode(src)?);
82 }
83
84 Ok(Self { rectangles })
85 }
86}
87
88#[derive(Clone, PartialEq, Eq)]
90pub struct BitmapData<'a> {
91 pub rectangle: InclusiveRectangle,
92 pub width: u16,
93 pub height: u16,
94 pub bits_per_pixel: u16,
95 pub compression_flags: Compression,
96 pub compressed_data_header: Option<CompressedDataHeader>,
97 pub bitmap_data: &'a [u8],
98}
99
100impl BitmapData<'_> {
101 const NAME: &'static str = "TS_BITMAP_DATA";
102 const FIXED_PART_SIZE: usize = InclusiveRectangle::ENCODED_SIZE + 2 + 2 + 2 + 2 + 2 ;
103
104 fn encoded_bitmap_data_length(&self) -> usize {
105 self.bitmap_data.len() + self.compressed_data_header.as_ref().map(|hdr| hdr.size()).unwrap_or(0)
106 }
107}
108
109impl Encode for BitmapData<'_> {
110 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
111 ensure_size!(in: dst, size: self.size());
112
113 let encoded_bitmap_data_length = self.encoded_bitmap_data_length();
114 if encoded_bitmap_data_length > u16::MAX as usize {
115 return Err(invalid_field_err!("bitmapLength", "bitmap data length is too big"));
116 }
117
118 self.rectangle.encode(dst)?;
119 dst.write_u16(self.width);
120 dst.write_u16(self.height);
121 dst.write_u16(self.bits_per_pixel);
122 dst.write_u16(self.compression_flags.bits());
123 dst.write_u16(encoded_bitmap_data_length as u16);
124 if let Some(compressed_data_header) = &self.compressed_data_header {
125 compressed_data_header.encode(dst)?;
126 };
127 dst.write_slice(self.bitmap_data);
128
129 Ok(())
130 }
131
132 fn name(&self) -> &'static str {
133 Self::NAME
134 }
135
136 fn size(&self) -> usize {
137 Self::FIXED_PART_SIZE + self.encoded_bitmap_data_length()
138 }
139}
140
141impl<'de> Decode<'de> for BitmapData<'de> {
142 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
143 ensure_fixed_part_size!(in: src);
144
145 let rectangle = InclusiveRectangle::decode(src)?;
146 let width = src.read_u16();
147 let height = src.read_u16();
148 let bits_per_pixel = src.read_u16();
149 let compression_flags = Compression::from_bits_truncate(src.read_u16());
150
151 let encoded_bitmap_data_length = src.read_u16();
154
155 ensure_size!(in: src, size: encoded_bitmap_data_length as usize);
156
157 let (compressed_data_header, buffer_length) = if compression_flags.contains(Compression::BITMAP_COMPRESSION)
158 && !compression_flags.contains(Compression::NO_BITMAP_COMPRESSION_HDR)
159 {
160 if encoded_bitmap_data_length < CompressedDataHeader::ENCODED_SIZE as u16 {
162 return Err(invalid_field_err!(
163 "cbCompEncodedBitmapDataLength",
164 "length is less than CompressedDataHeader::ENCODED_SIZE"
165 ));
166 }
167
168 let buffer_length = encoded_bitmap_data_length as usize - CompressedDataHeader::ENCODED_SIZE;
169 (Some(CompressedDataHeader::decode(src)?), buffer_length)
170 } else {
171 (None, encoded_bitmap_data_length as usize)
172 };
173
174 let bitmap_data = src.read_slice(buffer_length);
175
176 Ok(BitmapData {
177 rectangle,
178 width,
179 height,
180 bits_per_pixel,
181 compression_flags,
182 compressed_data_header,
183 bitmap_data,
184 })
185 }
186}
187
188impl Debug for BitmapData<'_> {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_struct("BitmapData")
191 .field("rectangle", &self.rectangle)
192 .field("width", &self.width)
193 .field("height", &self.height)
194 .field("bits_per_pixel", &self.bits_per_pixel)
195 .field("compression_flags", &self.compression_flags)
196 .field("compressed_data_header", &self.compressed_data_header)
197 .field("bitmap_data.len()", &self.bitmap_data.len())
198 .finish()
199 }
200}
201
202#[derive(Debug, Clone, PartialEq, Eq)]
204pub struct CompressedDataHeader {
205 pub main_body_size: u16,
206 pub scan_width: u16,
207 pub uncompressed_size: u16,
208}
209
210impl CompressedDataHeader {
211 const NAME: &'static str = "TS_CD_HEADER";
212 const FIXED_PART_SIZE: usize = 2 + 2 + 2 + 2 ;
213
214 pub const ENCODED_SIZE: usize = Self::FIXED_PART_SIZE;
215}
216
217impl<'de> Decode<'de> for CompressedDataHeader {
218 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
219 ensure_fixed_part_size!(in: src);
220
221 let size = src.read_u16();
222 if size != FIRST_ROW_SIZE_VALUE {
223 return Err(invalid_field_err!("cbCompFirstRowSize", "invalid first row size"));
224 }
225
226 let main_body_size = src.read_u16();
227 let scan_width = src.read_u16();
228
229 if scan_width % 4 != 0 {
230 return Err(invalid_field_err!(
231 "cbScanWidth",
232 "The width of the bitmap must be divisible by 4"
233 ));
234 }
235 let uncompressed_size = src.read_u16();
236
237 Ok(Self {
238 main_body_size,
239 scan_width,
240 uncompressed_size,
241 })
242 }
243}
244
245impl Encode for CompressedDataHeader {
246 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
247 ensure_fixed_part_size!(in: dst);
248
249 if self.scan_width % 4 != 0 {
250 return Err(invalid_field_err!(
251 "cbScanWidth",
252 "The width of the bitmap must be divisible by 4"
253 ));
254 }
255 dst.write_u16(FIRST_ROW_SIZE_VALUE);
256 dst.write_u16(self.main_body_size);
257 dst.write_u16(self.scan_width);
258 dst.write_u16(self.uncompressed_size);
259
260 Ok(())
261 }
262
263 fn name(&self) -> &'static str {
264 Self::NAME
265 }
266
267 fn size(&self) -> usize {
268 Self::FIXED_PART_SIZE
269 }
270}
271
272bitflags! {
273 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
274 pub struct BitmapFlags: u16{
275 const BITMAP_UPDATE_TYPE = 0x0001;
276 }
277}
278
279bitflags! {
280 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
281 pub struct Compression: u16 {
282 const BITMAP_COMPRESSION = 0x0001;
283 const NO_BITMAP_COMPRESSION_HDR = 0x0400;
284 }
285}