当前位置:   article > 正文

wfreerdp中剪切板原理_wf_cliprdr.c

wf_cliprdr.c

剪切板是freerdp中相对复杂的一个实现,主要难点在于整个通讯的流程,channel部分和rail的实现相似。主要是在剪切板初始化的时候实现MonitorReady、ServerFormatDataRequest、ServerFormatDataResponse函数。此处仅完成从client->server端的拷贝。

流程简介

在这里插入图片描述

  1. MonitorReady部分,剪切板准备部分。主要是把本地支持的剪切板类型发送给rdp server,这部固定写法,不用纠结。
UINT cliprdr_send_capabilities(CliprdrClientContext* clipboard) {
	CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
		.capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
		.capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
		.version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
		.generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
	};
	CLIPRDR_CAPABILITIES caps = {
		.cCapabilitiesSets = 1,
		.capabilitySets = (CLIPRDR_CAPABILITY_SET*)&cap_set
	};
	return clipboard->ClientCapabilities(clipboard, &caps);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 在 rdp 客户端剪切板有变化的时候,通知rdp server,这里需要监听windows事件:WM_CLIPBOARDUPDATE。重点:这里只需要通知rdp server支持的类型即可,只有当rdp server内部需要使用剪切板的时候才会找客户端获取。
case WM_CLIPBOARDUPDATE:
			cliprdr_send_format_list(swfc->clipboard->context);
			break;
  • 1
  • 2
  • 3
UINT cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
	CLIPRDR_FORMAT_LIST format_list = {
		.formats = (CLIPRDR_FORMAT[]) {
			{.formatId = CF_TEXT },
			{ .formatId = CF_UNICODETEXT }
		},
		.numFormats = 2
	};
	return cliprdr->ClientFormatList(cliprdr, &format_list);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 当rdp server内部按ctrl-v或者右键->粘贴的时候,freerdp内部会调用swf_cliprdr_server_format_data_request回调。在回调中,打开剪切板、获取数据、发送给rdp server(ClientFormatDataResponse)。
UINT swf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) {
	UINT rc = CHANNEL_RC_OK;
	HANDLE hClipdata;
	swfContext * swfContxt = (swfContext *)context->custom;
	UINT32 requestedFormatId = formatDataRequest->requestedFormatId;
	CLIPRDR_FORMAT_DATA_RESPONSE response;
	size_t size = 0;
	char* globlemem = NULL;
	void* buff = NULL;

	if (!OpenClipboard(swfContxt->hwnd))
		return ERROR_INTERNAL_ERROR;

	hClipdata = GetClipboardData(requestedFormatId);

	if (!hClipdata)
	{
		CloseClipboard();
		return ERROR_INTERNAL_ERROR;
	}
	globlemem = (char*)GlobalLock(hClipdata);
	size = (int)GlobalSize(hClipdata);
	buff = malloc(size);
	CopyMemory(buff, globlemem, size);
	GlobalUnlock(hClipdata);
	CloseClipboard();

	response.msgFlags = CB_RESPONSE_OK;
	response.dataLen = size;
	response.requestedFormatData = (BYTE*)buff;
	rc = context->ClientFormatDataResponse(context,&response);
	free(buff);
	return rc;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/402858
推荐阅读
相关标签
  

闽ICP备14008679号