ironrdp_pdu/rdp/
headers.rs

1use bitflags::bitflags;
2use ironrdp_core::{
3    cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, not_enough_bytes_err, other_err, read_padding,
4    write_padding, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
5};
6use num_derive::{FromPrimitive, ToPrimitive};
7use num_traits::{FromPrimitive as _, ToPrimitive as _};
8
9use crate::codecs::rfx::FrameAcknowledgePdu;
10use crate::input::InputEventPdu;
11use crate::rdp::capability_sets::{ClientConfirmActive, ServerDemandActive};
12use crate::rdp::client_info;
13use crate::rdp::finalization_messages::{ControlPdu, FontPdu, MonitorLayoutPdu, SynchronizePdu};
14use crate::rdp::refresh_rectangle::RefreshRectanglePdu;
15use crate::rdp::server_error_info::ServerSetErrorInfoPdu;
16use crate::rdp::session_info::SaveSessionInfoPdu;
17use crate::rdp::suppress_output::SuppressOutputPdu;
18
19pub const BASIC_SECURITY_HEADER_SIZE: usize = 4;
20pub const SHARE_DATA_HEADER_COMPRESSION_MASK: u8 = 0xF;
21const SHARE_CONTROL_HEADER_MASK: u16 = 0xF;
22const SHARE_CONTROL_HEADER_SIZE: usize = 2 * 3 + 4;
23
24const PROTOCOL_VERSION: u16 = 0x10;
25
26// ShareDataHeader
27const PADDING_FIELD_SIZE: usize = 1;
28const STREAM_ID_FIELD_SIZE: usize = 1;
29const UNCOMPRESSED_LENGTH_FIELD_SIZE: usize = 2;
30const PDU_TYPE_FIELD_SIZE: usize = 1;
31const COMPRESSION_TYPE_FIELD_SIZE: usize = 1;
32const COMPRESSED_LENGTH_FIELD_SIZE: usize = 2;
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct BasicSecurityHeader {
36    pub flags: BasicSecurityHeaderFlags,
37}
38
39impl BasicSecurityHeader {
40    const NAME: &'static str = "BasicSecurityHeader";
41
42    pub const FIXED_PART_SIZE: usize = BASIC_SECURITY_HEADER_SIZE;
43}
44
45impl Encode for BasicSecurityHeader {
46    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
47        ensure_fixed_part_size!(in: dst);
48
49        dst.write_u16(self.flags.bits());
50        dst.write_u16(0); // flags_hi
51        Ok(())
52    }
53
54    fn name(&self) -> &'static str {
55        Self::NAME
56    }
57
58    fn size(&self) -> usize {
59        Self::FIXED_PART_SIZE
60    }
61}
62
63impl<'de> Decode<'de> for BasicSecurityHeader {
64    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
65        ensure_fixed_part_size!(in: src);
66
67        let flags = BasicSecurityHeaderFlags::from_bits(src.read_u16())
68            .ok_or_else(|| invalid_field_err!("securityHeader", "invalid basic security header"))?;
69        let _flags_hi = src.read_u16(); // unused
70
71        Ok(Self { flags })
72    }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub struct ShareControlHeader {
77    pub share_control_pdu: ShareControlPdu,
78    pub pdu_source: u16,
79    pub share_id: u32,
80}
81
82impl ShareControlHeader {
83    const NAME: &'static str = "ShareControlHeader";
84
85    const FIXED_PART_SIZE: usize = SHARE_CONTROL_HEADER_SIZE;
86}
87
88impl Encode for ShareControlHeader {
89    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
90        ensure_size!(in: dst, size: self.size());
91
92        let pdu_type_with_version = PROTOCOL_VERSION | self.share_control_pdu.share_header_type().to_u16().unwrap();
93
94        dst.write_u16(cast_length!(
95            "len",
96            self.share_control_pdu.size() + SHARE_CONTROL_HEADER_SIZE
97        )?);
98        dst.write_u16(pdu_type_with_version);
99        dst.write_u16(self.pdu_source);
100        dst.write_u32(self.share_id);
101
102        self.share_control_pdu.encode(dst)
103    }
104
105    fn name(&self) -> &'static str {
106        Self::NAME
107    }
108
109    fn size(&self) -> usize {
110        Self::FIXED_PART_SIZE + self.share_control_pdu.size()
111    }
112}
113
114impl<'de> Decode<'de> for ShareControlHeader {
115    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
116        ensure_fixed_part_size!(in: src);
117
118        let total_length = src.read_u16() as usize;
119        let pdu_type_with_version = src.read_u16();
120        let pdu_source = src.read_u16();
121        let share_id = src.read_u32();
122
123        let pdu_type = ShareControlPduType::from_u16(pdu_type_with_version & SHARE_CONTROL_HEADER_MASK)
124            .ok_or_else(|| invalid_field_err!("pdu_type", "invalid pdu type"))?;
125        let pdu_version = pdu_type_with_version & !SHARE_CONTROL_HEADER_MASK;
126        if pdu_version != PROTOCOL_VERSION {
127            return Err(invalid_field_err!("pdu_version", "invalid PDU version"));
128        }
129
130        let share_pdu = ShareControlPdu::from_type(src, pdu_type)?;
131        let header = Self {
132            share_control_pdu: share_pdu,
133            pdu_source,
134            share_id,
135        };
136
137        if pdu_type == ShareControlPduType::DataPdu {
138            // Some windows version have an issue where
139            // there is some padding not part of the inner unit.
140            // Consume that data
141            let header_length = header.size();
142
143            if header_length != total_length {
144                if total_length < header_length {
145                    return Err(not_enough_bytes_err!(total_length, header_length));
146                }
147
148                let padding = total_length - header_length;
149                ensure_size!(in: src, size: padding);
150                read_padding!(src, padding);
151            }
152        }
153
154        Ok(header)
155    }
156}
157
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum ShareControlPdu {
160    ServerDemandActive(ServerDemandActive),
161    ClientConfirmActive(ClientConfirmActive),
162    Data(ShareDataHeader),
163    ServerDeactivateAll(ServerDeactivateAll),
164}
165
166impl ShareControlPdu {
167    const NAME: &'static str = "ShareControlPdu";
168
169    pub fn as_short_name(&self) -> &str {
170        match self {
171            ShareControlPdu::ServerDemandActive(_) => "Server Demand Active PDU",
172            ShareControlPdu::ClientConfirmActive(_) => "Client Confirm Active PDU",
173            ShareControlPdu::Data(_) => "Data PDU",
174            ShareControlPdu::ServerDeactivateAll(_) => "Server Deactivate All PDU",
175        }
176    }
177
178    pub fn share_header_type(&self) -> ShareControlPduType {
179        match self {
180            ShareControlPdu::ServerDemandActive(_) => ShareControlPduType::DemandActivePdu,
181            ShareControlPdu::ClientConfirmActive(_) => ShareControlPduType::ConfirmActivePdu,
182            ShareControlPdu::Data(_) => ShareControlPduType::DataPdu,
183            ShareControlPdu::ServerDeactivateAll(_) => ShareControlPduType::DeactivateAllPdu,
184        }
185    }
186
187    pub fn from_type(src: &mut ReadCursor<'_>, share_type: ShareControlPduType) -> DecodeResult<Self> {
188        match share_type {
189            ShareControlPduType::DemandActivePdu => {
190                Ok(ShareControlPdu::ServerDemandActive(ServerDemandActive::decode(src)?))
191            }
192            ShareControlPduType::ConfirmActivePdu => {
193                Ok(ShareControlPdu::ClientConfirmActive(ClientConfirmActive::decode(src)?))
194            }
195            ShareControlPduType::DataPdu => Ok(ShareControlPdu::Data(ShareDataHeader::decode(src)?)),
196            ShareControlPduType::DeactivateAllPdu => {
197                Ok(ShareControlPdu::ServerDeactivateAll(ServerDeactivateAll::decode(src)?))
198            }
199            _ => Err(invalid_field_err!("share_type", "unexpected share control PDU type")),
200        }
201    }
202}
203
204impl Encode for ShareControlPdu {
205    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
206        match self {
207            ShareControlPdu::ServerDemandActive(pdu) => pdu.encode(dst),
208            ShareControlPdu::ClientConfirmActive(pdu) => pdu.encode(dst),
209            ShareControlPdu::Data(share_data_header) => share_data_header.encode(dst),
210            ShareControlPdu::ServerDeactivateAll(deactivate_all) => deactivate_all.encode(dst),
211        }
212    }
213
214    fn name(&self) -> &'static str {
215        Self::NAME
216    }
217
218    fn size(&self) -> usize {
219        match self {
220            ShareControlPdu::ServerDemandActive(pdu) => pdu.size(),
221            ShareControlPdu::ClientConfirmActive(pdu) => pdu.size(),
222            ShareControlPdu::Data(share_data_header) => share_data_header.size(),
223            ShareControlPdu::ServerDeactivateAll(deactivate_all) => deactivate_all.size(),
224        }
225    }
226}
227
228#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct ShareDataHeader {
230    pub share_data_pdu: ShareDataPdu,
231    pub stream_priority: StreamPriority,
232    pub compression_flags: CompressionFlags,
233    pub compression_type: client_info::CompressionType,
234}
235
236impl ShareDataHeader {
237    const NAME: &'static str = "ShareDataHeader";
238
239    const FIXED_PART_SIZE: usize = PADDING_FIELD_SIZE
240        + STREAM_ID_FIELD_SIZE
241        + UNCOMPRESSED_LENGTH_FIELD_SIZE
242        + PDU_TYPE_FIELD_SIZE
243        + COMPRESSION_TYPE_FIELD_SIZE
244        + COMPRESSED_LENGTH_FIELD_SIZE;
245}
246
247impl Encode for ShareDataHeader {
248    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
249        ensure_size!(in: dst, size: self.size());
250
251        if self.compression_flags.is_empty() {
252            let compression_flags_with_type = self.compression_flags.bits() | self.compression_type.to_u8().unwrap();
253
254            write_padding!(dst, 1);
255            dst.write_u8(self.stream_priority.to_u8().unwrap());
256            dst.write_u16(cast_length!(
257                "uncompressedLength",
258                self.share_data_pdu.size()
259                    + PDU_TYPE_FIELD_SIZE
260                    + COMPRESSION_TYPE_FIELD_SIZE
261                    + COMPRESSED_LENGTH_FIELD_SIZE
262            )?);
263            dst.write_u8(self.share_data_pdu.share_header_type().to_u8().unwrap());
264            dst.write_u8(compression_flags_with_type);
265            dst.write_u16(0); // compressed length
266
267            self.share_data_pdu.encode(dst)
268        } else {
269            Err(other_err!("Compression is not implemented"))
270        }
271    }
272
273    fn name(&self) -> &'static str {
274        Self::NAME
275    }
276
277    fn size(&self) -> usize {
278        Self::FIXED_PART_SIZE + self.share_data_pdu.size()
279    }
280}
281
282impl<'de> Decode<'de> for ShareDataHeader {
283    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
284        ensure_fixed_part_size!(in: src);
285
286        read_padding!(src, 1);
287        let stream_priority = StreamPriority::from_u8(src.read_u8())
288            .ok_or_else(|| invalid_field_err!("streamPriority", "Invalid stream priority"))?;
289        let _uncompressed_length = src.read_u16();
290        let pdu_type = ShareDataPduType::from_u8(src.read_u8())
291            .ok_or_else(|| invalid_field_err!("pduType", "Invalid pdu type"))?;
292        let compression_flags_with_type = src.read_u8();
293
294        let compression_flags =
295            CompressionFlags::from_bits_truncate(compression_flags_with_type & !SHARE_DATA_HEADER_COMPRESSION_MASK);
296        let compression_type =
297            client_info::CompressionType::from_u8(compression_flags_with_type & SHARE_DATA_HEADER_COMPRESSION_MASK)
298                .ok_or_else(|| invalid_field_err!("compressionType", "Invalid compression type"))?;
299        let _compressed_length = src.read_u16();
300
301        let share_data_pdu = ShareDataPdu::from_type(src, pdu_type)?;
302
303        Ok(Self {
304            share_data_pdu,
305            stream_priority,
306            compression_flags,
307            compression_type,
308        })
309    }
310}
311
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub enum ShareDataPdu {
314    Synchronize(SynchronizePdu),
315    Control(ControlPdu),
316    FontList(FontPdu),
317    FontMap(FontPdu),
318    MonitorLayout(MonitorLayoutPdu),
319    SaveSessionInfo(SaveSessionInfoPdu),
320    FrameAcknowledge(FrameAcknowledgePdu),
321    ServerSetErrorInfo(ServerSetErrorInfoPdu),
322    Input(InputEventPdu),
323    ShutdownRequest,
324    ShutdownDenied,
325    SuppressOutput(SuppressOutputPdu),
326    RefreshRectangle(RefreshRectanglePdu),
327    Update(Vec<u8>),
328    Pointer(Vec<u8>),
329    PlaySound(Vec<u8>),
330    SetKeyboardIndicators(Vec<u8>),
331    BitmapCachePersistentList(Vec<u8>),
332    BitmapCacheErrorPdu(Vec<u8>),
333    SetKeyboardImeStatus(Vec<u8>),
334    OffscreenCacheErrorPdu(Vec<u8>),
335    DrawNineGridErrorPdu(Vec<u8>),
336    DrawGdiPusErrorPdu(Vec<u8>),
337    ArcStatusPdu(Vec<u8>),
338    StatusInfoPdu(Vec<u8>),
339}
340
341impl ShareDataPdu {
342    const NAME: &'static str = "ShareDataPdu";
343
344    pub fn as_short_name(&self) -> &str {
345        match self {
346            ShareDataPdu::Synchronize(_) => "Synchronize PDU",
347            ShareDataPdu::Control(_) => "Control PDU",
348            ShareDataPdu::FontList(_) => "FontList PDU",
349            ShareDataPdu::FontMap(_) => "Font Map PDU",
350            ShareDataPdu::MonitorLayout(_) => "Monitor Layout PDU",
351            ShareDataPdu::SaveSessionInfo(_) => "Save session info PDU",
352            ShareDataPdu::FrameAcknowledge(_) => "Frame Acknowledge PDU",
353            ShareDataPdu::ServerSetErrorInfo(_) => "Server Set Error Info PDU",
354            ShareDataPdu::Input(_) => "Server Input PDU",
355            ShareDataPdu::ShutdownRequest => "Shutdown Request PDU",
356            ShareDataPdu::ShutdownDenied => "Shutdown Denied PDU",
357            ShareDataPdu::SuppressOutput(_) => "Suppress Output PDU",
358            ShareDataPdu::RefreshRectangle(_) => "Refresh Rectangle PDU",
359            ShareDataPdu::Update(_) => "Update PDU",
360            ShareDataPdu::Pointer(_) => "Pointer PDU",
361            ShareDataPdu::PlaySound(_) => "Play Sound PDU",
362            ShareDataPdu::SetKeyboardIndicators(_) => "Set Keyboard Indicators PDU",
363            ShareDataPdu::BitmapCachePersistentList(_) => "Bitmap Cache Persistent List PDU",
364            ShareDataPdu::BitmapCacheErrorPdu(_) => "Bitmap Cache Error PDU",
365            ShareDataPdu::SetKeyboardImeStatus(_) => "Set Keyboard IME Status PDU",
366            ShareDataPdu::OffscreenCacheErrorPdu(_) => "Offscreen Cache Error PDU",
367            ShareDataPdu::DrawNineGridErrorPdu(_) => "Draw Nine Grid Error PDU",
368            ShareDataPdu::DrawGdiPusErrorPdu(_) => "Draw GDI PUS Error PDU",
369            ShareDataPdu::ArcStatusPdu(_) => "Arc Status PDU",
370            ShareDataPdu::StatusInfoPdu(_) => "Status Info PDU",
371        }
372    }
373
374    pub fn share_header_type(&self) -> ShareDataPduType {
375        match self {
376            ShareDataPdu::Synchronize(_) => ShareDataPduType::Synchronize,
377            ShareDataPdu::Control(_) => ShareDataPduType::Control,
378            ShareDataPdu::FontList(_) => ShareDataPduType::FontList,
379            ShareDataPdu::FontMap(_) => ShareDataPduType::FontMap,
380            ShareDataPdu::MonitorLayout(_) => ShareDataPduType::MonitorLayoutPdu,
381            ShareDataPdu::SaveSessionInfo(_) => ShareDataPduType::SaveSessionInfo,
382            ShareDataPdu::FrameAcknowledge(_) => ShareDataPduType::FrameAcknowledgePdu,
383            ShareDataPdu::ServerSetErrorInfo(_) => ShareDataPduType::SetErrorInfoPdu,
384            ShareDataPdu::Input(_) => ShareDataPduType::Input,
385            ShareDataPdu::ShutdownRequest => ShareDataPduType::ShutdownRequest,
386            ShareDataPdu::ShutdownDenied => ShareDataPduType::ShutdownDenied,
387            ShareDataPdu::SuppressOutput(_) => ShareDataPduType::SuppressOutput,
388            ShareDataPdu::RefreshRectangle(_) => ShareDataPduType::RefreshRectangle,
389            ShareDataPdu::Update(_) => ShareDataPduType::Update,
390            ShareDataPdu::Pointer(_) => ShareDataPduType::Pointer,
391            ShareDataPdu::PlaySound(_) => ShareDataPduType::PlaySound,
392            ShareDataPdu::SetKeyboardIndicators(_) => ShareDataPduType::SetKeyboardIndicators,
393            ShareDataPdu::BitmapCachePersistentList(_) => ShareDataPduType::BitmapCachePersistentList,
394            ShareDataPdu::BitmapCacheErrorPdu(_) => ShareDataPduType::BitmapCacheErrorPdu,
395            ShareDataPdu::SetKeyboardImeStatus(_) => ShareDataPduType::SetKeyboardImeStatus,
396            ShareDataPdu::OffscreenCacheErrorPdu(_) => ShareDataPduType::OffscreenCacheErrorPdu,
397            ShareDataPdu::DrawNineGridErrorPdu(_) => ShareDataPduType::DrawNineGridErrorPdu,
398            ShareDataPdu::DrawGdiPusErrorPdu(_) => ShareDataPduType::DrawGdiPusErrorPdu,
399            ShareDataPdu::ArcStatusPdu(_) => ShareDataPduType::ArcStatusPdu,
400            ShareDataPdu::StatusInfoPdu(_) => ShareDataPduType::StatusInfoPdu,
401        }
402    }
403
404    fn from_type(src: &mut ReadCursor<'_>, share_type: ShareDataPduType) -> DecodeResult<Self> {
405        match share_type {
406            ShareDataPduType::Synchronize => Ok(ShareDataPdu::Synchronize(SynchronizePdu::decode(src)?)),
407            ShareDataPduType::Control => Ok(ShareDataPdu::Control(ControlPdu::decode(src)?)),
408            ShareDataPduType::FontList => Ok(ShareDataPdu::FontList(FontPdu::decode(src)?)),
409            ShareDataPduType::FontMap => Ok(ShareDataPdu::FontMap(FontPdu::decode(src)?)),
410            ShareDataPduType::MonitorLayoutPdu => Ok(ShareDataPdu::MonitorLayout(MonitorLayoutPdu::decode(src)?)),
411            ShareDataPduType::SaveSessionInfo => Ok(ShareDataPdu::SaveSessionInfo(SaveSessionInfoPdu::decode(src)?)),
412            ShareDataPduType::FrameAcknowledgePdu => {
413                Ok(ShareDataPdu::FrameAcknowledge(FrameAcknowledgePdu::decode(src)?))
414            }
415            ShareDataPduType::SetErrorInfoPdu => {
416                Ok(ShareDataPdu::ServerSetErrorInfo(ServerSetErrorInfoPdu::decode(src)?))
417            }
418            ShareDataPduType::Input => Ok(ShareDataPdu::Input(InputEventPdu::decode(src)?)),
419            ShareDataPduType::ShutdownRequest => Ok(ShareDataPdu::ShutdownRequest),
420            ShareDataPduType::ShutdownDenied => Ok(ShareDataPdu::ShutdownDenied),
421            ShareDataPduType::SuppressOutput => Ok(ShareDataPdu::SuppressOutput(SuppressOutputPdu::decode(src)?)),
422            ShareDataPduType::RefreshRectangle => Ok(ShareDataPdu::RefreshRectangle(RefreshRectanglePdu::decode(src)?)),
423            ShareDataPduType::Update => Ok(ShareDataPdu::Update(src.remaining().to_vec())),
424            ShareDataPduType::Pointer => Ok(ShareDataPdu::Pointer(src.remaining().to_vec())),
425            ShareDataPduType::PlaySound => Ok(ShareDataPdu::PlaySound(src.remaining().to_vec())),
426            ShareDataPduType::SetKeyboardIndicators => {
427                Ok(ShareDataPdu::SetKeyboardIndicators(src.remaining().to_vec()))
428            }
429            ShareDataPduType::BitmapCachePersistentList => {
430                Ok(ShareDataPdu::BitmapCachePersistentList(src.remaining().to_vec()))
431            }
432            ShareDataPduType::BitmapCacheErrorPdu => Ok(ShareDataPdu::BitmapCacheErrorPdu(src.remaining().to_vec())),
433            ShareDataPduType::SetKeyboardImeStatus => Ok(ShareDataPdu::SetKeyboardImeStatus(src.remaining().to_vec())),
434            ShareDataPduType::OffscreenCacheErrorPdu => {
435                Ok(ShareDataPdu::OffscreenCacheErrorPdu(src.remaining().to_vec()))
436            }
437            ShareDataPduType::DrawNineGridErrorPdu => Ok(ShareDataPdu::DrawNineGridErrorPdu(src.remaining().to_vec())),
438            ShareDataPduType::DrawGdiPusErrorPdu => Ok(ShareDataPdu::DrawGdiPusErrorPdu(src.remaining().to_vec())),
439            ShareDataPduType::ArcStatusPdu => Ok(ShareDataPdu::ArcStatusPdu(src.remaining().to_vec())),
440            ShareDataPduType::StatusInfoPdu => Ok(ShareDataPdu::StatusInfoPdu(src.remaining().to_vec())),
441        }
442    }
443}
444
445impl Encode for ShareDataPdu {
446    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
447        match self {
448            ShareDataPdu::Synchronize(pdu) => pdu.encode(dst),
449            ShareDataPdu::Control(pdu) => pdu.encode(dst),
450            ShareDataPdu::FontList(pdu) | ShareDataPdu::FontMap(pdu) => pdu.encode(dst),
451            ShareDataPdu::MonitorLayout(pdu) => pdu.encode(dst),
452            ShareDataPdu::SaveSessionInfo(pdu) => pdu.encode(dst),
453            ShareDataPdu::FrameAcknowledge(pdu) => pdu.encode(dst),
454            ShareDataPdu::ServerSetErrorInfo(pdu) => pdu.encode(dst),
455            ShareDataPdu::Input(pdu) => pdu.encode(dst),
456            ShareDataPdu::ShutdownRequest | ShareDataPdu::ShutdownDenied => Ok(()),
457            ShareDataPdu::SuppressOutput(pdu) => pdu.encode(dst),
458            ShareDataPdu::RefreshRectangle(pdu) => pdu.encode(dst),
459            _ => Err(other_err!("Encoding not implemented")),
460        }
461    }
462
463    fn name(&self) -> &'static str {
464        Self::NAME
465    }
466
467    fn size(&self) -> usize {
468        match self {
469            ShareDataPdu::Synchronize(pdu) => pdu.size(),
470            ShareDataPdu::Control(pdu) => pdu.size(),
471            ShareDataPdu::FontList(pdu) | ShareDataPdu::FontMap(pdu) => pdu.size(),
472            ShareDataPdu::MonitorLayout(pdu) => pdu.size(),
473            ShareDataPdu::SaveSessionInfo(pdu) => pdu.size(),
474            ShareDataPdu::FrameAcknowledge(pdu) => pdu.size(),
475            ShareDataPdu::ServerSetErrorInfo(pdu) => pdu.size(),
476            ShareDataPdu::Input(pdu) => pdu.size(),
477            ShareDataPdu::ShutdownRequest | ShareDataPdu::ShutdownDenied => 0,
478            ShareDataPdu::SuppressOutput(pdu) => pdu.size(),
479            ShareDataPdu::RefreshRectangle(pdu) => pdu.size(),
480            ShareDataPdu::Update(buffer)
481            | ShareDataPdu::Pointer(buffer)
482            | ShareDataPdu::PlaySound(buffer)
483            | ShareDataPdu::SetKeyboardIndicators(buffer)
484            | ShareDataPdu::BitmapCachePersistentList(buffer)
485            | ShareDataPdu::BitmapCacheErrorPdu(buffer)
486            | ShareDataPdu::SetKeyboardImeStatus(buffer)
487            | ShareDataPdu::OffscreenCacheErrorPdu(buffer)
488            | ShareDataPdu::DrawNineGridErrorPdu(buffer)
489            | ShareDataPdu::DrawGdiPusErrorPdu(buffer)
490            | ShareDataPdu::ArcStatusPdu(buffer)
491            | ShareDataPdu::StatusInfoPdu(buffer) => buffer.len(),
492        }
493    }
494}
495
496bitflags! {
497    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
498    pub struct BasicSecurityHeaderFlags: u16 {
499        const EXCHANGE_PKT = 0x0001;
500        const TRANSPORT_REQ = 0x0002;
501        const TRANSPORT_RSP = 0x0004;
502        const ENCRYPT = 0x0008;
503        const RESET_SEQNO = 0x0010;
504        const IGNORE_SEQNO = 0x0020;
505        const INFO_PKT = 0x0040;
506        const LICENSE_PKT = 0x0080;
507        const LICENSE_ENCRYPT_CS = 0x0100;
508        const LICENSE_ENCRYPT_SC = 0x0200;
509        const REDIRECTION_PKT = 0x0400;
510        const SECURE_CHECKSUM = 0x0800;
511        const AUTODETECT_REQ = 0x1000;
512        const AUTODETECT_RSP = 0x2000;
513        const HEARTBEAT = 0x4000;
514        const FLAGSHI_VALID = 0x8000;
515    }
516}
517
518#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
519pub enum StreamPriority {
520    Undefined = 0,
521    Low = 1,
522    Medium = 2,
523    High = 4,
524}
525
526#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
527pub enum ShareControlPduType {
528    DemandActivePdu = 0x1,
529    ConfirmActivePdu = 0x3,
530    DeactivateAllPdu = 0x6,
531    DataPdu = 0x7,
532    ServerRedirect = 0xa,
533}
534
535#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
536#[repr(u8)]
537pub enum ShareDataPduType {
538    Update = 0x02,
539    Control = 0x14,
540    Pointer = 0x1b,
541    Input = 0x1c,
542    Synchronize = 0x1f,
543    RefreshRectangle = 0x21,
544    PlaySound = 0x22,
545    SuppressOutput = 0x23,
546    ShutdownRequest = 0x24,
547    ShutdownDenied = 0x25,
548    SaveSessionInfo = 0x26,
549    FontList = 0x27,
550    FontMap = 0x28,
551    SetKeyboardIndicators = 0x29,
552    BitmapCachePersistentList = 0x2b,
553    BitmapCacheErrorPdu = 0x2c,
554    SetKeyboardImeStatus = 0x2d,
555    OffscreenCacheErrorPdu = 0x2e,
556    SetErrorInfoPdu = 0x2f,
557    DrawNineGridErrorPdu = 0x30,
558    DrawGdiPusErrorPdu = 0x31,
559    ArcStatusPdu = 0x32,
560    StatusInfoPdu = 0x36,
561    MonitorLayoutPdu = 0x37,
562    FrameAcknowledgePdu = 0x38,
563}
564
565bitflags! {
566    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
567    pub struct CompressionFlags: u8 {
568        const COMPRESSED = 0x20;
569        const AT_FRONT = 0x40;
570        const FLUSHED = 0x80;
571    }
572}
573
574/// 2.2.3.1 Server Deactivate All PDU
575///
576/// [2.2.3.1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/8a29971a-df3c-48da-add2-8ed9a05edc89
577#[derive(Debug, Clone, PartialEq, Eq)]
578pub struct ServerDeactivateAll;
579
580impl ServerDeactivateAll {
581    const FIXED_PART_SIZE: usize = 2 /* length_source_descriptor */ + 1 /* source_descriptor */;
582}
583
584impl Decode<'_> for ServerDeactivateAll {
585    fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
586        ensure_fixed_part_size!(in: src);
587        let length_source_descriptor = src.read_u16();
588        ensure_size!(in: src, size: length_source_descriptor.into());
589        let _ = src.read_slice(length_source_descriptor.into());
590        Ok(Self)
591    }
592}
593
594impl Encode for ServerDeactivateAll {
595    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
596        ensure_fixed_part_size!(in: dst);
597        // A 16-bit, unsigned integer. The size in bytes of the sourceDescriptor field.
598        dst.write_u16(1);
599        // Variable number of bytes. The source descriptor. This field SHOULD be set to 0x00.
600        dst.write_u8(0);
601        Ok(())
602    }
603
604    fn name(&self) -> &'static str {
605        "Server Deactivate All"
606    }
607
608    fn size(&self) -> usize {
609        Self::FIXED_PART_SIZE
610    }
611}