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) 
   32static UINT64 filetime_to_uint64(
FILETIME value)
 
   35  converted |= (UINT32)value.dwHighDateTime;
 
   37  converted |= (UINT32)value.dwLowDateTime;
 
   41static FILETIME uint64_to_filetime(UINT64 value)
 
   44  converted.dwLowDateTime = (UINT32)(value >> 0);
 
   45  converted.dwHighDateTime = (UINT32)(value >> 32);
 
   61UINT 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)); 
 
  185UINT 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);
 
  193UINT 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);