diff --git a/winpr/include/winpr/clipboard.h b/winpr/include/winpr/clipboard.h index 4caaf1204..ebede5655 100644 --- a/winpr/include/winpr/clipboard.h +++ b/winpr/include/winpr/clipboard.h @@ -27,12 +27,25 @@ typedef struct _wClipboard wClipboard; typedef void* (*CLIPBOARD_SYNTHESIZE_FN)(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize); +struct _wClipboardFileSizeRequest +{ + UINT32 streamId; + UINT32 listIndex; +}; +typedef struct _wClipboardFileSizeRequest wClipboardFileSizeRequest; + typedef struct _wClipboardDelegate wClipboardDelegate; struct _wClipboardDelegate { wClipboard* clipboard; void* custom; + + UINT (*ClientRequestFileSize)(wClipboardDelegate*, const wClipboardFileSizeRequest*); + UINT (*ClipboardFileSizeSuccess)(wClipboardDelegate*, const wClipboardFileSizeRequest*, + UINT64 fileSize); + UINT (*ClipboardFileSizeFailure)(wClipboardDelegate*, const wClipboardFileSizeRequest*, + UINT errorCode); }; #ifdef __cplusplus diff --git a/winpr/libwinpr/clipboard/posix.c b/winpr/libwinpr/clipboard/posix.c index bf7e85550..da934dc46 100644 --- a/winpr/libwinpr/clipboard/posix.c +++ b/winpr/libwinpr/clipboard/posix.c @@ -590,6 +590,66 @@ error: return FALSE; } +static UINT posix_file_get_size(const struct posix_file* file, off_t* size) +{ + struct stat statbuf; + + if (stat(file->local_name, &statbuf) < 0) + { + int err = errno; + WLog_ERR(TAG, "failed to stat %s: %s", file->local_name, strerror(err)); + return ERROR_FILE_INVALID; + } + + *size = statbuf.st_size; + + return NO_ERROR; +} + +static UINT posix_file_request_size(wClipboardDelegate* delegate, + const wClipboardFileSizeRequest* request) +{ + UINT error = NO_ERROR; + off_t size = 0; + struct posix_file* file = NULL; + + if (!delegate || !delegate->clipboard || !request) + return ERROR_BAD_ARGUMENTS; + + file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex); + if (!file) + return ERROR_INDEX_ABSENT; + + error = posix_file_get_size(file, &size); + + if (error) + error = delegate->ClipboardFileSizeFailure(delegate, request, error); + else + error = delegate->ClipboardFileSizeSuccess(delegate, request, size); + + if (error) + WLog_WARN(TAG, "failed to report file size result: 0x%08X", error); + + return NO_ERROR; +} + +static UINT dummy_file_size_success(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT64 fileSize) +{ + return ERROR_NOT_SUPPORTED; +} + +static UINT dummy_file_size_failure(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT errorCode) +{ + return ERROR_NOT_SUPPORTED; +} + +static void setup_delegate(wClipboardDelegate* delegate) +{ + delegate->ClientRequestFileSize = posix_file_request_size; + delegate->ClipboardFileSizeSuccess = dummy_file_size_success; + delegate->ClipboardFileSizeFailure = dummy_file_size_failure; +} + BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard) { if (!clipboard) @@ -598,5 +658,7 @@ BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard) if (!register_file_formats_and_synthesizers(clipboard)) return FALSE; + setup_delegate(&clipboard->delegate); + return TRUE; }