23#include <freerdp/config.h> 
   25#include <winpr/wtypes.h> 
   26#include <winpr/assert.h> 
   28#include <winpr/print.h> 
   29#include <winpr/clipboard.h> 
   31#include <freerdp/types.h> 
   32#include <freerdp/constants.h> 
   33#include <freerdp/freerdp.h> 
   34#include <freerdp/client/cliprdr.h> 
   36#include "../../../channels/client/addin.h" 
   38#include "cliprdr_main.h" 
   39#include "cliprdr_format.h" 
   40#include "../cliprdr_common.h" 
   42const char type_FileGroupDescriptorW[] = 
"FileGroupDescriptorW";
 
   43const char type_FileContents[] = 
"FileContents";
 
   45CliprdrClientContext* cliprdr_get_client_interface(
cliprdrPlugin* cliprdr)
 
   47  CliprdrClientContext* pInterface = NULL;
 
   52  pInterface = (CliprdrClientContext*)cliprdr->channelEntryPoints.pInterface;
 
   63  UINT status = CHANNEL_RC_OK;
 
   65  WINPR_ASSERT(cliprdr);
 
   68  const size_t pos = Stream_GetPosition(s);
 
   69  WINPR_ASSERT(pos >= 8ULL);
 
   70  WINPR_ASSERT(pos <= UINT32_MAX - 8);
 
   72  const uint32_t dataLen = WINPR_ASSERTING_INT_CAST(uint32_t, pos - 8UL);
 
   74  Stream_SetPosition(s, 4);
 
   75  Stream_Write_UINT32(s, dataLen);
 
   76  Stream_SetPosition(s, pos);
 
   78  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"Cliprdr Sending (%" PRIuz 
" bytes)", pos);
 
   82    status = CHANNEL_RC_BAD_INIT_HANDLE;
 
   86    WINPR_ASSERT(cliprdr->channelEntryPoints.pVirtualChannelWriteEx);
 
   87    status = cliprdr->channelEntryPoints.pVirtualChannelWriteEx(
 
   88        cliprdr->InitHandle, cliprdr->OpenHandle, Stream_Buffer(s),
 
   89        (UINT32)Stream_GetPosition(s), s);
 
   92  if (status != CHANNEL_RC_OK)
 
   95    WLog_Print(cliprdr->log, WLOG_ERROR, 
"VirtualChannelWrite failed with %s [%08" PRIX32 
"]",
 
   96               WTSErrorToString(status), status);
 
  102UINT cliprdr_send_error_response(
cliprdrPlugin* cliprdr, UINT16 type)
 
  104  wStream* s = cliprdr_packet_new(type, CB_RESPONSE_FAIL, 0);
 
  107    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  108    return ERROR_OUTOFMEMORY;
 
  111  return cliprdr_packet_send(cliprdr, s);
 
  114static void cliprdr_print_general_capability_flags(wLog* log, UINT32 flags)
 
  116  WLog_Print(log, WLOG_DEBUG, 
"generalFlags (0x%08" PRIX32 
") {", flags);
 
  118  if (flags & CB_USE_LONG_FORMAT_NAMES)
 
  119    WLog_Print(log, WLOG_DEBUG, 
"\tCB_USE_LONG_FORMAT_NAMES");
 
  121  if (flags & CB_STREAM_FILECLIP_ENABLED)
 
  122    WLog_Print(log, WLOG_DEBUG, 
"\tCB_STREAM_FILECLIP_ENABLED");
 
  124  if (flags & CB_FILECLIP_NO_FILE_PATHS)
 
  125    WLog_Print(log, WLOG_DEBUG, 
"\tCB_FILECLIP_NO_FILE_PATHS");
 
  127  if (flags & CB_CAN_LOCK_CLIPDATA)
 
  128    WLog_Print(log, WLOG_DEBUG, 
"\tCB_CAN_LOCK_CLIPDATA");
 
  130  if (flags & CB_HUGE_FILE_SUPPORT_ENABLED)
 
  131    WLog_Print(log, WLOG_DEBUG, 
"\tCB_HUGE_FILE_SUPPORT_ENABLED");
 
  133  WLog_Print(log, WLOG_DEBUG, 
"}");
 
  144  UINT32 generalFlags = 0;
 
  147  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  148  UINT error = CHANNEL_RC_OK;
 
  150  WINPR_ASSERT(cliprdr);
 
  155    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_get_client_interface failed!");
 
  156    return ERROR_INTERNAL_ERROR;
 
  159  if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, 8))
 
  160    return ERROR_INVALID_DATA;
 
  162  Stream_Read_UINT32(s, version);      
 
  163  Stream_Read_UINT32(s, generalFlags); 
 
  164  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"Version: %" PRIu32 
"", version);
 
  166  cliprdr_print_general_capability_flags(cliprdr->log, generalFlags);
 
  168  cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE;
 
  169  cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE;
 
  170  cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE;
 
  171  cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
 
  172  cliprdr->hasHugeFileSupport = (generalFlags & CB_HUGE_FILE_SUPPORT_ENABLED) ? TRUE : FALSE;
 
  173  cliprdr->capabilitiesReceived = TRUE;
 
  175  capabilities.common.msgType = CB_CLIP_CAPS;
 
  176  capabilities.cCapabilitiesSets = 1;
 
  178  generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
 
  179  generalCapabilitySet.capabilitySetLength = 12;
 
  180  generalCapabilitySet.version = version;
 
  181  generalCapabilitySet.generalFlags = generalFlags;
 
  182  IFCALLRET(context->ServerCapabilities, error, context, &capabilities);
 
  185    WLog_Print(cliprdr->log, WLOG_ERROR, 
"ServerCapabilities failed with error %" PRIu32 
"!",
 
  197                                      WINPR_ATTR_UNUSED UINT32 length,
 
  198                                      WINPR_ATTR_UNUSED UINT16 flags)
 
  200  UINT16 lengthCapability = 0;
 
  201  UINT16 cCapabilitiesSets = 0;
 
  202  UINT16 capabilitySetType = 0;
 
  203  UINT error = CHANNEL_RC_OK;
 
  205  WINPR_ASSERT(cliprdr);
 
  208  if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, 4))
 
  209    return ERROR_INVALID_DATA;
 
  211  Stream_Read_UINT16(s, cCapabilitiesSets); 
 
  212  Stream_Seek_UINT16(s);                    
 
  213  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ServerCapabilities");
 
  215  for (UINT16 index = 0; index < cCapabilitiesSets; index++)
 
  217    if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, 4))
 
  218      return ERROR_INVALID_DATA;
 
  220    Stream_Read_UINT16(s, capabilitySetType); 
 
  221    Stream_Read_UINT16(s, lengthCapability);  
 
  223    if ((lengthCapability < 4) ||
 
  224        (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, lengthCapability - 4U)))
 
  225      return ERROR_INVALID_DATA;
 
  227    switch (capabilitySetType)
 
  229      case CB_CAPSTYPE_GENERAL:
 
  230        if ((error = cliprdr_process_general_capability(cliprdr, s)))
 
  232          WLog_Print(cliprdr->log, WLOG_ERROR,
 
  233                     "cliprdr_process_general_capability failed with error %" PRIu32 
"!",
 
  241        WLog_Print(cliprdr->log, WLOG_ERROR, 
"unknown cliprdr capability set: %" PRIu16 
"",
 
  243        return CHANNEL_RC_BAD_PROC;
 
  256                                          UINT32 length, UINT16 flags)
 
  259  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  260  UINT error = CHANNEL_RC_OK;
 
  262  WINPR_ASSERT(cliprdr);
 
  265  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"MonitorReady");
 
  267  if (!cliprdr->capabilitiesReceived)
 
  275    cliprdr->useLongFormatNames = FALSE;
 
  276    cliprdr->streamFileClipEnabled = FALSE;
 
  277    cliprdr->fileClipNoFilePaths = TRUE;
 
  278    cliprdr->canLockClipData = FALSE;
 
  281  monitorReady.common.msgType = CB_MONITOR_READY;
 
  282  monitorReady.common.msgFlags = flags;
 
  283  monitorReady.common.dataLen = length;
 
  284  IFCALLRET(context->MonitorReady, error, context, &monitorReady);
 
  287    WLog_Print(cliprdr->log, WLOG_ERROR, 
"MonitorReady failed with error %" PRIu32 
"!", error);
 
  297static UINT cliprdr_process_filecontents_request(
cliprdrPlugin* cliprdr, 
wStream* s, UINT32 length,
 
  301  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  302  UINT error = CHANNEL_RC_OK;
 
  304  WINPR_ASSERT(cliprdr);
 
  307  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"FileContentsRequest");
 
  309  request.common.msgType = CB_FILECONTENTS_REQUEST;
 
  310  request.common.msgFlags = flags;
 
  311  request.common.dataLen = length;
 
  313  if ((error = cliprdr_read_file_contents_request(s, &request)))
 
  318  if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0)
 
  320    WLog_Print(cliprdr->log, WLOG_WARN, 
"local -> remote file copy disabled, ignoring request");
 
  321    return cliprdr_send_error_response(cliprdr, CB_FILECONTENTS_RESPONSE);
 
  323  IFCALLRET(context->ServerFileContentsRequest, error, context, &request);
 
  326    WLog_Print(cliprdr->log, WLOG_ERROR,
 
  327               "ServerFileContentsRequest failed with error %" PRIu32 
"!", error);
 
  337static UINT cliprdr_process_filecontents_response(
cliprdrPlugin* cliprdr, 
wStream* s, UINT32 length,
 
  341  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  342  UINT error = CHANNEL_RC_OK;
 
  344  WINPR_ASSERT(cliprdr);
 
  347  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"FileContentsResponse");
 
  349  response.common.msgType = CB_FILECONTENTS_RESPONSE;
 
  350  response.common.msgFlags = flags;
 
  351  response.common.dataLen = length;
 
  353  if ((error = cliprdr_read_file_contents_response(s, &response)))
 
  356  IFCALLRET(context->ServerFileContentsResponse, error, context, &response);
 
  359    WLog_Print(cliprdr->log, WLOG_ERROR,
 
  360               "ServerFileContentsResponse failed with error %" PRIu32 
"!", error);
 
  374  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  375  UINT error = CHANNEL_RC_OK;
 
  377  WINPR_ASSERT(cliprdr);
 
  380  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"LockClipData");
 
  382  if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, 4))
 
  383    return ERROR_INVALID_DATA;
 
  385  lockClipboardData.common.msgType = CB_LOCK_CLIPDATA;
 
  386  lockClipboardData.common.msgFlags = flags;
 
  387  lockClipboardData.common.dataLen = length;
 
  388  Stream_Read_UINT32(s, lockClipboardData.clipDataId); 
 
  389  IFCALLRET(context->ServerLockClipboardData, error, context, &lockClipboardData);
 
  392    WLog_Print(cliprdr->log, WLOG_ERROR,
 
  393               "ServerLockClipboardData failed with error %" PRIu32 
"!", error);
 
  407  CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
 
  408  UINT error = CHANNEL_RC_OK;
 
  410  WINPR_ASSERT(cliprdr);
 
  413  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"UnlockClipData");
 
  415  if ((error = cliprdr_read_unlock_clipdata(s, &unlockClipboardData)))
 
  418  unlockClipboardData.common.msgType = CB_UNLOCK_CLIPDATA;
 
  419  unlockClipboardData.common.msgFlags = flags;
 
  420  unlockClipboardData.common.dataLen = length;
 
  422  IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData);
 
  425    WLog_Print(cliprdr->log, WLOG_ERROR,
 
  426               "ServerUnlockClipboardData failed with error %" PRIu32 
"!", error);
 
  436static UINT cliprdr_order_recv(LPVOID userdata, 
wStream* s)
 
  444  WINPR_ASSERT(cliprdr);
 
  447  if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, 8))
 
  448    return ERROR_INVALID_DATA;
 
  450  Stream_Read_UINT16(s, msgType);  
 
  451  Stream_Read_UINT16(s, msgFlags); 
 
  452  Stream_Read_UINT32(s, dataLen);  
 
  454  if (!Stream_CheckAndLogRequiredLengthWLog(cliprdr->log, s, dataLen))
 
  455    return ERROR_INVALID_DATA;
 
  457  char buffer1[64] = { 0 };
 
  458  char buffer2[64] = { 0 };
 
  459  WLog_Print(cliprdr->log, WLOG_DEBUG,
 
  460             "msgType: %s (%" PRIu16 
"), msgFlags: %s dataLen: %" PRIu32 
"",
 
  461             CB_MSG_TYPE_STRING(msgType, buffer1, 
sizeof(buffer1)), msgType,
 
  462             CB_MSG_FLAGS_STRING(msgFlags, buffer2, 
sizeof(buffer2)), dataLen);
 
  467      if ((error = cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags)))
 
  468        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  469                   "cliprdr_process_clip_caps failed with error %" PRIu32 
"!", error);
 
  473    case CB_MONITOR_READY:
 
  474      if ((error = cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags)))
 
  475        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  476                   "cliprdr_process_monitor_ready failed with error %" PRIu32 
"!", error);
 
  481      if ((error = cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags)))
 
  482        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  483                   "cliprdr_process_format_list failed with error %" PRIu32 
"!", error);
 
  487    case CB_FORMAT_LIST_RESPONSE:
 
  488      if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags)))
 
  489        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  490                   "cliprdr_process_format_list_response failed with error %" PRIu32 
"!",
 
  495    case CB_FORMAT_DATA_REQUEST:
 
  496      if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags)))
 
  497        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  498                   "cliprdr_process_format_data_request failed with error %" PRIu32 
"!",
 
  503    case CB_FORMAT_DATA_RESPONSE:
 
  504      if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags)))
 
  505        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  506                   "cliprdr_process_format_data_response failed with error %" PRIu32 
"!",
 
  511    case CB_FILECONTENTS_REQUEST:
 
  512      if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags)))
 
  513        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  514                   "cliprdr_process_filecontents_request failed with error %" PRIu32 
"!",
 
  519    case CB_FILECONTENTS_RESPONSE:
 
  520      if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags)))
 
  521        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  522                   "cliprdr_process_filecontents_response failed with error %" PRIu32 
"!",
 
  527    case CB_LOCK_CLIPDATA:
 
  528      if ((error = cliprdr_process_lock_clipdata(cliprdr, s, dataLen, msgFlags)))
 
  529        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  530                   "cliprdr_process_lock_clipdata failed with error %" PRIu32 
"!", error);
 
  534    case CB_UNLOCK_CLIPDATA:
 
  535      if ((error = cliprdr_process_unlock_clipdata(cliprdr, s, dataLen, msgFlags)))
 
  536        WLog_Print(cliprdr->log, WLOG_ERROR,
 
  537                   "cliprdr_process_unlock_clipdata failed with error %" PRIu32 
"!", error);
 
  542      error = CHANNEL_RC_BAD_PROC;
 
  543      WLog_Print(cliprdr->log, WLOG_ERROR, 
"unknown msgType %" PRIu16 
"", msgType);
 
  547  Stream_Free(s, TRUE);
 
  560static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
 
  568  WINPR_ASSERT(context);
 
  571  WINPR_ASSERT(cliprdr);
 
  573  s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
 
  577    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  578    return ERROR_INTERNAL_ERROR;
 
  581  Stream_Write_UINT16(s, 1); 
 
  582  Stream_Write_UINT16(s, 0); 
 
  584  Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType);   
 
  585  Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); 
 
  586  Stream_Write_UINT32(s, generalCapabilitySet->version);             
 
  587  flags = generalCapabilitySet->generalFlags;
 
  593  if (!cliprdr->useLongFormatNames)
 
  594    flags &= (uint32_t)~CB_USE_LONG_FORMAT_NAMES;
 
  595  if (!cliprdr->streamFileClipEnabled)
 
  596    flags &= (uint32_t)~CB_STREAM_FILECLIP_ENABLED;
 
  597  if (!cliprdr->fileClipNoFilePaths)
 
  598    flags &= (uint32_t)~CB_FILECLIP_NO_FILE_PATHS;
 
  599  if (!cliprdr->canLockClipData)
 
  600    flags &= (uint32_t)~CB_CAN_LOCK_CLIPDATA;
 
  601  if (!cliprdr->hasHugeFileSupport)
 
  602    flags &= (uint32_t)~CB_HUGE_FILE_SUPPORT_ENABLED;
 
  604  cliprdr->useLongFormatNames = (flags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE;
 
  605  cliprdr->streamFileClipEnabled = (flags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE;
 
  606  cliprdr->fileClipNoFilePaths = (flags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE;
 
  607  cliprdr->canLockClipData = (flags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
 
  608  cliprdr->hasHugeFileSupport = (flags & CB_HUGE_FILE_SUPPORT_ENABLED) ? TRUE : FALSE;
 
  610  Stream_Write_UINT32(s, flags); 
 
  611  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientCapabilities");
 
  613  cliprdr->initialFormatListSent = FALSE;
 
  615  return cliprdr_packet_send(cliprdr, s);
 
  623static UINT cliprdr_temp_directory(CliprdrClientContext* context,
 
  629  WINPR_ASSERT(context);
 
  630  WINPR_ASSERT(tempDirectory);
 
  633  WINPR_ASSERT(cliprdr);
 
  635  const size_t tmpDirCharLen = 
sizeof(tempDirectory->szTempDir) / 
sizeof(WCHAR);
 
  636  s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, tmpDirCharLen * 
sizeof(WCHAR));
 
  640    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  641    return ERROR_INTERNAL_ERROR;
 
  644  if (Stream_Write_UTF16_String_From_UTF8(s, tmpDirCharLen - 1, tempDirectory->szTempDir,
 
  645                                          ARRAYSIZE(tempDirectory->szTempDir), TRUE) < 0)
 
  647    Stream_Free(s, TRUE);
 
  648    return ERROR_INTERNAL_ERROR;
 
  652  Stream_Write_UINT16(s, 0);
 
  654  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"TempDirectory: %s", tempDirectory->szTempDir);
 
  655  return cliprdr_packet_send(cliprdr, s);
 
  663static UINT cliprdr_client_format_list(CliprdrClientContext* context,
 
  669  WINPR_ASSERT(context);
 
  670  WINPR_ASSERT(formatList);
 
  673  WINPR_ASSERT(cliprdr);
 
  676    const UINT32 mask = CB_RESPONSE_OK | CB_RESPONSE_FAIL;
 
  677    if ((formatList->common.msgFlags & mask) != 0)
 
  678      WLog_Print(cliprdr->log, WLOG_WARN,
 
  679                 "Sending clipboard request with invalid flags msgFlags = 0x%08" PRIx32
 
  680                 ". Correct in your client!",
 
  681                 formatList->common.msgFlags & mask);
 
  687      formatList, mask, CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES);
 
  690  if ((filterList.numFormats == 0) && cliprdr->initialFormatListSent)
 
  692    cliprdr_free_format_list(&filterList);
 
  693    return CHANNEL_RC_OK;
 
  695  cliprdr->initialFormatListSent = TRUE;
 
  697  const uint32_t level = WLOG_DEBUG;
 
  698  if (WLog_IsLevelActive(cliprdr->log, level))
 
  700    WLog_Print(cliprdr->log, level, 
"ClientFormatList: numFormats: %" PRIu32 
"",
 
  701               formatList->numFormats);
 
  702    for (
size_t x = 0; x < filterList.numFormats; x++)
 
  705      WLog_Print(cliprdr->log, level, 
"[%" PRIuz 
"]: id=0x%08" PRIx32 
" [%s|%s]", x,
 
  706                 format->formatId, ClipboardGetFormatIdString(format->formatId),
 
  711  s = cliprdr_packet_format_list_new(&filterList, cliprdr->useLongFormatNames, FALSE);
 
  712  cliprdr_free_format_list(&filterList);
 
  716    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_format_list_new failed!");
 
  717    return ERROR_INTERNAL_ERROR;
 
  720  return cliprdr_packet_send(cliprdr, s);
 
  729cliprdr_client_format_list_response(CliprdrClientContext* context,
 
  735  WINPR_ASSERT(context);
 
  736  WINPR_ASSERT(formatListResponse);
 
  739  WINPR_ASSERT(cliprdr);
 
  741  s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, formatListResponse->common.msgFlags, 0);
 
  745    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  746    return ERROR_INTERNAL_ERROR;
 
  749  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientFormatListResponse");
 
  750  return cliprdr_packet_send(cliprdr, s);
 
  758static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
 
  764  WINPR_ASSERT(context);
 
  765  WINPR_ASSERT(lockClipboardData);
 
  768  WINPR_ASSERT(cliprdr);
 
  770  s = cliprdr_packet_lock_clipdata_new(lockClipboardData);
 
  774    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_lock_clipdata_new failed!");
 
  775    return ERROR_INTERNAL_ERROR;
 
  778  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientLockClipboardData: clipDataId: 0x%08" PRIX32 
"",
 
  779             lockClipboardData->clipDataId);
 
  780  return cliprdr_packet_send(cliprdr, s);
 
  789cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
 
  795  WINPR_ASSERT(context);
 
  796  WINPR_ASSERT(unlockClipboardData);
 
  799  WINPR_ASSERT(cliprdr);
 
  801  s = cliprdr_packet_unlock_clipdata_new(unlockClipboardData);
 
  805    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_unlock_clipdata_new failed!");
 
  806    return ERROR_INTERNAL_ERROR;
 
  809  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientUnlockClipboardData: clipDataId: 0x%08" PRIX32 
"",
 
  810             unlockClipboardData->clipDataId);
 
  811  return cliprdr_packet_send(cliprdr, s);
 
  819static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
 
  822  WINPR_ASSERT(context);
 
  823  WINPR_ASSERT(formatDataRequest);
 
  826  WINPR_ASSERT(cliprdr);
 
  830  if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0)
 
  832    WLog_Print(cliprdr->log, WLOG_WARN, 
"remote -> local copy disabled, ignoring request");
 
  833    return CHANNEL_RC_OK;
 
  836  wStream* s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
 
  839    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  840    return ERROR_INTERNAL_ERROR;
 
  843  Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); 
 
  844  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientFormatDataRequest(0x%08" PRIx32 
" [%s])",
 
  845             formatDataRequest->requestedFormatId,
 
  846             ClipboardGetFormatIdString(formatDataRequest->requestedFormatId));
 
  847  return cliprdr_packet_send(cliprdr, s);
 
  856cliprdr_client_format_data_response(CliprdrClientContext* context,
 
  859  WINPR_ASSERT(context);
 
  860  WINPR_ASSERT(formatDataResponse);
 
  863  WINPR_ASSERT(cliprdr);
 
  867       (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) != 0);
 
  869  wStream* s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->common.msgFlags,
 
  870                                  formatDataResponse->common.dataLen);
 
  874    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_new failed!");
 
  875    return ERROR_INTERNAL_ERROR;
 
  878  Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->common.dataLen);
 
  879  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientFormatDataResponse");
 
  880  return cliprdr_packet_send(cliprdr, s);
 
  889cliprdr_client_file_contents_request(CliprdrClientContext* context,
 
  894  WINPR_ASSERT(context);
 
  895  WINPR_ASSERT(fileContentsRequest);
 
  899    return ERROR_INTERNAL_ERROR;
 
  903  if ((mask & CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES) == 0)
 
  905    WLog_Print(cliprdr->log, WLOG_WARN, 
"remote -> local file copy disabled, ignoring request");
 
  906    return CHANNEL_RC_OK;
 
  909  if (!cliprdr->hasHugeFileSupport)
 
  911    if (((UINT64)fileContentsRequest->cbRequested + fileContentsRequest->nPositionLow) >
 
  913      return ERROR_INVALID_PARAMETER;
 
  914    if (fileContentsRequest->nPositionHigh != 0)
 
  915      return ERROR_INVALID_PARAMETER;
 
  918  s = cliprdr_packet_file_contents_request_new(fileContentsRequest);
 
  922    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_file_contents_request_new failed!");
 
  923    return ERROR_INTERNAL_ERROR;
 
  926  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientFileContentsRequest: streamId: 0x%08" PRIX32 
"",
 
  927             fileContentsRequest->streamId);
 
  928  return cliprdr_packet_send(cliprdr, s);
 
  937cliprdr_client_file_contents_response(CliprdrClientContext* context,
 
  943  WINPR_ASSERT(context);
 
  944  WINPR_ASSERT(fileContentsResponse);
 
  947  WINPR_ASSERT(cliprdr);
 
  951  if ((mask & CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES) == 0)
 
  952    return cliprdr_send_error_response(cliprdr, CB_FILECONTENTS_RESPONSE);
 
  954  s = cliprdr_packet_file_contents_response_new(fileContentsResponse);
 
  958    WLog_Print(cliprdr->log, WLOG_ERROR, 
"cliprdr_packet_file_contents_response_new failed!");
 
  959    return ERROR_INTERNAL_ERROR;
 
  962  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"ClientFileContentsResponse: streamId: 0x%08" PRIX32 
"",
 
  963             fileContentsResponse->streamId);
 
  964  return cliprdr_packet_send(cliprdr, s);
 
  967static VOID VCAPITYPE cliprdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
 
  968                                                            UINT event, LPVOID pData,
 
  969                                                            UINT32 dataLength, UINT32 totalLength,
 
  972  UINT error = CHANNEL_RC_OK;
 
  974  WINPR_ASSERT(cliprdr);
 
  978    case CHANNEL_EVENT_DATA_RECEIVED:
 
  979      if (cliprdr->OpenHandle != openHandle)
 
  981        WLog_Print(cliprdr->log, WLOG_ERROR, 
"error no match");
 
  984      if ((error = channel_client_post_message(cliprdr->MsgsHandle, pData, dataLength,
 
  985                                               totalLength, dataFlags)))
 
  986        WLog_Print(cliprdr->log, WLOG_ERROR, 
"failed with error %" PRIu32 
"", error);
 
  990    case CHANNEL_EVENT_WRITE_CANCELLED:
 
  991    case CHANNEL_EVENT_WRITE_COMPLETE:
 
  994      Stream_Free(s, TRUE);
 
  998    case CHANNEL_EVENT_USER:
 
 1004  if (error && cliprdr->context->rdpcontext)
 
 1005    setChannelError(cliprdr->context->rdpcontext, error,
 
 1006                    "cliprdr_virtual_channel_open_event_ex reported an error");
 
 1014static UINT cliprdr_virtual_channel_event_connected(
cliprdrPlugin* cliprdr,
 
 1015                                                    WINPR_ATTR_UNUSED LPVOID pData,
 
 1016                                                    WINPR_ATTR_UNUSED UINT32 dataLength)
 
 1019  WINPR_ASSERT(cliprdr);
 
 1020  WINPR_ASSERT(cliprdr->context);
 
 1022  WINPR_ASSERT(cliprdr->channelEntryPoints.pVirtualChannelOpenEx);
 
 1023  status = cliprdr->channelEntryPoints.pVirtualChannelOpenEx(
 
 1024      cliprdr->InitHandle, &cliprdr->OpenHandle, cliprdr->channelDef.name,
 
 1025      cliprdr_virtual_channel_open_event_ex);
 
 1026  if (status != CHANNEL_RC_OK)
 
 1029  cliprdr->MsgsHandle = channel_client_create_handler(
 
 1030      cliprdr->context->rdpcontext, cliprdr, cliprdr_order_recv, CLIPRDR_SVC_CHANNEL_NAME);
 
 1031  if (!cliprdr->MsgsHandle)
 
 1032    return ERROR_INTERNAL_ERROR;
 
 1042static UINT cliprdr_virtual_channel_event_disconnected(
cliprdrPlugin* cliprdr)
 
 1046  WINPR_ASSERT(cliprdr);
 
 1048  channel_client_quit_handler(cliprdr->MsgsHandle);
 
 1049  cliprdr->MsgsHandle = NULL;
 
 1051  if (cliprdr->OpenHandle == 0)
 
 1052    return CHANNEL_RC_OK;
 
 1054  WINPR_ASSERT(cliprdr->channelEntryPoints.pVirtualChannelCloseEx);
 
 1055  rc = cliprdr->channelEntryPoints.pVirtualChannelCloseEx(cliprdr->InitHandle,
 
 1056                                                          cliprdr->OpenHandle);
 
 1058  if (CHANNEL_RC_OK != rc)
 
 1060    WLog_Print(cliprdr->log, WLOG_ERROR, 
"pVirtualChannelClose failed with %s [%08" PRIX32 
"]",
 
 1061               WTSErrorToString(rc), rc);
 
 1065  cliprdr->OpenHandle = 0;
 
 1067  return CHANNEL_RC_OK;
 
 1075static UINT cliprdr_virtual_channel_event_terminated(
cliprdrPlugin* cliprdr)
 
 1077  WINPR_ASSERT(cliprdr);
 
 1079  cliprdr->InitHandle = 0;
 
 1080  free(cliprdr->context);
 
 1082  return CHANNEL_RC_OK;
 
 1085static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
 
 1086                                                            UINT event, LPVOID pData,
 
 1089  UINT error = CHANNEL_RC_OK;
 
 1091  WINPR_ASSERT(cliprdr);
 
 1093  if (cliprdr->InitHandle != pInitHandle)
 
 1095    WLog_Print(cliprdr->log, WLOG_ERROR, 
"error no match");
 
 1101    case CHANNEL_EVENT_CONNECTED:
 
 1102      if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength)))
 
 1103        WLog_Print(cliprdr->log, WLOG_ERROR,
 
 1104                   "cliprdr_virtual_channel_event_connected failed with error %" PRIu32 
"!",
 
 1109    case CHANNEL_EVENT_DISCONNECTED:
 
 1110      if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr)))
 
 1111        WLog_Print(cliprdr->log, WLOG_ERROR,
 
 1112                   "cliprdr_virtual_channel_event_disconnected failed with error %" PRIu32
 
 1118    case CHANNEL_EVENT_TERMINATED:
 
 1119      if ((error = cliprdr_virtual_channel_event_terminated(cliprdr)))
 
 1120        WLog_Print(cliprdr->log, WLOG_ERROR,
 
 1121                   "cliprdr_virtual_channel_event_terminated failed with error %" PRIu32
 
 1129  if (error && cliprdr->context->rdpcontext)
 
 1130    setChannelError(cliprdr->context->rdpcontext, error,
 
 1131                    "cliprdr_virtual_channel_init_event reported an error");
 
 1135#define VirtualChannelEntryEx cliprdr_VirtualChannelEntryEx 
 1137FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints,
 
 1144  wLog* log = WLog_Get(CHANNELS_TAG(
"cliprdr.client"));
 
 1149    WLog_Print(log, WLOG_ERROR, 
"calloc failed!");
 
 1154  cliprdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
 
 1155                                CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
 
 1156  (void)sprintf_s(cliprdr->channelDef.name, ARRAYSIZE(cliprdr->channelDef.name),
 
 1157                  CLIPRDR_SVC_CHANNEL_NAME);
 
 1159  WINPR_ASSERT(pEntryPointsEx);
 
 1162      (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
 
 1164    CliprdrClientContext* context =
 
 1165        (CliprdrClientContext*)calloc(1, 
sizeof(CliprdrClientContext));
 
 1169      WLog_Print(cliprdr->log, WLOG_ERROR, 
"calloc failed!");
 
 1174    context->handle = (
void*)cliprdr;
 
 1175    context->custom = NULL;
 
 1176    context->ClientCapabilities = cliprdr_client_capabilities;
 
 1177    context->TempDirectory = cliprdr_temp_directory;
 
 1178    context->ClientFormatList = cliprdr_client_format_list;
 
 1179    context->ClientFormatListResponse = cliprdr_client_format_list_response;
 
 1180    context->ClientLockClipboardData = cliprdr_client_lock_clipboard_data;
 
 1181    context->ClientUnlockClipboardData = cliprdr_client_unlock_clipboard_data;
 
 1182    context->ClientFormatDataRequest = cliprdr_client_format_data_request;
 
 1183    context->ClientFormatDataResponse = cliprdr_client_format_data_response;
 
 1184    context->ClientFileContentsRequest = cliprdr_client_file_contents_request;
 
 1185    context->ClientFileContentsResponse = cliprdr_client_file_contents_response;
 
 1186    cliprdr->context = context;
 
 1187    context->rdpcontext = pEntryPointsEx->context;
 
 1190  WLog_Print(cliprdr->log, WLOG_DEBUG, 
"VirtualChannelEntryEx");
 
 1191  CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints,
 
 1193  cliprdr->InitHandle = pInitHandle;
 
 1194  rc = cliprdr->channelEntryPoints.pVirtualChannelInitEx(
 
 1195      cliprdr, cliprdr->context, pInitHandle, &cliprdr->channelDef, 1,
 
 1196      VIRTUAL_CHANNEL_VERSION_WIN2000, cliprdr_virtual_channel_init_event_ex);
 
 1198  if (CHANNEL_RC_OK != rc)
 
 1200    WLog_Print(cliprdr->log, WLOG_ERROR, 
"pVirtualChannelInit failed with %s [%08" PRIX32 
"]",
 
 1201               WTSErrorToString(rc), rc);
 
 1202    free(cliprdr->context);
 
 1207  cliprdr->channelEntryPoints.pInterface = cliprdr->context;
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.