23#include <freerdp/config.h>
26#include <winpr/stream.h>
27#include <winpr/clipboard.h>
29#include <freerdp/client/channels.h>
30#include <freerdp/client/cliprdr.h>
32#include "ios_cliprdr.h"
33#include "ios_freerdp_ui.h"
35static void ios_cliprdr_free_formats(
CLIPRDR_FORMAT *formats, UINT32 numFormats)
40 for (UINT32 index = 0; index < numFormats; index++)
41 free(formats[index].formatName);
46UINT ios_cliprdr_send_client_format_list(CliprdrClientContext *cliprdr)
51 if (!cliprdr || !cliprdr->ClientFormatList)
52 return ERROR_INVALID_PARAMETER;
57 return ERROR_INVALID_PARAMETER;
61 format.formatId = CF_UNICODETEXT;
62 formatList.common.msgFlags = 0;
63 formatList.numFormats = afc->clipboardHasText ? 1 : 0;
64 formatList.formats = &format;
65 formatList.common.msgType = CB_FORMAT_LIST;
66 return cliprdr->ClientFormatList(cliprdr, &formatList);
69static UINT ios_cliprdr_send_client_format_data_request(CliprdrClientContext *cliprdr,
72 UINT rc = ERROR_INVALID_PARAMETER;
81 if (!afc || !afc->clipboardRequestEvent || !cliprdr->ClientFormatDataRequest)
84 formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
85 formatDataRequest.common.msgFlags = 0;
86 formatDataRequest.requestedFormatId = formatId;
87 afc->requestedFormatId = formatId;
88 (void)ResetEvent(afc->clipboardRequestEvent);
89 rc = cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
94static UINT ios_cliprdr_send_client_capabilities(CliprdrClientContext *cliprdr)
99 if (!cliprdr || !cliprdr->ClientCapabilities)
100 return ERROR_INVALID_PARAMETER;
102 capabilities.cCapabilitiesSets = 1;
104 generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
105 generalCapabilitySet.capabilitySetLength = 12;
106 generalCapabilitySet.version = CB_CAPS_VERSION_2;
107 generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
108 return cliprdr->ClientCapabilities(cliprdr, &capabilities);
116static UINT ios_cliprdr_monitor_ready(CliprdrClientContext *cliprdr,
122 if (!cliprdr || !monitorReady)
123 return ERROR_INVALID_PARAMETER;
128 return ERROR_INVALID_PARAMETER;
130 if ((rc = ios_cliprdr_send_client_capabilities(cliprdr)) != CHANNEL_RC_OK)
133 if ((rc = ios_cliprdr_send_client_format_list(cliprdr)) != CHANNEL_RC_OK)
136 afc->clipboardSync = TRUE;
137 return CHANNEL_RC_OK;
145static UINT ios_cliprdr_server_capabilities(CliprdrClientContext *cliprdr,
151 if (!cliprdr || !capabilities)
152 return ERROR_INVALID_PARAMETER;
157 return ERROR_INVALID_PARAMETER;
159 for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
161 capabilitySet = &(capabilities->capabilitySets[index]);
163 if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
164 (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
168 afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
173 return CHANNEL_RC_OK;
176static UINT ios_cliprdr_send_client_format_list_response(CliprdrClientContext *cliprdr, BOOL status)
180 formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
181 formatListResponse.common.msgFlags = status ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
182 formatListResponse.common.dataLen = 0;
184 if (!cliprdr || !cliprdr->ClientFormatListResponse)
185 return ERROR_INVALID_PARAMETER;
187 return cliprdr->ClientFormatListResponse(cliprdr, &formatListResponse);
195static UINT ios_cliprdr_server_format_list(CliprdrClientContext *cliprdr,
202 if (!cliprdr || !formatList)
203 return ERROR_INVALID_PARAMETER;
208 return ERROR_INVALID_PARAMETER;
210 ios_cliprdr_free_formats(afc->serverFormats, afc->numServerFormats);
211 afc->serverFormats =
nullptr;
212 afc->numServerFormats = 0;
214 if (formatList->numFormats < 1)
215 return ios_cliprdr_send_client_format_list_response(cliprdr, TRUE);
217 afc->numServerFormats = formatList->numFormats;
220 if (!afc->serverFormats)
221 return CHANNEL_RC_NO_MEMORY;
223 for (UINT32 index = 0; index < afc->numServerFormats; index++)
225 afc->serverFormats[index].formatId = formatList->formats[index].formatId;
226 afc->serverFormats[index].formatName =
nullptr;
228 if (formatList->formats[index].formatName)
230 afc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
232 if (!afc->serverFormats[index].formatName)
233 return CHANNEL_RC_NO_MEMORY;
237 if ((rc = ios_cliprdr_send_client_format_list_response(cliprdr, TRUE)) != CHANNEL_RC_OK)
240 BOOL unicode = FALSE;
242 for (UINT32 index = 0; index < afc->numServerFormats; index++)
244 format = &(afc->serverFormats[index]);
246 if (format->formatId == CF_UNICODETEXT)
249 else if (format->formatId == CF_TEXT)
254 return ios_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
256 return ios_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
257 return CHANNEL_RC_OK;
266ios_cliprdr_server_format_list_response(CliprdrClientContext *cliprdr,
269 if (!cliprdr || !formatListResponse)
270 return ERROR_INVALID_PARAMETER;
272 return CHANNEL_RC_OK;
281ios_cliprdr_server_lock_clipboard_data(CliprdrClientContext *cliprdr,
284 if (!cliprdr || !lockClipboardData)
285 return ERROR_INVALID_PARAMETER;
287 return CHANNEL_RC_OK;
296ios_cliprdr_server_unlock_clipboard_data(CliprdrClientContext *cliprdr,
299 if (!cliprdr || !unlockClipboardData)
300 return ERROR_INVALID_PARAMETER;
302 return CHANNEL_RC_OK;
311ios_cliprdr_server_format_data_request(CliprdrClientContext *cliprdr,
315 BYTE *data =
nullptr;
321 if (!cliprdr || !formatDataRequest || !cliprdr->ClientFormatDataResponse)
322 return ERROR_INVALID_PARAMETER;
327 return ERROR_INVALID_PARAMETER;
329 formatId = formatDataRequest->requestedFormatId;
331 if ((formatId == CF_UNICODETEXT) || (formatId == CF_TEXT) || (formatId == CF_OEMTEXT))
333 char *text = ios_ui_get_clipboard_text((rdpContext *)afc);
337 ClipboardLock(afc->clipboard);
338 if (ClipboardSetData(afc->clipboard,
339 ClipboardRegisterFormat(afc->clipboard,
"UTF8_STRING"), text,
340 (UINT32)strlen(text)))
341 data = (BYTE *)ClipboardGetData(afc->clipboard, formatId, &size);
342 ClipboardUnlock(afc->clipboard);
347 response.common.msgFlags = CB_RESPONSE_OK;
348 response.common.dataLen = size;
349 response.requestedFormatData = data;
353 response.common.msgFlags = CB_RESPONSE_FAIL;
354 response.common.dataLen = 0;
355 response.requestedFormatData =
nullptr;
358 rc = cliprdr->ClientFormatDataResponse(cliprdr, &response);
369ios_cliprdr_server_format_data_response(CliprdrClientContext *cliprdr,
379 if (!cliprdr || !formatDataResponse)
380 return ERROR_INVALID_PARAMETER;
385 return ERROR_INVALID_PARAMETER;
387 instance = ((rdpContext *)afc)->instance;
390 return ERROR_INVALID_PARAMETER;
392 for (UINT32 index = 0; index < afc->numServerFormats; index++)
394 if (afc->requestedFormatId == afc->serverFormats[index].formatId)
395 format = &(afc->serverFormats[index]);
400 (void)SetEvent(afc->clipboardRequestEvent);
401 return ERROR_INTERNAL_ERROR;
405 if (formatDataResponse->common.msgFlags & CB_RESPONSE_FAIL)
407 (void)SetEvent(afc->clipboardRequestEvent);
408 return CHANNEL_RC_OK;
411 if (format->formatName)
412 formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
414 formatId = format->formatId;
416 size = formatDataResponse->common.dataLen;
418 ClipboardLock(afc->clipboard);
419 if (!ClipboardSetData(afc->clipboard, formatId, formatDataResponse->requestedFormatData, size))
421 ClipboardUnlock(afc->clipboard);
422 return ERROR_INTERNAL_ERROR;
425 (void)SetEvent(afc->clipboardRequestEvent);
427 if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
429 formatId = ClipboardRegisterFormat(afc->clipboard,
"UTF8_STRING");
430 data = (BYTE *)ClipboardGetData(afc->clipboard, formatId, &size);
433 size = (UINT32)strnlen((
const char *)data, size);
434 ios_ui_set_clipboard_text((rdpContext *)afc, (
const char *)data, size);
438 ClipboardUnlock(afc->clipboard);
440 return CHANNEL_RC_OK;
449ios_cliprdr_server_file_contents_request(CliprdrClientContext *cliprdr,
452 if (!cliprdr || !fileContentsRequest)
453 return ERROR_INVALID_PARAMETER;
455 return CHANNEL_RC_OK;
463static UINT ios_cliprdr_server_file_contents_response(
466 if (!cliprdr || !fileContentsResponse)
467 return ERROR_INVALID_PARAMETER;
469 return CHANNEL_RC_OK;
472BOOL ios_cliprdr_init(
mfContext *afc, CliprdrClientContext *cliprdr)
474 wClipboard *clipboard;
477 if (!afc || !cliprdr)
480 if (!(hevent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
483 if (!(clipboard = ClipboardCreate()))
485 (void)CloseHandle(hevent);
489 afc->cliprdr = cliprdr;
490 afc->clipboard = clipboard;
491 afc->clipboardRequestEvent = hevent;
492 cliprdr->custom = (
void *)afc;
493 cliprdr->MonitorReady = ios_cliprdr_monitor_ready;
494 cliprdr->ServerCapabilities = ios_cliprdr_server_capabilities;
495 cliprdr->ServerFormatList = ios_cliprdr_server_format_list;
496 cliprdr->ServerFormatListResponse = ios_cliprdr_server_format_list_response;
497 cliprdr->ServerLockClipboardData = ios_cliprdr_server_lock_clipboard_data;
498 cliprdr->ServerUnlockClipboardData = ios_cliprdr_server_unlock_clipboard_data;
499 cliprdr->ServerFormatDataRequest = ios_cliprdr_server_format_data_request;
500 cliprdr->ServerFormatDataResponse = ios_cliprdr_server_format_data_response;
501 cliprdr->ServerFileContentsRequest = ios_cliprdr_server_file_contents_request;
502 cliprdr->ServerFileContentsResponse = ios_cliprdr_server_file_contents_response;
506BOOL ios_cliprdr_uninit(
mfContext *afc, CliprdrClientContext *cliprdr)
508 if (!afc || !cliprdr)
511 cliprdr->custom =
nullptr;
512 afc->cliprdr =
nullptr;
513 afc->clipboardSync = FALSE;
514 ios_cliprdr_free_formats(afc->serverFormats, afc->numServerFormats);
515 afc->serverFormats =
nullptr;
516 afc->numServerFormats = 0;
517 ClipboardDestroy(afc->clipboard);
518 (void)CloseHandle(afc->clipboardRequestEvent);