Fixed support for huge files in clipboard
authorakallabeth <akallabeth@posteo.net>
Tue, 24 Nov 2020 10:00:13 +0000 (11:00 +0100)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
(cherry picked from commit f3dad4106a62cf29db0685221cd90b751e3ac2b1)

channels/cliprdr/client/cliprdr_format.c
channels/cliprdr/client/cliprdr_main.c
client/X11/xf_cliprdr.c
include/freerdp/channels/cliprdr.h
libfreerdp/core/fastpath.c
winpr/libwinpr/crt/string.c

index 43b967e..8359ca9 100644 (file)
@@ -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) */
index 12c2d6f..5aed224 100644 (file)
 #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
 
index d297d21..b7d6b23 100644 (file)
@@ -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);
 }
 
index b01e8bd..a016be1 100644 (file)
@@ -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
 }
index 2271be3..7a67638 100644 (file)
@@ -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:
index a25aac4..37fcb4b 100644 (file)
@@ -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");