wClipboard/posix: implement file size retrieval
This is an example of wClipboardDelegate method implementation. POSIX subsystem uses synchronous methods, but the interface can be used for asynchronous request processing as well. The client should call a Client* callback to request some action and the wClipboard will process the request and report the result by calling an approriate Clipboard* callback. Usually there will be two callbacks: one for reporting success and one to report errors. All callbacks have at least two arguments: the wClipboardDelegate itself to pass the system context, and the wClipboard*Request structure with the arguments to pass the call context. The request context is also passed to the result callbacks by wClipboard so that the client can match up the result with its previous request. The fields of wClipboard*Request structures are heavily influenced by the MS-RDPECLIP spec and mirror the respective fields of CLIPRDR_FILECONTENTS_REQUEST. wClipboard should not depend on MS-RDPECLIP, that's the reason we don't use CLIPRDR_FILECONTENTS_REQUEST directly. However, I believe that we should not have void* fields in the request structs so that they can be easily copied around if needed. This is why have the weird 'streamId' field there which has nothing to do with wClipboard and will be used only by the clients when sending replies to the server. Return values of the callbacks are to be used for reporting errors with processing the request or reply per se, not for errors encountered while performing the action requested. Thus, for example, we return NO_ERROR from posix_file_request_size() even when we fail to report the result to the client, because we have successfully performed the request and do not care if the client could not handle our reply for some reason. Also note that setup_delegate() fills in dummy implementations of Clipboard* reply callbacks so that we do not crash in case the client does not fill them and do not have to perform paranoid NULL checks before calling every single callback.
This commit is contained in:
parent
28afbe61f9
commit
33719d24ce
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user