FreeRDP
Clipboard.m
1 
21 #import "Clipboard.h"
22 #import "MRDPView.h"
23 
24 int mac_cliprdr_send_client_format_list(CliprdrClientContext *cliprdr)
25 {
26  UINT32 formatId;
27  UINT32 numFormats;
28  UINT32 *pFormatIds;
29  const char *formatName;
30  CLIPRDR_FORMAT *formats;
31  CLIPRDR_FORMAT_LIST formatList = { 0 };
32 
33  WINPR_ASSERT(cliprdr);
34  mfContext *mfc = (mfContext *)cliprdr->custom;
35  WINPR_ASSERT(mfc);
36 
37  pFormatIds = NULL;
38  numFormats = ClipboardGetFormatIds(mfc->clipboard, &pFormatIds);
39 
40  formats = (CLIPRDR_FORMAT *)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
41 
42  if (!formats)
43  return -1;
44 
45  for (UINT32 index = 0; index < numFormats; index++)
46  {
47  formatId = pFormatIds[index];
48  formatName = ClipboardGetFormatName(mfc->clipboard, formatId);
49 
50  formats[index].formatId = formatId;
51  formats[index].formatName = NULL;
52 
53  if ((formatId > CF_MAX) && formatName)
54  formats[index].formatName = _strdup(formatName);
55  }
56 
57  formatList.common.msgFlags = 0;
58  formatList.numFormats = numFormats;
59  formatList.formats = formats;
60  formatList.common.msgType = CB_FORMAT_LIST;
61 
62  mfc->cliprdr->ClientFormatList(mfc->cliprdr, &formatList);
63 
64  for (UINT32 index = 0; index < numFormats; index++)
65  {
66  free(formats[index].formatName);
67  }
68 
69  free(pFormatIds);
70  free(formats);
71 
72  return 1;
73 }
74 
75 static int mac_cliprdr_send_client_format_list_response(CliprdrClientContext *cliprdr, BOOL status)
76 {
77  CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
78 
79  formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
80  formatListResponse.common.msgFlags = status ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
81  formatListResponse.common.dataLen = 0;
82 
83  cliprdr->ClientFormatListResponse(cliprdr, &formatListResponse);
84 
85  return 1;
86 }
87 
88 static int mac_cliprdr_send_client_format_data_request(CliprdrClientContext *cliprdr,
89  UINT32 formatId)
90 {
91  CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = { 0 };
92  WINPR_ASSERT(cliprdr);
93 
94  mfContext *mfc = (mfContext *)cliprdr->custom;
95  WINPR_ASSERT(mfc);
96 
97  formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
98  formatDataRequest.common.msgFlags = 0;
99 
100  formatDataRequest.requestedFormatId = formatId;
101  mfc->requestedFormatId = formatId;
102  (void)ResetEvent(mfc->clipboardRequestEvent);
103 
104  cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
105 
106  return 1;
107 }
108 
109 static int mac_cliprdr_send_client_capabilities(CliprdrClientContext *cliprdr)
110 {
111  CLIPRDR_CAPABILITIES capabilities;
112  CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
113 
114  capabilities.cCapabilitiesSets = 1;
115  capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET *)&(generalCapabilitySet);
116 
117  generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
118  generalCapabilitySet.capabilitySetLength = 12;
119 
120  generalCapabilitySet.version = CB_CAPS_VERSION_2;
121  generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
122 
123  cliprdr->ClientCapabilities(cliprdr, &capabilities);
124 
125  return 1;
126 }
127 
133 static UINT mac_cliprdr_monitor_ready(CliprdrClientContext *cliprdr,
134  const CLIPRDR_MONITOR_READY *monitorReady)
135 {
136  mfContext *mfc = (mfContext *)cliprdr->custom;
137 
138  mfc->clipboardSync = TRUE;
139  mac_cliprdr_send_client_capabilities(cliprdr);
140  mac_cliprdr_send_client_format_list(cliprdr);
141 
142  return CHANNEL_RC_OK;
143 }
144 
150 static UINT mac_cliprdr_server_capabilities(CliprdrClientContext *cliprdr,
151  const CLIPRDR_CAPABILITIES *capabilities)
152 {
153  CLIPRDR_CAPABILITY_SET *capabilitySet;
154  mfContext *mfc = (mfContext *)cliprdr->custom;
155 
156  for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
157  {
158  capabilitySet = &(capabilities->capabilitySets[index]);
159 
160  if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
161  (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
162  {
163  CLIPRDR_GENERAL_CAPABILITY_SET *generalCapabilitySet =
164  (CLIPRDR_GENERAL_CAPABILITY_SET *)capabilitySet;
165 
166  mfc->clipboardCapabilities = generalCapabilitySet->generalFlags;
167  break;
168  }
169  }
170 
171  return CHANNEL_RC_OK;
172 }
173 
179 static UINT mac_cliprdr_server_format_list(CliprdrClientContext *cliprdr,
180  const CLIPRDR_FORMAT_LIST *formatList)
181 {
182  CLIPRDR_FORMAT *format;
183  mfContext *mfc = (mfContext *)cliprdr->custom;
184 
185  if (mfc->serverFormats)
186  {
187  for (UINT32 index = 0; index < mfc->numServerFormats; index++)
188  {
189  free(mfc->serverFormats[index].formatName);
190  }
191 
192  free(mfc->serverFormats);
193  mfc->serverFormats = NULL;
194  mfc->numServerFormats = 0;
195  }
196 
197  if (formatList->numFormats < 1)
198  return CHANNEL_RC_OK;
199 
200  mfc->numServerFormats = formatList->numFormats;
201  mfc->serverFormats = (CLIPRDR_FORMAT *)calloc(mfc->numServerFormats, sizeof(CLIPRDR_FORMAT));
202 
203  if (!mfc->serverFormats)
204  return CHANNEL_RC_NO_MEMORY;
205 
206  for (UINT32 index = 0; index < mfc->numServerFormats; index++)
207  {
208  mfc->serverFormats[index].formatId = formatList->formats[index].formatId;
209  mfc->serverFormats[index].formatName = NULL;
210 
211  if (formatList->formats[index].formatName)
212  mfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
213  }
214 
215  mac_cliprdr_send_client_format_list_response(cliprdr, TRUE);
216 
217  for (UINT32 index = 0; index < mfc->numServerFormats; index++)
218  {
219  format = &(mfc->serverFormats[index]);
220 
221  if (format->formatId == CF_UNICODETEXT)
222  {
223  mac_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
224  break;
225  }
226  else if (format->formatId == CF_OEMTEXT)
227  {
228  mac_cliprdr_send_client_format_data_request(cliprdr, CF_OEMTEXT);
229  break;
230  }
231  else if (format->formatId == CF_TEXT)
232  {
233  mac_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
234  break;
235  }
236  }
237 
238  return CHANNEL_RC_OK;
239 }
240 
246 static UINT
247 mac_cliprdr_server_format_list_response(CliprdrClientContext *cliprdr,
248  const CLIPRDR_FORMAT_LIST_RESPONSE *formatListResponse)
249 {
250  return CHANNEL_RC_OK;
251 }
252 
258 static UINT
259 mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext *cliprdr,
260  const CLIPRDR_LOCK_CLIPBOARD_DATA *lockClipboardData)
261 {
262  return CHANNEL_RC_OK;
263 }
264 
270 static UINT
271 mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext *cliprdr,
272  const CLIPRDR_UNLOCK_CLIPBOARD_DATA *unlockClipboardData)
273 {
274  return CHANNEL_RC_OK;
275 }
276 
282 static UINT
283 mac_cliprdr_server_format_data_request(CliprdrClientContext *cliprdr,
284  const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest)
285 {
286  BYTE *data;
287  UINT32 size;
288  UINT32 formatId;
289  CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
290 
291  WINPR_ASSERT(cliprdr);
292 
293  mfContext *mfc = (mfContext *)cliprdr->custom;
294  WINPR_ASSERT(mfc);
295 
296  formatId = formatDataRequest->requestedFormatId;
297  data = (BYTE *)ClipboardGetData(mfc->clipboard, formatId, &size);
298 
299  response.common.msgFlags = CB_RESPONSE_OK;
300  response.common.dataLen = size;
301  response.requestedFormatData = data;
302 
303  if (!data)
304  {
305  response.common.msgFlags = CB_RESPONSE_FAIL;
306  response.common.dataLen = 0;
307  response.requestedFormatData = NULL;
308  }
309 
310  cliprdr->ClientFormatDataResponse(cliprdr, &response);
311 
312  free(data);
313 
314  return CHANNEL_RC_OK;
315 }
316 
322 static UINT
323 mac_cliprdr_server_format_data_response(CliprdrClientContext *cliprdr,
324  const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse)
325 {
326  UINT32 formatId;
327  CLIPRDR_FORMAT *format = NULL;
328  mfContext *mfc = (mfContext *)cliprdr->custom;
329  MRDPView *view = (MRDPView *)mfc->view;
330 
331  if (formatDataResponse->common.msgFlags & CB_RESPONSE_FAIL)
332  {
333  (void)SetEvent(mfc->clipboardRequestEvent);
334  return ERROR_INTERNAL_ERROR;
335  }
336 
337  for (UINT32 index = 0; index < mfc->numServerFormats; index++)
338  {
339  if (mfc->requestedFormatId == mfc->serverFormats[index].formatId)
340  format = &(mfc->serverFormats[index]);
341  }
342 
343  if (!format)
344  {
345  (void)SetEvent(mfc->clipboardRequestEvent);
346  return ERROR_INTERNAL_ERROR;
347  }
348 
349  if (format->formatName)
350  formatId = ClipboardRegisterFormat(mfc->clipboard, format->formatName);
351  else
352  formatId = format->formatId;
353 
354  const size_t size = formatDataResponse->common.dataLen;
355 
356  ClipboardSetData(mfc->clipboard, formatId, formatDataResponse->requestedFormatData, size);
357 
358  (void)SetEvent(mfc->clipboardRequestEvent);
359 
360  if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || (formatId == CF_UNICODETEXT))
361  {
362  formatId = ClipboardRegisterFormat(mfc->clipboard, "text/plain");
363 
364  UINT32 dstSize = 0;
365  char *data = ClipboardGetData(mfc->clipboard, formatId, &dstSize);
366 
367  dstSize = strnlen(data, dstSize); /* we need the size without the null terminator */
368 
369  NSString *str = [[NSString alloc] initWithBytes:(void *)data
370  length:dstSize
371  encoding:NSUTF8StringEncoding];
372  free(data);
373 
374  NSArray *types = [[NSArray alloc] initWithObjects:NSPasteboardTypeString, nil];
375  [view->pasteboard_wr declareTypes:types owner:view];
376  [view->pasteboard_wr setString:str forType:NSPasteboardTypeString];
377  }
378 
379  return CHANNEL_RC_OK;
380 }
381 
387 static UINT
388 mac_cliprdr_server_file_contents_request(CliprdrClientContext *cliprdr,
389  const CLIPRDR_FILE_CONTENTS_REQUEST *fileContentsRequest)
390 {
391  return CHANNEL_RC_OK;
392 }
393 
399 static UINT mac_cliprdr_server_file_contents_response(
400  CliprdrClientContext *cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse)
401 {
402  return CHANNEL_RC_OK;
403 }
404 
405 void mac_cliprdr_init(mfContext *mfc, CliprdrClientContext *cliprdr)
406 {
407  cliprdr->custom = (void *)mfc;
408  mfc->cliprdr = cliprdr;
409 
410  mfc->clipboard = ClipboardCreate();
411  mfc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
412 
413  cliprdr->MonitorReady = mac_cliprdr_monitor_ready;
414  cliprdr->ServerCapabilities = mac_cliprdr_server_capabilities;
415  cliprdr->ServerFormatList = mac_cliprdr_server_format_list;
416  cliprdr->ServerFormatListResponse = mac_cliprdr_server_format_list_response;
417  cliprdr->ServerLockClipboardData = mac_cliprdr_server_lock_clipboard_data;
418  cliprdr->ServerUnlockClipboardData = mac_cliprdr_server_unlock_clipboard_data;
419  cliprdr->ServerFormatDataRequest = mac_cliprdr_server_format_data_request;
420  cliprdr->ServerFormatDataResponse = mac_cliprdr_server_format_data_response;
421  cliprdr->ServerFileContentsRequest = mac_cliprdr_server_file_contents_request;
422  cliprdr->ServerFileContentsResponse = mac_cliprdr_server_file_contents_response;
423 }
424 
425 void mac_cliprdr_uninit(mfContext *mfc, CliprdrClientContext *cliprdr)
426 {
427  cliprdr->custom = NULL;
428  mfc->cliprdr = NULL;
429 
430  ClipboardDestroy(mfc->clipboard);
431  (void)CloseHandle(mfc->clipboardRequestEvent);
432 }