FreeRDP
ios_cliprdr.m
1 
23 #include <freerdp/config.h>
24 
25 #include <winpr/crt.h>
26 #include <winpr/stream.h>
27 #include <winpr/clipboard.h>
28 
29 #include <freerdp/client/channels.h>
30 #include <freerdp/client/cliprdr.h>
31 
32 #include "ios_cliprdr.h"
33 
34 UINT ios_cliprdr_send_client_format_list(CliprdrClientContext *cliprdr)
35 {
36  UINT rc = ERROR_INTERNAL_ERROR;
37  UINT32 formatId;
38  UINT32 numFormats;
39  UINT32 *pFormatIds;
40  const char *formatName;
41  CLIPRDR_FORMAT *formats;
42  CLIPRDR_FORMAT_LIST formatList = { 0 };
43 
44  if (!cliprdr)
45  return ERROR_INVALID_PARAMETER;
46 
47  mfContext *afc = (mfContext *)cliprdr->custom;
48 
49  if (!afc || !afc->cliprdr)
50  return ERROR_INVALID_PARAMETER;
51 
52  pFormatIds = NULL;
53  numFormats = ClipboardGetFormatIds(afc->clipboard, &pFormatIds);
54  formats = (CLIPRDR_FORMAT *)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
55 
56  if (!formats)
57  goto fail;
58 
59  for (UINT32 index = 0; index < numFormats; index++)
60  {
61  formatId = pFormatIds[index];
62  formatName = ClipboardGetFormatName(afc->clipboard, formatId);
63  formats[index].formatId = formatId;
64  formats[index].formatName = NULL;
65 
66  if ((formatId > CF_MAX) && formatName)
67  {
68  formats[index].formatName = _strdup(formatName);
69 
70  if (!formats[index].formatName)
71  goto fail;
72  }
73  }
74 
75  formatList.common.msgFlags = 0;
76  formatList.numFormats = numFormats;
77  formatList.formats = formats;
78  formatList.common.msgType = CB_FORMAT_LIST;
79 
80  if (!afc->cliprdr->ClientFormatList)
81  goto fail;
82 
83  rc = afc->cliprdr->ClientFormatList(afc->cliprdr, &formatList);
84 fail:
85  free(pFormatIds);
86  free(formats);
87  return rc;
88 }
89 
90 static UINT ios_cliprdr_send_client_format_data_request(CliprdrClientContext *cliprdr,
91  UINT32 formatId)
92 {
93  UINT rc = ERROR_INVALID_PARAMETER;
94  CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = { 0 };
95  mfContext *afc;
96 
97  if (!cliprdr)
98  goto fail;
99 
100  afc = (mfContext *)cliprdr->custom;
101 
102  if (!afc || !afc->clipboardRequestEvent || !cliprdr->ClientFormatDataRequest)
103  goto fail;
104 
105  formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
106  formatDataRequest.common.msgFlags = 0;
107  formatDataRequest.requestedFormatId = formatId;
108  afc->requestedFormatId = formatId;
109  (void)ResetEvent(afc->clipboardRequestEvent);
110  rc = cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
111 fail:
112  return rc;
113 }
114 
115 static UINT ios_cliprdr_send_client_capabilities(CliprdrClientContext *cliprdr)
116 {
117  CLIPRDR_CAPABILITIES capabilities;
118  CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
119 
120  if (!cliprdr || !cliprdr->ClientCapabilities)
121  return ERROR_INVALID_PARAMETER;
122 
123  capabilities.cCapabilitiesSets = 1;
124  capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET *)&(generalCapabilitySet);
125  generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
126  generalCapabilitySet.capabilitySetLength = 12;
127  generalCapabilitySet.version = CB_CAPS_VERSION_2;
128  generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
129  return cliprdr->ClientCapabilities(cliprdr, &capabilities);
130 }
131 
137 static UINT ios_cliprdr_monitor_ready(CliprdrClientContext *cliprdr,
138  const CLIPRDR_MONITOR_READY *monitorReady)
139 {
140  UINT rc;
141  mfContext *afc;
142 
143  if (!cliprdr || !monitorReady)
144  return ERROR_INVALID_PARAMETER;
145 
146  afc = (mfContext *)cliprdr->custom;
147 
148  if (!afc)
149  return ERROR_INVALID_PARAMETER;
150 
151  if ((rc = ios_cliprdr_send_client_capabilities(cliprdr)) != CHANNEL_RC_OK)
152  return rc;
153 
154  if ((rc = ios_cliprdr_send_client_format_list(cliprdr)) != CHANNEL_RC_OK)
155  return rc;
156 
157  afc->clipboardSync = TRUE;
158  return CHANNEL_RC_OK;
159 }
160 
166 static UINT ios_cliprdr_server_capabilities(CliprdrClientContext *cliprdr,
167  const CLIPRDR_CAPABILITIES *capabilities)
168 {
169  CLIPRDR_CAPABILITY_SET *capabilitySet;
170  mfContext *afc;
171 
172  if (!cliprdr || !capabilities)
173  return ERROR_INVALID_PARAMETER;
174 
175  afc = (mfContext *)cliprdr->custom;
176 
177  if (!afc)
178  return ERROR_INVALID_PARAMETER;
179 
180  for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
181  {
182  capabilitySet = &(capabilities->capabilitySets[index]);
183 
184  if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
185  (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
186  {
187  CLIPRDR_GENERAL_CAPABILITY_SET *generalCapabilitySet =
188  (CLIPRDR_GENERAL_CAPABILITY_SET *)capabilitySet;
189  afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
190  break;
191  }
192  }
193 
194  return CHANNEL_RC_OK;
195 }
196 
202 static UINT ios_cliprdr_server_format_list(CliprdrClientContext *cliprdr,
203  const CLIPRDR_FORMAT_LIST *formatList)
204 {
205  UINT rc;
206  CLIPRDR_FORMAT *format;
207  mfContext *afc;
208 
209  if (!cliprdr || !formatList)
210  return ERROR_INVALID_PARAMETER;
211 
212  afc = (mfContext *)cliprdr->custom;
213 
214  if (!afc)
215  return ERROR_INVALID_PARAMETER;
216 
217  if (afc->serverFormats)
218  {
219  for (UINT32 index = 0; index < afc->numServerFormats; index++)
220  free(afc->serverFormats[index].formatName);
221 
222  free(afc->serverFormats);
223  afc->serverFormats = NULL;
224  afc->numServerFormats = 0;
225  }
226 
227  if (formatList->numFormats < 1)
228  return CHANNEL_RC_OK;
229 
230  afc->numServerFormats = formatList->numFormats;
231  afc->serverFormats = (CLIPRDR_FORMAT *)calloc(afc->numServerFormats, sizeof(CLIPRDR_FORMAT));
232 
233  if (!afc->serverFormats)
234  return CHANNEL_RC_NO_MEMORY;
235 
236  for (UINT32 index = 0; index < afc->numServerFormats; index++)
237  {
238  afc->serverFormats[index].formatId = formatList->formats[index].formatId;
239  afc->serverFormats[index].formatName = NULL;
240 
241  if (formatList->formats[index].formatName)
242  {
243  afc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
244 
245  if (!afc->serverFormats[index].formatName)
246  return CHANNEL_RC_NO_MEMORY;
247  }
248  }
249 
250  BOOL unicode = FALSE;
251  BOOL text = FALSE;
252  for (UINT32 index = 0; index < afc->numServerFormats; index++)
253  {
254  format = &(afc->serverFormats[index]);
255 
256  if (format->formatId == CF_UNICODETEXT)
257  unicode = TRUE;
258 
259  else if (format->formatId == CF_TEXT)
260  text = TRUE;
261  }
262 
263  if (unicode)
264  return ios_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
265  if (text)
266  return ios_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
267  return CHANNEL_RC_OK;
268 }
269 
275 static UINT
276 ios_cliprdr_server_format_list_response(CliprdrClientContext *cliprdr,
277  const CLIPRDR_FORMAT_LIST_RESPONSE *formatListResponse)
278 {
279  if (!cliprdr || !formatListResponse)
280  return ERROR_INVALID_PARAMETER;
281 
282  return CHANNEL_RC_OK;
283 }
284 
290 static UINT
291 ios_cliprdr_server_lock_clipboard_data(CliprdrClientContext *cliprdr,
292  const CLIPRDR_LOCK_CLIPBOARD_DATA *lockClipboardData)
293 {
294  if (!cliprdr || !lockClipboardData)
295  return ERROR_INVALID_PARAMETER;
296 
297  return CHANNEL_RC_OK;
298 }
299 
305 static UINT
306 ios_cliprdr_server_unlock_clipboard_data(CliprdrClientContext *cliprdr,
307  const CLIPRDR_UNLOCK_CLIPBOARD_DATA *unlockClipboardData)
308 {
309  if (!cliprdr || !unlockClipboardData)
310  return ERROR_INVALID_PARAMETER;
311 
312  return CHANNEL_RC_OK;
313 }
314 
320 static UINT
321 ios_cliprdr_server_format_data_request(CliprdrClientContext *cliprdr,
322  const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest)
323 {
324  UINT rc;
325  BYTE *data;
326  UINT32 size;
327  UINT32 formatId;
328  CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
329  mfContext *afc;
330 
331  if (!cliprdr || !formatDataRequest || !cliprdr->ClientFormatDataResponse)
332  return ERROR_INVALID_PARAMETER;
333 
334  afc = (mfContext *)cliprdr->custom;
335 
336  if (!afc)
337  return ERROR_INVALID_PARAMETER;
338 
339  formatId = formatDataRequest->requestedFormatId;
340  data = (BYTE *)ClipboardGetData(afc->clipboard, formatId, &size);
341  response.common.msgFlags = CB_RESPONSE_OK;
342  response.common.dataLen = size;
343  response.requestedFormatData = data;
344 
345  if (!data)
346  {
347  response.common.msgFlags = CB_RESPONSE_FAIL;
348  response.common.dataLen = 0;
349  response.requestedFormatData = NULL;
350  }
351 
352  rc = cliprdr->ClientFormatDataResponse(cliprdr, &response);
353  free(data);
354  return rc;
355 }
356 
362 static UINT
363 ios_cliprdr_server_format_data_response(CliprdrClientContext *cliprdr,
364  const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse)
365 {
366  BYTE *data;
367  UINT32 size;
368  UINT32 formatId;
369  CLIPRDR_FORMAT *format = NULL;
370  mfContext *afc;
371  freerdp *instance;
372 
373  if (!cliprdr || !formatDataResponse)
374  return ERROR_INVALID_PARAMETER;
375 
376  afc = (mfContext *)cliprdr->custom;
377 
378  if (!afc)
379  return ERROR_INVALID_PARAMETER;
380 
381  instance = ((rdpContext *)afc)->instance;
382 
383  if (!instance)
384  return ERROR_INVALID_PARAMETER;
385 
386  for (UINT32 index = 0; index < afc->numServerFormats; index++)
387  {
388  if (afc->requestedFormatId == afc->serverFormats[index].formatId)
389  format = &(afc->serverFormats[index]);
390  }
391 
392  if (!format)
393  {
394  (void)SetEvent(afc->clipboardRequestEvent);
395  return ERROR_INTERNAL_ERROR;
396  }
397 
398  if (format->formatName)
399  formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
400  else
401  formatId = format->formatId;
402 
403  size = formatDataResponse->common.dataLen;
404 
405  ClipboardLock(afc->clipboard);
406  if (!ClipboardSetData(afc->clipboard, formatId, formatDataResponse->requestedFormatData, size))
407  return ERROR_INTERNAL_ERROR;
408 
409  (void)SetEvent(afc->clipboardRequestEvent);
410 
411  if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
412  {
413  formatId = ClipboardRegisterFormat(afc->clipboard, "UTF8_STRING");
414  data = (BYTE *)ClipboardGetData(afc->clipboard, formatId, &size);
415  size = (UINT32)strnlen(data, size);
416  if (afc->ServerCutText != NULL)
417  {
418  afc->ServerCutText((rdpContext *)afc, (uint8_t *)data, size);
419  }
420  }
421  ClipboardUnlock(afc->clipboard);
422 
423  return CHANNEL_RC_OK;
424 }
425 
431 static UINT
432 ios_cliprdr_server_file_contents_request(CliprdrClientContext *cliprdr,
433  const CLIPRDR_FILE_CONTENTS_REQUEST *fileContentsRequest)
434 {
435  if (!cliprdr || !fileContentsRequest)
436  return ERROR_INVALID_PARAMETER;
437 
438  return CHANNEL_RC_OK;
439 }
440 
446 static UINT ios_cliprdr_server_file_contents_response(
447  CliprdrClientContext *cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse)
448 {
449  if (!cliprdr || !fileContentsResponse)
450  return ERROR_INVALID_PARAMETER;
451 
452  return CHANNEL_RC_OK;
453 }
454 
455 BOOL ios_cliprdr_init(mfContext *afc, CliprdrClientContext *cliprdr)
456 {
457  wClipboard *clipboard;
458  HANDLE hevent;
459 
460  if (!afc || !cliprdr)
461  return FALSE;
462 
463  if (!(hevent = CreateEvent(NULL, TRUE, FALSE, NULL)))
464  return FALSE;
465 
466  if (!(clipboard = ClipboardCreate()))
467  {
468  (void)CloseHandle(hevent);
469  return FALSE;
470  }
471 
472  afc->cliprdr = cliprdr;
473  afc->clipboard = clipboard;
474  afc->clipboardRequestEvent = hevent;
475  cliprdr->custom = (void *)afc;
476  cliprdr->MonitorReady = ios_cliprdr_monitor_ready;
477  cliprdr->ServerCapabilities = ios_cliprdr_server_capabilities;
478  cliprdr->ServerFormatList = ios_cliprdr_server_format_list;
479  cliprdr->ServerFormatListResponse = ios_cliprdr_server_format_list_response;
480  cliprdr->ServerLockClipboardData = ios_cliprdr_server_lock_clipboard_data;
481  cliprdr->ServerUnlockClipboardData = ios_cliprdr_server_unlock_clipboard_data;
482  cliprdr->ServerFormatDataRequest = ios_cliprdr_server_format_data_request;
483  cliprdr->ServerFormatDataResponse = ios_cliprdr_server_format_data_response;
484  cliprdr->ServerFileContentsRequest = ios_cliprdr_server_file_contents_request;
485  cliprdr->ServerFileContentsResponse = ios_cliprdr_server_file_contents_response;
486  return TRUE;
487 }
488 
489 BOOL ios_cliprdr_uninit(mfContext *afc, CliprdrClientContext *cliprdr)
490 {
491  if (!afc || !cliprdr)
492  return FALSE;
493 
494  cliprdr->custom = NULL;
495  afc->cliprdr = NULL;
496  ClipboardDestroy(afc->clipboard);
497  (void)CloseHandle(afc->clipboardRequestEvent);
498  return TRUE;
499 }