FreeRDP
Loading...
Searching...
No Matches
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
34UINT 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);
84fail:
85 free(pFormatIds);
86 free(formats);
87 return rc;
88}
89
90static 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);
111fail:
112 return rc;
113}
114
115static 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
137static 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
166static 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
202static 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
275static UINT
276ios_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
290static UINT
291ios_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
305static UINT
306ios_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
320static UINT
321ios_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
362static UINT
363ios_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
431static UINT
432ios_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
446static 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
455BOOL 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
489BOOL 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}