From 43516beb70075974c7d3b8615f2a6065af5ff4f7 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 24 Nov 2020 11:00:13 +0100 Subject: [PATCH] Fixed support for huge files in clipboard (cherry picked from commit f3dad4106a62cf29db0685221cd90b751e3ac2b1) --- channels/cliprdr/client/cliprdr_format.c | 25 +++++++++++++++--- channels/cliprdr/client/cliprdr_main.c | 44 ++++++++++++++++++++++---------- client/X11/xf_cliprdr.c | 9 ++++--- include/freerdp/channels/cliprdr.h | 4 +++ libfreerdp/core/fastpath.c | 1 - winpr/libwinpr/crt/string.c | 13 +++------- 6 files changed, 65 insertions(+), 31 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 43b967e..8359ca9 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -292,6 +292,14 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, UINT32 file_descriptor_count, BYTE** format_data, UINT32* format_data_length) { + return cliprdr_serialize_file_list_ex(CB_STREAM_FILECLIP_ENABLED, file_descriptor_array, + file_descriptor_count, format_data, format_data_length); +} + +UINT cliprdr_serialize_file_list_ex(UINT32 flags, const FILEDESCRIPTORW* file_descriptor_array, + UINT32 file_descriptor_count, BYTE** format_data, + UINT32* format_data_length) +{ UINT result = NO_ERROR; UINT32 i; wStream* s = NULL; @@ -299,6 +307,12 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, if (!file_descriptor_array || !format_data || !format_data_length) return ERROR_BAD_ARGUMENTS; + if ((flags & CB_STREAM_FILECLIP_ENABLED) == 0) + { + WLog_WARN(TAG, "No file clipboard support annouonced!"); + return ERROR_BAD_ARGUMENTS; + } + s = Stream_New(NULL, 4 + file_descriptor_count * CLIPRDR_FILEDESCRIPTOR_SIZE); if (!s) return ERROR_NOT_ENOUGH_MEMORY; @@ -318,11 +332,14 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, * * https://support.microsoft.com/en-us/help/2258090 */ - if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE)) + if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0) { - WLog_ERR(TAG, "cliprdr does not support files over 2 GB"); - result = ERROR_FILE_TOO_LARGE; - goto error; + if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE)) + { + WLog_ERR(TAG, "cliprdr does not support files over 2 GB"); + result = ERROR_FILE_TOO_LARGE; + goto error; + } } Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */ diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 12c2d6f..5aed224 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -36,18 +36,36 @@ #include "../cliprdr_common.h" #ifdef WITH_DEBUG_CLIPRDR -static const char* const CB_MSG_TYPE_STRINGS[] = { "", - "CB_MONITOR_READY", - "CB_FORMAT_LIST", - "CB_FORMAT_LIST_RESPONSE", - "CB_FORMAT_DATA_REQUEST", - "CB_FORMAT_DATA_RESPONSE", - "CB_TEMP_DIRECTORY", - "CB_CLIP_CAPS", - "CB_FILECONTENTS_REQUEST", - "CB_FILECONTENTS_RESPONSE", - "CB_LOCK_CLIPDATA", - "CB_UNLOCK_CLIPDATA" }; +static const char* CB_MSG_TYPE_STRINGS(UINT32 type) +{ + switch (type) + { + case CB_MONITOR_READY: + return "CB_MONITOR_READY"; + case CB_FORMAT_LIST: + return "CB_FORMAT_LIST"; + case CB_FORMAT_LIST_RESPONSE: + return "CB_FORMAT_LIST_RESPONSE"; + case CB_FORMAT_DATA_REQUEST: + return "CB_FORMAT_DATA_REQUEST"; + case CB_FORMAT_DATA_RESPONSE: + return "CB_FORMAT_DATA_RESPONSE"; + case CB_TEMP_DIRECTORY: + return "CB_TEMP_DIRECTORY"; + case CB_CLIP_CAPS: + return "CB_CLIP_CAPS"; + case CB_FILECONTENTS_REQUEST: + return "CB_FILECONTENTS_REQUEST"; + case CB_FILECONTENTS_RESPONSE: + return "CB_FILECONTENTS_RESPONSE"; + case CB_LOCK_CLIPDATA: + return "CB_LOCK_CLIPDATA"; + case CB_UNLOCK_CLIPDATA: + return "CB_UNLOCK_CLIPDATA"; + default: + return "UNKNOWN"; + } +} #endif CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr) @@ -445,7 +463,7 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) #ifdef WITH_DEBUG_CLIPRDR WLog_DBG(TAG, "msgType: %s (%" PRIu16 "), msgFlags: %" PRIu16 " dataLen: %" PRIu32 "", - CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); + CB_MSG_TYPE_STRINGS(msgType), msgType, msgFlags, dataLen); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index d297d21..b7d6b23 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -108,6 +108,7 @@ struct xf_clipboard /* File clipping */ BOOL streams_supported; BOOL file_formats_registered; + UINT32 file_capability_flags; }; static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard); @@ -636,11 +637,12 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa (dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW"))) { UINT error = NO_ERROR; - FILEDESCRIPTOR* file_array = (FILEDESCRIPTOR*)pDstData; - UINT32 file_count = DstSize / sizeof(FILEDESCRIPTOR); + FILEDESCRIPTORW* file_array = (FILEDESCRIPTORW*)pDstData; + UINT32 file_count = DstSize / sizeof(FILEDESCRIPTORW); pDstData = NULL; DstSize = 0; - error = cliprdr_serialize_file_list(file_array, file_count, &pDstData, &DstSize); + error = cliprdr_serialize_file_list_ex(clipboard->file_capability_flags, file_array, + file_count, &pDstData, &DstSize); if (error) WLog_ERR(TAG, "failed to serialize CLIPRDR_FILELIST: 0x%08X", error); @@ -1085,6 +1087,7 @@ static UINT xf_cliprdr_send_client_capabilities(xfClipboard* clipboard) generalCapabilitySet.generalFlags |= CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS | CB_HUGE_FILE_SUPPORT_ENABLED; + clipboard->file_capability_flags = generalCapabilitySet.generalFlags; return clipboard->context->ClientCapabilities(clipboard->context, &capabilities); } diff --git a/include/freerdp/channels/cliprdr.h b/include/freerdp/channels/cliprdr.h index b01e8bd..a016be1 100644 --- a/include/freerdp/channels/cliprdr.h +++ b/include/freerdp/channels/cliprdr.h @@ -99,6 +99,10 @@ extern "C" FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, UINT32 file_descriptor_count, BYTE** format_data, UINT32* format_data_length); + FREERDP_API UINT cliprdr_serialize_file_list_ex(UINT32 flags, + const FILEDESCRIPTORW* file_descriptor_array, + UINT32 file_descriptor_count, + BYTE** format_data, UINT32* format_data_length); #ifdef __cplusplus } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 2271be3..7a67638 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -317,7 +317,6 @@ static BOOL fastpath_recv_update_common(rdpFastPath* fastpath, wStream* s) return FALSE; Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */ - switch (updateType) { case UPDATE_TYPE_BITMAP: diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index a25aac4..37fcb4b 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -52,20 +52,13 @@ char* _strdup(const char* strSource) WCHAR* _wcsdup(const WCHAR* strSource) { + size_t len = _wcslen(strSource); WCHAR* strDestination; - if (strSource == NULL) - return NULL; - -#if defined(__APPLE__) && defined(__MACH__) || defined(ANDROID) || defined(sun) - strDestination = malloc(wcslen((wchar_t*)strSource)); + strDestination = calloc(len + 1, sizeof(WCHAR)); if (strDestination != NULL) - wcscpy((wchar_t*)strDestination, (const wchar_t*)strSource); - -#else - strDestination = (WCHAR*)wcsdup((wchar_t*)strSource); -#endif + memcpy(strDestination, strSource, len * sizeof(WCHAR)); if (strDestination == NULL) WLog_ERR(TAG, "wcsdup"); -- 2.7.4