FreeRDP
cliprdr_format.c
1 
23 #include <freerdp/config.h>
24 
25 #include <winpr/crt.h>
26 #include <winpr/print.h>
27 
28 #include <freerdp/types.h>
29 #include <freerdp/freerdp.h>
30 #include <freerdp/settings.h>
31 #include <freerdp/constants.h>
32 #include <freerdp/client/cliprdr.h>
33 
34 #include "cliprdr_main.h"
35 #include "cliprdr_format.h"
36 #include "../cliprdr_common.h"
37 
38 CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list, const UINT32 mask,
39  const UINT32 checkMask)
40 {
41  const UINT32 maskData =
42  checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_REMOTE_TO_LOCAL);
43  const UINT32 maskFiles =
44  checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
45  WINPR_ASSERT(list);
46 
47  CLIPRDR_FORMAT_LIST filtered = { 0 };
48  filtered.common.msgType = CB_FORMAT_LIST;
49  filtered.numFormats = list->numFormats;
50  filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT));
51 
52  size_t wpos = 0;
53  if ((mask & checkMask) == checkMask)
54  {
55  for (size_t x = 0; x < list->numFormats; x++)
56  {
57  const CLIPRDR_FORMAT* format = &list->formats[x];
58  CLIPRDR_FORMAT* cur = &filtered.formats[x];
59  cur->formatId = format->formatId;
60  if (format->formatName)
61  cur->formatName = _strdup(format->formatName);
62  wpos++;
63  }
64  }
65  else if ((mask & maskFiles) != 0)
66  {
67  for (size_t x = 0; x < list->numFormats; x++)
68  {
69  const CLIPRDR_FORMAT* format = &list->formats[x];
70  CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
71 
72  if (!format->formatName)
73  continue;
74  if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0 ||
75  strcmp(format->formatName, type_FileContents) == 0)
76  {
77  cur->formatId = format->formatId;
78  cur->formatName = _strdup(format->formatName);
79  wpos++;
80  }
81  }
82  }
83  else if ((mask & maskData) != 0)
84  {
85  for (size_t x = 0; x < list->numFormats; x++)
86  {
87  const CLIPRDR_FORMAT* format = &list->formats[x];
88  CLIPRDR_FORMAT* cur = &filtered.formats[wpos];
89 
90  if (!format->formatName ||
91  (strcmp(format->formatName, type_FileGroupDescriptorW) != 0 &&
92  strcmp(format->formatName, type_FileContents) != 0))
93  {
94  cur->formatId = format->formatId;
95  if (format->formatName)
96  cur->formatName = _strdup(format->formatName);
97  wpos++;
98  }
99  }
100  }
101  WINPR_ASSERT(wpos <= UINT32_MAX);
102  filtered.numFormats = (UINT32)wpos;
103  return filtered;
104 }
105 
111 UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
112  UINT16 msgFlags)
113 {
114  CLIPRDR_FORMAT_LIST formatList = { 0 };
115  CLIPRDR_FORMAT_LIST filteredFormatList = { 0 };
116  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
117  UINT error = CHANNEL_RC_OK;
118 
119  formatList.common.msgType = CB_FORMAT_LIST;
120  formatList.common.msgFlags = msgFlags;
121  formatList.common.dataLen = dataLen;
122 
123  if ((error = cliprdr_read_format_list(s, &formatList, cliprdr->useLongFormatNames)))
124  goto error_out;
125 
126  const UINT32 mask =
127  freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
128  filteredFormatList = cliprdr_filter_format_list(
129  &formatList, mask, CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES);
130  if (filteredFormatList.numFormats == 0)
131  goto error_out;
132 
133  WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %" PRIu32 "",
134  filteredFormatList.numFormats);
135 
136  if (context->ServerFormatList)
137  {
138  if ((error = context->ServerFormatList(context, &filteredFormatList)))
139  WLog_ERR(TAG, "ServerFormatList failed with error %" PRIu32 "", error);
140  }
141 
142 error_out:
143  cliprdr_free_format_list(&filteredFormatList);
144  cliprdr_free_format_list(&formatList);
145  return error;
146 }
147 
153 UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
154  UINT16 msgFlags)
155 {
156  CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse = { 0 };
157  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
158  UINT error = CHANNEL_RC_OK;
159 
160  WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse");
161 
162  formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
163  formatListResponse.common.msgFlags = msgFlags;
164  formatListResponse.common.dataLen = dataLen;
165 
166  IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse);
167  if (error)
168  WLog_ERR(TAG, "ServerFormatListResponse failed with error %" PRIu32 "!", error);
169 
170  return error;
171 }
172 
178 UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
179  UINT16 msgFlags)
180 {
181  CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = { 0 };
182  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
183  UINT error = CHANNEL_RC_OK;
184 
185  WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest");
186 
187  formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
188  formatDataRequest.common.msgFlags = msgFlags;
189  formatDataRequest.common.dataLen = dataLen;
190 
191  if ((error = cliprdr_read_format_data_request(s, &formatDataRequest)))
192  return error;
193 
194  const UINT32 mask =
195  freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
196  if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
197  {
198  return cliprdr_send_error_response(cliprdr, CB_FORMAT_DATA_RESPONSE);
199  }
200 
201  context->lastRequestedFormatId = formatDataRequest.requestedFormatId;
202  IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest);
203  if (error)
204  WLog_ERR(TAG, "ServerFormatDataRequest failed with error %" PRIu32 "!", error);
205 
206  return error;
207 }
208 
214 UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen,
215  UINT16 msgFlags)
216 {
217  CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse = { 0 };
218  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
219  UINT error = CHANNEL_RC_OK;
220 
221  WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataResponse");
222 
223  formatDataResponse.common.msgType = CB_FORMAT_DATA_RESPONSE;
224  formatDataResponse.common.msgFlags = msgFlags;
225  formatDataResponse.common.dataLen = dataLen;
226 
227  if ((error = cliprdr_read_format_data_response(s, &formatDataResponse)))
228  return error;
229 
230  const UINT32 mask =
231  freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
232  if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
233  {
234  WLog_WARN(TAG,
235  "Received ServerFormatDataResponse but remote -> local clipboard is disabled");
236  return CHANNEL_RC_OK;
237  }
238 
239  IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse);
240  if (error)
241  WLog_ERR(TAG, "ServerFormatDataResponse failed with error %" PRIu32 "!", error);
242 
243  return error;
244 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.