1use core::fmt::{self, Display};
2
3use ironrdp_core::{
4 ensure_size, invalid_field_err, unsupported_value_err, Decode, DecodeError, DecodeResult, Encode, EncodeResult,
5 ReadCursor, WriteCursor,
6};
7use ironrdp_svc::SvcEncode;
8
9use self::efs::{
10 ClientDeviceListAnnounce, ClientDeviceListRemove, ClientDriveQueryDirectoryResponse,
11 ClientDriveQueryInformationResponse, ClientDriveQueryVolumeInformationResponse, ClientDriveSetInformationResponse,
12 ClientNameRequest, CoreCapability, CoreCapabilityKind, DeviceCloseResponse, DeviceControlResponse,
13 DeviceCreateResponse, DeviceIoRequest, DeviceReadResponse, DeviceWriteResponse, ServerDeviceAnnounceResponse,
14 VersionAndIdPdu, VersionAndIdPduKind,
15};
16
17pub mod efs;
18pub mod esc;
19
20pub enum RdpdrPdu {
22 VersionAndIdPdu(VersionAndIdPdu),
23 ClientNameRequest(ClientNameRequest),
24 CoreCapability(CoreCapability),
25 ClientDeviceListAnnounce(ClientDeviceListAnnounce),
26 ClientDeviceListRemove(ClientDeviceListRemove),
27 ServerDeviceAnnounceResponse(ServerDeviceAnnounceResponse),
28 DeviceIoRequest(DeviceIoRequest),
29 DeviceControlResponse(DeviceControlResponse),
30 DeviceCreateResponse(DeviceCreateResponse),
31 ClientDriveQueryInformationResponse(ClientDriveQueryInformationResponse),
32 DeviceCloseResponse(DeviceCloseResponse),
33 ClientDriveQueryDirectoryResponse(ClientDriveQueryDirectoryResponse),
34 ClientDriveQueryVolumeInformationResponse(ClientDriveQueryVolumeInformationResponse),
35 DeviceReadResponse(DeviceReadResponse),
36 DeviceWriteResponse(DeviceWriteResponse),
37 ClientDriveSetInformationResponse(ClientDriveSetInformationResponse),
38 UserLoggedon,
39 EmptyResponse,
40}
41
42impl RdpdrPdu {
43 fn header(&self) -> SharedHeader {
45 match self {
46 RdpdrPdu::VersionAndIdPdu(pdu) => match pdu.kind {
47 VersionAndIdPduKind::ClientAnnounceReply => SharedHeader {
48 component: Component::RdpdrCtypCore,
49 packet_id: PacketId::CoreClientidConfirm,
50 },
51 VersionAndIdPduKind::ServerAnnounceRequest => SharedHeader {
52 component: Component::RdpdrCtypCore,
53 packet_id: PacketId::CoreServerAnnounce,
54 },
55 VersionAndIdPduKind::ServerClientIdConfirm => SharedHeader {
56 component: Component::RdpdrCtypCore,
57 packet_id: PacketId::CoreClientidConfirm,
58 },
59 },
60 RdpdrPdu::ClientNameRequest(_) => SharedHeader {
61 component: Component::RdpdrCtypCore,
62 packet_id: PacketId::CoreClientName,
63 },
64 RdpdrPdu::CoreCapability(pdu) => match pdu.kind {
65 CoreCapabilityKind::ServerCoreCapabilityRequest => SharedHeader {
66 component: Component::RdpdrCtypCore,
67 packet_id: PacketId::CoreServerCapability,
68 },
69 CoreCapabilityKind::ClientCoreCapabilityResponse => SharedHeader {
70 component: Component::RdpdrCtypCore,
71 packet_id: PacketId::CoreClientCapability,
72 },
73 },
74 RdpdrPdu::ClientDeviceListAnnounce(_) => SharedHeader {
75 component: Component::RdpdrCtypCore,
76 packet_id: PacketId::CoreDevicelistAnnounce,
77 },
78 RdpdrPdu::ClientDeviceListRemove(_) => SharedHeader {
79 component: Component::RdpdrCtypCore,
80 packet_id: PacketId::CoreDevicelistRemove,
81 },
82 RdpdrPdu::ServerDeviceAnnounceResponse(_) => SharedHeader {
83 component: Component::RdpdrCtypCore,
84 packet_id: PacketId::CoreDeviceReply,
85 },
86 RdpdrPdu::DeviceIoRequest(_) => SharedHeader {
87 component: Component::RdpdrCtypCore,
88 packet_id: PacketId::CoreDeviceIoRequest,
89 },
90 RdpdrPdu::DeviceControlResponse(_)
91 | RdpdrPdu::DeviceCreateResponse(_)
92 | RdpdrPdu::ClientDriveQueryInformationResponse(_)
93 | RdpdrPdu::DeviceCloseResponse(_)
94 | RdpdrPdu::ClientDriveQueryDirectoryResponse(_)
95 | RdpdrPdu::ClientDriveQueryVolumeInformationResponse(_)
96 | RdpdrPdu::DeviceReadResponse(_)
97 | RdpdrPdu::DeviceWriteResponse(_)
98 | RdpdrPdu::ClientDriveSetInformationResponse(_)
99 | RdpdrPdu::EmptyResponse => SharedHeader {
100 component: Component::RdpdrCtypCore,
101 packet_id: PacketId::CoreDeviceIoCompletion,
102 },
103 RdpdrPdu::UserLoggedon => SharedHeader {
104 component: Component::RdpdrCtypCore,
105 packet_id: PacketId::CoreUserLoggedon,
106 },
107 }
108 }
109}
110
111impl Decode<'_> for RdpdrPdu {
112 fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
113 let header = SharedHeader::decode(src)?;
114 match header.packet_id {
115 PacketId::CoreServerAnnounce => Ok(RdpdrPdu::VersionAndIdPdu(VersionAndIdPdu::decode(header, src)?)),
116 PacketId::CoreServerCapability => Ok(RdpdrPdu::CoreCapability(CoreCapability::decode(header, src)?)),
117 PacketId::CoreClientidConfirm => Ok(RdpdrPdu::VersionAndIdPdu(VersionAndIdPdu::decode(header, src)?)),
118 PacketId::CoreDeviceReply => Ok(RdpdrPdu::ServerDeviceAnnounceResponse(
119 ServerDeviceAnnounceResponse::decode(src)?,
120 )),
121 PacketId::CoreDeviceIoRequest => Ok(RdpdrPdu::DeviceIoRequest(DeviceIoRequest::decode(src)?)),
122 PacketId::CoreUserLoggedon => Ok(RdpdrPdu::UserLoggedon),
123 _ => Err(unsupported_value_err!(
124 "RdpdrPdu",
125 "PacketId",
126 header.packet_id.to_string()
127 )),
128 }
129 }
130}
131
132impl Encode for RdpdrPdu {
133 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
134 self.header().encode(dst)?;
135
136 match self {
137 RdpdrPdu::VersionAndIdPdu(pdu) => pdu.encode(dst),
138 RdpdrPdu::ClientNameRequest(pdu) => pdu.encode(dst),
139 RdpdrPdu::CoreCapability(pdu) => pdu.encode(dst),
140 RdpdrPdu::ClientDeviceListAnnounce(pdu) => pdu.encode(dst),
141 RdpdrPdu::ClientDeviceListRemove(pdu) => pdu.encode(dst),
142 RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.encode(dst),
143 RdpdrPdu::DeviceIoRequest(pdu) => pdu.encode(dst),
144 RdpdrPdu::DeviceControlResponse(pdu) => pdu.encode(dst),
145 RdpdrPdu::DeviceCreateResponse(pdu) => pdu.encode(dst),
146 RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.encode(dst),
147 RdpdrPdu::DeviceCloseResponse(pdu) => pdu.encode(dst),
148 RdpdrPdu::ClientDriveQueryDirectoryResponse(pdu) => pdu.encode(dst),
149 RdpdrPdu::ClientDriveQueryVolumeInformationResponse(pdu) => pdu.encode(dst),
150 RdpdrPdu::DeviceReadResponse(pdu) => pdu.encode(dst),
151 RdpdrPdu::DeviceWriteResponse(pdu) => pdu.encode(dst),
152 RdpdrPdu::ClientDriveSetInformationResponse(pdu) => pdu.encode(dst),
153 RdpdrPdu::UserLoggedon => Ok(()),
154 RdpdrPdu::EmptyResponse => {
155 dst.write_u32(0);
157 Ok(())
158 }
159 }
160 }
161
162 fn name(&self) -> &'static str {
163 match self {
164 RdpdrPdu::VersionAndIdPdu(pdu) => pdu.name(),
165 RdpdrPdu::ClientNameRequest(pdu) => pdu.name(),
166 RdpdrPdu::CoreCapability(pdu) => pdu.name(),
167 RdpdrPdu::ClientDeviceListAnnounce(pdu) => pdu.name(),
168 RdpdrPdu::ClientDeviceListRemove(pdu) => pdu.name(),
169 RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.name(),
170 RdpdrPdu::DeviceIoRequest(pdu) => pdu.name(),
171 RdpdrPdu::DeviceControlResponse(pdu) => pdu.name(),
172 RdpdrPdu::DeviceCreateResponse(pdu) => pdu.name(),
173 RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.name(),
174 RdpdrPdu::DeviceCloseResponse(pdu) => pdu.name(),
175 RdpdrPdu::ClientDriveQueryDirectoryResponse(pdu) => pdu.name(),
176 RdpdrPdu::ClientDriveQueryVolumeInformationResponse(pdu) => pdu.name(),
177 RdpdrPdu::DeviceReadResponse(pdu) => pdu.name(),
178 RdpdrPdu::DeviceWriteResponse(pdu) => pdu.name(),
179 RdpdrPdu::ClientDriveSetInformationResponse(pdu) => pdu.name(),
180 RdpdrPdu::UserLoggedon => "UserLoggedon",
181 RdpdrPdu::EmptyResponse => "EmptyResponse",
182 }
183 }
184
185 fn size(&self) -> usize {
186 SharedHeader::SIZE
187 + match self {
188 RdpdrPdu::VersionAndIdPdu(pdu) => pdu.size(),
189 RdpdrPdu::ClientNameRequest(pdu) => pdu.size(),
190 RdpdrPdu::CoreCapability(pdu) => pdu.size(),
191 RdpdrPdu::ClientDeviceListAnnounce(pdu) => pdu.size(),
192 RdpdrPdu::ClientDeviceListRemove(pdu) => pdu.size(),
193 RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.size(),
194 RdpdrPdu::DeviceIoRequest(pdu) => pdu.size(),
195 RdpdrPdu::DeviceControlResponse(pdu) => pdu.size(),
196 RdpdrPdu::DeviceCreateResponse(pdu) => pdu.size(),
197 RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.size(),
198 RdpdrPdu::DeviceCloseResponse(pdu) => pdu.size(),
199 RdpdrPdu::ClientDriveQueryDirectoryResponse(pdu) => pdu.size(),
200 RdpdrPdu::ClientDriveQueryVolumeInformationResponse(pdu) => pdu.size(),
201 RdpdrPdu::DeviceReadResponse(pdu) => pdu.size(),
202 RdpdrPdu::DeviceWriteResponse(pdu) => pdu.size(),
203 RdpdrPdu::ClientDriveSetInformationResponse(pdu) => pdu.size(),
204 RdpdrPdu::UserLoggedon => 0,
205 RdpdrPdu::EmptyResponse => size_of::<u32>(),
206 }
207 }
208}
209
210impl SvcEncode for RdpdrPdu {}
211
212impl fmt::Debug for RdpdrPdu {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 match self {
215 Self::VersionAndIdPdu(it) => {
216 write!(f, "RdpdrPdu({it:?})")
217 }
218 Self::ClientNameRequest(it) => {
219 write!(f, "RdpdrPdu({it:?})")
220 }
221 Self::CoreCapability(it) => {
222 write!(f, "RdpdrPdu({it:?})")
223 }
224 Self::ClientDeviceListAnnounce(it) => {
225 write!(f, "RdpdrPdu({it:?})")
226 }
227 Self::ClientDeviceListRemove(it) => {
228 write!(f, "RdpdrPdu({it:?})")
229 }
230 Self::ServerDeviceAnnounceResponse(it) => {
231 write!(f, "RdpdrPdu({it:?})")
232 }
233 Self::DeviceIoRequest(it) => {
234 write!(f, "RdpdrPdu({it:?})")
235 }
236 Self::DeviceControlResponse(it) => {
237 write!(f, "RdpdrPdu({it:?})")
238 }
239 Self::DeviceCreateResponse(it) => {
240 write!(f, "RdpdrPdu({it:?})")
241 }
242 Self::ClientDriveQueryInformationResponse(it) => {
243 write!(f, "RdpdrPdu({it:?})")
244 }
245 Self::DeviceCloseResponse(it) => {
246 write!(f, "RdpdrPdu({it:?})")
247 }
248 Self::ClientDriveQueryDirectoryResponse(it) => {
249 write!(f, "RdpdrPdu({it:?})")
250 }
251 Self::ClientDriveQueryVolumeInformationResponse(it) => {
252 write!(f, "RdpdrPdu({it:?})")
253 }
254 Self::DeviceReadResponse(it) => {
255 write!(f, "RdpdrPdu({it:?})")
256 }
257 Self::DeviceWriteResponse(it) => {
258 write!(f, "RdpdrPdu({it:?})")
259 }
260 Self::ClientDriveSetInformationResponse(it) => {
261 write!(f, "RdpdrPdu({it:?})")
262 }
263 Self::UserLoggedon => {
264 write!(f, "RdpdrPdu(UserLoggedon)")
265 }
266 Self::EmptyResponse => {
267 write!(f, "RdpdrPdu(EmptyResponse)")
268 }
269 }
270 }
271}
272
273impl From<DeviceControlResponse> for RdpdrPdu {
274 fn from(value: DeviceControlResponse) -> Self {
275 Self::DeviceControlResponse(value)
276 }
277}
278
279impl From<DeviceCreateResponse> for RdpdrPdu {
280 fn from(value: DeviceCreateResponse) -> Self {
281 Self::DeviceCreateResponse(value)
282 }
283}
284
285impl From<ClientDriveQueryInformationResponse> for RdpdrPdu {
286 fn from(value: ClientDriveQueryInformationResponse) -> Self {
287 Self::ClientDriveQueryInformationResponse(value)
288 }
289}
290
291impl From<DeviceCloseResponse> for RdpdrPdu {
292 fn from(value: DeviceCloseResponse) -> Self {
293 Self::DeviceCloseResponse(value)
294 }
295}
296
297impl From<ClientDriveQueryDirectoryResponse> for RdpdrPdu {
298 fn from(value: ClientDriveQueryDirectoryResponse) -> Self {
299 Self::ClientDriveQueryDirectoryResponse(value)
300 }
301}
302
303impl From<ClientDriveQueryVolumeInformationResponse> for RdpdrPdu {
304 fn from(value: ClientDriveQueryVolumeInformationResponse) -> Self {
305 Self::ClientDriveQueryVolumeInformationResponse(value)
306 }
307}
308
309impl From<DeviceReadResponse> for RdpdrPdu {
310 fn from(value: DeviceReadResponse) -> Self {
311 Self::DeviceReadResponse(value)
312 }
313}
314
315impl From<DeviceWriteResponse> for RdpdrPdu {
316 fn from(value: DeviceWriteResponse) -> Self {
317 Self::DeviceWriteResponse(value)
318 }
319}
320
321impl From<ClientDriveSetInformationResponse> for RdpdrPdu {
322 fn from(value: ClientDriveSetInformationResponse) -> Self {
323 Self::ClientDriveSetInformationResponse(value)
324 }
325}
326
327#[derive(Debug)]
331pub struct SharedHeader {
332 pub component: Component,
333 pub packet_id: PacketId,
334}
335
336impl SharedHeader {
337 const SIZE: usize = size_of::<u16>() * 2;
338
339 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
340 ensure_size!(in: dst, size: Self::SIZE);
341 dst.write_u16(self.component.into());
342 dst.write_u16(self.packet_id.into());
343 Ok(())
344 }
345
346 pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
347 ensure_size!(in: src, size: Self::SIZE);
348 Ok(Self {
349 component: src.read_u16().try_into()?,
350 packet_id: src.read_u16().try_into()?,
351 })
352 }
353}
354
355#[derive(Debug, Clone, Copy)]
356#[repr(u16)]
357pub enum Component {
358 RdpdrCtypCore = 0x4472,
360 RdpdrCtypPrn = 0x5052,
362}
363
364impl TryFrom<u16> for Component {
365 type Error = DecodeError;
366
367 fn try_from(value: u16) -> Result<Self, Self::Error> {
368 match value {
369 0x4472 => Ok(Component::RdpdrCtypCore),
370 0x5052 => Ok(Component::RdpdrCtypPrn),
371 _ => Err(invalid_field_err!("try_from", "Component", "invalid value")),
372 }
373 }
374}
375
376impl From<Component> for u16 {
377 fn from(component: Component) -> Self {
378 component as u16
379 }
380}
381
382#[derive(Debug, Clone, Copy)]
383#[repr(u16)]
384pub enum PacketId {
385 CoreServerAnnounce = 0x496E,
387 CoreClientidConfirm = 0x4343,
389 CoreClientName = 0x434E,
391 CoreDevicelistAnnounce = 0x4441,
393 CoreDeviceReply = 0x6472,
395 CoreDeviceIoRequest = 0x4952,
397 CoreDeviceIoCompletion = 0x4943,
399 CoreServerCapability = 0x5350,
401 CoreClientCapability = 0x4350,
403 CoreDevicelistRemove = 0x444D,
405 PrnCacheData = 0x5043,
407 CoreUserLoggedon = 0x554C,
409 PrnUsingXps = 0x5543,
411}
412
413impl TryFrom<u16> for PacketId {
414 type Error = DecodeError;
415
416 fn try_from(value: u16) -> Result<Self, Self::Error> {
417 match value {
418 0x496E => Ok(PacketId::CoreServerAnnounce),
419 0x4343 => Ok(PacketId::CoreClientidConfirm),
420 0x434E => Ok(PacketId::CoreClientName),
421 0x4441 => Ok(PacketId::CoreDevicelistAnnounce),
422 0x6472 => Ok(PacketId::CoreDeviceReply),
423 0x4952 => Ok(PacketId::CoreDeviceIoRequest),
424 0x4943 => Ok(PacketId::CoreDeviceIoCompletion),
425 0x5350 => Ok(PacketId::CoreServerCapability),
426 0x4350 => Ok(PacketId::CoreClientCapability),
427 0x444D => Ok(PacketId::CoreDevicelistRemove),
428 0x5043 => Ok(PacketId::PrnCacheData),
429 0x554C => Ok(PacketId::CoreUserLoggedon),
430 0x5543 => Ok(PacketId::PrnUsingXps),
431 _ => Err(invalid_field_err!("try_from", "PacketId", "invalid value")),
432 }
433 }
434}
435
436impl Display for PacketId {
437 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438 match self {
439 PacketId::CoreServerAnnounce => write!(f, "PAKID_CORE_SERVER_ANNOUNCE"),
440 PacketId::CoreClientidConfirm => write!(f, "PAKID_CORE_CLIENTID_CONFIRM"),
441 PacketId::CoreClientName => write!(f, "PAKID_CORE_CLIENT_NAME"),
442 PacketId::CoreDevicelistAnnounce => write!(f, "PAKID_CORE_DEVICELIST_ANNOUNCE"),
443 PacketId::CoreDeviceReply => write!(f, "PAKID_CORE_DEVICE_REPLY"),
444 PacketId::CoreDeviceIoRequest => write!(f, "PAKID_CORE_DEVICE_IOREQUEST"),
445 PacketId::CoreDeviceIoCompletion => write!(f, "PAKID_CORE_DEVICE_IOCOMPLETION"),
446 PacketId::CoreServerCapability => write!(f, "PAKID_CORE_SERVER_CAPABILITY"),
447 PacketId::CoreClientCapability => write!(f, "PAKID_CORE_CLIENT_CAPABILITY"),
448 PacketId::CoreDevicelistRemove => write!(f, "PAKID_CORE_DEVICELIST_REMOVE"),
449 PacketId::PrnCacheData => write!(f, "PAKID_PRN_CACHE_DATA"),
450 PacketId::CoreUserLoggedon => write!(f, "PAKID_CORE_USER_LOGGEDON"),
451 PacketId::PrnUsingXps => write!(f, "PAKID_PRN_USING_XPS"),
452 }
453 }
454}
455
456impl From<PacketId> for u16 {
457 fn from(packet_id: PacketId) -> Self {
458 packet_id as u16
459 }
460}