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, const UINT32 mask,
40 const 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 = { 0 };
49 filtered.common.msgType = CB_FORMAT_LIST;
50 filtered.numFormats = list->numFormats;
51 filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT));
52
53 size_t wpos = 0;
54 if ((mask & checkMask) == checkMask)
55 {
56 for (size_t x = 0; x < list->numFormats; x++)
57 {
58 const CLIPRDR_FORMAT* format = &list->formats[x];
59 CLIPRDR_FORMAT* cur = &filtered.formats[x];
60 cur->formatId = format->formatId;
61 if (format->formatName)
62 cur->formatName = _strdup(format->formatName);
63 wpos++;
64 }
65 }
66 else if ((mask & maskFiles) != 0)
67 {
68 for (size_t x = 0; x < list->numFormats; x++)
69 {
70 const CLIPRDR_FORMAT* format = &list->formats[x];
71 CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
72
73 if (!format->formatName)
74 continue;
75 if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0 ||
76 strcmp(format->formatName, type_FileContents) == 0)
77 {
78 cur->formatId = format->formatId;
79 cur->formatName = _strdup(format->formatName);
80 wpos++;
81 }
82 }
83 }
84 else if ((mask & maskData) != 0)
85 {
86 for (size_t x = 0; x < list->numFormats; x++)
87 {
88 const CLIPRDR_FORMAT* format = &list->formats[x];
89 CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
90
91 if (!format->formatName ||
92 (strcmp(format->formatName, type_FileGroupDescriptorW) != 0 &&
93 strcmp(format->formatName, type_FileContents) != 0))
94 {
95 cur->formatId = format->formatId;
96 if (format->formatName)
97 cur->formatName = _strdup(format->formatName);
98 wpos++;
99 }
100 }
101 }
102 WINPR_ASSERT(wpos <= UINT32_MAX);
103 filtered.numFormats = (UINT32)wpos;
104 return filtered;
105}
106
112UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
113 UINT16 msgFlags)
114{
115 CLIPRDR_FORMAT_LIST formatList = { 0 };
116 CLIPRDR_FORMAT_LIST filteredFormatList = { 0 };
117 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
118 UINT error = CHANNEL_RC_OK;
119
120 formatList.common.msgType = CB_FORMAT_LIST;
121 formatList.common.msgFlags = msgFlags;
122 formatList.common.dataLen = dataLen;
123
124 if ((error =
125 cliprdr_read_format_list(cliprdr->log, s, &formatList, cliprdr->useLongFormatNames)))
126 goto error_out;
127
128 {
129 const UINT32 mask = freerdp_settings_get_uint32(context->rdpcontext->settings,
130 FreeRDP_ClipboardFeatureMask);
131 filteredFormatList = cliprdr_filter_format_list(
132 &formatList, mask, CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
133 }
134
135 if (filteredFormatList.numFormats == 0)
136 goto error_out;
137
138 {
139 const DWORD level = WLOG_DEBUG;
140 if (WLog_IsLevelActive(cliprdr->log, level))
141 {
142 WLog_Print(cliprdr->log, level, "ServerFormatList: numFormats: %" PRIu32 "",
143 formatList.numFormats);
144 for (size_t x = 0; x < formatList.numFormats; x++)
145 {
146 const CLIPRDR_FORMAT* format = &formatList.formats[x];
147 WLog_Print(cliprdr->log, level, "[%" PRIuz "]: id=0x%08" PRIx32 " [%s|%s]", x,
148 format->formatId, ClipboardGetFormatIdString(format->formatId),
149 format->formatName);
150 }
151
152 WLog_Print(cliprdr->log, level, "ServerFormatList [filtered]: numFormats: %" PRIu32 "",
153 filteredFormatList.numFormats);
154 for (size_t x = 0; x < filteredFormatList.numFormats; x++)
155 {
156 const CLIPRDR_FORMAT* format = &filteredFormatList.formats[x];
157 WLog_Print(cliprdr->log, level, "[%" PRIuz "]: id=0x%08" PRIx32 " [%s|%s]", x,
158 format->formatId, ClipboardGetFormatIdString(format->formatId),
159 format->formatName);
160 }
161 }
162 }
163
164 if (context->ServerFormatList)
165 {
166 if ((error = context->ServerFormatList(context, &filteredFormatList)))
167 WLog_Print(cliprdr->log, WLOG_ERROR, "ServerFormatList failed with error %" PRIu32 "",
168 error);
169 }
170
171error_out:
172 cliprdr_free_format_list(&filteredFormatList);
173 cliprdr_free_format_list(&formatList);
174 return error;
175}
176
182UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, WINPR_ATTR_UNUSED wStream* s,
183 UINT32 dataLen, UINT16 msgFlags)
184{
185 CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse = { 0 };
186 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
187 UINT error = CHANNEL_RC_OK;
188
189 WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse");
190
191 formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
192 formatListResponse.common.msgFlags = msgFlags;
193 formatListResponse.common.dataLen = dataLen;
194
195 IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse);
196 if (error)
197 WLog_Print(cliprdr->log, WLOG_ERROR,
198 "ServerFormatListResponse failed with error %" PRIu32 "!", error);
199
200 return error;
201}
202
208UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
209 UINT16 msgFlags)
210{
211 CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = { 0 };
212 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
213 UINT error = CHANNEL_RC_OK;
214
215 formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
216 formatDataRequest.common.msgFlags = msgFlags;
217 formatDataRequest.common.dataLen = dataLen;
218
219 if ((error = cliprdr_read_format_data_request(s, &formatDataRequest)))
220 return error;
221
222 WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest (0x%08" PRIx32 " [%s])",
223 formatDataRequest.requestedFormatId,
224 ClipboardGetFormatIdString(formatDataRequest.requestedFormatId));
225
226 const UINT32 mask =
227 freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
228 if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
229 {
230 return cliprdr_send_error_response(cliprdr, CB_FORMAT_DATA_RESPONSE);
231 }
232
233 context->lastRequestedFormatId = formatDataRequest.requestedFormatId;
234 IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest);
235 if (error)
236 WLog_Print(cliprdr->log, WLOG_ERROR,
237 "ServerFormatDataRequest failed with error %" PRIu32 "!", error);
238
239 return error;
240}
241
247UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
248 UINT16 msgFlags)
249{
250 CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse = { 0 };
251 CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
252 UINT error = CHANNEL_RC_OK;
253
254 WLog_Print(cliprdr->log, WLOG_DEBUG,
255 "ServerFormatDataResponse: msgFlags=0x%08" PRIx32 ", dataLen=%" PRIu32, msgFlags,
256 dataLen);
257
258 formatDataResponse.common.msgType = CB_FORMAT_DATA_RESPONSE;
259 formatDataResponse.common.msgFlags = msgFlags;
260 formatDataResponse.common.dataLen = dataLen;
261
262 if ((error = cliprdr_read_format_data_response(s, &formatDataResponse)))
263 return error;
264
265 const UINT32 mask =
266 freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
267 if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
268 {
269 WLog_Print(cliprdr->log, WLOG_WARN,
270 "Received ServerFormatDataResponse but remote -> local clipboard is disabled");
271 return CHANNEL_RC_OK;
272 }
273
274 IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse);
275 if (error)
276 WLog_Print(cliprdr->log, WLOG_ERROR,
277 "ServerFormatDataResponse failed with error %" PRIu32 "!", error);
278
279 return error;
280}
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.