FreeRDP
Loading...
Searching...
No Matches
cliprdr_format.c
1
23#include <freerdp/config.h>
24
25#include <winpr/crt.h>
26#include <winpr/print.h>
27#include <winpr/clipboard.h>
28
29#include <freerdp/types.h>
30#include <freerdp/freerdp.h>
31#include <freerdp/settings.h>
32#include <freerdp/constants.h>
33#include <freerdp/client/cliprdr.h>
34
35#include "cliprdr_main.h"
36#include "cliprdr_format.h"
37#include "../cliprdr_common.h"
38
39CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list, UINT32 mask,
40 UINT32 checkMask)
41{
42 const UINT32 maskData =
43 checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_REMOTE_TO_LOCAL);
44 const UINT32 maskFiles =
45 checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
46 WINPR_ASSERT(list);
47
48 CLIPRDR_FORMAT_LIST filtered = WINPR_C_ARRAY_INIT;
49 filtered.common.msgType = CB_FORMAT_LIST;
50 filtered.numFormats = list->numFormats;
51 if (filtered.numFormats > 0)
52 {
53 filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT));
54 if (!filtered.formats)
55 {
56 const CLIPRDR_FORMAT_LIST empty = WINPR_C_ARRAY_INIT;
57 return empty;
58 }
59 }
60
61 size_t wpos = 0;
62 if ((mask & checkMask) == checkMask)
63 {
64 for (size_t x = 0; x < list->numFormats; x++)
65 {
66 const CLIPRDR_FORMAT* format = &list->formats[x];
67 CLIPRDR_FORMAT* cur = &filtered.formats[x];
68 cur->formatId = format->formatId;
69 if (format->formatName)
70 cur->formatName = _strdup(format->formatName);
71 wpos++;
72 }
73 }
74 else if ((mask & maskFiles) != 0)
75 {
76 for (size_t x = 0; x < list->numFormats; x++)
77 {
78 const CLIPRDR_FORMAT* format = &list->formats[x];
79 CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
80
81 if (!format->formatName)
82 continue;
83 if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0 ||
84 strcmp(format->formatName, type_FileContents) == 0)
85 {
86 cur->formatId = format->formatId;
87 cur->formatName = _strdup(format->formatName);
88 wpos++;
89 }
90 }
91 }
92 else if ((mask & maskData) != 0)
93 {
94 for (size_t x = 0; x < list->numFormats; x++)
95 {
96 const CLIPRDR_FORMAT* format = &list->formats[x];
97 CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
98
99 if (!format->formatName ||
100 (strcmp(format->formatName, type_FileGroupDescriptorW) != 0 &&
101 strcmp(format->formatName, type_FileContents) != 0))
102 {
103 cur->formatId = format->formatId;
104 if (format->formatName)
105 cur->formatName = _strdup(format->formatName);
106 wpos++;
107 }
108 }
109 }
110 WINPR_ASSERT(wpos <= UINT32_MAX);
111 filtered.numFormats = (UINT32)wpos;
112 return filtered;
113}
114
120UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
121 UINT16 msgFlags)
122{
123 CLIPRDR_FORMAT_LIST formatList = WINPR_C_ARRAY_INIT;
124 CLIPRDR_FORMAT_LIST filteredFormatList = WINPR_C_ARRAY_INIT;
125 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
126 UINT error = CHANNEL_RC_OK;
127
128 formatList.common.msgType = CB_FORMAT_LIST;
129 formatList.common.msgFlags = msgFlags;
130 formatList.common.dataLen = dataLen;
131
132 if ((error =
133 cliprdr_read_format_list(cliprdr->log, s, &formatList, cliprdr->useLongFormatNames)))
134 goto error_out;
135
136 {
137 const UINT32 mask = freerdp_settings_get_uint32(context->rdpcontext->settings,
138 FreeRDP_ClipboardFeatureMask);
139 filteredFormatList = cliprdr_filter_format_list(
140 &formatList, mask, CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
141 }
142
143 if (filteredFormatList.numFormats == 0)
144 goto error_out;
145
146 {
147 const DWORD level = WLOG_DEBUG;
148 if (WLog_IsLevelActive(cliprdr->log, level))
149 {
150 WLog_Print(cliprdr->log, level, "ServerFormatList: numFormats: %" PRIu32 "",
151 formatList.numFormats);
152 for (size_t x = 0; x < formatList.numFormats; x++)
153 {
154 const CLIPRDR_FORMAT* format = &formatList.formats[x];
155 WLog_Print(cliprdr->log, level, "[%" PRIuz "]: id=0x%08" PRIx32 " [%s|%s]", x,
156 format->formatId, ClipboardGetFormatIdString(format->formatId),
157 format->formatName);
158 }
159
160 WLog_Print(cliprdr->log, level, "ServerFormatList [filtered]: numFormats: %" PRIu32 "",
161 filteredFormatList.numFormats);
162 for (size_t x = 0; x < filteredFormatList.numFormats; x++)
163 {
164 const CLIPRDR_FORMAT* format = &filteredFormatList.formats[x];
165 WLog_Print(cliprdr->log, level, "[%" PRIuz "]: id=0x%08" PRIx32 " [%s|%s]", x,
166 format->formatId, ClipboardGetFormatIdString(format->formatId),
167 format->formatName);
168 }
169 }
170 }
171
172 if (context->ServerFormatList)
173 {
174 if ((error = context->ServerFormatList(context, &filteredFormatList)))
175 WLog_Print(cliprdr->log, WLOG_ERROR, "ServerFormatList failed with error %" PRIu32 "",
176 error);
177 }
178
179error_out:
180 cliprdr_free_format_list(&filteredFormatList);
181 cliprdr_free_format_list(&formatList);
182 return error;
183}
184
190UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, WINPR_ATTR_UNUSED wStream* s,
191 UINT32 dataLen, UINT16 msgFlags)
192{
193 CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse = WINPR_C_ARRAY_INIT;
194 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
195 UINT error = CHANNEL_RC_OK;
196
197 WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse");
198
199 formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
200 formatListResponse.common.msgFlags = msgFlags;
201 formatListResponse.common.dataLen = dataLen;
202
203 IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse);
204 if (error)
205 WLog_Print(cliprdr->log, WLOG_ERROR,
206 "ServerFormatListResponse failed with error %" PRIu32 "!", error);
207
208 return error;
209}
210
216UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
217 UINT16 msgFlags)
218{
219 CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = WINPR_C_ARRAY_INIT;
220 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
221 UINT error = CHANNEL_RC_OK;
222
223 formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
224 formatDataRequest.common.msgFlags = msgFlags;
225 formatDataRequest.common.dataLen = dataLen;
226
227 if ((error = cliprdr_read_format_data_request(s, &formatDataRequest)))
228 return error;
229
230 WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest (0x%08" PRIx32 " [%s])",
231 formatDataRequest.requestedFormatId,
232 ClipboardGetFormatIdString(formatDataRequest.requestedFormatId));
233
234 const UINT32 mask =
235 freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
236 if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
237 {
238 return cliprdr_send_error_response(cliprdr, CB_FORMAT_DATA_RESPONSE);
239 }
240
241 context->lastRequestedFormatId = formatDataRequest.requestedFormatId;
242 IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest);
243 if (error)
244 WLog_Print(cliprdr->log, WLOG_ERROR,
245 "ServerFormatDataRequest failed with error %" PRIu32 "!", error);
246
247 return error;
248}
249
255UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
256 UINT16 msgFlags)
257{
258 CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse = WINPR_C_ARRAY_INIT;
259 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
260 UINT error = CHANNEL_RC_OK;
261
262 WLog_Print(cliprdr->log, WLOG_DEBUG,
263 "ServerFormatDataResponse: msgFlags=0x%08" PRIx32 ", dataLen=%" PRIu32, msgFlags,
264 dataLen);
265
266 formatDataResponse.common.msgType = CB_FORMAT_DATA_RESPONSE;
267 formatDataResponse.common.msgFlags = msgFlags;
268 formatDataResponse.common.dataLen = dataLen;
269
270 if ((error = cliprdr_read_format_data_response(s, &formatDataResponse)))
271 return error;
272
273 const UINT32 mask =
274 freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
275 if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
276 {
277 WLog_Print(cliprdr->log, WLOG_WARN,
278 "Received ServerFormatDataResponse but remote -> local clipboard is disabled");
279 return CHANNEL_RC_OK;
280 }
281
282 IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse);
283 if (error)
284 WLog_Print(cliprdr->log, WLOG_ERROR,
285 "ServerFormatDataResponse failed with error %" PRIu32 "!", error);
286
287 return error;
288}
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.