ironrdp_pdu/rdp/vc/dvc/
gfx.rs

1mod graphics_messages;
2
3pub use graphics_messages::{
4    Avc420BitmapStream, Avc444BitmapStream, CacheImportReplyPdu, CacheToSurfacePdu, CapabilitiesAdvertisePdu,
5    CapabilitiesConfirmPdu, CapabilitiesV103Flags, CapabilitiesV104Flags, CapabilitiesV107Flags, CapabilitiesV10Flags,
6    CapabilitiesV81Flags, CapabilitiesV8Flags, CapabilitySet, Codec1Type, Codec2Type, Color, CreateSurfacePdu,
7    DeleteEncodingContextPdu, DeleteSurfacePdu, Encoding, EndFramePdu, EvictCacheEntryPdu, FrameAcknowledgePdu,
8    MapSurfaceToOutputPdu, MapSurfaceToScaledOutputPdu, MapSurfaceToScaledWindowPdu, PixelFormat, Point, QuantQuality,
9    QueueDepth, ResetGraphicsPdu, SolidFillPdu, StartFramePdu, SurfaceToCachePdu, SurfaceToSurfacePdu, Timestamp,
10    WireToSurface1Pdu, WireToSurface2Pdu,
11};
12use ironrdp_core::{
13    cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
14    ReadCursor, WriteCursor,
15};
16use num_derive::{FromPrimitive, ToPrimitive};
17use num_traits::{FromPrimitive as _, ToPrimitive as _};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum ServerPdu {
21    WireToSurface1(WireToSurface1Pdu),
22    WireToSurface2(WireToSurface2Pdu),
23    DeleteEncodingContext(DeleteEncodingContextPdu),
24    SolidFill(SolidFillPdu),
25    SurfaceToSurface(SurfaceToSurfacePdu),
26    SurfaceToCache(SurfaceToCachePdu),
27    CacheToSurface(CacheToSurfacePdu),
28    EvictCacheEntry(EvictCacheEntryPdu),
29    CreateSurface(CreateSurfacePdu),
30    DeleteSurface(DeleteSurfacePdu),
31    StartFrame(StartFramePdu),
32    EndFrame(EndFramePdu),
33    ResetGraphics(ResetGraphicsPdu),
34    MapSurfaceToOutput(MapSurfaceToOutputPdu),
35    CapabilitiesConfirm(CapabilitiesConfirmPdu),
36    CacheImportReply(CacheImportReplyPdu),
37    MapSurfaceToScaledOutput(MapSurfaceToScaledOutputPdu),
38    MapSurfaceToScaledWindow(MapSurfaceToScaledWindowPdu),
39}
40
41const RDP_GFX_HEADER_SIZE: usize = 2 /* PduType */ + 2 /* flags */ + 4 /* bufferLen */;
42
43impl ServerPdu {
44    const NAME: &'static str = "GfxServerPdu";
45
46    const FIXED_PART_SIZE: usize = RDP_GFX_HEADER_SIZE;
47}
48
49impl Encode for ServerPdu {
50    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
51        ensure_size!(in: dst, size: self.size());
52
53        let buffer_length = self.size();
54
55        dst.write_u16(ServerPduType::from(self).to_u16().unwrap());
56        dst.write_u16(0); // flags
57        dst.write_u32(cast_length!("bufferLen", buffer_length)?);
58
59        match self {
60            ServerPdu::WireToSurface1(pdu) => pdu.encode(dst),
61            ServerPdu::WireToSurface2(pdu) => pdu.encode(dst),
62            ServerPdu::DeleteEncodingContext(pdu) => pdu.encode(dst),
63            ServerPdu::SolidFill(pdu) => pdu.encode(dst),
64            ServerPdu::SurfaceToSurface(pdu) => pdu.encode(dst),
65            ServerPdu::SurfaceToCache(pdu) => pdu.encode(dst),
66            ServerPdu::CacheToSurface(pdu) => pdu.encode(dst),
67            ServerPdu::CreateSurface(pdu) => pdu.encode(dst),
68            ServerPdu::DeleteSurface(pdu) => pdu.encode(dst),
69            ServerPdu::ResetGraphics(pdu) => pdu.encode(dst),
70            ServerPdu::MapSurfaceToOutput(pdu) => pdu.encode(dst),
71            ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.encode(dst),
72            ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.encode(dst),
73            ServerPdu::StartFrame(pdu) => pdu.encode(dst),
74            ServerPdu::EndFrame(pdu) => pdu.encode(dst),
75            ServerPdu::EvictCacheEntry(pdu) => pdu.encode(dst),
76            ServerPdu::CapabilitiesConfirm(pdu) => pdu.encode(dst),
77            ServerPdu::CacheImportReply(pdu) => pdu.encode(dst),
78        }
79    }
80
81    fn name(&self) -> &'static str {
82        Self::NAME
83    }
84
85    fn size(&self) -> usize {
86        Self::FIXED_PART_SIZE
87            + match self {
88                ServerPdu::WireToSurface1(pdu) => pdu.size(),
89                ServerPdu::WireToSurface2(pdu) => pdu.size(),
90                ServerPdu::DeleteEncodingContext(pdu) => pdu.size(),
91                ServerPdu::SolidFill(pdu) => pdu.size(),
92                ServerPdu::SurfaceToSurface(pdu) => pdu.size(),
93                ServerPdu::SurfaceToCache(pdu) => pdu.size(),
94                ServerPdu::CacheToSurface(pdu) => pdu.size(),
95                ServerPdu::CreateSurface(pdu) => pdu.size(),
96                ServerPdu::DeleteSurface(pdu) => pdu.size(),
97                ServerPdu::ResetGraphics(pdu) => pdu.size(),
98                ServerPdu::MapSurfaceToOutput(pdu) => pdu.size(),
99                ServerPdu::MapSurfaceToScaledOutput(pdu) => pdu.size(),
100                ServerPdu::MapSurfaceToScaledWindow(pdu) => pdu.size(),
101                ServerPdu::StartFrame(pdu) => pdu.size(),
102                ServerPdu::EndFrame(pdu) => pdu.size(),
103                ServerPdu::EvictCacheEntry(pdu) => pdu.size(),
104                ServerPdu::CapabilitiesConfirm(pdu) => pdu.size(),
105                ServerPdu::CacheImportReply(pdu) => pdu.size(),
106            }
107    }
108}
109
110impl<'a> Decode<'a> for ServerPdu {
111    fn decode(src: &mut ReadCursor<'a>) -> DecodeResult<Self> {
112        ensure_fixed_part_size!(in: src);
113
114        let pdu_type = ServerPduType::from_u16(src.read_u16())
115            .ok_or_else(|| invalid_field_err!("serverPduType", "invalid pdu type"))?;
116        let _flags = src.read_u16();
117        let pdu_length = cast_length!("pduLen", src.read_u32())?;
118
119        let (server_pdu, buffer_length) = {
120            let pdu = match pdu_type {
121                ServerPduType::DeleteEncodingContext => {
122                    ServerPdu::DeleteEncodingContext(DeleteEncodingContextPdu::decode(src)?)
123                }
124                ServerPduType::WireToSurface1 => ServerPdu::WireToSurface1(WireToSurface1Pdu::decode(src)?),
125                ServerPduType::WireToSurface2 => ServerPdu::WireToSurface2(WireToSurface2Pdu::decode(src)?),
126                ServerPduType::SolidFill => ServerPdu::SolidFill(SolidFillPdu::decode(src)?),
127                ServerPduType::SurfaceToSurface => ServerPdu::SurfaceToSurface(SurfaceToSurfacePdu::decode(src)?),
128                ServerPduType::SurfaceToCache => ServerPdu::SurfaceToCache(SurfaceToCachePdu::decode(src)?),
129                ServerPduType::CacheToSurface => ServerPdu::CacheToSurface(CacheToSurfacePdu::decode(src)?),
130                ServerPduType::EvictCacheEntry => ServerPdu::EvictCacheEntry(EvictCacheEntryPdu::decode(src)?),
131                ServerPduType::CreateSurface => ServerPdu::CreateSurface(CreateSurfacePdu::decode(src)?),
132                ServerPduType::DeleteSurface => ServerPdu::DeleteSurface(DeleteSurfacePdu::decode(src)?),
133                ServerPduType::StartFrame => ServerPdu::StartFrame(StartFramePdu::decode(src)?),
134                ServerPduType::EndFrame => ServerPdu::EndFrame(EndFramePdu::decode(src)?),
135                ServerPduType::ResetGraphics => ServerPdu::ResetGraphics(ResetGraphicsPdu::decode(src)?),
136                ServerPduType::MapSurfaceToOutput => ServerPdu::MapSurfaceToOutput(MapSurfaceToOutputPdu::decode(src)?),
137                ServerPduType::CapabilitiesConfirm => {
138                    ServerPdu::CapabilitiesConfirm(CapabilitiesConfirmPdu::decode(src)?)
139                }
140                ServerPduType::CacheImportReply => ServerPdu::CacheImportReply(CacheImportReplyPdu::decode(src)?),
141                ServerPduType::MapSurfaceToScaledOutput => {
142                    ServerPdu::MapSurfaceToScaledOutput(MapSurfaceToScaledOutputPdu::decode(src)?)
143                }
144                ServerPduType::MapSurfaceToScaledWindow => {
145                    ServerPdu::MapSurfaceToScaledWindow(MapSurfaceToScaledWindowPdu::decode(src)?)
146                }
147                _ => return Err(invalid_field_err!("pduType", "invalid pdu type")),
148            };
149            let buffer_length = pdu.size();
150
151            (pdu, buffer_length)
152        };
153
154        if buffer_length != pdu_length {
155            Err(invalid_field_err!("len", "invalid pdu length"))
156        } else {
157            Ok(server_pdu)
158        }
159    }
160}
161
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub enum ClientPdu {
164    FrameAcknowledge(FrameAcknowledgePdu),
165    CapabilitiesAdvertise(CapabilitiesAdvertisePdu),
166}
167
168impl ClientPdu {
169    const NAME: &'static str = "GfxClientPdu";
170
171    const FIXED_PART_SIZE: usize = RDP_GFX_HEADER_SIZE;
172}
173
174impl Encode for ClientPdu {
175    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
176        ensure_size!(in: dst, size: self.size());
177
178        dst.write_u16(ClientPduType::from(self).to_u16().unwrap());
179        dst.write_u16(0); // flags
180        dst.write_u32(cast_length!("bufferLen", self.size())?);
181
182        match self {
183            ClientPdu::FrameAcknowledge(pdu) => pdu.encode(dst),
184            ClientPdu::CapabilitiesAdvertise(pdu) => pdu.encode(dst),
185        }
186    }
187
188    fn name(&self) -> &'static str {
189        Self::NAME
190    }
191
192    fn size(&self) -> usize {
193        Self::FIXED_PART_SIZE
194            + match self {
195                ClientPdu::FrameAcknowledge(pdu) => pdu.size(),
196                ClientPdu::CapabilitiesAdvertise(pdu) => pdu.size(),
197            }
198    }
199}
200
201impl<'a> Decode<'a> for ClientPdu {
202    fn decode(src: &mut ReadCursor<'a>) -> DecodeResult<Self> {
203        let pdu_type = ClientPduType::from_u16(src.read_u16())
204            .ok_or_else(|| invalid_field_err!("clientPduType", "invalid pdu type"))?;
205        let _flags = src.read_u16();
206        let pdu_length = cast_length!("bufferLen", src.read_u32())?;
207
208        let client_pdu = match pdu_type {
209            ClientPduType::FrameAcknowledge => ClientPdu::FrameAcknowledge(FrameAcknowledgePdu::decode(src)?),
210            ClientPduType::CapabilitiesAdvertise => {
211                ClientPdu::CapabilitiesAdvertise(CapabilitiesAdvertisePdu::decode(src)?)
212            }
213            _ => return Err(invalid_field_err!("pduType", "invalid pdu type")),
214        };
215
216        if client_pdu.size() != pdu_length {
217            Err(invalid_field_err!("len", "invalid pdu length"))
218        } else {
219            Ok(client_pdu)
220        }
221    }
222}
223
224#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
225pub enum ClientPduType {
226    FrameAcknowledge = 0x0d,
227    CacheImportOffer = 0x10,
228    CapabilitiesAdvertise = 0x12,
229    QoeFrameAcknowledge = 0x16,
230}
231
232impl<'a> From<&'a ClientPdu> for ClientPduType {
233    fn from(c: &'a ClientPdu) -> Self {
234        match c {
235            ClientPdu::FrameAcknowledge(_) => Self::FrameAcknowledge,
236            ClientPdu::CapabilitiesAdvertise(_) => Self::CapabilitiesAdvertise,
237        }
238    }
239}
240
241#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
242pub enum ServerPduType {
243    WireToSurface1 = 0x01,
244    WireToSurface2 = 0x02,
245    DeleteEncodingContext = 0x03,
246    SolidFill = 0x04,
247    SurfaceToSurface = 0x05,
248    SurfaceToCache = 0x06,
249    CacheToSurface = 0x07,
250    EvictCacheEntry = 0x08,
251    CreateSurface = 0x09,
252    DeleteSurface = 0x0a,
253    StartFrame = 0x0b,
254    EndFrame = 0x0c,
255    ResetGraphics = 0x0e,
256    MapSurfaceToOutput = 0x0f,
257    CacheImportReply = 0x11,
258    CapabilitiesConfirm = 0x13,
259    MapSurfaceToWindow = 0x15,
260    MapSurfaceToScaledOutput = 0x17,
261    MapSurfaceToScaledWindow = 0x18,
262}
263
264impl<'a> From<&'a ServerPdu> for ServerPduType {
265    fn from(s: &'a ServerPdu) -> Self {
266        match s {
267            ServerPdu::WireToSurface1(_) => Self::WireToSurface1,
268            ServerPdu::WireToSurface2(_) => Self::WireToSurface2,
269            ServerPdu::DeleteEncodingContext(_) => Self::DeleteEncodingContext,
270            ServerPdu::SolidFill(_) => Self::SolidFill,
271            ServerPdu::SurfaceToSurface(_) => Self::SurfaceToSurface,
272            ServerPdu::SurfaceToCache(_) => Self::SurfaceToCache,
273            ServerPdu::CacheToSurface(_) => Self::CacheToSurface,
274            ServerPdu::EvictCacheEntry(_) => Self::EvictCacheEntry,
275            ServerPdu::CreateSurface(_) => Self::CreateSurface,
276            ServerPdu::DeleteSurface(_) => Self::DeleteSurface,
277            ServerPdu::StartFrame(_) => Self::StartFrame,
278            ServerPdu::EndFrame(_) => Self::EndFrame,
279            ServerPdu::ResetGraphics(_) => Self::ResetGraphics,
280            ServerPdu::MapSurfaceToOutput(_) => Self::MapSurfaceToOutput,
281            ServerPdu::MapSurfaceToScaledOutput(_) => Self::MapSurfaceToScaledOutput,
282            ServerPdu::MapSurfaceToScaledWindow(_) => Self::MapSurfaceToScaledWindow,
283            ServerPdu::CapabilitiesConfirm(_) => Self::CapabilitiesConfirm,
284            ServerPdu::CacheImportReply(_) => Self::CacheImportReply,
285        }
286    }
287}