x11/cliprdr: provide file content to the server

xf_cliprdr_server_file_contents_request() handles the
CLIPRDR_FILECONTENTS_REQUEST which is sent by the server to retrieve the
size or data of a single file. The server can only request one of these
things at a time, do confirm this.

The actual handling of the requests is done by wClipboardDelegate. In
order to handle its resposes we register a bunch of our own callbacks
which simply pass the responses to the server.

In case of an error we should always send a CB_RESPONSE_FAIL to the
server. If we do not then the file transfer progress dialog may end up
hanging in the remote session forever until the user logs out or kills
explorer.exe. We do wnat this.
This commit is contained in:
ilammy 2017-04-09 02:29:51 +03:00
parent 5fb89985f0
commit 401bf8b0af

View File

@ -62,6 +62,7 @@ struct xf_clipboard
CliprdrClientContext* context;
wClipboard* system;
wClipboardDelegate* delegate;
Window root_window;
Atom clipboard_atom;
@ -1421,6 +1422,153 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
return CHANNEL_RC_OK;
}
UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileSizeRequest request;
ZeroMemory(&request, sizeof(request));
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
if (fileContentsRequest->cbRequested != sizeof(UINT64))
{
WLog_WARN(TAG, "unexpected FILECONTENTS_SIZE request: %"PRIu32" bytes",
fileContentsRequest->cbRequested);
}
return clipboard->delegate->ClientRequestFileSize(clipboard->delegate, &request);
}
UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileRangeRequest request;
ZeroMemory(&request, sizeof(request));
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
request.nPositionLow = fileContentsRequest->nPositionLow;
request.nPositionHigh = fileContentsRequest->nPositionHigh;
request.cbRequested = fileContentsRequest->cbRequested;
return clipboard->delegate->ClientRequestFileRange(clipboard->delegate, &request);
}
UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = fileContentsRequest->streamId;
response.dwFlags = fileContentsRequest->dwFlags;
return context->ClientFileContentsResponse(context, &response);
}
UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
UINT error = NO_ERROR;
xfClipboard* clipboard = context->custom;
/*
* MS-RDPECLIP 2.2.5.3 File Contents Request PDU (CLIPRDR_FILECONTENTS_REQUEST):
* The FILECONTENTS_SIZE and FILECONTENTS_RANGE flags MUST NOT be set at the same time.
*/
if ((fileContentsRequest->dwFlags & (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) ==
(FILECONTENTS_SIZE | FILECONTENTS_RANGE))
{
WLog_ERR(TAG, "invalid CLIPRDR_FILECONTENTS_REQUEST.dwFlags");
return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
if (fileContentsRequest->dwFlags & FILECONTENTS_SIZE)
error = xf_cliprdr_server_file_size_request(clipboard, fileContentsRequest);
if (fileContentsRequest->dwFlags & FILECONTENTS_RANGE)
error = xf_cliprdr_server_file_range_request(clipboard, fileContentsRequest);
if (error)
{
WLog_ERR(TAG, "failed to handle CLIPRDR_FILECONTENTS_REQUEST: 0x%08X", error);
return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
return CHANNEL_RC_OK;
}
UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT64 fileSize)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
response.cbRequested = sizeof(UINT64);
response.requestedData = (BYTE*) &fileSize;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
response.cbRequested = size;
response.requestedData = (BYTE*) data;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
xfClipboard* xf_clipboard_new(xfContext* xfc)
{
int i;
@ -1542,6 +1690,14 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->targets[1] = XInternAtom(xfc->display, "TARGETS", FALSE);
clipboard->numTargets = 2;
clipboard->incr_atom = XInternAtom(xfc->display, "INCR", FALSE);
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
clipboard->delegate->custom = clipboard;
clipboard->delegate->ClipboardFileSizeSuccess = xf_cliprdr_clipboard_file_size_success;
clipboard->delegate->ClipboardFileSizeFailure = xf_cliprdr_clipboard_file_size_failure;
clipboard->delegate->ClipboardFileRangeSuccess = xf_cliprdr_clipboard_file_range_success;
clipboard->delegate->ClipboardFileRangeFailure = xf_cliprdr_clipboard_file_range_failure;
return clipboard;
error:
@ -1596,6 +1752,7 @@ void xf_cliprdr_init(xfContext* xfc, CliprdrClientContext* cliprdr)
cliprdr->ServerFormatListResponse = xf_cliprdr_server_format_list_response;
cliprdr->ServerFormatDataRequest = xf_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = xf_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = xf_cliprdr_server_file_contents_request;
}
void xf_cliprdr_uninit(xfContext* xfc, CliprdrClientContext* cliprdr)