Пример #1
0
static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId,
        const void* data, UINT32* pSize)
{
	int size;
	int status;
	char* crlfStr = NULL;
	WCHAR* pDstData = NULL;

	if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
	    (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) ||
	    (formatId == ClipboardGetFormatId(clipboard, "text/plain")) ||
	    (formatId == ClipboardGetFormatId(clipboard, "TEXT")) ||
	    (formatId == ClipboardGetFormatId(clipboard, "STRING")))
	{
		if (!pSize || (*pSize > INT32_MAX))
			return NULL;

		size = (int) * pSize;
		crlfStr = ConvertLineEndingToCRLF((char*) data, &size);

		if (!crlfStr)
			return NULL;

		status = ConvertToUnicode(CP_UTF8, 0, crlfStr, size, &pDstData, 0);
		free(crlfStr);

		if (status <= 0)
			return NULL;

		*pSize = status * 2;
	}

	return (void*) pDstData;
}
Пример #2
0
static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId, const void* data,
        UINT32* pSize)
{
	int size;
	char* pDstData = NULL;

	if (formatId == CF_UNICODETEXT)
	{
		size_t wsize;
		char* str = NULL;

		if (*pSize > INT32_MAX)
			return NULL;

		wsize = _wcsnlen(data, (*pSize) / 2);
		size = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) data,
		                          wsize, (CHAR**) &str, 0, NULL, NULL);

		if (!str)
			return NULL;

		pDstData = ConvertLineEndingToCRLF((const char*) str, &size);
		free(str);
		*pSize = size;
		return pDstData;
	}
	else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
	         (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) ||
	         (formatId == ClipboardGetFormatId(clipboard, "text/plain")) ||
	         (formatId == ClipboardGetFormatId(clipboard, "TEXT")) ||
	         (formatId == ClipboardGetFormatId(clipboard, "STRING")))
	{
		size = (INT64) * pSize;
		pDstData = ConvertLineEndingToCRLF((const char*) data, &size);

		if (!pDstData)
			return NULL;

		*pSize = size;
		return pDstData;
	}

	return NULL;
}
Пример #3
0
static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId, const void* data,
        UINT32* pSize)
{
	if (formatId == CF_DIB)
	{
	}
	else if (formatId == ClipboardGetFormatId(clipboard, "image/bmp"))
	{
	}

	return NULL;
}
Пример #4
0
static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId,
        const void* data, UINT32* pSize)
{
	INT64 size;
	char* pDstData = NULL;

	if (formatId == CF_UNICODETEXT)
	{
		size_t wsize = _wcsnlen(data, (*pSize) / 2);
		size = ConvertFromUnicode(CP_UTF8, 0, (LPWSTR) data,
		                          wsize, (CHAR**) &pDstData, 0, NULL, NULL);

		if (!pDstData)
			return NULL;

		size = ConvertLineEndingToLF(pDstData, size);
		*pSize = size;
		return pDstData;
	}
	else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) ||
	         (formatId == ClipboardGetFormatId(clipboard, "text/plain")) ||
	         (formatId == ClipboardGetFormatId(clipboard, "TEXT")) ||
	         (formatId == ClipboardGetFormatId(clipboard, "STRING")))
	{
		size = (INT64) * pSize;
		pDstData = (char*) malloc(size);

		if (!pDstData)
			return NULL;

		CopyMemory(pDstData, data, size);
		size = ConvertLineEndingToLF((char*) pDstData, size);
		*pSize = size;
		return pDstData;
	}

	return NULL;
}
Пример #5
0
static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId,
        const void* data, UINT32* pSize)
{
	long beg;
	long end;
	char* str;
	char* begStr;
	char* endStr;
	INT64 SrcSize;
	long DstSize = -1;
	BYTE* pDstData = NULL;

	if (formatId == ClipboardGetFormatId(clipboard, "HTML Format"))
	{
		str = (char*) data;
		SrcSize = (INT64) * pSize;
		begStr = strstr(str, "StartHTML:");
		endStr = strstr(str, "EndHTML:");

		if (!begStr || !endStr)
			return NULL;

		errno = 0;
		beg = strtol(&begStr[10], NULL, 10);

		if (errno != 0)
			return NULL;

		end = strtol(&endStr[8], NULL, 10);

		if (beg < 0 || end < 0 || (beg > SrcSize) || (end > SrcSize) || (beg >= end) || (errno != 0))
			return NULL;

		DstSize = end - beg;
		pDstData = (BYTE*) malloc(SrcSize - beg + 1);

		if (!pDstData)
			return NULL;

		CopyMemory(pDstData, &str[beg], DstSize);
		DstSize = ConvertLineEndingToLF((char*) pDstData, DstSize);
		*pSize = (UINT32) DstSize;
	}

	return (void*) pDstData;
}
Пример #6
0
static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, const void* data,
        UINT32* pSize)
{
	UINT32 SrcSize;
	UINT32 DstSize;
	BYTE* pDstData;
	SrcSize = *pSize;

	if (formatId == CF_DIBV5)
	{
	}
	else if (formatId == ClipboardGetFormatId(clipboard, "image/bmp"))
	{
		BITMAPFILEHEADER* pFileHeader;

		if (SrcSize < (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)))
			return NULL;

		pFileHeader = (BITMAPFILEHEADER*) data;

		if (pFileHeader->bfType != 0x4D42)
			return NULL;

		DstSize = SrcSize - sizeof(BITMAPFILEHEADER);
		pDstData = (BYTE*) malloc(DstSize);

		if (!pDstData)
			return NULL;

		data = (void*) & ((BYTE*) data)[sizeof(BITMAPFILEHEADER)];
		CopyMemory(pDstData, data, DstSize);
		*pSize = DstSize;
		return pDstData;
	}

	return NULL;
}
Пример #7
0
static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId,
        const void* data, UINT32* pSize)
{
	char* pSrcData = NULL;
	char* pDstData = NULL;
	INT64 SrcSize = (INT64) * pSize;

	if (formatId == ClipboardGetFormatId(clipboard, "text/html"))
	{
		char* body;
		BYTE bom[2];
		char num[20];
		WCHAR* wstr;

		if (SrcSize > 2)
		{
			CopyMemory(bom, data, 2);

			if ((bom[0] == 0xFE) && (bom[1] == 0xFF))
			{
				ByteSwapUnicode((WCHAR*) data, SrcSize / 2);
			}

			if ((bom[0] == 0xFF) && (bom[1] == 0xFE))
			{
				wstr = (WCHAR*) & ((BYTE*) data)[2];
				ConvertFromUnicode(CP_UTF8, 0, wstr,
				                   (SrcSize - 2) / 2, &pSrcData, 0, NULL, NULL);
			}
		}

		if (!pSrcData)
		{
			pSrcData = (char*) calloc(1, SrcSize + 1);

			if (!pSrcData)
				return NULL;

			CopyMemory(pSrcData, data, SrcSize);
		}

		pDstData = (char*) calloc(1, SrcSize + 200);

		if (!pDstData)
		{
			free(pSrcData);
			return NULL;
		}

		sprintf_s(pDstData, SrcSize + 200,
		          "Version:0.9\r\n"
		          "StartHTML:0000000000\r\n"
		          "EndHTML:0000000000\r\n"
		          "StartFragment:0000000000\r\n"
		          "EndFragment:0000000000\r\n");
		body = strstr(pSrcData, "<body");

		if (!body)
			body = strstr(pSrcData, "<BODY");

		/* StartHTML */
		sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
		CopyMemory(&pDstData[23], num, 10);

		if (!body)
			strcat(pDstData, "<HTML><BODY>");

		strcat(pDstData, "<!--StartFragment-->");
		/* StartFragment */
		sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
		CopyMemory(&pDstData[69], num, 10);
		strcat(pDstData, pSrcData);
		/* EndFragment */
		sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
		CopyMemory(&pDstData[93], num, 10);
		strcat(pDstData, "<!--EndFragment-->");

		if (!body)
			strcat(pDstData, "</BODY></HTML>");

		/* EndHTML */
		sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
		CopyMemory(&pDstData[43], num, 10);
		*pSize = (UINT32) strlen(pDstData) + 1;
		free(pSrcData);
	}

	return pDstData;
}
Пример #8
0
static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
	BOOL bSuccess;
	BYTE* pSrcData;
	BYTE* pDstData;
	UINT32 DstSize;
	UINT32 SrcSize;
	UINT32 formatId;
	UINT32 altFormatId;
	xfCliprdrFormat* format;
	BOOL nullTerminated = FALSE;
	UINT32 size = formatDataResponse->dataLen;
	BYTE* data = formatDataResponse->requestedFormatData;
	xfClipboard* clipboard = (xfClipboard*) context->custom;
	xfContext* xfc = clipboard->xfc;

	if (!clipboard->respond)
		return 1;

	format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);

	if (clipboard->data)
	{
		free(clipboard->data);
		clipboard->data = NULL;
	}

	pDstData = NULL;
	DstSize = 0;

	formatId = 0;
	altFormatId = 0;

	switch (clipboard->data_format)
	{
		case CF_TEXT:
			formatId = CF_TEXT;
			altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
			nullTerminated = TRUE;
			break;

		case CF_OEMTEXT:
			formatId = CF_OEMTEXT;
			altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
			nullTerminated = TRUE;
			break;

		case CF_UNICODETEXT:
			formatId = CF_UNICODETEXT;
			altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
			nullTerminated = TRUE;
			break;

		case CF_DIB:
			formatId = CF_DIB;
			altFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
			break;

		case CB_FORMAT_HTML:
			formatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
			altFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
			nullTerminated = TRUE;
			break;
	}

	SrcSize = (UINT32) size;
	pSrcData = (BYTE*) malloc(SrcSize);

	if (!pSrcData)
		return -1;

	CopyMemory(pSrcData, data, SrcSize);

	bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);

	if (!bSuccess)
		free (pSrcData);

	if (bSuccess && altFormatId)
	{
		DstSize = 0;
		pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize);

		if ((DstSize > 1) && nullTerminated)
			DstSize--;
	}

	clipboard->data = pDstData;
	clipboard->data_length = DstSize;

	xf_cliprdr_provide_data(clipboard, clipboard->respond, pDstData, DstSize);

	XSendEvent(xfc->display, clipboard->respond->xselection.requestor, 0, 0, clipboard->respond);
	XFlush(xfc->display);

	free(clipboard->respond);
	clipboard->respond = NULL;

	return 1;
}
Пример #9
0
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data, int size)
{
	BOOL bSuccess;
	UINT32 SrcSize;
	UINT32 DstSize;
	UINT32 formatId;
	UINT32 altFormatId;
	BYTE* pSrcData = NULL;
	BYTE* pDstData = NULL;
	xfCliprdrFormat* format;

	if (clipboard->incr_starts && hasData)
		return;

	format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);

	if (!hasData || !data || !format)
	{
		xf_cliprdr_send_data_response(clipboard, NULL, 0);
		return;
	}

	formatId = 0;
	altFormatId = 0;

	switch (format->formatId)
	{
		case CF_TEXT:
		case CF_OEMTEXT:
		case CF_UNICODETEXT:
			size = strlen((char*) data) + 1;
			formatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
			break;

		case CF_DIB:
			formatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
			break;

		case CB_FORMAT_HTML:
			size = strlen((char*) data) + 1;
			formatId = ClipboardGetFormatId(clipboard->system, "text/html");
			break;
	}

	SrcSize = (UINT32) size;
	pSrcData = (BYTE*) malloc(SrcSize);

	if (!pSrcData)
		return;

	CopyMemory(pSrcData, data, SrcSize);

	bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);

	if (!bSuccess)
		free(pSrcData);

	altFormatId = clipboard->requestedFormatId;

	if (bSuccess && altFormatId)
	{
		DstSize = 0;
		pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize);
	}

	if (!pDstData)
	{
		xf_cliprdr_send_data_response(clipboard, NULL, 0);
		return;
	}

	xf_cliprdr_send_data_response(clipboard, pDstData, (int) DstSize);
	free(pDstData);
}
Пример #10
0
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard,
        BOOL hasData, BYTE* data, int size)
{
	BOOL bSuccess;
	UINT32 SrcSize;
	UINT32 DstSize;
	UINT32 srcFormatId;
	UINT32 dstFormatId;
	BYTE* pDstData = NULL;
	xfCliprdrFormat* format;

	if (clipboard->incr_starts && hasData)
		return;

	format = xf_cliprdr_get_client_format_by_id(clipboard,
	         clipboard->requestedFormatId);

	if (!hasData || !data || !format)
	{
		xf_cliprdr_send_data_response(clipboard, NULL, 0);
		return;
	}

	srcFormatId = 0;

	switch (format->formatId)
	{
		case CF_RAW:
			srcFormatId = CF_RAW;
			break;

		case CF_TEXT:
		case CF_OEMTEXT:
		case CF_UNICODETEXT:
			size = strlen((char*) data) + 1;
			srcFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
			break;

		case CF_DIB:
			srcFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
			break;

		case CB_FORMAT_HTML:
			srcFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
			break;

		case CB_FORMAT_TEXTURILIST:
			srcFormatId = ClipboardGetFormatId(clipboard->system, "text/uri-list");
			break;
	}

	SrcSize = (UINT32) size;
	bSuccess = ClipboardSetData(clipboard->system, srcFormatId, data, SrcSize);

	if (format->formatName)
		dstFormatId = ClipboardGetFormatId(clipboard->system, format->formatName);
	else
		dstFormatId = format->formatId;

	if (bSuccess)
	{
		DstSize = 0;
		pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);
	}

	if (!pDstData)
	{
		xf_cliprdr_send_data_response(clipboard, NULL, 0);
		return;
	}

	/*
	 * File lists require a bit of postprocessing to convert them from WinPR's FILDESCRIPTOR
	 * format to CLIPRDR_FILELIST expected by the server.
	 *
	 * We check for "FileGroupDescriptorW" format being registered (i.e., nonzero) in order
	 * to not process CF_RAW as a file list in case WinPR does not support file transfers.
	 */
	if (dstFormatId &&
	    (dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW")))
	{
		UINT error = NO_ERROR;
		FILEDESCRIPTOR* file_array = (FILEDESCRIPTOR*) pDstData;
		UINT32 file_count = DstSize / sizeof(FILEDESCRIPTOR);
		pDstData = NULL;
		DstSize = 0;
		error = cliprdr_serialize_file_list(file_array, file_count, &pDstData, &DstSize);

		if (error)
			WLog_ERR(TAG, "failed to serialize CLIPRDR_FILELIST: 0x%08X", error);

		free(file_array);
	}

	xf_cliprdr_send_data_response(clipboard, pDstData, (int) DstSize);
	free(pDstData);
}
Пример #11
0
xfClipboard* xf_clipboard_new(xfContext* xfc)
{
	int i, n = 0;
	rdpChannels* channels;
	xfClipboard* clipboard;

	if (!(clipboard = (xfClipboard*) calloc(1, sizeof(xfClipboard))))
	{
		WLog_ERR(TAG, "failed to allocate xfClipboard data");
		return NULL;
	}

	xfc->clipboard = clipboard;
	clipboard->xfc = xfc;
	channels = ((rdpContext*) xfc)->channels;
	clipboard->channels = channels;
	clipboard->system = ClipboardCreate();
	clipboard->requestedFormatId = -1;
	clipboard->root_window = DefaultRootWindow(xfc->display);
	clipboard->clipboard_atom = XInternAtom(xfc->display, "CLIPBOARD", FALSE);

	if (clipboard->clipboard_atom == None)
	{
		WLog_ERR(TAG, "unable to get CLIPBOARD atom");
		goto error;
	}

	clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE);
	clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE);
	clipboard->raw_format_list_atom =
	    XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE);
	xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE);
	XSelectInput(xfc->display, clipboard->root_window, PropertyChangeMask);
#ifdef WITH_XFIXES

	if (XFixesQueryExtension(xfc->display, &clipboard->xfixes_event_base,
	                         &clipboard->xfixes_error_base))
	{
		int xfmajor, xfminor;

		if (XFixesQueryVersion(xfc->display, &xfmajor, &xfminor))
		{
			XFixesSelectSelectionInput(xfc->display, clipboard->root_window,
			                           clipboard->clipboard_atom, XFixesSetSelectionOwnerNotifyMask);
			clipboard->xfixes_supported = TRUE;
		}
		else
		{
			WLog_ERR(TAG, "Error querying X Fixes extension version");
		}
	}
	else
	{
		WLog_ERR(TAG, "Error loading X Fixes extension");
	}

#else
	WLog_ERR(TAG,
	         "Warning: Using clipboard redirection without XFIXES extension is strongly discouraged!");
#endif
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False);
	clipboard->clientFormats[n].formatId = CF_RAW;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False);
	clipboard->clientFormats[n].formatId = CF_UNICODETEXT;
	n++;
	clipboard->clientFormats[n].atom = XA_STRING;
	clipboard->clientFormats[n].formatId = CF_TEXT;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/png", False);
	clipboard->clientFormats[n].formatId = CB_FORMAT_PNG;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/jpeg", False);
	clipboard->clientFormats[n].formatId = CB_FORMAT_JPEG;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/gif", False);
	clipboard->clientFormats[n].formatId = CB_FORMAT_GIF;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/bmp", False);
	clipboard->clientFormats[n].formatId = CF_DIB;
	n++;
	clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/html", False);
	clipboard->clientFormats[n].formatId = CB_FORMAT_HTML;
	clipboard->clientFormats[n].formatName = _strdup("HTML Format");

	if (!clipboard->clientFormats[n].formatName)
		goto error;

	n++;

	/*
	 * Existence of registered format IDs for file formats does not guarantee that they are
	 * in fact supported by wClipboard (as further initialization may have failed after format
	 * registration). However, they are definitely not supported if there are no registered
	 * formats. In this case we should not list file formats in TARGETS.
	 */
	if (ClipboardGetFormatId(clipboard->system, "text/uri-list"))
	{
		clipboard->file_formats_registered = TRUE;
		clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/uri-list", False);
		clipboard->clientFormats[n].formatId = CB_FORMAT_TEXTURILIST;
		clipboard->clientFormats[n].formatName = _strdup("FileGroupDescriptorW");

		if (!clipboard->clientFormats[n].formatName)
			goto error;

		n++;
	}

	clipboard->numClientFormats = n;
	clipboard->targets[0] = XInternAtom(xfc->display, "TIMESTAMP", FALSE);
	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:

	for (i = 0; i < n; i++)
		free(clipboard->clientFormats[i].formatName);

	ClipboardDestroy(clipboard->system);
	free(clipboard);
	return NULL;
}
Пример #12
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
        context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
	BOOL bSuccess;
	BYTE* pDstData;
	UINT32 DstSize;
	UINT32 SrcSize;
	UINT32 srcFormatId;
	UINT32 dstFormatId;
	BOOL nullTerminated = FALSE;
	UINT32 size = formatDataResponse->dataLen;
	BYTE* data = formatDataResponse->requestedFormatData;
	xfClipboard* clipboard = (xfClipboard*) context->custom;
	xfContext* xfc = clipboard->xfc;

	if (!clipboard->respond)
		return CHANNEL_RC_OK;

	xf_cliprdr_clear_cached_data(clipboard);
	pDstData = NULL;
	DstSize = 0;
	srcFormatId = 0;
	dstFormatId = 0;

	if (clipboard->data_raw_format)
	{
		srcFormatId = CF_RAW;
		dstFormatId = CF_RAW;
	}
	else if (clipboard->data_format_name)
	{
		if (strcmp(clipboard->data_format_name, "HTML Format") == 0)
		{
			srcFormatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
			dstFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
			nullTerminated = TRUE;
		}
	}
	else
	{
		switch (clipboard->data_format_id)
		{
			case CF_TEXT:
				srcFormatId = CF_TEXT;
				dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
				nullTerminated = TRUE;
				break;

			case CF_OEMTEXT:
				srcFormatId = CF_OEMTEXT;
				dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
				nullTerminated = TRUE;
				break;

			case CF_UNICODETEXT:
				srcFormatId = CF_UNICODETEXT;
				dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
				nullTerminated = TRUE;
				break;

			case CF_DIB:
				srcFormatId = CF_DIB;
				dstFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
				break;
		}
	}

	SrcSize = (UINT32) size;
	bSuccess = ClipboardSetData(clipboard->system, srcFormatId, data, SrcSize);

	if (bSuccess)
	{
		DstSize = 0;
		pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);

		if (!pDstData)
		{
			WLog_ERR(TAG, "failed to get clipboard data in format %s [source format %s]",
			         ClipboardGetFormatName(clipboard, dstFormatId),
			         ClipboardGetFormatName(clipboard, srcFormatId));
			return ERROR_INTERNAL_ERROR;
		}

		if (nullTerminated)
		{
			while (DstSize > 0 && pDstData[DstSize - 1] == '\0')
				DstSize--;
		}
	}

	/* Cache converted and original data to avoid doing a possibly costly
	 * conversion again on subsequent requests */
	clipboard->data = pDstData;
	clipboard->data_length = DstSize;
	/* We have to copy the original data again, as pSrcData is now owned
	 * by clipboard->system. Memory allocation failure is not fatal here
	 * as this is only a cached value. */
	clipboard->data_raw = (BYTE*) malloc(size);

	if (clipboard->data_raw)
	{
		CopyMemory(clipboard->data_raw, data, size);
		clipboard->data_raw_length = size;
	}
	else
	{
		WLog_WARN(TAG, "failed to allocate %"PRIu32" bytes for a copy of raw clipboard data", size);
	}

	xf_cliprdr_provide_data(clipboard, clipboard->respond, pDstData, DstSize);
	XSendEvent(xfc->display, clipboard->respond->xselection.requestor, 0, 0,
	           clipboard->respond);
	XFlush(xfc->display);
	free(clipboard->respond);
	clipboard->respond = NULL;
	return CHANNEL_RC_OK;
}