static int cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsResponse"); if (context->custom) { CLIPRDR_FILE_CONTENTS_RESPONSE response; if (Stream_GetRemainingLength(s) < 4) return -1; response.msgType = CB_FILECONTENTS_RESPONSE; response.msgFlags = flags; response.dataLen = length; Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */ response.cbRequested = length - 4; response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ if (context->ServerFileContentsResponse) context->ServerFileContentsResponse(context, &response); } return 1; }
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); /* http://msdn.microsoft.com/en-us/library/hh872154.aspx */ if (context->custom) { CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; formatListResponse.msgFlags = msgFlags; formatListResponse.dataLen = dataLen; if (context->ServerFormatListResponse) context->ServerFormatListResponse(context, &formatListResponse); } else { if ((msgFlags & CB_RESPONSE_FAIL) != 0) { /* In case of an error the clipboard will not be synchronized with the server. * Post this event to restart format negotiation and data transfer. */ wMessage* event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); } } }
static int cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest"); if (context->custom) { CLIPRDR_FILE_CONTENTS_REQUEST request; if (Stream_GetRemainingLength(s) < 28) return -1; request.msgType = CB_FILECONTENTS_REQUEST; request.msgFlags = flags; request.dataLen = length; Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */ Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */ Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */ Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */ Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */ Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */ Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */ if (context->ServerFileContentsRequest) context->ServerFileContentsRequest(context, &request); } return 1; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought remaining data"); return ERROR_INVALID_DATA; } unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = flags; unlockClipboardData.dataLen = length; Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData); if (error) WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %lu!", error); return error; }
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); if (context->custom) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; formatDataRequest.msgFlags = msgFlags; formatDataRequest.dataLen = dataLen; Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ if (context->ServerFormatDataRequest) context->ServerFormatDataRequest(context, &formatDataRequest); } else { RDP_CB_DATA_REQUEST_EVENT* cb_event; cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataRequest, NULL, NULL); Stream_Read_UINT32(s, cb_event->format); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; formatDataRequest.msgFlags = msgFlags; formatDataRequest.dataLen = dataLen; Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest); if (error) WLog_ERR(TAG, "ServerFormatDataRequest failed with error %lu!", error); return error; }
static int cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData"); if (context->custom) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; if (Stream_GetRemainingLength(s) < 4) return -1; unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = flags; unlockClipboardData.dataLen = length; Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ if (context->ServerUnlockClipboardData) context->ServerUnlockClipboardData(context, &unlockClipboardData); } return 1; }
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); if (context->custom) { CLIPRDR_MONITOR_READY monitorReady; monitorReady.msgType = CB_MONITOR_READY; monitorReady.msgFlags = flags; monitorReady.dataLen = length; if (context->MonitorReady) context->MonitorReady(context, &monitorReady); } else { RDP_CB_MONITOR_READY_EVENT* event; if (cliprdr->received_caps) cliprdr_send_clip_caps(cliprdr); event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; CLIPRDR_CAPABILITIES capabilities; CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; if (!context) { WLog_ERR(TAG, "cliprdr_get_client_interface failed!"); return ERROR_INTERNAL_ERROR; } Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (cliprdr->useLongFormatNames) cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE; if (cliprdr->streamFileClipEnabled) cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE; if (cliprdr->fileClipNoFilePaths) cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE; if (cliprdr->canLockClipData) cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; cliprdr->capabilitiesReceived = TRUE; if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } capabilities.cCapabilitiesSets = 1; capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = version; generalCapabilitySet.generalFlags = generalFlags; IFCALLRET(context->ServerCapabilities, error, context, &capabilities); if (error) WLog_ERR(TAG, "ServerCapabilities failed with error %lu!", error); return error; }
static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; CliprdrClientContext* context; context = cliprdr_get_client_interface(cliprdr); Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = TRUE; if (generalFlags & CB_STREAM_FILECLIP_ENABLED) cliprdr->stream_fileclip_enabled = TRUE; if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) cliprdr->fileclip_no_file_paths = TRUE; if (generalFlags & CB_CAN_LOCK_CLIPDATA) cliprdr->can_lock_clipdata = TRUE; cliprdr->received_caps = TRUE; if (context->custom) { CLIPRDR_CAPABILITIES capabilities; CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; capabilities.cCapabilitiesSets = 1; capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = version; generalCapabilitySet.generalFlags = generalFlags; if (context->ServerCapabilities) context->ServerCapabilities(context, &capabilities); } else { RDP_CB_CLIP_CAPS* caps_event; caps_event = (RDP_CB_CLIP_CAPS*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL); caps_event->capabilities = generalFlags; svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event); } }
static int cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "MonitorReady"); if (context->custom) { CLIPRDR_MONITOR_READY monitorReady; monitorReady.msgType = CB_MONITOR_READY; monitorReady.msgFlags = flags; monitorReady.dataLen = length; if (context->MonitorReady) context->MonitorReady(context, &monitorReady); } return 1; }
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); if (context->custom) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = msgFlags; formatDataResponse.dataLen = dataLen; formatDataResponse.requestedFormatData = NULL; if (dataLen) { formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen); Stream_Read(s, formatDataResponse.requestedFormatData, dataLen); } if (context->ClientFormatDataResponse) context->ClientFormatDataResponse(context, &formatDataResponse); free(formatDataResponse.requestedFormatData); } else { RDP_CB_DATA_RESPONSE_EVENT* cb_event; cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL); if (dataLen > 0) { cb_event->size = dataLen; cb_event->data = (BYTE*) malloc(dataLen); CopyMemory(cb_event->data, Stream_Pointer(s), dataLen); } svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CLIPRDR_FILE_CONTENTS_REQUEST request; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } if (Stream_GetRemainingLength(s) < 28) { WLog_ERR(TAG, "not enought remaining data"); return ERROR_INVALID_DATA; } request.msgType = CB_FILECONTENTS_REQUEST; request.msgFlags = flags; request.dataLen = length; Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */ Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */ Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */ Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */ Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */ Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */ Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */ IFCALLRET(context->ServerFileContentsRequest, error, context, &request); if (error) WLog_ERR(TAG, "ServerFileContentsRequest failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { CLIPRDR_MONITOR_READY monitorReady; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "MonitorReady"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } if (!cliprdr->capabilitiesReceived) { /** * The clipboard capabilities pdu from server to client is optional, * but a server using it must send it before sending the monitor ready pdu. * When the server capabilities pdu is not used, default capabilities * corresponding to a generalFlags field set to zero are assumed. */ cliprdr->useLongFormatNames = FALSE; cliprdr->streamFileClipEnabled = FALSE; cliprdr->fileClipNoFilePaths = TRUE; cliprdr->canLockClipData = FALSE; } monitorReady.msgType = CB_MONITOR_READY; monitorReady.msgFlags = flags; monitorReady.dataLen = length; IFCALLRET(context->MonitorReady, error, context, &monitorReady); if (error) WLog_ERR(TAG, "MonitorReady failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataResponse"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = msgFlags; formatDataResponse.dataLen = dataLen; formatDataResponse.requestedFormatData = NULL; if (dataLen) { formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen); if (!formatDataResponse.requestedFormatData) { WLog_ERR(TAG, "malloc failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Read(s, formatDataResponse.requestedFormatData, dataLen); } IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse); if (error) WLog_ERR(TAG, "ServerFormatDataResponse failed with error %lu!", error); free(formatDataResponse.requestedFormatData); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; formatListResponse.msgFlags = msgFlags; formatListResponse.dataLen = dataLen; IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse); if (error) WLog_ERR(TAG, "ServerFormatListResponse failed with error %lu!", error); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { CLIPRDR_FILE_CONTENTS_RESPONSE response; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsResponse"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } if (Stream_GetRemainingLength(s) < 4) { WLog_ERR(TAG, "not enought remaining data"); return ERROR_INVALID_DATA; } response.msgType = CB_FILECONTENTS_RESPONSE; response.msgFlags = flags; response.dataLen = length; Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */ response.cbRequested = length - 4; response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ IFCALLRET(context->ServerFileContentsResponse, error, context, &response); if (error) WLog_ERR(TAG, "ServerFileContentsResponse failed with error %lu!", error); return error; }
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); if (context->custom) { UINT32 index; int formatNameLength; CLIPRDR_FORMAT* formats; CLIPRDR_FORMAT_LIST formatList; formatList.msgType = CB_FORMAT_LIST; formatList.msgFlags = msgFlags; formatList.dataLen = dataLen; formatList.cFormats = 0; while (dataLen) { Stream_Seek(s, 4); /* formatId */ dataLen -= 4; formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); Stream_Seek(s, (formatNameLength + 1) * 2); dataLen -= ((formatNameLength + 1) * 2); formatList.cFormats++; } index = 0; dataLen = formatList.dataLen; Stream_Rewind(s, dataLen); formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats); formatList.formats = formats; while (dataLen) { Stream_Read_UINT32(s, formats[index].formatId); /* formatId */ dataLen -= 4; formats[index].formatName = NULL; formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); if (formatNameLength) { formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &(formats[index].formatName), 0, NULL, NULL); Stream_Seek(s, formatNameLength * 2); dataLen -= (formatNameLength * 2); } else { Stream_Seek(s, 2); dataLen -= 2; } index++; } if (context->ServerFormatList) context->ServerFormatList(context, &formatList); for (index = 0; index < formatList.cFormats; index++) free(formats[index].formatName); free(formats); } else { int i; UINT32 format; BOOL supported; CLIPRDR_FORMAT_NAME* format_name; RDP_CB_FORMAT_LIST_EVENT* cb_event; cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); if (dataLen > 0) { cb_event->raw_format_data = (BYTE*) malloc(dataLen); memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen); cb_event->raw_format_data_size = dataLen; cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE; } if (cliprdr->use_long_format_names) cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags); else cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags); if (cliprdr->num_format_names > 0) cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names); cb_event->num_formats = 0; for (i = 0; i < cliprdr->num_format_names; i++) { supported = TRUE; format_name = &cliprdr->format_names[i]; format = format_name->id; switch (format) { case CB_FORMAT_TEXT: case CB_FORMAT_DIB: case CB_FORMAT_UNICODETEXT: break; default: if (format_name->length > 0) { DEBUG_CLIPRDR("format: %s", format_name->name); if (strcmp(format_name->name, "HTML Format") == 0) { format = CB_FORMAT_HTML; break; } if (strcmp(format_name->name, "PNG") == 0) { format = CB_FORMAT_PNG; break; } if (strcmp(format_name->name, "JFIF") == 0) { format = CB_FORMAT_JPEG; break; } if (strcmp(format_name->name, "GIF") == 0) { format = CB_FORMAT_GIF; break; } } else { supported = FALSE; } break; } if (supported) cb_event->formats[cb_event->num_formats++] = format; if (format_name->length > 0) free(format_name->name); } free(cliprdr->format_names); cliprdr->format_names = NULL; cliprdr->num_format_names = 0; svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); cliprdr_send_format_list_response(cliprdr); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { UINT32 index; UINT32 position; BOOL asciiNames; int formatNameLength; char* szFormatName; WCHAR* wszFormatName; CLIPRDR_FORMAT* formats = NULL; CLIPRDR_FORMAT_LIST formatList; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } asciiNames = (msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE; formatList.msgType = CB_FORMAT_LIST; formatList.msgFlags = msgFlags; formatList.dataLen = dataLen; index = 0; formatList.numFormats = 0; position = Stream_GetPosition(s); if (!formatList.dataLen) { /* empty format list */ formatList.formats = NULL; formatList.numFormats = 0; } else if (!cliprdr->useLongFormatNames) { formatList.numFormats = (dataLen / 36); if ((formatList.numFormats * 36) != dataLen) { WLog_ERR(TAG, "Invalid short format list length: %d", dataLen); return ERROR_INTERNAL_ERROR; } if (formatList.numFormats) formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); if (!formats) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } formatList.formats = formats; while (dataLen) { Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ dataLen -= 4; formats[index].formatName = NULL; if (asciiNames) { szFormatName = (char*) Stream_Pointer(s); if (szFormatName[0]) { formats[index].formatName = (char*) malloc(32 + 1); if (!formats[index].formatName) { WLog_ERR(TAG, "calloc failed!"); error = CHANNEL_RC_NO_MEMORY; goto error_out; } CopyMemory(formats[index].formatName, szFormatName, 32); formats[index].formatName[32] = '\0'; } } else { wszFormatName = (WCHAR*) Stream_Pointer(s); if (wszFormatName[0]) { ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, &(formats[index].formatName), 0, NULL, NULL); } } Stream_Seek(s, 32); dataLen -= 32; index++; } } else { while (dataLen) { Stream_Seek(s, 4); /* formatId (4 bytes) */ dataLen -= 4; wszFormatName = (WCHAR*) Stream_Pointer(s); if (!wszFormatName[0]) formatNameLength = 0; else formatNameLength = _wcslen(wszFormatName); Stream_Seek(s, (formatNameLength + 1) * 2); dataLen -= ((formatNameLength + 1) * 2); formatList.numFormats++; } dataLen = formatList.dataLen; Stream_SetPosition(s, position); if (formatList.numFormats) formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); if (!formats) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } formatList.formats = formats; while (dataLen) { Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ dataLen -= 4; formats[index].formatName = NULL; wszFormatName = (WCHAR*) Stream_Pointer(s); if (!wszFormatName[0]) formatNameLength = 0; else formatNameLength = _wcslen(wszFormatName); if (formatNameLength) { ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, &(formats[index].formatName), 0, NULL, NULL); } Stream_Seek(s, (formatNameLength + 1) * 2); dataLen -= ((formatNameLength + 1) * 2); index++; } } WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %d", formatList.numFormats); if (context->ServerFormatList) { if ((error = context->ServerFormatList(context, &formatList))) WLog_ERR(TAG, "ServerFormatList failed with error %d", error); } error_out: if (formats) { for (index = 0; index < formatList.numFormats; index++) { free(formats[index].formatName); } free(formats); } return error; }