ironrdp_cliprdr/pdu/format_data/
mod.rs1mod file_list;
2mod metafile;
3mod palette;
4
5pub use self::file_list::*;
6pub use self::metafile::*;
7pub use self::palette::*;
8
9#[rustfmt::skip]
10use std::borrow::Cow;
11
12use ironrdp_core::{
13 cast_int, ensure_fixed_part_size, ensure_size, Decode, DecodeResult, Encode, EncodeResult, IntoOwned, ReadCursor,
14 WriteCursor,
15};
16use ironrdp_pdu::impl_pdu_borrowing;
17use ironrdp_pdu::utils::{read_string_from_cursor, to_utf16_bytes, CharacterSet};
18
19use super::ClipboardFormatId;
20use crate::pdu::{ClipboardPduFlags, PartialHeader};
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct FormatDataResponse<'a> {
25 is_error: bool,
26 data: Cow<'a, [u8]>,
27}
28
29impl_pdu_borrowing!(FormatDataResponse<'_>, OwnedFormatDataResponse);
30
31impl IntoOwned for FormatDataResponse<'_> {
32 type Owned = OwnedFormatDataResponse;
33
34 fn into_owned(self) -> Self::Owned {
35 OwnedFormatDataResponse {
36 is_error: self.is_error,
37 data: Cow::Owned(self.data.into_owned()),
38 }
39 }
40}
41
42impl<'a> FormatDataResponse<'a> {
43 const NAME: &'static str = "CLIPRDR_FORMAT_DATA_RESPONSE";
44
45 pub fn new_data(data: impl Into<Cow<'a, [u8]>>) -> Self {
47 Self {
48 is_error: false,
49 data: data.into(),
50 }
51 }
52
53 pub fn new_error() -> Self {
55 Self {
56 is_error: true,
57 data: Cow::Borrowed(&[]),
58 }
59 }
60
61 pub fn data(&self) -> &[u8] {
62 &self.data
63 }
64
65 pub fn is_error(&self) -> bool {
66 self.is_error
67 }
68
69 pub fn new_palette(palette: &ClipboardPalette) -> EncodeResult<Self> {
73 let mut data = vec![0u8; palette.size()];
74
75 let mut cursor = WriteCursor::new(&mut data);
76 palette.encode(&mut cursor)?;
77
78 Ok(Self {
79 is_error: false,
80 data: data.into(),
81 })
82 }
83
84 pub fn new_metafile(metafile: &PackedMetafile<'_>) -> EncodeResult<Self> {
88 let mut data = vec![0u8; metafile.size()];
89
90 let mut cursor = WriteCursor::new(&mut data);
91 metafile.encode(&mut cursor)?;
92
93 Ok(Self {
94 is_error: false,
95 data: data.into(),
96 })
97 }
98
99 pub fn new_file_list(list: &PackedFileList) -> EncodeResult<Self> {
103 let mut data = vec![0u8; list.size()];
104
105 let mut cursor = WriteCursor::new(&mut data);
106 list.encode(&mut cursor)?;
107
108 Ok(Self {
109 is_error: false,
110 data: data.into(),
111 })
112 }
113
114 pub fn new_unicode_string(value: &str) -> Self {
116 let mut encoded = to_utf16_bytes(value);
117 encoded.push(b'\0');
118 encoded.push(b'\0');
119
120 Self {
121 is_error: false,
122 data: encoded.into(),
123 }
124 }
125
126 pub fn new_string(value: &str) -> Self {
128 let mut encoded = value.as_bytes().to_vec();
129 encoded.push(b'\0');
130
131 Self {
132 is_error: false,
133 data: encoded.into(),
134 }
135 }
136
137 pub fn to_palette(&self) -> DecodeResult<ClipboardPalette> {
139 let mut cursor = ReadCursor::new(&self.data);
140 ClipboardPalette::decode(&mut cursor)
141 }
142
143 pub fn to_metafile(&self) -> DecodeResult<PackedMetafile<'_>> {
145 let mut cursor = ReadCursor::new(&self.data);
146 PackedMetafile::decode(&mut cursor)
147 }
148
149 pub fn to_file_list(&self) -> DecodeResult<PackedFileList> {
151 let mut cursor = ReadCursor::new(&self.data);
152 PackedFileList::decode(&mut cursor)
153 }
154
155 pub fn to_string(&self) -> DecodeResult<String> {
157 let mut cursor = ReadCursor::new(&self.data);
158 read_string_from_cursor(&mut cursor, CharacterSet::Ansi, true)
159 }
160
161 pub fn to_unicode_string(&self) -> DecodeResult<String> {
163 let mut cursor = ReadCursor::new(&self.data);
164 read_string_from_cursor(&mut cursor, CharacterSet::Unicode, true)
165 }
166
167 pub fn into_data(self) -> Cow<'a, [u8]> {
168 self.data
169 }
170}
171
172impl Encode for FormatDataResponse<'_> {
173 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
174 let flags = if self.is_error {
175 ClipboardPduFlags::RESPONSE_FAIL
176 } else {
177 ClipboardPduFlags::RESPONSE_OK
178 };
179
180 let header = PartialHeader::new_with_flags(cast_int!("dataLen", self.data.len())?, flags);
181 header.encode(dst)?;
182
183 ensure_size!(in: dst, size: self.data.len());
184 dst.write_slice(&self.data);
185
186 Ok(())
187 }
188
189 fn name(&self) -> &'static str {
190 Self::NAME
191 }
192
193 fn size(&self) -> usize {
194 PartialHeader::SIZE + self.data.len()
195 }
196}
197
198impl<'de> Decode<'de> for FormatDataResponse<'de> {
199 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
200 let header = PartialHeader::decode(src)?;
201
202 let is_error = header.message_flags.contains(ClipboardPduFlags::RESPONSE_FAIL);
203
204 ensure_size!(in: src, size: header.data_length());
205 let data = src.read_slice(header.data_length());
206
207 Ok(Self {
208 is_error,
209 data: Cow::Borrowed(data),
210 })
211 }
212}
213
214#[derive(Debug, Clone, PartialEq, Eq)]
216pub struct FormatDataRequest {
217 pub format: ClipboardFormatId,
218}
219
220impl FormatDataRequest {
221 const NAME: &'static str = "CLIPRDR_FORMAT_DATA_REQUEST";
222 const FIXED_PART_SIZE: usize = 4 ;
223}
224
225impl Encode for FormatDataRequest {
226 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
227 let header = PartialHeader::new(cast_int!("dataLen", Self::FIXED_PART_SIZE)?);
228 header.encode(dst)?;
229
230 ensure_fixed_part_size!(in: dst);
231 dst.write_u32(self.format.value());
232
233 Ok(())
234 }
235
236 fn name(&self) -> &'static str {
237 Self::NAME
238 }
239
240 fn size(&self) -> usize {
241 PartialHeader::SIZE + Self::FIXED_PART_SIZE
242 }
243}
244
245impl<'de> Decode<'de> for FormatDataRequest {
246 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
247 let _header = PartialHeader::decode(src)?;
248
249 ensure_fixed_part_size!(in: src);
250 let format = ClipboardFormatId::new(src.read_u32());
251
252 Ok(Self { format })
253 }
254}