22 #include <winpr/stream.h>
23 #include <freerdp/utils/cliprdr_utils.h>
24 #include <freerdp/channels/cliprdr.h>
26 #include <freerdp/log.h>
27 #define TAG FREERDP_TAG("utils." CLIPRDR_SVC_CHANNEL_NAME)
29 #define CLIPRDR_FILEDESCRIPTOR_SIZE (4 + 32 + 4 + 16 + 8 + 8 + 520)
30 #define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024)
32 static UINT64 filetime_to_uint64(FILETIME value)
35 converted |= (UINT32)value.dwHighDateTime;
37 converted |= (UINT32)value.dwLowDateTime;
41 static FILETIME uint64_to_filetime(UINT64 value)
44 converted.dwLowDateTime = (UINT32)(value >> 0);
45 converted.dwHighDateTime = (UINT32)(value >> 32);
61 UINT cliprdr_parse_file_list(
const BYTE* format_data, UINT32 format_data_length,
64 UINT result = NO_ERROR;
69 if (!format_data || !file_descriptor_array || !file_descriptor_count)
70 return ERROR_BAD_ARGUMENTS;
72 s = Stream_StaticConstInit(&sbuffer, format_data, format_data_length);
74 return ERROR_NOT_ENOUGH_MEMORY;
76 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
78 result = ERROR_INCORRECT_SIZE;
82 Stream_Read_UINT32(s, count);
84 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, count, CLIPRDR_FILEDESCRIPTOR_SIZE))
86 result = ERROR_INCORRECT_SIZE;
90 *file_descriptor_count = count;
92 if (!*file_descriptor_array)
94 result = ERROR_NOT_ENOUGH_MEMORY;
98 for (UINT32 i = 0; i < count; i++)
102 if (!cliprdr_read_filedescriptor(s, file))
106 if (Stream_GetRemainingLength(s) > 0)
107 WLog_WARN(TAG,
"packed file list has %" PRIuz
" excess bytes",
108 Stream_GetRemainingLength(s));
119 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(
FILEDESCRIPTORW)))
122 Stream_Read_UINT32(s, file->dwFlags);
123 Stream_Read_UINT32(s, file->clsid.Data1);
124 Stream_Read_UINT16(s, file->clsid.Data2);
125 Stream_Read_UINT16(s, file->clsid.Data3);
126 Stream_Read(s, &file->clsid.Data4,
sizeof(file->clsid.Data4));
127 Stream_Read_INT32(s, file->sizel.cx);
128 Stream_Read_INT32(s, file->sizel.cy);
129 Stream_Read_INT32(s, file->pointl.x);
130 Stream_Read_INT32(s, file->pointl.y);
131 Stream_Read_UINT32(s, file->dwFileAttributes);
132 Stream_Read_UINT64(s, tmp);
133 file->ftCreationTime = uint64_to_filetime(tmp);
134 Stream_Read_UINT64(s, tmp);
135 file->ftLastAccessTime = uint64_to_filetime(tmp);
136 Stream_Read_UINT64(s, tmp);
137 file->ftLastWriteTime = uint64_to_filetime(tmp);
138 Stream_Read_UINT32(s, file->nFileSizeHigh);
139 Stream_Read_UINT32(s, file->nFileSizeLow);
140 Stream_Read_UTF16_String(s, file->cFileName,
141 ARRAYSIZE(file->cFileName));
152 Stream_Write_UINT32(s, file->dwFlags);
154 Stream_Write_UINT32(s, file->clsid.Data1);
155 Stream_Write_UINT16(s, file->clsid.Data2);
156 Stream_Write_UINT16(s, file->clsid.Data3);
157 Stream_Write(s, &file->clsid.Data4,
sizeof(file->clsid.Data4));
158 Stream_Write_INT32(s, file->sizel.cx);
159 Stream_Write_INT32(s, file->sizel.cy);
160 Stream_Write_INT32(s, file->pointl.x);
161 Stream_Write_INT32(s, file->pointl.y);
162 Stream_Write_UINT32(s, file->dwFileAttributes);
163 Stream_Write_UINT64(s, filetime_to_uint64(file->ftCreationTime));
164 Stream_Write_UINT64(s, filetime_to_uint64(file->ftLastAccessTime));
165 Stream_Write_UINT64(s, filetime_to_uint64(file->ftLastWriteTime));
166 Stream_Write_UINT32(s, file->nFileSizeHigh);
167 Stream_Write_UINT32(s, file->nFileSizeLow);
168 Stream_Write_UTF16_String(s, file->cFileName,
169 ARRAYSIZE(file->cFileName));
185 UINT cliprdr_serialize_file_list(
const FILEDESCRIPTORW* file_descriptor_array,
186 UINT32 file_descriptor_count, BYTE** format_data,
187 UINT32* format_data_length)
189 return cliprdr_serialize_file_list_ex(CB_STREAM_FILECLIP_ENABLED, file_descriptor_array,
190 file_descriptor_count, format_data, format_data_length);
193 UINT cliprdr_serialize_file_list_ex(UINT32 flags,
const FILEDESCRIPTORW* file_descriptor_array,
194 UINT32 file_descriptor_count, BYTE** format_data,
195 UINT32* format_data_length)
197 UINT result = NO_ERROR;
201 if (!file_descriptor_array || !format_data || !format_data_length)
202 return ERROR_BAD_ARGUMENTS;
204 if ((flags & CB_STREAM_FILECLIP_ENABLED) == 0)
206 WLog_WARN(TAG,
"No file clipboard support annouonced!");
207 return ERROR_BAD_ARGUMENTS;
210 s = Stream_New(NULL, 4 + file_descriptor_count * CLIPRDR_FILEDESCRIPTOR_SIZE);
212 return ERROR_NOT_ENOUGH_MEMORY;
214 Stream_Write_UINT32(s, file_descriptor_count);
216 for (UINT32 i = 0; i < file_descriptor_count; i++)
227 if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0)
229 if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE))
231 WLog_ERR(TAG,
"cliprdr does not support files over 2 GB");
232 result = ERROR_FILE_TOO_LARGE;
237 if (!cliprdr_write_filedescriptor(s, file))
241 Stream_SealLength(s);
243 Stream_GetBuffer(s, *format_data);
244 Stream_GetLength(s, len);
245 if (len > UINT32_MAX)
248 *format_data_length = (UINT32)len;
250 Stream_Free(s, FALSE);
255 Stream_Free(s, TRUE);