22#include <freerdp/config.h> 
   25#include <winpr/assert.h> 
   26#include <winpr/print.h> 
   27#include <winpr/stream.h> 
   29#include <freerdp/freerdp.h> 
   30#include <freerdp/channels/log.h> 
   31#include "cliprdr_main.h" 
   32#include "../cliprdr_common.h" 
   87  WINPR_ASSERT(cliprdr);
 
   89  pos = Stream_GetPosition(s);
 
   90  if ((pos < 8) || (pos > UINT32_MAX))
 
   96  dataLen = (UINT32)(pos - 8);
 
   97  Stream_SetPosition(s, 4);
 
   98  Stream_Write_UINT32(s, dataLen);
 
  100  WINPR_ASSERT(pos <= UINT32_MAX);
 
  101  status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, Stream_BufferAs(s, 
char), (UINT32)pos,
 
  103  rc = status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
 
  105  Stream_Free(s, TRUE);
 
  114static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
 
  119  WINPR_ASSERT(context);
 
  120  WINPR_ASSERT(capabilities);
 
  124  if (capabilities->common.msgType != CB_CLIP_CAPS)
 
  125    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, capabilities->common.msgType);
 
  127  if (capabilities->cCapabilitiesSets > UINT16_MAX)
 
  129    WLog_ERR(TAG, 
"Invalid number of capability sets in clipboard caps");
 
  130    return ERROR_INVALID_PARAMETER;
 
  133  wStream* s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
 
  137    WLog_ERR(TAG, 
"cliprdr_packet_new failed!");
 
  138    return ERROR_INTERNAL_ERROR;
 
  141  Stream_Write_UINT16(s,
 
  142                      (UINT16)capabilities->cCapabilitiesSets); 
 
  143  Stream_Write_UINT16(s, 0);                                    
 
  144  for (UINT32 x = 0; x < capabilities->cCapabilitiesSets; x++)
 
  148    offset += cap->capabilitySetLength;
 
  150    switch (cap->capabilitySetType)
 
  152      case CB_CAPSTYPE_GENERAL:
 
  157            s, generalCapabilitySet->capabilitySetType); 
 
  159            s, generalCapabilitySet->capabilitySetLength); 
 
  160        Stream_Write_UINT32(s, generalCapabilitySet->version); 
 
  162            s, generalCapabilitySet->generalFlags); 
 
  167        WLog_WARN(TAG, 
"Unknown capability set type %08" PRIx16, cap->capabilitySetType);
 
  168        if (!Stream_SafeSeek(s, cap->capabilitySetLength))
 
  170          WLog_ERR(TAG, 
"short stream");
 
  171          Stream_Free(s, TRUE);
 
  172          return ERROR_NO_DATA;
 
  177  WLog_DBG(TAG, 
"ServerCapabilities");
 
  178  return cliprdr_server_packet_send(cliprdr, s);
 
  186static UINT cliprdr_server_monitor_ready(CliprdrServerContext* context,
 
  192  WINPR_ASSERT(context);
 
  193  WINPR_ASSERT(monitorReady);
 
  197  if (monitorReady->common.msgType != CB_MONITOR_READY)
 
  198    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, monitorReady->common.msgType);
 
  200  s = cliprdr_packet_new(CB_MONITOR_READY, monitorReady->common.msgFlags,
 
  201                         monitorReady->common.dataLen);
 
  205    WLog_ERR(TAG, 
"cliprdr_packet_new failed!");
 
  206    return ERROR_INTERNAL_ERROR;
 
  209  WLog_DBG(TAG, 
"ServerMonitorReady");
 
  210  return cliprdr_server_packet_send(cliprdr, s);
 
  218static UINT cliprdr_server_format_list(CliprdrServerContext* context,
 
  224  WINPR_ASSERT(context);
 
  225  WINPR_ASSERT(formatList);
 
  229  s = cliprdr_packet_format_list_new(formatList, context->useLongFormatNames, FALSE);
 
  232    WLog_ERR(TAG, 
"cliprdr_packet_format_list_new failed!");
 
  233    return ERROR_INTERNAL_ERROR;
 
  236  WLog_DBG(TAG, 
"ServerFormatList: numFormats: %" PRIu32 
"", formatList->numFormats);
 
  237  return cliprdr_server_packet_send(cliprdr, s);
 
  246cliprdr_server_format_list_response(CliprdrServerContext* context,
 
  252  WINPR_ASSERT(context);
 
  253  WINPR_ASSERT(formatListResponse);
 
  256  if (formatListResponse->common.msgType != CB_FORMAT_LIST_RESPONSE)
 
  257    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, formatListResponse->common.msgType);
 
  259  s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, formatListResponse->common.msgFlags,
 
  260                         formatListResponse->common.dataLen);
 
  264    WLog_ERR(TAG, 
"cliprdr_packet_new failed!");
 
  265    return ERROR_INTERNAL_ERROR;
 
  268  WLog_DBG(TAG, 
"ServerFormatListResponse");
 
  269  return cliprdr_server_packet_send(cliprdr, s);
 
  277static UINT cliprdr_server_lock_clipboard_data(CliprdrServerContext* context,
 
  283  WINPR_ASSERT(context);
 
  284  WINPR_ASSERT(lockClipboardData);
 
  287  if (lockClipboardData->common.msgType != CB_LOCK_CLIPDATA)
 
  288    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, lockClipboardData->common.msgType);
 
  290  s = cliprdr_packet_lock_clipdata_new(lockClipboardData);
 
  293    WLog_ERR(TAG, 
"cliprdr_packet_lock_clipdata_new failed!");
 
  294    return ERROR_INTERNAL_ERROR;
 
  297  WLog_DBG(TAG, 
"ServerLockClipboardData: clipDataId: 0x%08" PRIX32 
"",
 
  298           lockClipboardData->clipDataId);
 
  299  return cliprdr_server_packet_send(cliprdr, s);
 
  308cliprdr_server_unlock_clipboard_data(CliprdrServerContext* context,
 
  314  WINPR_ASSERT(context);
 
  315  WINPR_ASSERT(unlockClipboardData);
 
  318  if (unlockClipboardData->common.msgType != CB_UNLOCK_CLIPDATA)
 
  319    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, unlockClipboardData->common.msgType);
 
  321  s = cliprdr_packet_unlock_clipdata_new(unlockClipboardData);
 
  325    WLog_ERR(TAG, 
"cliprdr_packet_unlock_clipdata_new failed!");
 
  326    return ERROR_INTERNAL_ERROR;
 
  329  WLog_DBG(TAG, 
"ServerUnlockClipboardData: clipDataId: 0x%08" PRIX32 
"",
 
  330           unlockClipboardData->clipDataId);
 
  331  return cliprdr_server_packet_send(cliprdr, s);
 
  339static UINT cliprdr_server_format_data_request(CliprdrServerContext* context,
 
  345  WINPR_ASSERT(context);
 
  346  WINPR_ASSERT(formatDataRequest);
 
  349  if (formatDataRequest->common.msgType != CB_FORMAT_DATA_REQUEST)
 
  350    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, formatDataRequest->common.msgType);
 
  352  s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, formatDataRequest->common.msgFlags,
 
  353                         formatDataRequest->common.dataLen);
 
  357    WLog_ERR(TAG, 
"cliprdr_packet_new failed!");
 
  358    return ERROR_INTERNAL_ERROR;
 
  361  Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); 
 
  362  WLog_DBG(TAG, 
"ClientFormatDataRequest");
 
  363  return cliprdr_server_packet_send(cliprdr, s);
 
  372cliprdr_server_format_data_response(CliprdrServerContext* context,
 
  378  WINPR_ASSERT(context);
 
  379  WINPR_ASSERT(formatDataResponse);
 
  383  if (formatDataResponse->common.msgType != CB_FORMAT_DATA_RESPONSE)
 
  384    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, formatDataResponse->common.msgType);
 
  386  s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->common.msgFlags,
 
  387                         formatDataResponse->common.dataLen);
 
  391    WLog_ERR(TAG, 
"cliprdr_packet_new failed!");
 
  392    return ERROR_INTERNAL_ERROR;
 
  395  Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->common.dataLen);
 
  396  WLog_DBG(TAG, 
"ServerFormatDataResponse");
 
  397  return cliprdr_server_packet_send(cliprdr, s);
 
  406cliprdr_server_file_contents_request(CliprdrServerContext* context,
 
  412  WINPR_ASSERT(context);
 
  413  WINPR_ASSERT(fileContentsRequest);
 
  417  if (fileContentsRequest->common.msgType != CB_FILECONTENTS_REQUEST)
 
  418    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, fileContentsRequest->common.msgType);
 
  420  s = cliprdr_packet_file_contents_request_new(fileContentsRequest);
 
  423    WLog_ERR(TAG, 
"cliprdr_packet_file_contents_request_new failed!");
 
  424    return ERROR_INTERNAL_ERROR;
 
  427  WLog_DBG(TAG, 
"ServerFileContentsRequest: streamId: 0x%08" PRIX32 
"",
 
  428           fileContentsRequest->streamId);
 
  429  return cliprdr_server_packet_send(cliprdr, s);
 
  438cliprdr_server_file_contents_response(CliprdrServerContext* context,
 
  444  WINPR_ASSERT(context);
 
  445  WINPR_ASSERT(fileContentsResponse);
 
  449  if (fileContentsResponse->common.msgType != CB_FILECONTENTS_RESPONSE)
 
  450    WLog_WARN(TAG, 
"called with invalid type %08" PRIx32, fileContentsResponse->common.msgType);
 
  452  s = cliprdr_packet_file_contents_response_new(fileContentsResponse);
 
  455    WLog_ERR(TAG, 
"cliprdr_packet_file_contents_response_new failed!");
 
  456    return ERROR_INTERNAL_ERROR;
 
  459  WLog_DBG(TAG, 
"ServerFileContentsResponse: streamId: 0x%08" PRIX32 
"",
 
  460           fileContentsResponse->streamId);
 
  461  return cliprdr_server_packet_send(cliprdr, s);
 
  469static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* context, 
wStream* s,
 
  472  WINPR_ASSERT(context);
 
  473  WINPR_ASSERT(cap_set);
 
  475  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
 
  476    return ERROR_INVALID_DATA;
 
  478  Stream_Read_UINT32(s, cap_set->version);      
 
  479  Stream_Read_UINT32(s, cap_set->generalFlags); 
 
  481  if (context->useLongFormatNames)
 
  482    context->useLongFormatNames =
 
  483        (cap_set->generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE;
 
  485  if (context->streamFileClipEnabled)
 
  486    context->streamFileClipEnabled =
 
  487        (cap_set->generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE;
 
  489  if (context->fileClipNoFilePaths)
 
  490    context->fileClipNoFilePaths =
 
  491        (cap_set->generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE;
 
  493  if (context->canLockClipData)
 
  494    context->canLockClipData = (cap_set->generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
 
  496  if (context->hasHugeFileSupport)
 
  497    context->hasHugeFileSupport =
 
  498        (cap_set->generalFlags & CB_HUGE_FILE_SUPPORT_ENABLED) ? TRUE : FALSE;
 
  500  return CHANNEL_RC_OK;
 
  508static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, 
wStream* s,
 
  511  UINT16 capabilitySetType = 0;
 
  512  UINT16 capabilitySetLength = 0;
 
  513  UINT error = ERROR_INVALID_DATA;
 
  514  size_t cap_sets_size = 0;
 
  518  WINPR_ASSERT(context);
 
  519  WINPR_UNUSED(header);
 
  521  WLog_DBG(TAG, 
"CliprdrClientCapabilities");
 
  522  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
  523    return ERROR_INVALID_DATA;
 
  525  Stream_Read_UINT16(s, capabilities.cCapabilitiesSets); 
 
  526  Stream_Seek_UINT16(s);                                 
 
  528  for (
size_t index = 0; index < capabilities.cCapabilitiesSets; index++)
 
  531    if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
  533    Stream_Read_UINT16(s, capabilitySetType);   
 
  534    Stream_Read_UINT16(s, capabilitySetLength); 
 
  536    cap_sets_size += capabilitySetLength;
 
  538    if (cap_sets_size > 0)
 
  539      tmp = realloc(capabilities.capabilitySets, cap_sets_size);
 
  542      WLog_ERR(TAG, 
"capabilities.capabilitySets realloc failed!");
 
  543      free(capabilities.capabilitySets);
 
  544      return CHANNEL_RC_NO_MEMORY;
 
  549    capSet = &(capabilities.capabilitySets[index]);
 
  551    capSet->capabilitySetType = capabilitySetType;
 
  552    capSet->capabilitySetLength = capabilitySetLength;
 
  554    switch (capSet->capabilitySetType)
 
  556      case CB_CAPSTYPE_GENERAL:
 
  557        error = cliprdr_server_receive_general_capability(
 
  562                   "cliprdr_server_receive_general_capability failed with error %" PRIu32
 
  570        WLog_ERR(TAG, 
"unknown cliprdr capability set: %" PRIu16 
"",
 
  571                 capSet->capabilitySetType);
 
  576  error = CHANNEL_RC_OK;
 
  577  IFCALLRET(context->ClientCapabilities, error, context, &capabilities);
 
  579  free(capabilities.capabilitySets);
 
  588static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, 
wStream* s,
 
  594  UINT error = CHANNEL_RC_OK;
 
  596  WINPR_ASSERT(context);
 
  597  WINPR_UNUSED(header);
 
  600  WINPR_ASSERT(cliprdr);
 
  602  if (!Stream_CheckAndLogRequiredLength(TAG, s,
 
  603                                        ARRAYSIZE(cliprdr->temporaryDirectory) * 
sizeof(WCHAR)))
 
  604    return CHANNEL_RC_NO_MEMORY;
 
  606  const WCHAR* wszTempDir = Stream_ConstPointer(s);
 
  608  if (wszTempDir[ARRAYSIZE(cliprdr->temporaryDirectory) - 1] != 0)
 
  610    WLog_ERR(TAG, 
"wszTempDir[259] was not 0");
 
  611    return ERROR_INVALID_DATA;
 
  614  if (ConvertWCharNToUtf8(wszTempDir, ARRAYSIZE(cliprdr->temporaryDirectory),
 
  615                          cliprdr->temporaryDirectory,
 
  616                          ARRAYSIZE(cliprdr->temporaryDirectory)) < 0)
 
  618    WLog_ERR(TAG, 
"failed to convert temporary directory name");
 
  619    return ERROR_INVALID_DATA;
 
  622  length = strnlen(cliprdr->temporaryDirectory, ARRAYSIZE(cliprdr->temporaryDirectory));
 
  624  if (length >= ARRAYSIZE(cliprdr->temporaryDirectory))
 
  625    length = ARRAYSIZE(cliprdr->temporaryDirectory) - 1;
 
  627  CopyMemory(tempDirectory.szTempDir, cliprdr->temporaryDirectory, length);
 
  628  tempDirectory.szTempDir[length] = 
'\0';
 
  629  WLog_DBG(TAG, 
"CliprdrTemporaryDirectory: %s", cliprdr->temporaryDirectory);
 
  630  IFCALLRET(context->TempDirectory, error, context, &tempDirectory);
 
  633    WLog_ERR(TAG, 
"TempDirectory failed with error %" PRIu32 
"!", error);
 
  643static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, 
wStream* s,
 
  647  UINT error = CHANNEL_RC_OK;
 
  649  WINPR_ASSERT(context);
 
  650  WINPR_ASSERT(header);
 
  652  formatList.common.msgType = CB_FORMAT_LIST;
 
  653  formatList.common.msgFlags = header->msgFlags;
 
  654  formatList.common.dataLen = header->dataLen;
 
  656  wLog* log = WLog_Get(TAG);
 
  657  if ((error = cliprdr_read_format_list(log, s, &formatList, context->useLongFormatNames)))
 
  660  WLog_Print(log, WLOG_DEBUG, 
"ClientFormatList: numFormats: %" PRIu32 
"", formatList.numFormats);
 
  661  IFCALLRET(context->ClientFormatList, error, context, &formatList);
 
  664    WLog_Print(log, WLOG_ERROR, 
"ClientFormatList failed with error %" PRIu32 
"!", error);
 
  667  cliprdr_free_format_list(&formatList);
 
  676static UINT cliprdr_server_receive_format_list_response(CliprdrServerContext* context, 
wStream* s,
 
  680  UINT error = CHANNEL_RC_OK;
 
  682  WINPR_ASSERT(context);
 
  683  WINPR_ASSERT(header);
 
  686  WLog_DBG(TAG, 
"CliprdrClientFormatListResponse");
 
  687  formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
 
  688  formatListResponse.common.msgFlags = header->msgFlags;
 
  689  formatListResponse.common.dataLen = header->dataLen;
 
  690  IFCALLRET(context->ClientFormatListResponse, error, context, &formatListResponse);
 
  693    WLog_ERR(TAG, 
"ClientFormatListResponse failed with error %" PRIu32 
"!", error);
 
  703static UINT cliprdr_server_receive_lock_clipdata(CliprdrServerContext* context, 
wStream* s,
 
  707  UINT error = CHANNEL_RC_OK;
 
  709  WINPR_ASSERT(context);
 
  710  WINPR_ASSERT(header);
 
  712  WLog_DBG(TAG, 
"CliprdrClientLockClipData");
 
  714  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
  715    return ERROR_INVALID_DATA;
 
  717  lockClipboardData.common.msgType = CB_LOCK_CLIPDATA;
 
  718  lockClipboardData.common.msgFlags = header->msgFlags;
 
  719  lockClipboardData.common.dataLen = header->dataLen;
 
  720  Stream_Read_UINT32(s, lockClipboardData.clipDataId); 
 
  721  IFCALLRET(context->ClientLockClipboardData, error, context, &lockClipboardData);
 
  724    WLog_ERR(TAG, 
"ClientLockClipboardData failed with error %" PRIu32 
"!", error);
 
  734static UINT cliprdr_server_receive_unlock_clipdata(CliprdrServerContext* context, 
wStream* s,
 
  738  UINT error = CHANNEL_RC_OK;
 
  740  WINPR_ASSERT(context);
 
  741  WINPR_ASSERT(header);
 
  743  WLog_DBG(TAG, 
"CliprdrClientUnlockClipData");
 
  745  unlockClipboardData.common.msgType = CB_UNLOCK_CLIPDATA;
 
  746  unlockClipboardData.common.msgFlags = header->msgFlags;
 
  747  unlockClipboardData.common.dataLen = header->dataLen;
 
  749  if ((error = cliprdr_read_unlock_clipdata(s, &unlockClipboardData)))
 
  752  IFCALLRET(context->ClientUnlockClipboardData, error, context, &unlockClipboardData);
 
  755    WLog_ERR(TAG, 
"ClientUnlockClipboardData failed with error %" PRIu32 
"!", error);
 
  765static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* context, 
wStream* s,
 
  769  UINT error = CHANNEL_RC_OK;
 
  771  WINPR_ASSERT(context);
 
  772  WINPR_ASSERT(header);
 
  774  WLog_DBG(TAG, 
"CliprdrClientFormatDataRequest");
 
  775  formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
 
  776  formatDataRequest.common.msgFlags = header->msgFlags;
 
  777  formatDataRequest.common.dataLen = header->dataLen;
 
  779  if ((error = cliprdr_read_format_data_request(s, &formatDataRequest)))
 
  782  context->lastRequestedFormatId = formatDataRequest.requestedFormatId;
 
  783  IFCALLRET(context->ClientFormatDataRequest, error, context, &formatDataRequest);
 
  786    WLog_ERR(TAG, 
"ClientFormatDataRequest failed with error %" PRIu32 
"!", error);
 
  796static UINT cliprdr_server_receive_format_data_response(CliprdrServerContext* context, 
wStream* s,
 
  800  UINT error = CHANNEL_RC_OK;
 
  802  WINPR_ASSERT(context);
 
  803  WINPR_ASSERT(header);
 
  805  WLog_DBG(TAG, 
"CliprdrClientFormatDataResponse");
 
  806  formatDataResponse.common.msgType = CB_FORMAT_DATA_RESPONSE;
 
  807  formatDataResponse.common.msgFlags = header->msgFlags;
 
  808  formatDataResponse.common.dataLen = header->dataLen;
 
  810  if ((error = cliprdr_read_format_data_response(s, &formatDataResponse)))
 
  813  IFCALLRET(context->ClientFormatDataResponse, error, context, &formatDataResponse);
 
  816    WLog_ERR(TAG, 
"ClientFormatDataResponse failed with error %" PRIu32 
"!", error);
 
  826static UINT cliprdr_server_receive_filecontents_request(CliprdrServerContext* context, 
wStream* s,
 
  830  UINT error = CHANNEL_RC_OK;
 
  832  WINPR_ASSERT(context);
 
  833  WINPR_ASSERT(header);
 
  835  WLog_DBG(TAG, 
"CliprdrClientFileContentsRequest");
 
  836  request.common.msgType = CB_FILECONTENTS_REQUEST;
 
  837  request.common.msgFlags = header->msgFlags;
 
  838  request.common.dataLen = header->dataLen;
 
  840  if ((error = cliprdr_read_file_contents_request(s, &request)))
 
  843  if (!context->hasHugeFileSupport)
 
  845    if (request.nPositionHigh > 0)
 
  846      return ERROR_INVALID_DATA;
 
  847    if ((UINT64)request.nPositionLow + request.cbRequested > UINT32_MAX)
 
  848      return ERROR_INVALID_DATA;
 
  850  IFCALLRET(context->ClientFileContentsRequest, error, context, &request);
 
  853    WLog_ERR(TAG, 
"ClientFileContentsRequest failed with error %" PRIu32 
"!", error);
 
  863static UINT cliprdr_server_receive_filecontents_response(CliprdrServerContext* context, 
wStream* s,
 
  867  UINT error = CHANNEL_RC_OK;
 
  869  WINPR_ASSERT(context);
 
  870  WINPR_ASSERT(header);
 
  872  WLog_DBG(TAG, 
"CliprdrClientFileContentsResponse");
 
  874  response.common.msgType = CB_FILECONTENTS_RESPONSE;
 
  875  response.common.msgFlags = header->msgFlags;
 
  876  response.common.dataLen = header->dataLen;
 
  878  if ((error = cliprdr_read_file_contents_response(s, &response)))
 
  881  IFCALLRET(context->ClientFileContentsResponse, error, context, &response);
 
  884    WLog_ERR(TAG, 
"ClientFileContentsResponse failed with error %" PRIu32 
"!", error);
 
  894static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, 
wStream* s,
 
  899  WINPR_ASSERT(context);
 
  900  WINPR_ASSERT(header);
 
  902  char buffer1[64] = { 0 };
 
  903  char buffer2[64] = { 0 };
 
  904  WLog_DBG(TAG, 
"CliprdrServerReceivePdu: msgType: %s, msgFlags: %s dataLen: %" PRIu32 
"",
 
  905           CB_MSG_TYPE_STRING(header->msgType, buffer1, 
sizeof(buffer1)),
 
  906           CB_MSG_FLAGS_STRING(header->msgFlags, buffer2, 
sizeof(buffer2)), header->dataLen);
 
  908  switch (header->msgType)
 
  911      if ((error = cliprdr_server_receive_capabilities(context, s, header)))
 
  912        WLog_ERR(TAG, 
"cliprdr_server_receive_capabilities failed with error %" PRIu32 
"!",
 
  917    case CB_TEMP_DIRECTORY:
 
  918      if ((error = cliprdr_server_receive_temporary_directory(context, s, header)))
 
  920                 "cliprdr_server_receive_temporary_directory failed with error %" PRIu32
 
  927      if ((error = cliprdr_server_receive_format_list(context, s, header)))
 
  928        WLog_ERR(TAG, 
"cliprdr_server_receive_format_list failed with error %" PRIu32 
"!",
 
  933    case CB_FORMAT_LIST_RESPONSE:
 
  934      if ((error = cliprdr_server_receive_format_list_response(context, s, header)))
 
  936                 "cliprdr_server_receive_format_list_response failed with error %" PRIu32
 
  942    case CB_LOCK_CLIPDATA:
 
  943      if ((error = cliprdr_server_receive_lock_clipdata(context, s, header)))
 
  944        WLog_ERR(TAG, 
"cliprdr_server_receive_lock_clipdata failed with error %" PRIu32 
"!",
 
  949    case CB_UNLOCK_CLIPDATA:
 
  950      if ((error = cliprdr_server_receive_unlock_clipdata(context, s, header)))
 
  952                 "cliprdr_server_receive_unlock_clipdata failed with error %" PRIu32 
"!",
 
  957    case CB_FORMAT_DATA_REQUEST:
 
  958      if ((error = cliprdr_server_receive_format_data_request(context, s, header)))
 
  960                 "cliprdr_server_receive_format_data_request failed with error %" PRIu32
 
  966    case CB_FORMAT_DATA_RESPONSE:
 
  967      if ((error = cliprdr_server_receive_format_data_response(context, s, header)))
 
  969                 "cliprdr_server_receive_format_data_response failed with error %" PRIu32
 
  975    case CB_FILECONTENTS_REQUEST:
 
  976      if ((error = cliprdr_server_receive_filecontents_request(context, s, header)))
 
  978                 "cliprdr_server_receive_filecontents_request failed with error %" PRIu32
 
  984    case CB_FILECONTENTS_RESPONSE:
 
  985      if ((error = cliprdr_server_receive_filecontents_response(context, s, header)))
 
  987                 "cliprdr_server_receive_filecontents_response failed with error %" PRIu32
 
  994      error = ERROR_INVALID_DATA;
 
  995      WLog_ERR(TAG, 
"Unexpected clipboard PDU type: %" PRIu16 
"", header->msgType);
 
 1007static UINT cliprdr_server_init(CliprdrServerContext* context)
 
 1009  UINT32 generalFlags = 0;
 
 1015  WINPR_ASSERT(context);
 
 1017  monitorReady.common.msgType = CB_MONITOR_READY;
 
 1018  capabilities.common.msgType = CB_CLIP_CAPS;
 
 1020  if (context->useLongFormatNames)
 
 1021    generalFlags |= CB_USE_LONG_FORMAT_NAMES;
 
 1023  if (context->streamFileClipEnabled)
 
 1024    generalFlags |= CB_STREAM_FILECLIP_ENABLED;
 
 1026  if (context->fileClipNoFilePaths)
 
 1027    generalFlags |= CB_FILECLIP_NO_FILE_PATHS;
 
 1029  if (context->canLockClipData)
 
 1030    generalFlags |= CB_CAN_LOCK_CLIPDATA;
 
 1032  if (context->hasHugeFileSupport)
 
 1033    generalFlags |= CB_HUGE_FILE_SUPPORT_ENABLED;
 
 1035  capabilities.common.msgType = CB_CLIP_CAPS;
 
 1036  capabilities.common.msgFlags = 0;
 
 1037  capabilities.common.dataLen = 4 + CB_CAPSTYPE_GENERAL_LEN;
 
 1038  capabilities.cCapabilitiesSets = 1;
 
 1040  generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
 
 1041  generalCapabilitySet.capabilitySetLength = CB_CAPSTYPE_GENERAL_LEN;
 
 1042  generalCapabilitySet.version = CB_CAPS_VERSION_2;
 
 1043  generalCapabilitySet.generalFlags = generalFlags;
 
 1045  if ((error = context->ServerCapabilities(context, &capabilities)))
 
 1047    WLog_ERR(TAG, 
"ServerCapabilities failed with error %" PRIu32 
"!", error);
 
 1051  if ((error = context->MonitorReady(context, &monitorReady)))
 
 1053    WLog_ERR(TAG, 
"MonitorReady failed with error %" PRIu32 
"!", error);
 
 1065static UINT cliprdr_server_read(CliprdrServerContext* context)
 
 1068  size_t position = 0;
 
 1069  DWORD BytesToRead = 0;
 
 1070  DWORD BytesReturned = 0;
 
 1076  WINPR_ASSERT(context);
 
 1079  WINPR_ASSERT(cliprdr);
 
 1083  if (Stream_GetPosition(s) < CLIPRDR_HEADER_LENGTH)
 
 1086    BytesToRead = (UINT32)(CLIPRDR_HEADER_LENGTH - Stream_GetPosition(s));
 
 1087    status = WaitForSingleObject(cliprdr->ChannelEvent, 0);
 
 1089    if (status == WAIT_FAILED)
 
 1091      error = GetLastError();
 
 1092      WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1096    if (status == WAIT_TIMEOUT)
 
 1097      return CHANNEL_RC_OK;
 
 1099    if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, Stream_Pointer(s), BytesToRead,
 
 1102      WLog_ERR(TAG, 
"WTSVirtualChannelRead failed!");
 
 1103      return ERROR_INTERNAL_ERROR;
 
 1106    Stream_Seek(s, BytesReturned);
 
 1109  if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
 
 1111    position = Stream_GetPosition(s);
 
 1112    Stream_SetPosition(s, 0);
 
 1113    Stream_Read_UINT16(s, header.msgType);  
 
 1114    Stream_Read_UINT16(s, header.msgFlags); 
 
 1115    Stream_Read_UINT32(s, header.dataLen);  
 
 1117    if (!Stream_EnsureRemainingCapacity(s, header.dataLen))
 
 1119      WLog_ERR(TAG, 
"Stream_EnsureCapacity failed!");
 
 1120      return CHANNEL_RC_NO_MEMORY;
 
 1123    Stream_SetPosition(s, position);
 
 1125    if (Stream_GetPosition(s) < (header.dataLen + CLIPRDR_HEADER_LENGTH))
 
 1129          (UINT32)((header.dataLen + CLIPRDR_HEADER_LENGTH) - Stream_GetPosition(s));
 
 1130      status = WaitForSingleObject(cliprdr->ChannelEvent, 0);
 
 1132      if (status == WAIT_FAILED)
 
 1134        error = GetLastError();
 
 1135        WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1139      if (status == WAIT_TIMEOUT)
 
 1140        return CHANNEL_RC_OK;
 
 1142      if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, Stream_Pointer(s), BytesToRead,
 
 1145        WLog_ERR(TAG, 
"WTSVirtualChannelRead failed!");
 
 1146        return ERROR_INTERNAL_ERROR;
 
 1149      Stream_Seek(s, BytesReturned);
 
 1152    if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH))
 
 1154      Stream_SetPosition(s, (header.dataLen + CLIPRDR_HEADER_LENGTH));
 
 1155      Stream_SealLength(s);
 
 1156      Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH);
 
 1158      if ((error = cliprdr_server_receive_pdu(context, s, &header)))
 
 1160        WLog_ERR(TAG, 
"cliprdr_server_receive_pdu failed with error code %" PRIu32 
"!",
 
 1165      Stream_SetPosition(s, 0);
 
 1167      status = WaitForSingleObject(cliprdr->ChannelEvent, 0);
 
 1169      if (status == WAIT_FAILED)
 
 1171        error = GetLastError();
 
 1172        WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1176      if (status == WAIT_TIMEOUT)
 
 1177        return CHANNEL_RC_OK;
 
 1182      if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, Stream_Pointer(s), BytesToRead,
 
 1185        WLog_ERR(TAG, 
"WTSVirtualChannelRead failed!");
 
 1186        return ERROR_INTERNAL_ERROR;
 
 1189      if (BytesReturned == 4)
 
 1191        Stream_Read_UINT16(s, header.msgType);  
 
 1192        Stream_Read_UINT16(s, header.msgFlags); 
 
 1194        if (!header.msgType)
 
 1197          Stream_SetPosition(s, 0);
 
 1202        Stream_Seek(s, BytesReturned);
 
 1207  return CHANNEL_RC_OK;
 
 1210static DWORD WINAPI cliprdr_server_thread(LPVOID arg)
 
 1214  HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
 
 1215  HANDLE ChannelEvent = NULL;
 
 1216  CliprdrServerContext* context = (CliprdrServerContext*)arg;
 
 1218  UINT error = CHANNEL_RC_OK;
 
 1220  WINPR_ASSERT(context);
 
 1223  WINPR_ASSERT(cliprdr);
 
 1225  ChannelEvent = context->GetEventHandle(context);
 
 1227  events[nCount++] = cliprdr->StopEvent;
 
 1228  events[nCount++] = ChannelEvent;
 
 1230  if (context->autoInitializationSequence)
 
 1232    if ((error = cliprdr_server_init(context)))
 
 1234      WLog_ERR(TAG, 
"cliprdr_server_init failed with error %" PRIu32 
"!", error);
 
 1241    status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
 
 1243    if (status == WAIT_FAILED)
 
 1245      error = GetLastError();
 
 1246      WLog_ERR(TAG, 
"WaitForMultipleObjects failed with error %" PRIu32 
"", error);
 
 1250    status = WaitForSingleObject(cliprdr->StopEvent, 0);
 
 1252    if (status == WAIT_FAILED)
 
 1254      error = GetLastError();
 
 1255      WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1259    if (status == WAIT_OBJECT_0)
 
 1262    status = WaitForSingleObject(ChannelEvent, 0);
 
 1264    if (status == WAIT_FAILED)
 
 1266      error = GetLastError();
 
 1267      WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1271    if (status == WAIT_OBJECT_0)
 
 1273      if ((error = context->CheckEventHandle(context)))
 
 1275        WLog_ERR(TAG, 
"CheckEventHandle failed with error %" PRIu32 
"!", error);
 
 1283  if (error && context->rdpcontext)
 
 1284    setChannelError(context->rdpcontext, error, 
"cliprdr_server_thread reported an error");
 
 1295static UINT cliprdr_server_open(CliprdrServerContext* context)
 
 1297  void* buffer = NULL;
 
 1298  DWORD BytesReturned = 0;
 
 1301  WINPR_ASSERT(context);
 
 1304  WINPR_ASSERT(cliprdr);
 
 1306  cliprdr->ChannelHandle =
 
 1307      WTSVirtualChannelOpen(cliprdr->vcm, WTS_CURRENT_SESSION, CLIPRDR_SVC_CHANNEL_NAME);
 
 1309  if (!cliprdr->ChannelHandle)
 
 1311    WLog_ERR(TAG, 
"WTSVirtualChannelOpen for cliprdr failed!");
 
 1312    return ERROR_INTERNAL_ERROR;
 
 1315  cliprdr->ChannelEvent = NULL;
 
 1317  if (WTSVirtualChannelQuery(cliprdr->ChannelHandle, WTSVirtualEventHandle, &buffer,
 
 1320    if (BytesReturned != 
sizeof(HANDLE))
 
 1322      WLog_ERR(TAG, 
"BytesReturned has not size of HANDLE!");
 
 1323      return ERROR_INTERNAL_ERROR;
 
 1326    cliprdr->ChannelEvent = *(HANDLE*)buffer;
 
 1327    WTSFreeMemory(buffer);
 
 1330  if (!cliprdr->ChannelEvent)
 
 1332    WLog_ERR(TAG, 
"WTSVirtualChannelQuery for cliprdr failed!");
 
 1333    return ERROR_INTERNAL_ERROR;
 
 1336  return CHANNEL_RC_OK;
 
 1344static UINT cliprdr_server_close(CliprdrServerContext* context)
 
 1348  WINPR_ASSERT(context);
 
 1351  WINPR_ASSERT(cliprdr);
 
 1353  if (cliprdr->ChannelHandle)
 
 1355    (void)WTSVirtualChannelClose(cliprdr->ChannelHandle);
 
 1356    cliprdr->ChannelHandle = NULL;
 
 1359  return CHANNEL_RC_OK;
 
 1367static UINT cliprdr_server_start(CliprdrServerContext* context)
 
 1372  WINPR_ASSERT(context);
 
 1375  WINPR_ASSERT(cliprdr);
 
 1377  if (!cliprdr->ChannelHandle)
 
 1379    if ((error = context->Open(context)))
 
 1381      WLog_ERR(TAG, 
"Open failed!");
 
 1386  if (!(cliprdr->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
 1388    WLog_ERR(TAG, 
"CreateEvent failed!");
 
 1389    return ERROR_INTERNAL_ERROR;
 
 1392  if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (
void*)context, 0, NULL)))
 
 1394    WLog_ERR(TAG, 
"CreateThread failed!");
 
 1395    (void)CloseHandle(cliprdr->StopEvent);
 
 1396    cliprdr->StopEvent = NULL;
 
 1397    return ERROR_INTERNAL_ERROR;
 
 1400  return CHANNEL_RC_OK;
 
 1408static UINT cliprdr_server_stop(CliprdrServerContext* context)
 
 1410  UINT error = CHANNEL_RC_OK;
 
 1413  WINPR_ASSERT(context);
 
 1416  WINPR_ASSERT(cliprdr);
 
 1418  if (cliprdr->StopEvent)
 
 1420    (void)SetEvent(cliprdr->StopEvent);
 
 1422    if (WaitForSingleObject(cliprdr->Thread, INFINITE) == WAIT_FAILED)
 
 1424      error = GetLastError();
 
 1425      WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", error);
 
 1429    (void)CloseHandle(cliprdr->Thread);
 
 1430    (void)CloseHandle(cliprdr->StopEvent);
 
 1433  if (cliprdr->ChannelHandle)
 
 1434    return context->Close(context);
 
 1439static HANDLE cliprdr_server_get_event_handle(CliprdrServerContext* context)
 
 1443  WINPR_ASSERT(context);
 
 1446  WINPR_ASSERT(cliprdr);
 
 1447  return cliprdr->ChannelEvent;
 
 1455static UINT cliprdr_server_check_event_handle(CliprdrServerContext* context)
 
 1457  return cliprdr_server_read(context);
 
 1460CliprdrServerContext* cliprdr_server_context_new(HANDLE vcm)
 
 1463  CliprdrServerContext* context = (CliprdrServerContext*)calloc(1, 
sizeof(CliprdrServerContext));
 
 1467    context->autoInitializationSequence = TRUE;
 
 1468    context->Open = cliprdr_server_open;
 
 1469    context->Close = cliprdr_server_close;
 
 1470    context->Start = cliprdr_server_start;
 
 1471    context->Stop = cliprdr_server_stop;
 
 1472    context->GetEventHandle = cliprdr_server_get_event_handle;
 
 1473    context->CheckEventHandle = cliprdr_server_check_event_handle;
 
 1474    context->ServerCapabilities = cliprdr_server_capabilities;
 
 1475    context->MonitorReady = cliprdr_server_monitor_ready;
 
 1476    context->ServerFormatList = cliprdr_server_format_list;
 
 1477    context->ServerFormatListResponse = cliprdr_server_format_list_response;
 
 1478    context->ServerLockClipboardData = cliprdr_server_lock_clipboard_data;
 
 1479    context->ServerUnlockClipboardData = cliprdr_server_unlock_clipboard_data;
 
 1480    context->ServerFormatDataRequest = cliprdr_server_format_data_request;
 
 1481    context->ServerFormatDataResponse = cliprdr_server_format_data_response;
 
 1482    context->ServerFileContentsRequest = cliprdr_server_file_contents_request;
 
 1483    context->ServerFileContentsResponse = cliprdr_server_file_contents_response;
 
 1489      cliprdr->s = Stream_New(NULL, 4096);
 
 1493        WLog_ERR(TAG, 
"Stream_New failed!");
 
 1494        free(context->handle);
 
 1501      WLog_ERR(TAG, 
"calloc failed!");
 
 1510void cliprdr_server_context_free(CliprdrServerContext* context)
 
 1521    Stream_Free(cliprdr->s, TRUE);
 
 1524  free(context->handle);