20 #include <winpr/config.h>
21 #include <winpr/platform.h>
23 WINPR_PRAGMA_DIAG_PUSH
24 WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO
25 WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO
27 #define _FILE_OFFSET_BITS 64
33 #include <winpr/wtypes.h>
35 #include <winpr/crt.h>
36 #include <winpr/clipboard.h>
37 #include <winpr/collections.h>
38 #include <winpr/file.h>
39 #include <winpr/shell.h>
40 #include <winpr/string.h>
41 #include <winpr/wlog.h>
42 #include <winpr/path.h>
43 #include <winpr/print.h>
45 #include "clipboard.h"
46 #include "synthetic_file.h"
49 #define TAG WINPR_TAG("clipboard.synthetic.file")
51 static const char* mime_uri_list =
"text/uri-list";
52 static const char* mime_FileGroupDescriptorW =
"FileGroupDescriptorW";
53 static const char* mime_gnome_copied_files =
"x-special/gnome-copied-files";
54 static const char* mime_mate_copied_files =
"x-special/mate-copied-files";
64 DWORD dwFileAttributes;
65 FILETIME ftCreationTime;
66 FILETIME ftLastAccessTime;
67 FILETIME ftLastWriteTime;
72 void free_synthetic_file(
struct synthetic_file* file);
74 static struct synthetic_file* make_synthetic_file(
const WCHAR* local_name,
const WCHAR* remote_name)
76 struct synthetic_file* file = NULL;
80 WINPR_ASSERT(local_name);
81 WINPR_ASSERT(remote_name);
83 hFind = FindFirstFileW(local_name, &fd);
84 if (INVALID_HANDLE_VALUE == hFind)
86 WLog_ERR(TAG,
"FindFirstFile failed (%" PRIu32
")", GetLastError());
91 file = calloc(1,
sizeof(*file));
95 file->fd = INVALID_HANDLE_VALUE;
97 file->local_name = _wcsdup(local_name);
98 if (!file->local_name)
101 file->remote_name = _wcsdup(remote_name);
102 if (!file->remote_name)
105 const size_t len = _wcslen(file->remote_name);
106 PathCchConvertStyleW(file->remote_name, len, PATH_STYLE_WINDOWS);
108 file->dwFileAttributes = fd.dwFileAttributes;
109 file->ftCreationTime = fd.ftCreationTime;
110 file->ftLastWriteTime = fd.ftLastWriteTime;
111 file->ftLastAccessTime = fd.ftLastAccessTime;
112 file->nFileSizeHigh = fd.nFileSizeHigh;
113 file->nFileSizeLow = fd.nFileSizeLow;
117 free_synthetic_file(file);
121 static UINT synthetic_file_read_close(
struct synthetic_file* file, BOOL force);
123 void free_synthetic_file(
struct synthetic_file* file)
128 synthetic_file_read_close(file, TRUE);
130 free(file->local_name);
131 free(file->remote_name);
139 static WCHAR* convert_local_name_component_to_remote(wClipboard* clipboard,
const WCHAR* local_name)
141 wClipboardDelegate* delegate = ClipboardGetDelegate(clipboard);
142 WCHAR* remote_name = NULL;
144 WINPR_ASSERT(delegate);
146 remote_name = _wcsdup(local_name);
157 if (!delegate->IsFileNameComponentValid(remote_name))
159 WLog_ERR(TAG,
"invalid file name component: %s", local_name);
169 static WCHAR* concat_file_name(
const WCHAR* dir,
const WCHAR* file)
173 const WCHAR slash =
'/';
174 WCHAR* buffer = NULL;
179 len_dir = _wcslen(dir);
180 len_file = _wcslen(file);
181 buffer = calloc(len_dir + 1 + len_file + 2,
sizeof(WCHAR));
186 memcpy(buffer, dir, len_dir *
sizeof(WCHAR));
187 buffer[len_dir] = slash;
188 memcpy(buffer + len_dir + 1, file, len_file *
sizeof(WCHAR));
192 static BOOL add_file_to_list(wClipboard* clipboard,
const WCHAR* local_name,
193 const WCHAR* remote_name, wArrayList* files);
195 static BOOL add_directory_entry_to_list(wClipboard* clipboard,
const WCHAR* local_dir_name,
196 const WCHAR* remote_dir_name,
200 WCHAR* local_name = NULL;
201 WCHAR* remote_name = NULL;
202 WCHAR* remote_base_name = NULL;
204 WCHAR dotbuffer[6] = { 0 };
205 WCHAR dotdotbuffer[6] = { 0 };
206 const WCHAR* dot = InitializeConstWCharFromUtf8(
".", dotbuffer, ARRAYSIZE(dotbuffer));
207 const WCHAR* dotdot = InitializeConstWCharFromUtf8(
"..", dotdotbuffer, ARRAYSIZE(dotdotbuffer));
209 WINPR_ASSERT(clipboard);
210 WINPR_ASSERT(local_dir_name);
211 WINPR_ASSERT(remote_dir_name);
212 WINPR_ASSERT(pFileData);
217 if ((_wcscmp(pFileData->cFileName, dot) == 0) || (_wcscmp(pFileData->cFileName, dotdot) == 0))
220 remote_base_name = convert_local_name_component_to_remote(clipboard, pFileData->cFileName);
222 if (!remote_base_name)
225 local_name = concat_file_name(local_dir_name, pFileData->cFileName);
226 remote_name = concat_file_name(remote_dir_name, remote_base_name);
228 if (local_name && remote_name)
229 result = add_file_to_list(clipboard, local_name, remote_name, files);
231 free(remote_base_name);
237 static BOOL do_add_directory_contents_to_list(wClipboard* clipboard,
const WCHAR* local_name,
238 const WCHAR* remote_name, WCHAR* namebuf,
241 WINPR_ASSERT(clipboard);
242 WINPR_ASSERT(local_name);
243 WINPR_ASSERT(remote_name);
245 WINPR_ASSERT(namebuf);
248 HANDLE hFind = FindFirstFileW(namebuf, &FindData);
249 if (INVALID_HANDLE_VALUE == hFind)
251 WLog_ERR(TAG,
"FindFirstFile failed (%" PRIu32
")", GetLastError());
256 if (!add_directory_entry_to_list(clipboard, local_name, remote_name, &FindData, files))
262 BOOL bRet = FindNextFileW(hFind, &FindData);
266 if (ERROR_NO_MORE_FILES == GetLastError())
268 WLog_WARN(TAG,
"FindNextFile failed (%" PRIu32
")", GetLastError());
276 static BOOL add_directory_contents_to_list(wClipboard* clipboard,
const WCHAR* local_name,
277 const WCHAR* remote_name, wArrayList* files)
285 const char buffer[6] =
"/\0*\0\0\0";
287 const size_t wildcardLen = ARRAYSIZE(buffer) /
sizeof(WCHAR);
289 WINPR_ASSERT(clipboard);
290 WINPR_ASSERT(local_name);
291 WINPR_ASSERT(remote_name);
294 size_t len = _wcslen(local_name);
295 WCHAR* namebuf = calloc(len + wildcardLen,
sizeof(WCHAR));
299 _wcsncat(namebuf, local_name, len);
300 _wcsncat(namebuf, wildcard.w, wildcardLen);
302 result = do_add_directory_contents_to_list(clipboard, local_name, remote_name, namebuf, files);
308 static BOOL add_file_to_list(wClipboard* clipboard,
const WCHAR* local_name,
309 const WCHAR* remote_name, wArrayList* files)
311 struct synthetic_file* file = NULL;
313 WINPR_ASSERT(clipboard);
314 WINPR_ASSERT(local_name);
315 WINPR_ASSERT(remote_name);
318 file = make_synthetic_file(local_name, remote_name);
323 if (!ArrayList_Append(files, file))
325 free_synthetic_file(file);
329 if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
335 if (!add_directory_contents_to_list(clipboard, local_name, remote_name, files))
342 static const WCHAR* get_basename(
const WCHAR* name)
344 const WCHAR* c = name;
345 const WCHAR* last_name = name;
346 const WCHAR slash =
'/';
359 static BOOL process_file_name(wClipboard* clipboard,
const WCHAR* local_name, wArrayList* files)
362 const WCHAR* base_name = NULL;
363 WCHAR* remote_name = NULL;
365 WINPR_ASSERT(clipboard);
366 WINPR_ASSERT(local_name);
374 base_name = get_basename(local_name);
375 remote_name = convert_local_name_component_to_remote(clipboard, base_name);
380 result = add_file_to_list(clipboard, local_name, remote_name, files);
385 static BOOL process_uri(wClipboard* clipboard,
const char* uri,
size_t uri_len)
391 WINPR_ASSERT(clipboard);
393 name = parse_uri_to_local_file(uri, uri_len);
404 wname = ConvertUtf8ToWCharAlloc(name, NULL);
406 result = process_file_name(clipboard, wname, clipboard->localFiles);
415 static BOOL process_uri_list(wClipboard* clipboard,
const char* data,
size_t length)
417 const char* cur = data;
418 const char* lim = data + length;
420 WINPR_ASSERT(clipboard);
423 WLog_VRB(TAG,
"processing URI list:\n%.*s", length, data);
424 ArrayList_Clear(clipboard->localFiles);
436 BOOL comment = (*cur ==
'#');
437 const char* start = cur;
438 const char* stop = cur;
440 for (; stop < lim; stop++)
444 if ((stop + 1 < lim) && (*(stop + 1) ==
'\n'))
461 if (strnlen(start, stop - start) < 1)
469 if (!process_uri(clipboard, start, stop - start))
476 static BOOL convert_local_file_to_filedescriptor(
const struct synthetic_file* file,
479 size_t remote_len = 0;
482 WINPR_ASSERT(descriptor);
484 descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_WRITESTIME | FD_PROGRESSUI;
486 if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
488 descriptor->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
489 descriptor->nFileSizeLow = 0;
490 descriptor->nFileSizeHigh = 0;
494 descriptor->dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
495 descriptor->nFileSizeLow = file->nFileSizeLow;
496 descriptor->nFileSizeHigh = file->nFileSizeHigh;
499 descriptor->ftLastWriteTime = file->ftLastWriteTime;
501 remote_len = _wcsnlen(file->remote_name, ARRAYSIZE(descriptor->cFileName));
503 if (remote_len >= ARRAYSIZE(descriptor->cFileName))
505 WLog_ERR(TAG,
"file name too long (%" PRIuz
" characters)", remote_len);
509 memcpy(descriptor->cFileName, file->remote_name, remote_len *
sizeof(WCHAR));
513 static FILEDESCRIPTORW* convert_local_file_list_to_filedescriptors(wArrayList* files)
518 count = ArrayList_Count(files);
525 for (
size_t i = 0; i < count; i++)
527 const struct synthetic_file* file = ArrayList_GetItem(files, i);
529 if (!convert_local_file_to_filedescriptor(file, &descriptors[i]))
539 static void* convert_any_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
544 WINPR_ASSERT(clipboard);
547 descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles);
552 *pSize = (UINT32)ArrayList_Count(clipboard->localFiles) *
sizeof(
FILEDESCRIPTORW);
553 clipboard->fileListSequenceNumber = clipboard->sequenceNumber;
557 static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
558 const void* data, UINT32* pSize)
560 const UINT32 expected = ClipboardGetFormatId(clipboard, mime_uri_list);
561 if (formatId != expected)
563 if (!process_uri_list(clipboard, (
const char*)data, *pSize))
565 return convert_any_uri_list_to_filedescriptors(clipboard, formatId, pSize);
568 static BOOL process_files(wClipboard* clipboard,
const char* data, UINT32 pSize,
const char* prefix)
570 WINPR_ASSERT(prefix);
572 const size_t prefix_len = strlen(prefix);
574 WINPR_ASSERT(clipboard);
576 ArrayList_Clear(clipboard->localFiles);
578 if (!data || (pSize < prefix_len))
580 if (strncmp(data, prefix, prefix_len) != 0)
586 char* copy = strndup(data, pSize);
591 char* tok = strtok_s(copy,
"\n", &endptr);
594 size_t tok_len = strnlen(tok, pSize);
595 if (!process_uri(clipboard, tok, tok_len))
598 tok = strtok_s(NULL,
"\n", &endptr);
607 static BOOL process_gnome_copied_files(wClipboard* clipboard,
const char* data, UINT32 pSize)
609 return process_files(clipboard, data, pSize,
"copy\n");
612 static BOOL process_mate_copied_files(wClipboard* clipboard,
const char* data, UINT32 pSize)
614 return process_files(clipboard, data, pSize,
"copy\n");
617 static BOOL process_nautilus_clipboard(wClipboard* clipboard,
const char* data, UINT32 pSize)
619 return process_files(clipboard, data, pSize,
"x-special/nautilus-clipboard\ncopy\n");
622 static void* convert_nautilus_clipboard_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
623 const void* data, UINT32* pSize)
625 const UINT32 expected = ClipboardGetFormatId(clipboard, mime_gnome_copied_files);
626 if (formatId != expected)
628 if (!process_nautilus_clipboard(clipboard, (
const char*)data, *pSize))
630 return convert_any_uri_list_to_filedescriptors(clipboard, formatId, pSize);
633 static void* convert_gnome_copied_files_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
634 const void* data, UINT32* pSize)
636 const UINT32 expected = ClipboardGetFormatId(clipboard, mime_gnome_copied_files);
637 if (formatId != expected)
639 if (!process_gnome_copied_files(clipboard, (
const char*)data, *pSize))
641 return convert_any_uri_list_to_filedescriptors(clipboard, formatId, pSize);
644 static void* convert_mate_copied_files_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
645 const void* data, UINT32* pSize)
647 const UINT32 expected = ClipboardGetFormatId(clipboard, mime_mate_copied_files);
648 if (formatId != expected)
651 if (!process_mate_copied_files(clipboard, (
const char*)data, *pSize))
654 return convert_any_uri_list_to_filedescriptors(clipboard, formatId, pSize);
657 static size_t count_special_chars(
const WCHAR* str)
660 const WCHAR* start = str;
665 const WCHAR sharp =
'#';
666 const WCHAR questionmark =
'?';
667 const WCHAR star =
'*';
668 const WCHAR exclamationmark =
'!';
669 const WCHAR percent =
'%';
671 if ((*start == sharp) || (*start == questionmark) || (*start == star) ||
672 (*start == exclamationmark) || (*start == percent))
681 static const char* stop_at_special_chars(
const char* str)
683 const char* start = str;
688 if (*start ==
'#' || *start ==
'?' || *start ==
'*' || *start ==
'!' || *start ==
'%')
698 static void* convert_filedescriptors_to_file_list(wClipboard* clipboard, UINT32 formatId,
699 const void* data, UINT32* pSize,
700 const char* header,
const char* lineprefix,
701 const char* lineending, BOOL skip_last_lineending)
708 backslash.c[0] =
'\\';
709 backslash.c[1] =
'\0';
712 UINT32 nrDescriptors = 0;
716 size_t baseLength = 0;
718 size_t header_len = strlen(header);
719 size_t lineprefix_len = strlen(lineprefix);
720 size_t lineending_len = strlen(lineending);
721 size_t decoration_len = 0;
723 if (!clipboard || !data || !pSize)
726 if (*pSize <
sizeof(UINT32))
729 if (clipboard->delegate.basePath)
730 baseLength = strnlen(clipboard->delegate.basePath, MAX_PATH);
736 wStream* s = Stream_StaticConstInit(&sbuffer, data, *pSize);
737 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
740 Stream_Read_UINT32(s, nrDescriptors);
744 if ((count < 1) || (count != nrDescriptors))
747 descriptors = Stream_ConstPointer(s);
749 if (formatId != ClipboardGetFormatId(clipboard, mime_FileGroupDescriptorW))
753 decoration_len = lineprefix_len + lineending_len + baseLength + 1;
757 for (
size_t x = 0; x < count; x++)
761 if (_wcschr(dsc->cFileName, backslash.w) == NULL)
763 alloc += ARRAYSIZE(dsc->cFileName) *
766 alloc += count_special_chars(dsc->cFileName) * 2;
767 alloc += decoration_len;
774 dst = calloc(alloc,
sizeof(
char));
779 (void)_snprintf(&dst[0], alloc,
"%s", header);
783 for (
size_t x = 0; x < count; x++)
787 if (_wcschr(dsc->cFileName, backslash.w) != NULL)
792 char curName[520] = { 0 };
793 const char* stop_at = NULL;
794 const char* previous_at = NULL;
796 if (ConvertWCharNToUtf8(dsc->cFileName, ARRAYSIZE(dsc->cFileName), curName,
797 ARRAYSIZE(curName)) < 0)
800 rc = _snprintf(&dst[pos], alloc - pos,
"%s%s/", lineprefix, clipboard->delegate.basePath);
807 previous_at = curName;
808 while ((stop_at = stop_at_special_chars(previous_at)) != NULL)
810 char* tmp = strndup(previous_at, stop_at - previous_at);
814 rc = _snprintf(&dst[pos], stop_at - previous_at + 1,
"%s", tmp);
820 rc = _snprintf(&dst[pos], 4,
"%%%x", *stop_at);
825 previous_at = stop_at + 1;
828 rc = _snprintf(&dst[pos], alloc - pos,
"%s%s", previous_at, lineending);
832 if ((rc < 0) || fail)
841 if (skip_last_lineending)
843 const size_t endlen = strlen(lineending);
846 const size_t len = strnlen(dst, alloc);
853 if (memcmp(&dst[len - endlen], lineending, endlen) == 0)
855 memset(&dst[len - endlen], 0, endlen);
861 alloc = strnlen(dst, alloc) + 1;
862 *pSize = (UINT32)alloc;
863 clipboard->fileListSequenceNumber = clipboard->sequenceNumber;
873 static void* convert_filedescriptors_to_uri_list(wClipboard* clipboard, UINT32 formatId,
874 const void* data, UINT32* pSize)
876 return convert_filedescriptors_to_file_list(clipboard, formatId, data, pSize,
"",
"file://",
881 static void* convert_filedescriptors_to_gnome_copied_files(wClipboard* clipboard, UINT32 formatId,
882 const void* data, UINT32* pSize)
884 return convert_filedescriptors_to_file_list(clipboard, formatId, data, pSize,
"copy\n",
885 "file://",
"\n", TRUE);
889 static void* convert_filedescriptors_to_nautilus_clipboard(wClipboard* clipboard, UINT32 formatId,
890 const void* data, UINT32* pSize)
907 return convert_filedescriptors_to_file_list(clipboard, formatId, data, pSize,
908 "x-special/nautilus-clipboard\ncopy\n",
"file://",
912 static void* convert_filedescriptors_to_mate_copied_files(wClipboard* clipboard, UINT32 formatId,
913 const void* data, UINT32* pSize)
916 char* pDstData = convert_filedescriptors_to_file_list(clipboard, formatId, data, pSize,
917 "copy\n",
"file://",
"\n", TRUE);
927 pDstData[*pSize - 1] =
'\0';
932 static void array_free_synthetic_file(
void* the_file)
934 struct synthetic_file* file = the_file;
935 free_synthetic_file(file);
938 static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard)
963 const UINT32 local_gnome_file_format_id =
964 ClipboardRegisterFormat(clipboard, mime_gnome_copied_files);
965 const UINT32 local_mate_file_format_id =
966 ClipboardRegisterFormat(clipboard, mime_mate_copied_files);
967 const UINT32 file_group_format_id =
968 ClipboardRegisterFormat(clipboard, mime_FileGroupDescriptorW);
969 const UINT32 local_file_format_id = ClipboardRegisterFormat(clipboard, mime_uri_list);
971 if (!file_group_format_id || !local_file_format_id || !local_gnome_file_format_id ||
972 !local_mate_file_format_id)
975 clipboard->localFiles = ArrayList_New(FALSE);
977 if (!clipboard->localFiles)
980 obj = ArrayList_Object(clipboard->localFiles);
981 obj->fnObjectFree = array_free_synthetic_file;
983 if (!ClipboardRegisterSynthesizer(clipboard, local_file_format_id, file_group_format_id,
984 convert_uri_list_to_filedescriptors))
985 goto error_free_local_files;
987 if (!ClipboardRegisterSynthesizer(clipboard, file_group_format_id, local_file_format_id,
988 convert_filedescriptors_to_uri_list))
989 goto error_free_local_files;
991 if (!ClipboardRegisterSynthesizer(clipboard, local_gnome_file_format_id, file_group_format_id,
992 convert_gnome_copied_files_to_filedescriptors))
993 goto error_free_local_files;
995 if (!ClipboardRegisterSynthesizer(clipboard, file_group_format_id, local_gnome_file_format_id,
996 convert_filedescriptors_to_gnome_copied_files))
997 goto error_free_local_files;
999 if (!ClipboardRegisterSynthesizer(clipboard, local_mate_file_format_id, file_group_format_id,
1000 convert_mate_copied_files_to_filedescriptors))
1001 goto error_free_local_files;
1003 if (!ClipboardRegisterSynthesizer(clipboard, file_group_format_id, local_mate_file_format_id,
1004 convert_filedescriptors_to_mate_copied_files))
1005 goto error_free_local_files;
1008 error_free_local_files:
1009 ArrayList_Free(clipboard->localFiles);
1010 clipboard->localFiles = NULL;
1015 static UINT file_get_size(
const struct synthetic_file* file, UINT64* size)
1020 return E_INVALIDARG;
1022 s = file->nFileSizeHigh;
1024 s |= file->nFileSizeLow;
1029 static UINT delegate_file_request_size(wClipboardDelegate* delegate,
1032 UINT error = NO_ERROR;
1034 struct synthetic_file* file = NULL;
1036 if (!delegate || !delegate->clipboard || !request)
1037 return ERROR_BAD_ARGUMENTS;
1039 if (delegate->clipboard->sequenceNumber != delegate->clipboard->fileListSequenceNumber)
1040 return ERROR_INVALID_STATE;
1042 file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex);
1045 return ERROR_INDEX_ABSENT;
1047 error = file_get_size(file, &size);
1050 error = delegate->ClipboardFileSizeFailure(delegate, request, error);
1052 error = delegate->ClipboardFileSizeSuccess(delegate, request, size);
1055 WLog_WARN(TAG,
"failed to report file size result: 0x%08X", error);
1060 UINT synthetic_file_read_close(
struct synthetic_file* file, BOOL force)
1062 if (!file || INVALID_HANDLE_VALUE == file->fd)
1068 file_get_size(file, &size);
1069 if ((file->offset < 0) || ((UINT64)file->offset >= size) || force)
1071 WLog_VRB(TAG,
"close file %d", file->fd);
1072 if (!CloseHandle(file->fd))
1074 WLog_WARN(TAG,
"failed to close fd %d: %" PRIu32, file->fd, GetLastError());
1077 file->fd = INVALID_HANDLE_VALUE;
1083 static UINT file_get_range(
struct synthetic_file* file, UINT64 offset, UINT32 size,
1084 BYTE** actual_data, UINT32* actual_size)
1086 UINT error = NO_ERROR;
1091 WINPR_ASSERT(actual_data);
1092 WINPR_ASSERT(actual_size);
1094 if (INVALID_HANDLE_VALUE == file->fd)
1098 file->fd = CreateFileW(file->local_name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1099 FILE_ATTRIBUTE_NORMAL, NULL);
1100 if (INVALID_HANDLE_VALUE == file->fd)
1102 error = GetLastError();
1103 WLog_ERR(TAG,
"failed to open file %s: 0x%08" PRIx32, file->local_name, error);
1107 if (!GetFileInformationByHandle(file->fd, &FileInfo))
1109 (void)CloseHandle(file->fd);
1110 file->fd = INVALID_HANDLE_VALUE;
1111 error = GetLastError();
1112 WLog_ERR(TAG,
"Get file [%s] information fail: 0x%08" PRIx32, file->local_name, error);
1117 file->nFileSizeHigh = FileInfo.nFileSizeHigh;
1118 file->nFileSizeLow = FileInfo.nFileSizeLow;
1137 if (offset > INT64_MAX)
1139 WLog_ERR(TAG,
"offset [%" PRIu64
"] > INT64_MAX", offset);
1144 if (file->offset != (INT64)offset)
1146 WLog_DBG(TAG,
"file %d force seeking to %" PRIu64
", current %" PRIu64, file->fd,
1147 offset, file->offset);
1149 dwHigh = offset >> 32;
1150 dwLow = offset & 0xFFFFFFFF;
1151 if (INVALID_SET_FILE_POINTER ==
1152 SetFilePointer(file->fd, dwLow, (PLONG)&dwHigh, FILE_BEGIN))
1154 error = GetLastError();
1159 BYTE* buffer = malloc(size);
1162 error = ERROR_NOT_ENOUGH_MEMORY;
1165 if (!ReadFile(file->fd, buffer, size, (LPDWORD)actual_size, NULL))
1168 error = GetLastError();
1172 *actual_data = buffer;
1173 file->offset += *actual_size;
1174 WLog_VRB(TAG,
"file %d actual read %" PRIu32
" bytes (offset %" PRIu64
")", file->fd,
1175 *actual_size, file->offset);
1178 synthetic_file_read_close(file, TRUE );
1182 static UINT delegate_file_request_range(wClipboardDelegate* delegate,
1189 struct synthetic_file* file = NULL;
1191 if (!delegate || !delegate->clipboard || !request)
1192 return ERROR_BAD_ARGUMENTS;
1194 if (delegate->clipboard->sequenceNumber != delegate->clipboard->fileListSequenceNumber)
1195 return ERROR_INVALID_STATE;
1197 file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex);
1200 return ERROR_INDEX_ABSENT;
1202 offset = (((UINT64)request->nPositionHigh) << 32) | ((UINT64)request->nPositionLow);
1203 error = file_get_range(file, offset, request->cbRequested, &data, &size);
1206 error = delegate->ClipboardFileRangeFailure(delegate, request, error);
1208 error = delegate->ClipboardFileRangeSuccess(delegate, request, data, size);
1211 WLog_WARN(TAG,
"failed to report file range result: 0x%08X", error);
1217 static UINT dummy_file_size_success(wClipboardDelegate* delegate,
1220 return ERROR_NOT_SUPPORTED;
1223 static UINT dummy_file_size_failure(wClipboardDelegate* delegate,
1226 return ERROR_NOT_SUPPORTED;
1229 static UINT dummy_file_range_success(wClipboardDelegate* delegate,
1233 return ERROR_NOT_SUPPORTED;
1236 static UINT dummy_file_range_failure(wClipboardDelegate* delegate,
1239 return ERROR_NOT_SUPPORTED;
1242 static void setup_delegate(wClipboardDelegate* delegate)
1244 WINPR_ASSERT(delegate);
1246 delegate->ClientRequestFileSize = delegate_file_request_size;
1247 delegate->ClipboardFileSizeSuccess = dummy_file_size_success;
1248 delegate->ClipboardFileSizeFailure = dummy_file_size_failure;
1249 delegate->ClientRequestFileRange = delegate_file_request_range;
1250 delegate->ClipboardFileRangeSuccess = dummy_file_range_success;
1251 delegate->ClipboardFileRangeFailure = dummy_file_range_failure;
1252 delegate->IsFileNameComponentValid = ValidFileNameComponent;
1255 BOOL ClipboardInitSyntheticFileSubsystem(wClipboard* clipboard)
1260 if (!register_file_formats_and_synthesizers(clipboard))
1263 setup_delegate(&clipboard->delegate);
This struct contains function pointer to initialize/free objects.