20#include <winpr/config.h>
24#include <winpr/user.h>
25#include <winpr/image.h>
27#include "../utils/image.h"
29#include "../crt/unicode.h"
32#define TAG WINPR_TAG("clipboard.synthetic")
34static const char mime_html[] =
"text/html";
35static const char mime_ms_html[] =
"HTML Format";
37#define BITMAP_MIME_TYPES "image/bmp", "image/x-bmp", "image/x-MS-bmp", "image/x-win-bitmap"
38static const char* mime_bitmap[] = { BITMAP_MIME_TYPES };
40#if defined(WINPR_UTILS_IMAGE_WEBP)
41static const char mime_webp[] =
"image/webp";
43#if defined(WINPR_UTILS_IMAGE_PNG)
44static const char mime_png[] =
"image/png";
46#if defined(WINPR_UTILS_IMAGE_JPEG)
47static const char mime_jpeg[] =
"image/jpeg";
49static const char mime_tiff[] =
"image/tiff";
51static const char* mime_images[] = {
52#if defined(WINPR_UTILS_IMAGE_WEBP)
55#if defined(WINPR_UTILS_IMAGE_PNG)
58#if defined(WINPR_UTILS_IMAGE_JPEG)
61 mime_tiff, BITMAP_MIME_TYPES
64static const BYTE enc_base64url[] =
65 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
68static inline char* b64_encode(
const BYTE* WINPR_RESTRICT data,
size_t length,
size_t* plen)
71 const BYTE* WINPR_RESTRICT alphabet = enc_base64url;
74 size_t outLen = (length + 3) * 4 / 3;
78 const size_t alen = outLen + extra + 1ull;
79 BYTE* p = malloc(alen);
98 blocks = length - (length % 3);
99 for (
size_t i = 0; i < blocks; i += 3, q += 3)
101 c = (q[0] << 16) + (q[1] << 8) + q[2];
103 *p++ = alphabet[(c & 0x00FC0000) >> 18];
104 *p++ = alphabet[(c & 0x0003F000) >> 12];
105 *p++ = alphabet[(c & 0x00000FC0) >> 6];
106 *p++ = alphabet[c & 0x0000003F];
116 *p++ = alphabet[(c & 0x00FC0000) >> 18];
117 *p++ = alphabet[(c & 0x0003F000) >> 12];
120 c = (q[0] << 16) + (q[1] << 8);
121 *p++ = alphabet[(c & 0x00FC0000) >> 18];
122 *p++ = alphabet[(c & 0x0003F000) >> 12];
123 *p++ = alphabet[(c & 0x00000FC0) >> 6];
130 *plen = WINPR_ASSERTING_INT_CAST(
size_t, p - ret);
145WINPR_ATTR_MALLOC(free, 1)
146static
void* clipboard_synthesize_cf_locale(WINPR_ATTR_UNUSED wClipboard* clipboard,
147 UINT32 dstFormatId, WINPR_ATTR_UNUSED const
void* data,
148 WINPR_ATTR_UNUSED UINT32* pSize)
150 if (dstFormatId != CF_LOCALE)
153 "Unuspported destination format %s [0x%04" PRIx32
154 "], trying to convert from %s [0x%04" PRIx32
"]",
155 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
156 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
160 switch (clipboard->formatId)
168 const UINT32 formatIdText = ClipboardRegisterFormat(clipboard, mime_text_plain);
169 const UINT32 formatIdUtf = ClipboardRegisterFormat(clipboard, mime_text_plain);
170 if ((clipboard->formatId != formatIdText) && (clipboard->formatId != formatIdUtf))
173 "Unuspported source format %s [0x%04" PRIx32
174 "], trying to convert to %s [0x%04" PRIx32
"]",
175 ClipboardGetFormatName(clipboard, clipboard->formatId),
176 clipboard->formatId, ClipboardGetFormatName(clipboard, dstFormatId),
184 UINT32* pDstData = (UINT32*)calloc(1,
sizeof(UINT32));
190 return (
void*)pDstData;
198WINPR_ATTR_MALLOC(free, 1)
199static
void* clipboard_synthesize_string(wClipboard* clipboard, UINT32 dstFormatId,
200 const
void* data, UINT32* pSize)
202 WINPR_ASSERT(clipboard);
205 char* utf8 =
nullptr;
207 if (clipboard->formatId == CF_UNICODETEXT)
210 utf8 = ConvertWCharNToUtf8Alloc(data, *pSize /
sizeof(WCHAR), &size);
215 const size_t rc = ConvertLineEndingToLF(utf8, size);
218 else if ((clipboard->formatId == CF_TEXT) || (clipboard->formatId == CF_OEMTEXT) ||
219 (clipboard->formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
221 const size_t size = *pSize;
222 utf8 = calloc(size + 1,
sizeof(
char));
227 CopyMemory(utf8, data, size);
228 const size_t rc = ConvertLineEndingToLF(utf8, size);
229 const SSIZE_T res = winpr_utfEscapedStringToUtf8(utf8, rc);
232 winpr_znfree(utf8, size);
235 utf8len = (size_t)res;
237 else if ((clipboard->formatId == ClipboardGetFormatId(clipboard, mime_text_utf8)) ||
238 (clipboard->formatId == ClipboardGetFormatId(clipboard, mime_text_UTF8_STRING)))
240 const size_t size = *pSize;
241 utf8 = strndup(data, size);
249 "Unuspported source format %s [0x%04" PRIx32
250 "], trying to convert to %s [0x%04" PRIx32
"]",
252 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
253 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
261 size_t crlfLen = utf8len;
262 char* crlf = ConvertLineEndingToCRLF(utf8, &crlfLen);
263 winpr_znfree(utf8, utf8len);
268 WCHAR* wstr = ConvertUtf8NToWCharAlloc(crlf, crlfLen, &wlen);
269 winpr_znfree(crlf, crlfLen);
270 if (!wstr || (wlen == 0) || (wlen > UINT32_MAX /
sizeof(WCHAR)))
272 winpr_znfree(wstr, wlen *
sizeof(WCHAR));
276 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, wlen *
sizeof(WCHAR));
283 char* escaped = winpr_utf8ToUtfEscapedString(utf8, utf8len, &esclen);
284 winpr_znfree(utf8, utf8len);
285 if (!escaped || (esclen == 0) || (esclen > UINT32_MAX))
287 winpr_znfree(escaped, esclen);
290 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, esclen);
294 if ((dstFormatId == ClipboardGetFormatId(clipboard, mime_text_utf8)) ||
295 (dstFormatId == ClipboardGetFormatId(clipboard, mime_text_UTF8_STRING)))
297 if (utf8len > UINT32_MAX)
299 winpr_znfree(utf8, utf8len);
302 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, utf8len);
306 if (dstFormatId == ClipboardGetFormatId(clipboard, mime_text_plain))
309 char* escaped = winpr_utf8ToUtfEscapedString(utf8, utf8len, &esclen);
310 winpr_znfree(utf8, utf8len);
311 if (!escaped || (esclen == 0) || (esclen > UINT32_MAX))
313 winpr_znfree(escaped, esclen);
316 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, esclen);
321 "Unuspported destination format %s [0x%04" PRIx32
322 "], trying to convert from %s [0x%04" PRIx32
"]",
323 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
324 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
325 winpr_znfree(utf8, utf8len);
330WINPR_ATTR_MALLOC(free, 1)
332 size_t offset, const
void* data,
size_t size,
335 WINPR_ASSERT(pInfoHeader);
339 if ((pInfoHeader->biBitCount < 1) || (pInfoHeader->biBitCount > 32))
345 if ((pInfoHeader->biSize > size) || (offset > (size - pInfoHeader->biSize)))
349 if (bitmapOffset > DstSize)
352 wStream* s = Stream_New(
nullptr, DstSize);
357 fileHeader.bfType[0] =
'B';
358 fileHeader.bfType[1] =
'M';
359 fileHeader.bfSize = (UINT32)DstSize;
360 fileHeader.bfOffBits = (UINT32)bitmapOffset;
361 if (!writeBitmapFileHeader(s, &fileHeader))
364 if (!Stream_EnsureRemainingCapacity(s, size))
366 Stream_Write(s, data, size);
369 const size_t len = Stream_GetPosition(s);
374 *pSize = (UINT32)DstSize;
377 BYTE* dst = Stream_Buffer(s);
378 Stream_Free(s, FALSE);
383 Stream_Free(s, TRUE);
392WINPR_ATTR_MALLOC(free, 1)
393static
void* clipboard_synthesize_image_bmp(WINPR_ATTR_UNUSED wClipboard* clipboard,
394 UINT32 dstFormatId, const
void* data, UINT32* pSize)
396 UINT32 SrcSize = *pSize;
398 if (dstFormatId == CF_DIB)
403 wStream sbuffer = WINPR_C_ARRAY_INIT;
406 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
407 if (!readBitmapInfoHeader(s, &header, &offset))
410 return clipboard_prepend_bmp_header(&header, offset, data, SrcSize, pSize);
412#if defined(WINPR_UTILS_IMAGE_DIBv5)
413 else if (dstFormatId == CF_DIBV5)
416 "Unuspported destination format %s [0x%04" PRIx32
417 "], trying to convert from %s [0x%04" PRIx32
"]",
418 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
419 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
425 "Unuspported destination format %s [0x%04" PRIx32
426 "], trying to convert from %s [0x%04" PRIx32
"]",
427 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
428 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
435static BOOL format_is_image(wClipboard* clipboard, UINT32 formatId)
445 for (
size_t x = 0; x < ARRAYSIZE(mime_images); x++)
447 const char* mime = mime_images[x];
448 const UINT32
id = ClipboardRegisterFormat(clipboard, mime);
456WINPR_ATTR_MALLOC(free, 1)
457static
void* clipboard_synthesize_image_dib_to_format(wClipboard* clipboard, UINT32 dstFormatId,
458 const
void* data, UINT32* pSize)
460 WINPR_ASSERT(clipboard);
464 if ((clipboard->formatId != CF_DIB) && (clipboard->formatId != CF_DIBV5))
467 "Unuspported source format %s [0x%04" PRIx32
468 "], trying to convert to %s [0x%04" PRIx32
"]",
470 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
471 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
474 if (!format_is_image(clipboard, dstFormatId))
477 "Unuspported destination format %s [0x%04" PRIx32
478 "], trying to convert from %s [0x%04" PRIx32
"]",
480 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
481 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
485 UINT32 format = WINPR_IMAGE_BITMAP;
486#if defined(WINPR_UTILS_IMAGE_PNG)
487 if (dstFormatId == ClipboardRegisterFormat(clipboard, mime_png))
488 format = WINPR_IMAGE_PNG;
490#if defined(WINPR_UTILS_IMAGE_JPEG)
491 if (dstFormatId == ClipboardRegisterFormat(clipboard, mime_jpeg))
492 format = WINPR_IMAGE_JPEG;
494#if defined(WINPR_UTILS_IMAGE_WEBP)
495 if (dstFormatId == ClipboardRegisterFormat(clipboard, mime_webp))
496 format = WINPR_IMAGE_WEBP;
500 void* result =
nullptr;
502 wImage* img = winpr_image_new();
503 void* bmp = clipboard_synthesize_image_bmp(clipboard, clipboard->formatId, data, pSize);
504 const UINT32 SrcSize = *pSize;
510 if (winpr_image_read_buffer(img, bmp, SrcSize) <= 0)
513 result = winpr_image_write_buffer(img, format, &dsize);
516 if (dsize <= UINT32_MAX)
517 *pSize = (UINT32)dsize;
527 winpr_image_free(img, TRUE);
536WINPR_ATTR_MALLOC(free, 1)
537static
void* clipboard_synthesize_cf_dib(const
void* pvdata,
size_t dataLen, UINT32* pSize)
540 const BYTE* data = pvdata;
543 wStream sbuffer = WINPR_C_ARRAY_INIT;
544 wStream* s = Stream_StaticConstInit(&sbuffer, data, dataLen);
545 if (!readBitmapFileHeader(s, &pFileHeader))
549 BYTE* pDstData = (BYTE*)calloc(DstSize, 1);
555 memcpy(pDstData, src, DstSize);
556 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, DstSize);
560WINPR_ATTR_MALLOC(free, 1)
561static
void* clipboard_synthesize_image_format_to_cf_dib(wClipboard* clipboard, UINT32 dstFormatId,
562 const
void* data, UINT32* pSize)
564 WINPR_ASSERT(clipboard);
568 if ((dstFormatId != CF_DIB) && (dstFormatId != CF_DIBV5))
571 "Unuspported destination format %s [0x%04" PRIx32
572 "], trying to convert from %s [0x%04" PRIx32
"]",
573 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
574 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
578 if (!format_is_image(clipboard, dstFormatId))
581 "Unuspported source format %s [0x%04" PRIx32
582 "], trying to convert to %s [0x%04" PRIx32
"]",
583 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
584 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
588 void* result =
nullptr;
590 const UINT32 SrcSize = *pSize;
592 wImage* image = winpr_image_new();
596 const int res = winpr_image_read_buffer(image, data, SrcSize);
600 dst = winpr_image_write_buffer(image, WINPR_IMAGE_BITMAP, &size);
604 result = clipboard_synthesize_cf_dib(dst, size, pSize);
607 winpr_image_free(image, TRUE);
617WINPR_ATTR_MALLOC(free, 1)
618static
void* clipboard_synthesize_ms_html_format(wClipboard* clipboard, UINT32 formatId,
619 const
void* pData, UINT32* pSize)
621 if (formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
624 "Unuspported destination format %s [0x%04" PRIx32
625 "], trying to convert from %s [0x%04" PRIx32
"]",
626 ClipboardGetFormatName(clipboard, formatId), formatId,
627 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
630 if (clipboard->formatId != ClipboardGetFormatId(clipboard, mime_html))
633 "Unuspported destination format %s [0x%04" PRIx32
634 "], trying to convert from %s [0x%04" PRIx32
"]",
635 ClipboardGetFormatName(clipboard, formatId), formatId,
636 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
646 char* pDstData =
nullptr;
648 pSrcData.cpv =
nullptr;
650 WINPR_ASSERT(clipboard);
653 if (formatId == ClipboardGetFormatId(clipboard, mime_html))
655 const size_t SrcSize = (size_t)*pSize;
656 const size_t DstSize = SrcSize + 200;
657 char* body =
nullptr;
658 char num[20] = WINPR_C_ARRAY_INIT;
661 pSrcData.pv = calloc(1, SrcSize + 1);
664 memcpy(pSrcData.pv, pData, SrcSize);
668 if (SrcSize > INT_MAX)
672 if ((pSrcData.cpb[0] == 0xFE) && (pSrcData.cpb[1] == 0xFF))
674 if (!ByteSwapUnicode(pSrcData.pv, (SrcSize / 2)))
679 if ((pSrcData.cpb[0] == 0xFF) && (pSrcData.cpb[1] == 0xFE))
681 char* utfString = ConvertWCharNToUtf8Alloc(&pSrcData.pv[1],
682 (SrcSize /
sizeof(WCHAR)) - 1,
nullptr);
684 pSrcData.cpc = utfString;
690 pDstData = (
char*)calloc(1, DstSize);
695 (void)sprintf_s(pDstData, DstSize,
697 "StartHTML:0000000000\r\n"
698 "EndHTML:0000000000\r\n"
699 "StartFragment:0000000000\r\n"
700 "EndFragment:0000000000\r\n");
701 body = strstr(pSrcData.cpc,
"<body");
704 body = strstr(pSrcData.cpc,
"<BODY");
707 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
708 CopyMemory(&pDstData[23], num, 10);
712 if (!winpr_str_append(
"<HTML><BODY>", pDstData, DstSize,
nullptr))
716 if (!winpr_str_append(
"<!--StartFragment-->", pDstData, DstSize,
nullptr))
720 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
721 CopyMemory(&pDstData[69], num, 10);
723 if (!winpr_str_append(pSrcData.cpc, pDstData, DstSize,
nullptr))
727 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
728 CopyMemory(&pDstData[93], num, 10);
730 if (!winpr_str_append(
"<!--EndFragment-->", pDstData, DstSize,
nullptr))
735 if (!winpr_str_append(
"</BODY></HTML>", pDstData, DstSize,
nullptr))
740 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
741 CopyMemory(&pDstData[43], num, 10);
742 *pSize = (UINT32)strnlen(pDstData, DstSize) + 1;
749WINPR_ATTR_MALLOC(free, 1)
750static
char* html_pre_write(
wStream* s, const
char* what)
752 const size_t len = strlen(what);
753 Stream_Write(s, what, len);
754 char* startHTML = Stream_PointerAs(s,
char);
755 for (
size_t x = 0; x < 10; x++)
756 Stream_Write_INT8(s,
'0');
757 Stream_Write(s,
"\r\n", 2);
761static void html_fill_number(
char* pos,
size_t val)
763 char str[11] = WINPR_C_ARRAY_INIT;
764 (void)_snprintf(str,
sizeof(str),
"%010" PRIuz, val);
765 memcpy(pos, str, 10);
768WINPR_ATTR_MALLOC(free, 1)
769static
void* clipboard_wrap_html(const
char* mime, const
char* idata,
size_t ilength,
778 char* b64 = b64_encode((
const BYTE*)idata, ilength, &b64len);
782 const size_t mimelen = strlen(mime);
783 wStream* s = Stream_New(
nullptr, b64len + 225 + mimelen);
790 char* startHTML = html_pre_write(s,
"Version:0.9\r\nStartHTML:");
791 char* endHTML = html_pre_write(s,
"EndHTML:");
792 char* startFragment = html_pre_write(s,
"StartFragment:");
793 char* endFragment = html_pre_write(s,
"EndFragment:");
795 html_fill_number(startHTML, Stream_GetPosition(s));
796 const char html[] =
"<html><!--StartFragment-->";
797 Stream_Write(s, html, strnlen(html,
sizeof(html)));
799 html_fill_number(startFragment, Stream_GetPosition(s));
801 const char body[] =
"<body><img alt=\"FreeRDP clipboard image\" src=\"data:";
802 Stream_Write(s, body, strnlen(body,
sizeof(body)));
804 Stream_Write(s, mime, mimelen);
806 const char base64[] =
";base64,";
807 Stream_Write(s, base64, strnlen(base64,
sizeof(base64)));
808 Stream_Write(s, b64, b64len);
810 const char end[] =
"\"/></body>";
811 Stream_Write(s, end, strnlen(end,
sizeof(end)));
813 html_fill_number(endFragment, Stream_GetPosition(s));
815 const char fragend[] =
"<!--EndFragment--></html>";
816 Stream_Write(s, fragend, strnlen(fragend,
sizeof(fragend)));
817 html_fill_number(endHTML, Stream_GetPosition(s));
819 void* res = Stream_Buffer(s);
820 const size_t pos = Stream_GetPosition(s);
821 *plen = WINPR_ASSERTING_INT_CAST(uint32_t, pos);
822 Stream_Free(s, FALSE);
827WINPR_ATTR_MALLOC(free, 1)
828static
void* clipboard_wrap_format_to_html(uint32_t bmpFormat, const
char* idata,
size_t ilength,
832 wImage* img = winpr_image_new();
836 if (winpr_image_read_buffer(img, (
const BYTE*)idata, ilength) <= 0)
841 void* bmp = winpr_image_write_buffer(img, bmpFormat, &bmpsize);
845 res = clipboard_wrap_html(winpr_image_format_mime(bmpFormat), bmp, bmpsize, plen);
849 winpr_image_free(img, TRUE);
853WINPR_ATTR_MALLOC(free, 1)
854static
void* clipboard_wrap_bmp_to_ms_html(const
char* idata,
size_t ilength, uint32_t* plen)
856 const uint32_t formats[] = { WINPR_IMAGE_WEBP, WINPR_IMAGE_PNG, WINPR_IMAGE_JPEG };
858 for (
size_t x = 0; x < ARRAYSIZE(formats); x++)
860 const uint32_t format = formats[x];
861 if (winpr_image_format_is_supported(format))
863 return clipboard_wrap_format_to_html(format, idata, ilength, plen);
866 const uint32_t bmpFormat = WINPR_IMAGE_BITMAP;
867 return clipboard_wrap_html(winpr_image_format_mime(bmpFormat), idata, ilength, plen);
870WINPR_ATTR_MALLOC(free, 1)
871static
void* clipboard_synthesize_image_ms_html(WINPR_ATTR_UNUSED wClipboard* clipboard,
872 UINT32 formatId, const
void* data, UINT32* pSize)
874 if (formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
877 "Unuspported destination format %s [0x%04" PRIx32
878 "], trying to convert from %s [0x%04" PRIx32
"]",
879 ClipboardGetFormatName(clipboard, formatId), formatId,
880 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
886 const size_t datalen = *pSize;
888 switch (clipboard->formatId)
891 return clipboard_wrap_html(mime_tiff, data, datalen, pSize);
895 uint32_t bmplen = *pSize;
897 clipboard_synthesize_image_bmp(clipboard, clipboard->formatId, data, &bmplen);
900 WLog_WARN(TAG,
"failed to convert formatId 0x%08" PRIx32
" [%s]",
902 ClipboardGetFormatName(clipboard, clipboard->formatId));
907 void* res = clipboard_wrap_bmp_to_ms_html(bmp, bmplen, pSize);
913#if defined(WINPR_UTILS_IMAGE_WEBP)
914 const uint32_t idWebp = ClipboardRegisterFormat(clipboard, mime_webp);
915 if (clipboard->formatId == idWebp)
916 return clipboard_wrap_html(mime_webp, data, datalen, pSize);
919#if defined(WINPR_UTILS_IMAGE_PNG)
920 const uint32_t idPng = ClipboardRegisterFormat(clipboard, mime_png);
921 if (clipboard->formatId == idPng)
922 return clipboard_wrap_html(mime_png, data, datalen, pSize);
924#if defined(WINPR_UTILS_IMAGE_JPEG)
925 const uint32_t idJpeg = ClipboardRegisterFormat(clipboard, mime_jpeg);
926 if (clipboard->formatId == idJpeg)
927 return clipboard_wrap_html(mime_jpeg, data, datalen, pSize);
930 const uint32_t idTiff = ClipboardRegisterFormat(clipboard, mime_tiff);
931 if (clipboard->formatId == idTiff)
932 return clipboard_wrap_html(mime_tiff, data, datalen, pSize);
934 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
936 const char* mime = mime_bitmap[x];
937 const uint32_t
id = ClipboardRegisterFormat(clipboard, mime);
940 return clipboard_wrap_bmp_to_ms_html(data, datalen, pSize);
943 WLog_WARN(TAG,
"Unsupported image format id 0x%08" PRIx32
" [%s]", clipboard->formatId,
944 ClipboardGetFormatName(clipboard, clipboard->formatId));
956WINPR_ATTR_MALLOC(free, 1)
957static
void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId,
958 const
void* data, UINT32* pSize)
960 if (formatId != ClipboardGetFormatId(clipboard, mime_html))
963 "Unuspported destination format %s [0x%04" PRIx32
964 "], trying to convert from %s [0x%04" PRIx32
"]",
965 ClipboardGetFormatName(clipboard, formatId), formatId,
966 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
969 if (clipboard->formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
972 "Unuspported destination format %s [0x%04" PRIx32
973 "], trying to convert from %s [0x%04" PRIx32
"]",
974 ClipboardGetFormatName(clipboard, formatId), formatId,
975 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
979 char* pDstData =
nullptr;
981 if (formatId == ClipboardGetFormatId(clipboard, mime_ms_html))
983 const char* str = (
const char*)data;
984 const size_t SrcSize = *pSize;
985 const char* begStr = strstr(str,
"StartHTML:");
986 const char* endStr = strstr(str,
"EndHTML:");
988 if (!begStr || !endStr)
992 const long beg = strtol(&begStr[10],
nullptr, 10);
997 const long end = strtol(&endStr[8],
nullptr, 10);
999 if ((beg < 0) || (end < 0) || ((
size_t)beg > SrcSize) || ((
size_t)end > SrcSize) ||
1000 (beg >= end) || (errno != 0))
1003 const size_t DstSize = (size_t)(end - beg);
1004 pDstData = calloc(DstSize + 1,
sizeof(
char));
1009 CopyMemory(pDstData, &str[beg], DstSize);
1010 const size_t rc = ConvertLineEndingToLF(pDstData, DstSize);
1011 WINPR_ASSERT(rc <= UINT32_MAX);
1012 *pSize = (UINT32)rc;
1018BOOL ClipboardInitSynthesizers(wClipboard* clipboard)
1020 WINPR_ASSERT(clipboard);
1022 const UINT32 formatIdUtf = ClipboardRegisterFormat(clipboard, mime_text_utf8);
1023 const UINT32 formatIdUtf8String = ClipboardRegisterFormat(clipboard, mime_text_UTF8_STRING);
1024 const UINT32 formatIdPlain = ClipboardRegisterFormat(clipboard, mime_text_plain);
1025 const UINT32 textFormatIds[] = { CF_TEXT, CF_OEMTEXT, CF_UNICODETEXT,
1026 formatIdUtf, formatIdUtf8String, formatIdPlain };
1030 for (
size_t x = 0; x < ARRAYSIZE(textFormatIds); x++)
1032 const UINT32 formatId = textFormatIds[x];
1034 for (
size_t y = 0; y < ARRAYSIZE(textFormatIds); y++)
1036 const UINT32 dstFormatId = textFormatIds[y];
1037 if (formatId == dstFormatId)
1040 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, dstFormatId,
1041 clipboard_synthesize_string))
1045 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, CF_LOCALE,
1046 clipboard_synthesize_cf_locale))
1050 const uint32_t msHtmlFormat = ClipboardRegisterFormat(clipboard, mime_ms_html);
1055 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_TIFF, msHtmlFormat,
1056 clipboard_synthesize_image_ms_html))
1062 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, CF_DIB,
1063 clipboard_synthesize_image_dib_to_format))
1065 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIB, msHtmlFormat,
1066 clipboard_synthesize_image_ms_html))
1069#if defined(WINPR_UTILS_IMAGE_DIBv5)
1070 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, CF_DIB,
1071 clipboard_synthesize_image_dib_to_format))
1073 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, msHtmlFormat,
1074 clipboard_synthesize_image_ms_html))
1081 for (
size_t x = 0; x < ARRAYSIZE(mime_images); x++)
1083 const char* mime = mime_images[x];
1084 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
1085 if (altFormatId == 0)
1087 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIB, altFormatId,
1088 clipboard_synthesize_image_dib_to_format))
1090 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, CF_DIB,
1091 clipboard_synthesize_image_format_to_cf_dib))
1093 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, msHtmlFormat,
1094 clipboard_synthesize_image_ms_html))
1096#if defined(WINPR_UTILS_IMAGE_DIBv5)
1097 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, altFormatId,
1098 clipboard_synthesize_image_dib_to_format))
1100 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, CF_DIBV5,
1101 clipboard_synthesize_image_format_to_cf_dib))
1111 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_html);
1112 if (!ClipboardRegisterSynthesizerEx(clipboard, msHtmlFormat, altFormatId,
1113 clipboard_synthesize_html_format))
1121 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_html);
1125 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_ms_html);
1126 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, altFormatId,
1127 clipboard_synthesize_ms_html_format))