561 lines
19 KiB
Diff
561 lines
19 KiB
Diff
|
From a441e68fccc8ef137c9e8e667fed6adaab34ba37 Mon Sep 17 00:00:00 2001
|
||
|
From: Ondrej Holy <oholy@redhat.com>
|
||
|
Date: Tue, 1 Oct 2024 15:43:07 +0200
|
||
|
Subject: [PATCH] Revert "Moved clipboard utils to core library, fixes #6760
|
||
|
(#7752)"
|
||
|
|
||
|
This reverts commit 26a83e6ccde272c1bbc2b2591325dc7a493811bc.
|
||
|
---
|
||
|
channels/cliprdr/client/cliprdr_format.c | 195 +++++++++++++++++++
|
||
|
include/freerdp/channels/cliprdr.h | 12 +-
|
||
|
include/freerdp/utils/cliprdr_utils.h | 48 -----
|
||
|
libfreerdp/utils/CMakeLists.txt | 1 -
|
||
|
libfreerdp/utils/cliprdr_utils.c | 235 -----------------------
|
||
|
5 files changed, 206 insertions(+), 285 deletions(-)
|
||
|
delete mode 100644 include/freerdp/utils/cliprdr_utils.h
|
||
|
delete mode 100644 libfreerdp/utils/cliprdr_utils.c
|
||
|
|
||
|
diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c
|
||
|
index 0b6111b96..4c31a1b08 100644
|
||
|
--- a/channels/cliprdr/client/cliprdr_format.c
|
||
|
+++ b/channels/cliprdr/client/cliprdr_format.c
|
||
|
@@ -173,3 +173,198 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
+
|
||
|
+static UINT64 filetime_to_uint64(FILETIME value)
|
||
|
+{
|
||
|
+ UINT64 converted = 0;
|
||
|
+ converted |= (UINT32)value.dwHighDateTime;
|
||
|
+ converted <<= 32;
|
||
|
+ converted |= (UINT32)value.dwLowDateTime;
|
||
|
+ return converted;
|
||
|
+}
|
||
|
+
|
||
|
+static FILETIME uint64_to_filetime(UINT64 value)
|
||
|
+{
|
||
|
+ FILETIME converted;
|
||
|
+ converted.dwLowDateTime = (UINT32)(value >> 0);
|
||
|
+ converted.dwHighDateTime = (UINT32)(value >> 32);
|
||
|
+ return converted;
|
||
|
+}
|
||
|
+
|
||
|
+#define CLIPRDR_FILEDESCRIPTOR_SIZE (4 + 32 + 4 + 16 + 8 + 8 + 520)
|
||
|
+
|
||
|
+/**
|
||
|
+ * Parse a packed file list.
|
||
|
+ *
|
||
|
+ * The resulting array must be freed with the `free()` function.
|
||
|
+ *
|
||
|
+ * @param [in] format_data packed `CLIPRDR_FILELIST` to parse.
|
||
|
+ * @param [in] format_data_length length of `format_data` in bytes.
|
||
|
+ * @param [out] file_descriptor_array parsed array of `FILEDESCRIPTOR` structs.
|
||
|
+ * @param [out] file_descriptor_count number of elements in `file_descriptor_array`.
|
||
|
+ *
|
||
|
+ * @returns 0 on success, otherwise a Win32 error code.
|
||
|
+ */
|
||
|
+UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
|
||
|
+ FILEDESCRIPTORW** file_descriptor_array, UINT32* file_descriptor_count)
|
||
|
+{
|
||
|
+ UINT result = NO_ERROR;
|
||
|
+ UINT32 i;
|
||
|
+ UINT32 count = 0;
|
||
|
+ wStream* s = NULL;
|
||
|
+
|
||
|
+ if (!format_data || !file_descriptor_array || !file_descriptor_count)
|
||
|
+ return ERROR_BAD_ARGUMENTS;
|
||
|
+
|
||
|
+ s = Stream_New((BYTE*)format_data, format_data_length);
|
||
|
+ if (!s)
|
||
|
+ return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
+
|
||
|
+ if (Stream_GetRemainingLength(s) < 4)
|
||
|
+ {
|
||
|
+ WLog_ERR(TAG, "invalid packed file list");
|
||
|
+
|
||
|
+ result = ERROR_INCORRECT_SIZE;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ Stream_Read_UINT32(s, count); /* cItems (4 bytes) */
|
||
|
+
|
||
|
+ if (Stream_GetRemainingLength(s) / CLIPRDR_FILEDESCRIPTOR_SIZE < count)
|
||
|
+ {
|
||
|
+ WLog_ERR(TAG, "packed file list is too short: expected %" PRIuz ", have %" PRIuz,
|
||
|
+ ((size_t)count) * CLIPRDR_FILEDESCRIPTOR_SIZE, Stream_GetRemainingLength(s));
|
||
|
+
|
||
|
+ result = ERROR_INCORRECT_SIZE;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ *file_descriptor_count = count;
|
||
|
+ *file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTORW));
|
||
|
+ if (!*file_descriptor_array)
|
||
|
+ {
|
||
|
+ result = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < count; i++)
|
||
|
+ {
|
||
|
+ int c;
|
||
|
+ UINT64 lastWriteTime;
|
||
|
+ FILEDESCRIPTORW* file = &((*file_descriptor_array)[i]);
|
||
|
+
|
||
|
+ Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */
|
||
|
+ Stream_Seek(s, 32); /* reserved1 (32 bytes) */
|
||
|
+ Stream_Read_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */
|
||
|
+ Stream_Seek(s, 16); /* reserved2 (16 bytes) */
|
||
|
+ Stream_Read_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */
|
||
|
+ file->ftLastWriteTime = uint64_to_filetime(lastWriteTime);
|
||
|
+ Stream_Read_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */
|
||
|
+ Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */
|
||
|
+ for (c = 0; c < 260; c++) /* cFileName (520 bytes) */
|
||
|
+ Stream_Read_UINT16(s, file->cFileName[c]);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (Stream_GetRemainingLength(s) > 0)
|
||
|
+ WLog_WARN(TAG, "packed file list has %" PRIuz " excess bytes",
|
||
|
+ Stream_GetRemainingLength(s));
|
||
|
+out:
|
||
|
+ Stream_Free(s, FALSE);
|
||
|
+
|
||
|
+ return result;
|
||
|
+}
|
||
|
+
|
||
|
+#define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024)
|
||
|
+
|
||
|
+/**
|
||
|
+ * Serialize a packed file list.
|
||
|
+ *
|
||
|
+ * The resulting format data must be freed with the `free()` function.
|
||
|
+ *
|
||
|
+ * @param [in] file_descriptor_array array of `FILEDESCRIPTOR` structs to serialize.
|
||
|
+ * @param [in] file_descriptor_count number of elements in `file_descriptor_array`.
|
||
|
+ * @param [out] format_data serialized CLIPRDR_FILELIST.
|
||
|
+ * @param [out] format_data_length length of `format_data` in bytes.
|
||
|
+ *
|
||
|
+ * @returns 0 on success, otherwise a Win32 error code.
|
||
|
+ */
|
||
|
+UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* 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;
|
||
|
+
|
||
|
+ 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;
|
||
|
+
|
||
|
+ Stream_Write_UINT32(s, file_descriptor_count); /* cItems (4 bytes) */
|
||
|
+
|
||
|
+ for (i = 0; i < file_descriptor_count; i++)
|
||
|
+ {
|
||
|
+ int c;
|
||
|
+ UINT64 lastWriteTime;
|
||
|
+ const FILEDESCRIPTORW* file = &file_descriptor_array[i];
|
||
|
+
|
||
|
+ /*
|
||
|
+ * There is a known issue with Windows server getting stuck in
|
||
|
+ * an infinite loop when downloading files that are larger than
|
||
|
+ * 2 gigabytes. Do not allow clients to send such file lists.
|
||
|
+ *
|
||
|
+ * https://support.microsoft.com/en-us/help/2258090
|
||
|
+ */
|
||
|
+ if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0)
|
||
|
+ {
|
||
|
+ 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) */
|
||
|
+ Stream_Zero(s, 32); /* reserved1 (32 bytes) */
|
||
|
+ Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */
|
||
|
+ Stream_Zero(s, 16); /* reserved2 (16 bytes) */
|
||
|
+ lastWriteTime = filetime_to_uint64(file->ftLastWriteTime);
|
||
|
+ Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */
|
||
|
+ Stream_Write_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */
|
||
|
+ Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */
|
||
|
+ for (c = 0; c < 260; c++) /* cFileName (520 bytes) */
|
||
|
+ Stream_Write_UINT16(s, file->cFileName[c]);
|
||
|
+ }
|
||
|
+
|
||
|
+ Stream_SealLength(s);
|
||
|
+
|
||
|
+ Stream_GetBuffer(s, *format_data);
|
||
|
+ Stream_GetLength(s, *format_data_length);
|
||
|
+
|
||
|
+ Stream_Free(s, FALSE);
|
||
|
+
|
||
|
+ return result;
|
||
|
+
|
||
|
+error:
|
||
|
+ Stream_Free(s, TRUE);
|
||
|
+
|
||
|
+ return result;
|
||
|
+}
|
||
|
diff --git a/include/freerdp/channels/cliprdr.h b/include/freerdp/channels/cliprdr.h
|
||
|
index fbf23f6e5..86fc65890 100644
|
||
|
--- a/include/freerdp/channels/cliprdr.h
|
||
|
+++ b/include/freerdp/channels/cliprdr.h
|
||
|
@@ -22,7 +22,6 @@
|
||
|
|
||
|
#include <freerdp/api.h>
|
||
|
#include <freerdp/types.h>
|
||
|
-#include <freerdp/utils/cliprdr_utils.h>
|
||
|
|
||
|
#include <winpr/shell.h>
|
||
|
|
||
|
@@ -94,6 +93,17 @@ extern "C"
|
||
|
{
|
||
|
#endif
|
||
|
|
||
|
+ FREERDP_API UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
|
||
|
+ FILEDESCRIPTORW** file_descriptor_array,
|
||
|
+ UINT32* file_descriptor_count);
|
||
|
+ FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* 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
|
||
|
}
|
||
|
#endif
|
||
|
diff --git a/include/freerdp/utils/cliprdr_utils.h b/include/freerdp/utils/cliprdr_utils.h
|
||
|
deleted file mode 100644
|
||
|
index 59ecf848f..000000000
|
||
|
--- a/include/freerdp/utils/cliprdr_utils.h
|
||
|
+++ /dev/null
|
||
|
@@ -1,48 +0,0 @@
|
||
|
-/**
|
||
|
- * FreeRDP: A Remote Desktop Protocol Implementation
|
||
|
- * RDPDR utility functions
|
||
|
- *
|
||
|
- * Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||
|
- * Copyright 2022 Thincast Technologies GmbH
|
||
|
- *
|
||
|
- * Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
- * you may not use this file except in compliance with the License.
|
||
|
- * You may obtain a copy of the License at
|
||
|
- *
|
||
|
- * http://www.apache.org/licenses/LICENSE-2.0
|
||
|
- *
|
||
|
- * Unless required by applicable law or agreed to in writing, software
|
||
|
- * distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
- * See the License for the specific language governing permissions and
|
||
|
- * limitations under the License.
|
||
|
- */
|
||
|
-
|
||
|
-#ifndef FREERDP_UTILS_CLIPRDR_H
|
||
|
-#define FREERDP_UTILS_CLIPRDR_H
|
||
|
-
|
||
|
-#include <winpr/wtypes.h>
|
||
|
-#include <winpr/shell.h>
|
||
|
-#include <freerdp/api.h>
|
||
|
-
|
||
|
-#ifdef __cplusplus
|
||
|
-extern "C"
|
||
|
-{
|
||
|
-#endif
|
||
|
-
|
||
|
- FREERDP_API UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
|
||
|
- FILEDESCRIPTORW** file_descriptor_array,
|
||
|
- UINT32* file_descriptor_count);
|
||
|
- FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* 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
|
||
|
-}
|
||
|
-#endif
|
||
|
-
|
||
|
-#endif
|
||
|
diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt
|
||
|
index 2ec561d33..7bff6736a 100644
|
||
|
--- a/libfreerdp/utils/CMakeLists.txt
|
||
|
+++ b/libfreerdp/utils/CMakeLists.txt
|
||
|
@@ -20,7 +20,6 @@ set(MODULE_PREFIX "FREERDP_UTILS")
|
||
|
|
||
|
set(${MODULE_PREFIX}_SRCS
|
||
|
passphrase.c
|
||
|
- cliprdr_utils.c
|
||
|
pcap.c
|
||
|
profiler.c
|
||
|
ringbuffer.c
|
||
|
diff --git a/libfreerdp/utils/cliprdr_utils.c b/libfreerdp/utils/cliprdr_utils.c
|
||
|
deleted file mode 100644
|
||
|
index 7fb99d63a..000000000
|
||
|
--- a/libfreerdp/utils/cliprdr_utils.c
|
||
|
+++ /dev/null
|
||
|
@@ -1,235 +0,0 @@
|
||
|
-/**
|
||
|
- * FreeRDP: A Remote Desktop Protocol Implementation
|
||
|
- * Clipboard Virtual Channel Extension
|
||
|
- *
|
||
|
- * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||
|
- * Copyright 2022 Armin Novak <anovak@thincast.com
|
||
|
- * Copyright 2022 Thincast Technologies GmbH
|
||
|
- *
|
||
|
- * Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
- * you may not use this file except in compliance with the License.
|
||
|
- * You may obtain a copy of the License at
|
||
|
- *
|
||
|
- * http://www.apache.org/licenses/LICENSE-2.0
|
||
|
- *
|
||
|
- * Unless required by applicable law or agreed to in writing, software
|
||
|
- * distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
- * See the License for the specific language governing permissions and
|
||
|
- * limitations under the License.
|
||
|
- */
|
||
|
-
|
||
|
-#include <winpr/stream.h>
|
||
|
-#include <freerdp/utils/cliprdr_utils.h>
|
||
|
-#include <freerdp/channels/cliprdr.h>
|
||
|
-
|
||
|
-#include <freerdp/log.h>
|
||
|
-#define TAG FREERDP_TAG("utils." CLIPRDR_SVC_CHANNEL_NAME)
|
||
|
-
|
||
|
-#define CLIPRDR_FILEDESCRIPTOR_SIZE (4 + 32 + 4 + 16 + 8 + 8 + 520)
|
||
|
-#define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024)
|
||
|
-
|
||
|
-static UINT64 filetime_to_uint64(FILETIME value)
|
||
|
-{
|
||
|
- UINT64 converted = 0;
|
||
|
- converted |= (UINT32)value.dwHighDateTime;
|
||
|
- converted <<= 32;
|
||
|
- converted |= (UINT32)value.dwLowDateTime;
|
||
|
- return converted;
|
||
|
-}
|
||
|
-
|
||
|
-static FILETIME uint64_to_filetime(UINT64 value)
|
||
|
-{
|
||
|
- FILETIME converted;
|
||
|
- converted.dwLowDateTime = (UINT32)(value >> 0);
|
||
|
- converted.dwHighDateTime = (UINT32)(value >> 32);
|
||
|
- return converted;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * Parse a packed file list.
|
||
|
- *
|
||
|
- * The resulting array must be freed with the `free()` function.
|
||
|
- *
|
||
|
- * @param [in] format_data packed `CLIPRDR_FILELIST` to parse.
|
||
|
- * @param [in] format_data_length length of `format_data` in bytes.
|
||
|
- * @param [out] file_descriptor_array parsed array of `FILEDESCRIPTOR` structs.
|
||
|
- * @param [out] file_descriptor_count number of elements in `file_descriptor_array`.
|
||
|
- *
|
||
|
- * @returns 0 on success, otherwise a Win32 error code.
|
||
|
- */
|
||
|
-UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
|
||
|
- FILEDESCRIPTORW** file_descriptor_array, UINT32* file_descriptor_count)
|
||
|
-{
|
||
|
- UINT result = NO_ERROR;
|
||
|
- UINT32 i;
|
||
|
- UINT32 count = 0;
|
||
|
- wStream sbuffer;
|
||
|
- wStream* s = &sbuffer;
|
||
|
-
|
||
|
- if (!format_data || !file_descriptor_array || !file_descriptor_count)
|
||
|
- return ERROR_BAD_ARGUMENTS;
|
||
|
-
|
||
|
- Stream_StaticInit(&sbuffer, format_data, format_data_length);
|
||
|
- if (!s)
|
||
|
- return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
-
|
||
|
- if (Stream_GetRemainingLength(s) < 4)
|
||
|
- {
|
||
|
- WLog_ERR(TAG, "invalid packed file list");
|
||
|
-
|
||
|
- result = ERROR_INCORRECT_SIZE;
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- Stream_Read_UINT32(s, count); /* cItems (4 bytes) */
|
||
|
-
|
||
|
- if (Stream_GetRemainingLength(s) / CLIPRDR_FILEDESCRIPTOR_SIZE < count)
|
||
|
- {
|
||
|
- WLog_ERR(TAG, "packed file list is too short: expected %" PRIuz ", have %" PRIuz,
|
||
|
- ((size_t)count) * CLIPRDR_FILEDESCRIPTOR_SIZE, Stream_GetRemainingLength(s));
|
||
|
-
|
||
|
- result = ERROR_INCORRECT_SIZE;
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- *file_descriptor_count = count;
|
||
|
- *file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTORW));
|
||
|
- if (!*file_descriptor_array)
|
||
|
- {
|
||
|
- result = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- for (i = 0; i < count; i++)
|
||
|
- {
|
||
|
- UINT64 tmp;
|
||
|
- FILEDESCRIPTORW* file = &((*file_descriptor_array)[i]);
|
||
|
-
|
||
|
- Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */
|
||
|
- Stream_Read_UINT32(s, file->clsid.Data1);
|
||
|
- Stream_Read_UINT16(s, file->clsid.Data2);
|
||
|
- Stream_Read_UINT16(s, file->clsid.Data3);
|
||
|
- Stream_Read(s, &file->clsid.Data4, sizeof(file->clsid.Data4));
|
||
|
- Stream_Read_INT32(s, file->sizel.cx);
|
||
|
- Stream_Read_INT32(s, file->sizel.cy);
|
||
|
- Stream_Read_INT32(s, file->pointl.x);
|
||
|
- Stream_Read_INT32(s, file->pointl.y);
|
||
|
- Stream_Read_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */
|
||
|
- Stream_Read_UINT64(s, tmp); /* ftCreationTime (8 bytes) */
|
||
|
- file->ftCreationTime = uint64_to_filetime(tmp);
|
||
|
- Stream_Read_UINT64(s, tmp); /* ftLastAccessTime (8 bytes) */
|
||
|
- file->ftLastAccessTime = uint64_to_filetime(tmp);
|
||
|
- Stream_Read_UINT64(s, tmp); /* lastWriteTime (8 bytes) */
|
||
|
- file->ftLastWriteTime = uint64_to_filetime(tmp);
|
||
|
- Stream_Read_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */
|
||
|
- Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */
|
||
|
- Stream_Read_UTF16_String(s, file->cFileName,
|
||
|
- ARRAYSIZE(file->cFileName)); /* cFileName (520 bytes) */
|
||
|
- }
|
||
|
-
|
||
|
- if (Stream_GetRemainingLength(s) > 0)
|
||
|
- WLog_WARN(TAG, "packed file list has %" PRIuz " excess bytes",
|
||
|
- Stream_GetRemainingLength(s));
|
||
|
-out:
|
||
|
-
|
||
|
- return result;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * Serialize a packed file list.
|
||
|
- *
|
||
|
- * The resulting format data must be freed with the `free()` function.
|
||
|
- *
|
||
|
- * @param [in] file_descriptor_array array of `FILEDESCRIPTOR` structs to serialize.
|
||
|
- * @param [in] file_descriptor_count number of elements in `file_descriptor_array`.
|
||
|
- * @param [out] format_data serialized CLIPRDR_FILELIST.
|
||
|
- * @param [out] format_data_length length of `format_data` in bytes.
|
||
|
- *
|
||
|
- * @returns 0 on success, otherwise a Win32 error code.
|
||
|
- */
|
||
|
-UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* 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;
|
||
|
- size_t len;
|
||
|
- wStream* s = NULL;
|
||
|
-
|
||
|
- 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;
|
||
|
-
|
||
|
- Stream_Write_UINT32(s, file_descriptor_count); /* cItems (4 bytes) */
|
||
|
-
|
||
|
- for (i = 0; i < file_descriptor_count; i++)
|
||
|
- {
|
||
|
- int c;
|
||
|
- UINT64 lastWriteTime;
|
||
|
- const FILEDESCRIPTORW* file = &file_descriptor_array[i];
|
||
|
-
|
||
|
- /*
|
||
|
- * There is a known issue with Windows server getting stuck in
|
||
|
- * an infinite loop when downloading files that are larger than
|
||
|
- * 2 gigabytes. Do not allow clients to send such file lists.
|
||
|
- *
|
||
|
- * https://support.microsoft.com/en-us/help/2258090
|
||
|
- */
|
||
|
- if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0)
|
||
|
- {
|
||
|
- 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) */
|
||
|
- Stream_Zero(s, 32); /* reserved1 (32 bytes) */
|
||
|
- Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */
|
||
|
- Stream_Zero(s, 16); /* reserved2 (16 bytes) */
|
||
|
- lastWriteTime = filetime_to_uint64(file->ftLastWriteTime);
|
||
|
- Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */
|
||
|
- Stream_Write_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */
|
||
|
- Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */
|
||
|
- for (c = 0; c < 260; c++) /* cFileName (520 bytes) */
|
||
|
- Stream_Write_UINT16(s, file->cFileName[c]);
|
||
|
- }
|
||
|
-
|
||
|
- Stream_SealLength(s);
|
||
|
-
|
||
|
- Stream_GetBuffer(s, *format_data);
|
||
|
- Stream_GetLength(s, len);
|
||
|
- if (len > UINT32_MAX)
|
||
|
- goto error;
|
||
|
-
|
||
|
- *format_data_length = (UINT32)len;
|
||
|
-
|
||
|
- Stream_Free(s, FALSE);
|
||
|
-
|
||
|
- return result;
|
||
|
-
|
||
|
-error:
|
||
|
- Stream_Free(s, TRUE);
|
||
|
-
|
||
|
- return result;
|
||
|
-}
|
||
|
--
|
||
|
2.46.1
|
||
|
|