From c4ab4ad12887a642d7007967055d1825de408d1b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andre=CC=81=20Moreau?= Date: Thu, 20 Nov 2014 14:28:05 -0500 Subject: [PATCH] channels/cliprdr: partially fix short format names --- channels/cliprdr/client/cliprdr_format.c | 298 ++++++++++++++-------------- channels/cliprdr/client/cliprdr_main.c | 320 +++++++++++++++++++------------ channels/cliprdr/client/cliprdr_main.h | 13 +- 3 files changed, 344 insertions(+), 287 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 3a52a0a..af2f958 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -32,127 +32,117 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" -void cliprdr_process_short_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) +void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - int i; - BOOL ascii; - int num_formats; - CLIPRDR_FORMAT_NAME* format_name; - - num_formats = length / 36; + 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); - if (num_formats <= 0) - { - cliprdr->format_names = NULL; - cliprdr->num_format_names = 0; + if (!context->custom) return; - } - - if (num_formats * 36 != length) - WLog_ERR(TAG, "dataLen %d not divided by 36!", length); - - ascii = (flags & CB_ASCII_NAMES) ? TRUE : FALSE; - - cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) malloc(sizeof(CLIPRDR_FORMAT_NAME) * num_formats); - cliprdr->num_format_names = num_formats; - - for (i = 0; i < num_formats; i++) - { - format_name = &cliprdr->format_names[i]; - - Stream_Read_UINT32(s, format_name->id); - - if (ascii) - { - format_name->name = _strdup((char*) s->pointer); - format_name->length = strlen(format_name->name); - } - else - { - format_name->name = NULL; - format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) s->pointer, 32 / 2, &format_name->name, 0, NULL, NULL); - } - - Stream_Seek(s, 32); - } -} - -void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) -{ - int allocated_formats = 8; - BYTE* end_mark; - CLIPRDR_FORMAT_NAME* format_name; - Stream_GetPointer(s, end_mark); - end_mark += length; - - cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) malloc(sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); - cliprdr->num_format_names = 0; + asciiNames = (msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE; + + formatList.msgType = CB_FORMAT_LIST; + formatList.msgFlags = msgFlags; + formatList.dataLen = dataLen; - while (Stream_GetRemainingLength(s) >= 6) + index = 0; + formatList.numFormats = 0; + position = Stream_GetPosition(s); + + if (!cliprdr->useLongFormatNames) { - BYTE* p; - int name_len; + formatList.numFormats = (dataLen / 36); - if (cliprdr->num_format_names >= allocated_formats) + if ((formatList.numFormats * 36) != dataLen) { - allocated_formats *= 2; - cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) realloc(cliprdr->format_names, - sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); + WLog_ERR(TAG, "Invalid short format list length: %d", dataLen); + return; } - format_name = &cliprdr->format_names[cliprdr->num_format_names++]; - Stream_Read_UINT32(s, format_name->id); + if (formatList.numFormats) + formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); - format_name->name = NULL; - format_name->length = 0; - - for (p = Stream_Pointer(s), name_len = 0; p + 1 < end_mark; p += 2, name_len += 2) + if (!formats) + return; + + formatList.formats = formats; + + while (dataLen) { - if (*((unsigned short*) p) == 0) - break; + 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]) + formatNameLength = 0; + else + formatNameLength = strlen(szFormatName); + + if (formatNameLength) + { + formats[index].formatName = _strdup(szFormatName); + } + } + else + { + 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, 32); + dataLen -= 32; + index++; } - - format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), name_len / 2, &format_name->name, 0, NULL, NULL); - - Stream_Seek(s, name_len + 2); } -} - -void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) -{ - CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); - - if (context->custom) + else { - UINT32 index; - int formatNameLength; - CLIPRDR_FORMAT* formats = NULL; - CLIPRDR_FORMAT_LIST formatList; - - formatList.msgType = CB_FORMAT_LIST; - formatList.msgFlags = msgFlags; - formatList.dataLen = dataLen; - - formatList.numFormats = 0; - while (dataLen) { - Stream_Seek(s, 4); /* formatId */ + Stream_Seek(s, 4); /* formatId (4 bytes) */ dataLen -= 4; - - formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); + + 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++; } - index = 0; dataLen = formatList.dataLen; - Stream_Rewind(s, dataLen); + Stream_SetPosition(s, position); if (formatList.numFormats) formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); + if (!formats) return; @@ -160,110 +150,110 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data while (dataLen) { - Stream_Read_UINT32(s, formats[index].formatId); /* formatId */ + Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ dataLen -= 4; formats[index].formatName = NULL; - formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); + + wszFormatName = (WCHAR*) Stream_Pointer(s); + + if (!wszFormatName[0]) + formatNameLength = 0; + else + formatNameLength = _wcslen(wszFormatName); if (formatNameLength) { - formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), + formatNameLength = ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, &(formats[index].formatName), 0, NULL, NULL); - - Stream_Seek(s, formatNameLength * 2); - dataLen -= (formatNameLength * 2); - } - else - { - formats[index].formatName = NULL; - Stream_Seek(s, 2); - dataLen -= 2; } + + Stream_Seek(s, (formatNameLength + 1) * 2); + dataLen -= ((formatNameLength + 1) * 2); index++; } + } - WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %d", - formatList.numFormats); + WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %d", + formatList.numFormats); - if (context->ServerFormatList) - context->ServerFormatList(context, &formatList); + if (context->ServerFormatList) + context->ServerFormatList(context, &formatList); - for (index = 0; index < formatList.numFormats; index++) - { - if (formats[index].formatName) - free(formats[index].formatName); - } - - free(formats); + for (index = 0; index < formatList.numFormats; index++) + { + fprintf(stderr, "[%02d] Format: 0x%04X %s\n", + index, formats[index].formatId, formats[index].formatName); + + if (formats[index].formatName) + free(formats[index].formatName); } + + free(formats); } void 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); WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse"); - if (context->custom) - { - CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; + if (!context->custom) + return; - formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; - formatListResponse.msgFlags = msgFlags; - formatListResponse.dataLen = dataLen; + formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; + formatListResponse.msgFlags = msgFlags; + formatListResponse.dataLen = dataLen; - if (context->ServerFormatListResponse) - context->ServerFormatListResponse(context, &formatListResponse); - } + if (context->ServerFormatListResponse) + context->ServerFormatListResponse(context, &formatListResponse); } void 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); WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest"); - if (context->custom) - { - CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; + if (!context->custom) + return; - formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest.msgFlags = msgFlags; - formatDataRequest.dataLen = dataLen; + formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest.msgFlags = msgFlags; + formatDataRequest.dataLen = dataLen; - Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ + Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ - if (context->ServerFormatDataRequest) - context->ServerFormatDataRequest(context, &formatDataRequest); - } + if (context->ServerFormatDataRequest) + context->ServerFormatDataRequest(context, &formatDataRequest); } void 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); WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataResponse"); - 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->ServerFormatDataResponse) - context->ServerFormatDataResponse(context, &formatDataResponse); + if (!context->custom) + return; - free(formatDataResponse.requestedFormatData); + 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->ServerFormatDataResponse) + context->ServerFormatDataResponse(context, &formatDataResponse); + + free(formatDataResponse.requestedFormatData); } diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index a481e9a..26ab10b 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -32,7 +32,7 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" -static const char* const CB_MSG_TYPE_STRINGS[] = +const char* const CB_MSG_TYPE_STRINGS[] = { "", "CB_MONITOR_READY", @@ -129,59 +129,61 @@ static int cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s { UINT32 version; UINT32 generalFlags; - CliprdrClientContext* context; - context = cliprdr_get_client_interface(cliprdr); + CLIPRDR_CAPABILITIES capabilities; + CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; + CliprdrClientContext* 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 (cliprdr->useLongFormatNames) + cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE; - if (generalFlags & CB_STREAM_FILECLIP_ENABLED) - cliprdr->stream_fileclip_enabled = TRUE; + if (cliprdr->streamFileClipEnabled) + cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE; - if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) - cliprdr->fileclip_no_file_paths = TRUE; + if (cliprdr->fileClipNoFilePaths) + cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE; - if (generalFlags & CB_CAN_LOCK_CLIPDATA) - cliprdr->can_lock_clipdata = TRUE; + if (cliprdr->canLockClipData) + cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; + + cliprdr->capabilitiesReceived = TRUE; - cliprdr->received_caps = TRUE; + if (!context->custom) + return -1; + + 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->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); - } + if (context->ServerCapabilities) + context->ServerCapabilities(context, &capabilities); return 1; } static int cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { - int i; + UINT16 index; UINT16 lengthCapability; UINT16 cCapabilitiesSets; UINT16 capabilitySetType; + Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerCapabilities"); - for (i = 0; i < cCapabilitiesSets; i++) + for (index = 0; index < cCapabilitiesSets; index++) { Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ @@ -191,6 +193,7 @@ static int cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 case CB_CAPSTYPE_GENERAL: cliprdr_process_general_capability(cliprdr, s); break; + default: WLog_ERR(TAG, "unknown cliprdr capability set: %d", capabilitySetType); break; @@ -202,133 +205,144 @@ static int cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 static int cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { + CLIPRDR_MONITOR_READY monitorReady; 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->custom) + return -1; - if (context->MonitorReady) - context->MonitorReady(context, &monitorReady); + 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; + + if (context->MonitorReady) + context->MonitorReady(context, &monitorReady); return 1; } static int cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { + CLIPRDR_FILE_CONTENTS_REQUEST request; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest"); - if (context->custom) - { - CLIPRDR_FILE_CONTENTS_REQUEST request; + if (!context->custom) + return -1; - if (Stream_GetRemainingLength(s) < 28) - return -1; + if (Stream_GetRemainingLength(s) < 28) + return -1; - request.msgType = CB_FILECONTENTS_REQUEST; - request.msgFlags = flags; - request.dataLen = length; + 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) */ + 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); - } + if (context->ServerFileContentsRequest) + context->ServerFileContentsRequest(context, &request); return 1; } static int cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { + CLIPRDR_FILE_CONTENTS_RESPONSE response; 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; + if (!context->custom) + return -1; + + if (Stream_GetRemainingLength(s) < 4) + return -1; - response.msgType = CB_FILECONTENTS_RESPONSE; - response.msgFlags = flags; - response.dataLen = length; + 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 */ + 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); - } + if (context->ServerFileContentsResponse) + context->ServerFileContentsResponse(context, &response); return 1; } static int cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { + CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); WLog_Print(cliprdr->log, WLOG_DEBUG, "LockClipData"); - if (context->custom) - { - CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData; - - if (Stream_GetRemainingLength(s) < 4) - return -1; + if (!context->custom) + return -1; + + if (Stream_GetRemainingLength(s) < 4) + return -1; - lockClipboardData.msgType = CB_LOCK_CLIPDATA; - lockClipboardData.msgFlags = flags; - lockClipboardData.dataLen = length; + lockClipboardData.msgType = CB_LOCK_CLIPDATA; + lockClipboardData.msgFlags = flags; + lockClipboardData.dataLen = length; - Stream_Read_UINT32(s, lockClipboardData.clipDataId); /* clipDataId (4 bytes) */ + Stream_Read_UINT32(s, lockClipboardData.clipDataId); /* clipDataId (4 bytes) */ - if (context->ServerLockClipboardData) - context->ServerLockClipboardData(context, &lockClipboardData); - } + if (context->ServerLockClipboardData) + context->ServerLockClipboardData(context, &lockClipboardData); return 1; } static int cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { + CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; 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; + if (!context->custom) + return -1; + + if (Stream_GetRemainingLength(s) < 4) + return -1; - unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; - unlockClipboardData.msgFlags = flags; - unlockClipboardData.dataLen = length; + unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; + unlockClipboardData.msgFlags = flags; + unlockClipboardData.dataLen = length; - Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ + Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ - if (context->ServerUnlockClipboardData) - context->ServerUnlockClipboardData(context, &unlockClipboardData); - } + if (context->ServerUnlockClipboardData) + context->ServerUnlockClipboardData(context, &unlockClipboardData); return 1; } @@ -339,9 +353,9 @@ static void cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) UINT16 msgFlags; UINT32 dataLen; - Stream_Read_UINT16(s, msgType); - Stream_Read_UINT16(s, msgFlags); - Stream_Read_UINT32(s, dataLen); + Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */ + Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */ + Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); @@ -459,47 +473,98 @@ int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIS wStream* s; UINT32 index; int length = 0; + int cchWideChar; + LPWSTR lpWideCharStr; int formatNameSize; + int formatNameLength; + char* szFormatName; + WCHAR* wszFormatName; + BOOL asciiNames = FALSE; CLIPRDR_FORMAT* format; cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - for (index = 0; index < formatList->numFormats; index++) + if (!cliprdr->useLongFormatNames) { - format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); - length += 4; - formatNameSize = 2; - - if (format->formatName) - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2; - - length += formatNameSize; + length = formatList->numFormats * 36; + + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + + for (index = 0; index < formatList->numFormats; index++) + { + format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); + + Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ + + formatNameSize = 0; + formatNameLength = 0; + + szFormatName = format->formatName; + + if (asciiNames) + { + if (szFormatName) + formatNameLength = strlen(szFormatName); + + if (formatNameLength > 31) + formatNameLength = 31; + + Stream_Write(s, szFormatName, formatNameLength); + Stream_Zero(s, 32 - formatNameLength); + } + else + { + wszFormatName = NULL; + + if (szFormatName) + formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0); + + if (formatNameSize > 15) + formatNameSize = 15; + + Stream_Write(s, wszFormatName, formatNameSize * 2); + Stream_Zero(s, 32 - (formatNameSize * 2)); + } + } } - - s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); - - for (index = 0; index < formatList->numFormats; index++) + else { - format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); - Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ - - if (format->formatName) + for (index = 0; index < formatList->numFormats; index++) { - int cchWideChar; - LPWSTR lpWideCharStr; - lpWideCharStr = (LPWSTR) Stream_Pointer(s); - cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, - format->formatName, -1, lpWideCharStr, cchWideChar) * 2; - Stream_Seek(s, formatNameSize); + format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); + length += 4; + formatNameSize = 2; + + if (format->formatName) + formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2; + + length += formatNameSize; } - else + + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + + for (index = 0; index < formatList->numFormats; index++) { - Stream_Write_UINT16(s, 0); + format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); + Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ + + if (format->formatName) + { + lpWideCharStr = (LPWSTR) Stream_Pointer(s); + cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; + formatNameSize = MultiByteToWideChar(CP_UTF8, 0, + format->formatName, -1, lpWideCharStr, cchWideChar) * 2; + Stream_Seek(s, formatNameSize); + } + else + { + Stream_Write_UINT16(s, 0); + } } } WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %d", formatList->numFormats); + cliprdr_packet_send(cliprdr, s); return 0; @@ -897,6 +962,11 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client"); + cliprdr->useLongFormatNames = TRUE; + cliprdr->streamFileClipEnabled = FALSE; + cliprdr->fileClipNoFilePaths = TRUE; + cliprdr->canLockClipData = FALSE; + WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntry"); CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index 28ff62d..65926dd 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -41,14 +41,11 @@ struct cliprdr_plugin DWORD OpenHandle; wMessagePipe* MsgPipe; - int num_format_names; - CLIPRDR_FORMAT_NAME* format_names; - - BOOL received_caps; - BOOL use_long_format_names; - BOOL stream_fileclip_enabled; - BOOL fileclip_no_file_paths; - BOOL can_lock_clipdata; + BOOL capabilitiesReceived; + BOOL useLongFormatNames; + BOOL streamFileClipEnabled; + BOOL fileClipNoFilePaths; + BOOL canLockClipData; }; typedef struct cliprdr_plugin cliprdrPlugin; -- 2.7.4