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 BOOL format_is_utf8(wClipboard* clipboard, UINT32 formatId);
71static inline char* b64_encode(
const BYTE* WINPR_RESTRICT data,
size_t length,
size_t* plen)
76 if (length > SIZE_MAX / 4 - 3)
79 const BYTE* WINPR_RESTRICT alphabet = enc_base64url;
82 size_t outLen = (length + 3) * 4 / 3;
86 const size_t alen = outLen + extra + 1ull;
87 BYTE* p = malloc(alen);
106 blocks = length - (length % 3);
107 for (
size_t i = 0; i < blocks; i += 3, q += 3)
109 c = (q[0] << 16) + (q[1] << 8) + q[2];
111 *p++ = alphabet[(c & 0x00FC0000) >> 18];
112 *p++ = alphabet[(c & 0x0003F000) >> 12];
113 *p++ = alphabet[(c & 0x00000FC0) >> 6];
114 *p++ = alphabet[c & 0x0000003F];
124 *p++ = alphabet[(c & 0x00FC0000) >> 18];
125 *p++ = alphabet[(c & 0x0003F000) >> 12];
128 c = (q[0] << 16) + (q[1] << 8);
129 *p++ = alphabet[(c & 0x00FC0000) >> 18];
130 *p++ = alphabet[(c & 0x0003F000) >> 12];
131 *p++ = alphabet[(c & 0x00000FC0) >> 6];
138 *plen = WINPR_ASSERTING_INT_CAST(
size_t, p - ret);
153WINPR_ATTR_MALLOC(free, 1)
154static
void* clipboard_synthesize_cf_locale(WINPR_ATTR_UNUSED wClipboard* clipboard,
155 UINT32 dstFormatId, WINPR_ATTR_UNUSED const
void* data,
156 WINPR_ATTR_UNUSED UINT32* pSize)
158 if (dstFormatId != CF_LOCALE)
161 "Unuspported destination format %s [0x%04" PRIx32
162 "], trying to convert from %s [0x%04" PRIx32
"]",
163 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
164 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
168 switch (clipboard->formatId)
176 const UINT32 formatIdText = ClipboardRegisterFormat(clipboard, mime_text_plain);
177 if ((clipboard->formatId != formatIdText) &&
178 !format_is_utf8(clipboard, clipboard->formatId))
181 "Unuspported source format %s [0x%04" PRIx32
182 "], trying to convert to %s [0x%04" PRIx32
"]",
183 ClipboardGetFormatName(clipboard, clipboard->formatId),
184 clipboard->formatId, ClipboardGetFormatName(clipboard, dstFormatId),
192 UINT32* pDstData = (UINT32*)calloc(1,
sizeof(UINT32));
198 *pSize =
sizeof(UINT32);
199 return (
void*)pDstData;
204BOOL format_is_utf8(wClipboard* clipboard, UINT32 formatId)
207 if (formatId == ClipboardGetFormatId(clipboard, mime_text_plain))
210 return (formatId == ClipboardGetFormatId(clipboard, mime_text_utf8)) ||
211 (formatId == ClipboardGetFormatId(clipboard, mime_text_UTF8_STRING));
219WINPR_ATTR_MALLOC(free, 1)
220static
void* clipboard_synthesize_string(wClipboard* clipboard, UINT32 dstFormatId,
221 const
void* data, UINT32* pSize)
223 WINPR_ASSERT(clipboard);
226 char* utf8 =
nullptr;
228 if (clipboard->formatId == CF_UNICODETEXT)
231 utf8 = ConvertWCharNToUtf8Alloc(data, *pSize /
sizeof(WCHAR), &size);
236 const size_t rc = ConvertLineEndingToLF(utf8, size);
239 else if (format_is_utf8(clipboard, clipboard->formatId))
241 const size_t size = *pSize;
242 utf8 = strndup(data, size);
245 utf8len = strlen(utf8);
247 else if ((clipboard->formatId == CF_TEXT) || (clipboard->formatId == CF_OEMTEXT) ||
248 (clipboard->formatId == ClipboardGetFormatId(clipboard, mime_text_plain)))
250 const size_t size = *pSize;
251 utf8 = calloc(size + 1,
sizeof(
char));
256 CopyMemory(utf8, data, size);
257 const size_t rc = ConvertLineEndingToLF(utf8, size);
258 const SSIZE_T res = winpr_utfEscapedStringToUtf8(utf8, rc);
261 winpr_znfree(utf8, size);
264 utf8len = (size_t)res;
269 "Unuspported source format %s [0x%04" PRIx32
270 "], trying to convert to %s [0x%04" PRIx32
"]",
272 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
273 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
281 size_t crlfLen = utf8len;
282 char* crlf = ConvertLineEndingToCRLF(utf8, &crlfLen);
283 winpr_znfree(utf8, utf8len);
288 WCHAR* wstr = ConvertUtf8NToWCharAlloc(crlf, crlfLen, &wlen);
289 winpr_znfree(crlf, crlfLen);
290 if (!wstr || (wlen == 0) || (wlen >= UINT32_MAX /
sizeof(WCHAR)))
292 winpr_znfree(wstr, wlen *
sizeof(WCHAR));
296 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, (wlen + 1) *
sizeof(WCHAR));
303 char* escaped = winpr_utf8ToUtfEscapedString(utf8, utf8len, &esclen);
304 winpr_znfree(utf8, utf8len);
305 if (!escaped || (esclen == 0) || (esclen >= UINT32_MAX))
307 winpr_znfree(escaped, esclen);
310 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, esclen + 1);
314 if (format_is_utf8(clipboard, dstFormatId))
316 if (utf8len >= UINT32_MAX)
318 winpr_znfree(utf8, utf8len);
321 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, utf8len + 1);
325 if (dstFormatId == ClipboardGetFormatId(clipboard, mime_text_plain))
328 char* escaped = winpr_utf8ToUtfEscapedString(utf8, utf8len, &esclen);
329 winpr_znfree(utf8, utf8len);
330 if (!escaped || (esclen == 0) || (esclen >= UINT32_MAX))
332 winpr_znfree(escaped, esclen);
335 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, esclen + 1);
340 "Unuspported destination format %s [0x%04" PRIx32
341 "], trying to convert from %s [0x%04" PRIx32
"]",
342 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
343 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
344 winpr_znfree(utf8, utf8len);
349WINPR_ATTR_MALLOC(free, 1)
351 size_t offset, const
void* data,
size_t size,
354 WINPR_ASSERT(pInfoHeader);
358 if ((pInfoHeader->biBitCount < 1) || (pInfoHeader->biBitCount > 32))
364 if ((pInfoHeader->biSize > size) || (offset > (size - pInfoHeader->biSize)))
368 if (bitmapOffset > DstSize)
371 wStream* s = Stream_New(
nullptr, DstSize);
376 fileHeader.bfType[0] =
'B';
377 fileHeader.bfType[1] =
'M';
378 fileHeader.bfSize = (UINT32)DstSize;
379 fileHeader.bfOffBits = (UINT32)bitmapOffset;
380 if (!writeBitmapFileHeader(s, &fileHeader))
383 if (!Stream_EnsureRemainingCapacity(s, size))
385 Stream_Write(s, data, size);
388 const size_t len = Stream_GetPosition(s);
393 *pSize = (UINT32)DstSize;
396 BYTE* dst = Stream_Buffer(s);
397 Stream_Free(s, FALSE);
402 Stream_Free(s, TRUE);
411WINPR_ATTR_MALLOC(free, 1)
412static
void* clipboard_synthesize_image_bmp(WINPR_ATTR_UNUSED wClipboard* clipboard,
413 UINT32 dstFormatId, const
void* data, UINT32* pSize)
415 UINT32 SrcSize = *pSize;
417 if (dstFormatId == CF_DIB)
422 wStream sbuffer = WINPR_C_ARRAY_INIT;
425 wStream* s = Stream_StaticConstInit(&sbuffer, data, SrcSize);
426 if (!readBitmapInfoHeader(s, &header, &offset))
429 return clipboard_prepend_bmp_header(&header, offset, data, SrcSize, pSize);
431#if defined(WINPR_UTILS_IMAGE_DIBv5)
432 else if (dstFormatId == CF_DIBV5)
435 "Unuspported destination format %s [0x%04" PRIx32
436 "], trying to convert from %s [0x%04" PRIx32
"]",
437 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
438 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
444 "Unuspported destination format %s [0x%04" PRIx32
445 "], trying to convert from %s [0x%04" PRIx32
"]",
446 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
447 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
454static BOOL format_is_image(wClipboard* clipboard, UINT32 formatId)
464 for (
size_t x = 0; x < ARRAYSIZE(mime_images); x++)
466 const char* mime = mime_images[x];
467 const UINT32
id = ClipboardRegisterFormat(clipboard, mime);
476static UINT32 image_format(WINPR_ATTR_UNUSED wClipboard* clipboard,
477 WINPR_ATTR_UNUSED UINT32 formatId)
479#if defined(WINPR_UTILS_IMAGE_PNG)
480 if (formatId == ClipboardRegisterFormat(clipboard, mime_png))
481 return WINPR_IMAGE_PNG;
483#if defined(WINPR_UTILS_IMAGE_JPEG)
484 if (formatId == ClipboardRegisterFormat(clipboard, mime_jpeg))
485 return WINPR_IMAGE_JPEG;
487#if defined(WINPR_UTILS_IMAGE_WEBP)
488 if (formatId == ClipboardRegisterFormat(clipboard, mime_webp))
489 return WINPR_IMAGE_WEBP;
491 return WINPR_IMAGE_BITMAP;
494WINPR_ATTR_MALLOC(free, 1)
495static
void* clipboard_synthesize_image_dib_to_format(wClipboard* clipboard, UINT32 dstFormatId,
496 const
void* data, UINT32* pSize)
498 WINPR_ASSERT(clipboard);
502 if ((clipboard->formatId != CF_DIB) && (clipboard->formatId != CF_DIBV5))
505 "Unuspported source format %s [0x%04" PRIx32
506 "], trying to convert to %s [0x%04" PRIx32
"]",
508 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
509 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
512 if (!format_is_image(clipboard, dstFormatId))
515 "Unuspported destination format %s [0x%04" PRIx32
516 "], trying to convert from %s [0x%04" PRIx32
"]",
518 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
519 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
523 const UINT32 format = image_format(clipboard, dstFormatId);
525 void* result =
nullptr;
527 wImage* img = winpr_image_new();
528 void* bmp = clipboard_synthesize_image_bmp(clipboard, clipboard->formatId, data, pSize);
529 const UINT32 SrcSize = *pSize;
535 if (winpr_image_read_buffer(img, bmp, SrcSize) <= 0)
538 result = winpr_image_write_buffer(img, format, &dsize);
541 if (dsize <= UINT32_MAX)
542 *pSize = (UINT32)dsize;
552 winpr_image_free(img, TRUE);
561WINPR_ATTR_MALLOC(free, 1)
562static
void* clipboard_synthesize_cf_dib(const
void* pvdata,
size_t dataLen, UINT32* pSize)
565 const BYTE* data = pvdata;
568 wStream sbuffer = WINPR_C_ARRAY_INIT;
569 wStream* s = Stream_StaticConstInit(&sbuffer, data, dataLen);
570 if (!readBitmapFileHeader(s, &pFileHeader))
574 BYTE* pDstData = (BYTE*)calloc(DstSize, 1);
580 memcpy(pDstData, src, DstSize);
581 *pSize = WINPR_ASSERTING_INT_CAST(UINT32, DstSize);
585WINPR_ATTR_MALLOC(free, 1)
586static
void* clipboard_synthesize_image_format_to_cf_dib(wClipboard* clipboard, UINT32 dstFormatId,
587 const
void* data, UINT32* pSize)
589 WINPR_ASSERT(clipboard);
593 if ((dstFormatId != CF_DIB) && (dstFormatId != CF_DIBV5))
596 "Unuspported destination format %s [0x%04" PRIx32
597 "], trying to convert from %s [0x%04" PRIx32
"]",
598 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId,
599 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
603 if (!format_is_image(clipboard, dstFormatId))
606 "Unuspported source format %s [0x%04" PRIx32
607 "], trying to convert to %s [0x%04" PRIx32
"]",
608 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
609 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
613 void* result =
nullptr;
615 const UINT32 SrcSize = *pSize;
617 wImage* image = winpr_image_new();
621 const int res = winpr_image_read_buffer(image, data, SrcSize);
625 dst = winpr_image_write_buffer(image, WINPR_IMAGE_BITMAP, &size);
629 result = clipboard_synthesize_cf_dib(dst, size, pSize);
632 winpr_image_free(image, TRUE);
642WINPR_ATTR_MALLOC(free, 1)
643static
void* clipboard_synthesize_image_format_to_format(wClipboard* clipboard, UINT32 dstFormatId,
644 const
void* data, UINT32* pSize)
646 WINPR_ASSERT(clipboard);
650 if (!format_is_image(clipboard, clipboard->formatId) ||
651 !format_is_image(clipboard, dstFormatId))
653 WLog_ERR(TAG,
"Unsupported conversion from %s [0x%04" PRIx32
"] to %s [0x%04" PRIx32
"]",
654 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId,
655 ClipboardGetFormatName(clipboard, dstFormatId), dstFormatId);
659 void* result =
nullptr;
661 const UINT32 SrcSize = *pSize;
664 wImage* image = winpr_image_new();
668 if (winpr_image_read_buffer(image, data, SrcSize) <= 0)
671 result = winpr_image_write_buffer(image, image_format(clipboard, dstFormatId), &size);
674 if (size <= UINT32_MAX)
675 *pSize = (UINT32)size;
684 winpr_image_free(image, TRUE);
693WINPR_ATTR_MALLOC(free, 1)
694static
void* clipboard_synthesize_ms_html_format(wClipboard* clipboard, UINT32 formatId,
695 const
void* pData, UINT32* pSize)
697 if (formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
700 "Unuspported destination format %s [0x%04" PRIx32
701 "], trying to convert from %s [0x%04" PRIx32
"]",
702 ClipboardGetFormatName(clipboard, formatId), formatId,
703 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
706 if (clipboard->formatId != ClipboardGetFormatId(clipboard, mime_html))
709 "Unuspported destination format %s [0x%04" PRIx32
710 "], trying to convert from %s [0x%04" PRIx32
"]",
711 ClipboardGetFormatName(clipboard, formatId), formatId,
712 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
722 char* pDstData =
nullptr;
724 pSrcData.cpv =
nullptr;
726 WINPR_ASSERT(clipboard);
729 if (formatId == ClipboardGetFormatId(clipboard, mime_ms_html))
731 const size_t SrcSize = (size_t)*pSize;
732 const size_t DstSize = SrcSize + 200;
733 char* body =
nullptr;
734 char num[20] = WINPR_C_ARRAY_INIT;
737 pSrcData.pv = calloc(1, SrcSize + 1);
740 memcpy(pSrcData.pv, pData, SrcSize);
744 if (SrcSize > INT_MAX)
748 if ((pSrcData.cpb[0] == 0xFE) && (pSrcData.cpb[1] == 0xFF))
750 if (!ByteSwapUnicode(pSrcData.pv, (SrcSize / 2)))
755 if ((pSrcData.cpb[0] == 0xFF) && (pSrcData.cpb[1] == 0xFE))
757 char* utfString = ConvertWCharNToUtf8Alloc(&pSrcData.pv[1],
758 (SrcSize /
sizeof(WCHAR)) - 1,
nullptr);
760 pSrcData.cpc = utfString;
766 pDstData = (
char*)calloc(1, DstSize);
771 (void)sprintf_s(pDstData, DstSize,
773 "StartHTML:0000000000\r\n"
774 "EndHTML:0000000000\r\n"
775 "StartFragment:0000000000\r\n"
776 "EndFragment:0000000000\r\n");
777 body = strstr(pSrcData.cpc,
"<body");
780 body = strstr(pSrcData.cpc,
"<BODY");
783 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
784 CopyMemory(&pDstData[23], num, 10);
788 if (!winpr_str_append(
"<HTML><BODY>", pDstData, DstSize,
nullptr))
792 if (!winpr_str_append(
"<!--StartFragment-->", pDstData, DstSize,
nullptr))
796 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
797 CopyMemory(&pDstData[69], num, 10);
799 if (!winpr_str_append(pSrcData.cpc, pDstData, DstSize,
nullptr))
803 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, SrcSize + 200));
804 CopyMemory(&pDstData[93], num, 10);
806 if (!winpr_str_append(
"<!--EndFragment-->", pDstData, DstSize,
nullptr))
811 if (!winpr_str_append(
"</BODY></HTML>", pDstData, DstSize,
nullptr))
816 (void)sprintf_s(num,
sizeof(num),
"%010" PRIuz
"", strnlen(pDstData, DstSize));
817 CopyMemory(&pDstData[43], num, 10);
818 *pSize = (UINT32)strnlen(pDstData, DstSize) + 1;
825WINPR_ATTR_MALLOC(free, 1)
826static
char* html_pre_write(
wStream* s, const
char* what)
828 const size_t len = strlen(what);
829 Stream_Write(s, what, len);
830 char* startHTML = Stream_PointerAs(s,
char);
831 for (
size_t x = 0; x < 10; x++)
832 Stream_Write_INT8(s,
'0');
833 Stream_Write(s,
"\r\n", 2);
837static void html_fill_number(
char* pos,
size_t val)
839 char str[11] = WINPR_C_ARRAY_INIT;
840 (void)_snprintf(str,
sizeof(str),
"%010" PRIuz, val);
841 memcpy(pos, str, 10);
844WINPR_ATTR_MALLOC(free, 1)
845static
void* clipboard_wrap_html(const
char* mime, const
char* idata,
size_t ilength,
854 char* b64 = b64_encode((
const BYTE*)idata, ilength, &b64len);
858 const size_t mimelen = strlen(mime);
859 wStream* s = Stream_New(
nullptr, b64len + 225 + mimelen);
866 char* startHTML = html_pre_write(s,
"Version:0.9\r\nStartHTML:");
867 char* endHTML = html_pre_write(s,
"EndHTML:");
868 char* startFragment = html_pre_write(s,
"StartFragment:");
869 char* endFragment = html_pre_write(s,
"EndFragment:");
871 html_fill_number(startHTML, Stream_GetPosition(s));
872 const char html[] =
"<html><!--StartFragment-->";
873 Stream_Write(s, html, strnlen(html,
sizeof(html)));
875 html_fill_number(startFragment, Stream_GetPosition(s));
877 const char body[] =
"<body><img alt=\"FreeRDP clipboard image\" src=\"data:";
878 Stream_Write(s, body, strnlen(body,
sizeof(body)));
880 Stream_Write(s, mime, mimelen);
882 const char base64[] =
";base64,";
883 Stream_Write(s, base64, strnlen(base64,
sizeof(base64)));
884 Stream_Write(s, b64, b64len);
886 const char end[] =
"\"/></body>";
887 Stream_Write(s, end, strnlen(end,
sizeof(end)));
889 html_fill_number(endFragment, Stream_GetPosition(s));
891 const char fragend[] =
"<!--EndFragment--></html>";
892 Stream_Write(s, fragend, strnlen(fragend,
sizeof(fragend)));
893 html_fill_number(endHTML, Stream_GetPosition(s));
895 void* res = Stream_Buffer(s);
896 const size_t pos = Stream_GetPosition(s);
897 *plen = WINPR_ASSERTING_INT_CAST(uint32_t, pos);
898 Stream_Free(s, FALSE);
903WINPR_ATTR_MALLOC(free, 1)
904static
void* clipboard_wrap_format_to_html(uint32_t bmpFormat, const
char* idata,
size_t ilength,
908 wImage* img = winpr_image_new();
912 if (winpr_image_read_buffer(img, (
const BYTE*)idata, ilength) <= 0)
917 void* bmp = winpr_image_write_buffer(img, bmpFormat, &bmpsize);
921 res = clipboard_wrap_html(winpr_image_format_mime(bmpFormat), bmp, bmpsize, plen);
925 winpr_image_free(img, TRUE);
929WINPR_ATTR_MALLOC(free, 1)
930static
void* clipboard_wrap_bmp_to_ms_html(const
char* idata,
size_t ilength, uint32_t* plen)
932 const uint32_t formats[] = { WINPR_IMAGE_WEBP, WINPR_IMAGE_PNG, WINPR_IMAGE_JPEG };
934 for (
size_t x = 0; x < ARRAYSIZE(formats); x++)
936 const uint32_t format = formats[x];
937 if (winpr_image_format_is_supported(format))
939 return clipboard_wrap_format_to_html(format, idata, ilength, plen);
942 const uint32_t bmpFormat = WINPR_IMAGE_BITMAP;
943 return clipboard_wrap_html(winpr_image_format_mime(bmpFormat), idata, ilength, plen);
946WINPR_ATTR_MALLOC(free, 1)
947static
void* clipboard_synthesize_image_ms_html(WINPR_ATTR_UNUSED wClipboard* clipboard,
948 UINT32 formatId, const
void* data, UINT32* pSize)
950 if (formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
953 "Unuspported destination format %s [0x%04" PRIx32
954 "], trying to convert from %s [0x%04" PRIx32
"]",
955 ClipboardGetFormatName(clipboard, formatId), formatId,
956 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
962 const size_t datalen = *pSize;
964 switch (clipboard->formatId)
967 return clipboard_wrap_html(mime_tiff, data, datalen, pSize);
971 uint32_t bmplen = *pSize;
973 clipboard_synthesize_image_bmp(clipboard, clipboard->formatId, data, &bmplen);
976 WLog_WARN(TAG,
"failed to convert formatId 0x%08" PRIx32
" [%s]",
978 ClipboardGetFormatName(clipboard, clipboard->formatId));
983 void* res = clipboard_wrap_bmp_to_ms_html(bmp, bmplen, pSize);
989#if defined(WINPR_UTILS_IMAGE_WEBP)
990 const uint32_t idWebp = ClipboardRegisterFormat(clipboard, mime_webp);
991 if (clipboard->formatId == idWebp)
992 return clipboard_wrap_html(mime_webp, data, datalen, pSize);
995#if defined(WINPR_UTILS_IMAGE_PNG)
996 const uint32_t idPng = ClipboardRegisterFormat(clipboard, mime_png);
997 if (clipboard->formatId == idPng)
998 return clipboard_wrap_html(mime_png, data, datalen, pSize);
1000#if defined(WINPR_UTILS_IMAGE_JPEG)
1001 const uint32_t idJpeg = ClipboardRegisterFormat(clipboard, mime_jpeg);
1002 if (clipboard->formatId == idJpeg)
1003 return clipboard_wrap_html(mime_jpeg, data, datalen, pSize);
1006 const uint32_t idTiff = ClipboardRegisterFormat(clipboard, mime_tiff);
1007 if (clipboard->formatId == idTiff)
1008 return clipboard_wrap_html(mime_tiff, data, datalen, pSize);
1010 for (
size_t x = 0; x < ARRAYSIZE(mime_bitmap); x++)
1012 const char* mime = mime_bitmap[x];
1013 const uint32_t
id = ClipboardRegisterFormat(clipboard, mime);
1016 return clipboard_wrap_bmp_to_ms_html(data, datalen, pSize);
1019 WLog_WARN(TAG,
"Unsupported image format id 0x%08" PRIx32
" [%s]", clipboard->formatId,
1020 ClipboardGetFormatName(clipboard, clipboard->formatId));
1032WINPR_ATTR_MALLOC(free, 1)
1033static
void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId,
1034 const
void* data, UINT32* pSize)
1036 if (formatId != ClipboardGetFormatId(clipboard, mime_html))
1039 "Unuspported destination format %s [0x%04" PRIx32
1040 "], trying to convert from %s [0x%04" PRIx32
"]",
1041 ClipboardGetFormatName(clipboard, formatId), formatId,
1042 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
1045 if (clipboard->formatId != ClipboardGetFormatId(clipboard, mime_ms_html))
1048 "Unuspported destination format %s [0x%04" PRIx32
1049 "], trying to convert from %s [0x%04" PRIx32
"]",
1050 ClipboardGetFormatName(clipboard, formatId), formatId,
1051 ClipboardGetFormatName(clipboard, clipboard->formatId), clipboard->formatId);
1055 char* pDstData =
nullptr;
1057 if (formatId == ClipboardGetFormatId(clipboard, mime_html))
1059 const char* str = (
const char*)data;
1060 const size_t SrcSize = *pSize;
1061 const char* begStr = strstr(str,
"StartHTML:");
1062 const char* endStr = strstr(str,
"EndHTML:");
1064 if (!begStr || !endStr)
1068 const long beg = strtol(&begStr[10],
nullptr, 10);
1073 const long end = strtol(&endStr[8],
nullptr, 10);
1075 if ((beg < 0) || (end < 0) || ((
size_t)beg > SrcSize) || ((
size_t)end > SrcSize) ||
1076 (beg >= end) || (errno != 0))
1079 const size_t DstSize = (size_t)(end - beg);
1080 pDstData = calloc(DstSize + 1,
sizeof(
char));
1085 CopyMemory(pDstData, &str[beg], DstSize);
1086 const size_t rc = ConvertLineEndingToLF(pDstData, DstSize);
1087 WINPR_ASSERT(rc <= UINT32_MAX);
1088 *pSize = (UINT32)rc;
1094BOOL ClipboardInitSynthesizers(wClipboard* clipboard)
1096 WINPR_ASSERT(clipboard);
1098 const UINT32 formatIdUtf = ClipboardRegisterFormat(clipboard, mime_text_utf8);
1099 const UINT32 formatIdUtf8String = ClipboardRegisterFormat(clipboard, mime_text_UTF8_STRING);
1100 const UINT32 formatIdPlain = ClipboardRegisterFormat(clipboard, mime_text_plain);
1101 const UINT32 textFormatIds[] = { CF_TEXT, CF_OEMTEXT, CF_UNICODETEXT,
1102 formatIdUtf, formatIdUtf8String, formatIdPlain };
1106 for (
size_t x = 0; x < ARRAYSIZE(textFormatIds); x++)
1108 const UINT32 formatId = textFormatIds[x];
1110 for (
size_t y = 0; y < ARRAYSIZE(textFormatIds); y++)
1112 const UINT32 dstFormatId = textFormatIds[y];
1113 if (formatId == dstFormatId)
1116 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, dstFormatId,
1117 clipboard_synthesize_string))
1121 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, CF_LOCALE,
1122 clipboard_synthesize_cf_locale))
1126 const uint32_t msHtmlFormat = ClipboardRegisterFormat(clipboard, mime_ms_html);
1131 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_TIFF, msHtmlFormat,
1132 clipboard_synthesize_image_ms_html))
1138 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, CF_DIB,
1139 clipboard_synthesize_image_dib_to_format))
1141 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIB, msHtmlFormat,
1142 clipboard_synthesize_image_ms_html))
1145#if defined(WINPR_UTILS_IMAGE_DIBv5)
1146 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, CF_DIB,
1147 clipboard_synthesize_image_dib_to_format))
1149 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, msHtmlFormat,
1150 clipboard_synthesize_image_ms_html))
1157 for (
size_t x = 0; x < ARRAYSIZE(mime_images); x++)
1159 const char* mime = mime_images[x];
1160 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime);
1161 if (altFormatId == 0)
1163 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIB, altFormatId,
1164 clipboard_synthesize_image_dib_to_format))
1166 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, CF_DIB,
1167 clipboard_synthesize_image_format_to_cf_dib))
1169 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, msHtmlFormat,
1170 clipboard_synthesize_image_ms_html))
1172#if defined(WINPR_UTILS_IMAGE_DIBv5)
1173 if (!ClipboardRegisterSynthesizerEx(clipboard, CF_DIBV5, altFormatId,
1174 clipboard_synthesize_image_dib_to_format))
1176 if (!ClipboardRegisterSynthesizerEx(clipboard, altFormatId, CF_DIBV5,
1177 clipboard_synthesize_image_format_to_cf_dib))
1182 for (
size_t x = 0; x < ARRAYSIZE(mime_images); x++)
1184 const char* mime = mime_images[x];
1185 if (strcmp(mime, mime_tiff) == 0)
1187 const UINT32 formatId = ClipboardRegisterFormat(clipboard, mime);
1188 for (
size_t y = 0; y < ARRAYSIZE(mime_images); y++)
1190 const char* altMime = mime_images[y];
1191 if ((x == y) || (strcmp(altMime, mime_tiff) == 0))
1193 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, altMime);
1194 if ((formatId == 0) || (altFormatId == 0))
1196 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, altFormatId,
1197 clipboard_synthesize_image_format_to_format))
1207 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_html);
1208 if (!ClipboardRegisterSynthesizerEx(clipboard, msHtmlFormat, altFormatId,
1209 clipboard_synthesize_html_format))
1217 UINT32 formatId = ClipboardRegisterFormat(clipboard, mime_html);
1221 const UINT32 altFormatId = ClipboardRegisterFormat(clipboard, mime_ms_html);
1222 if (!ClipboardRegisterSynthesizerEx(clipboard, formatId, altFormatId,
1223 clipboard_synthesize_ms_html_format))