FreeRDP
Loading...
Searching...
No Matches
TestClipboardFormats.c
1
2#include <winpr/crt.h>
3#include <winpr/print.h>
4#include <winpr/image.h>
5#include <winpr/clipboard.h>
6#include <winpr/stream.h>
7#include <winpr/user.h>
8
9static BOOL test_dib_to_bmp(const BYTE* dib, size_t dibSize, size_t expectedOffset)
10{
11 BOOL rc = FALSE;
12
13 wClipboard* clipboard = ClipboardCreate();
14 if (!clipboard)
15 return FALSE;
16
17 const UINT32 bmpId = ClipboardRegisterFormat(clipboard, "image/bmp");
18 if ((bmpId == 0) || (dibSize > UINT32_MAX) ||
19 !ClipboardSetData(clipboard, CF_DIB, dib, (UINT32)dibSize))
20 goto fail;
21
22 UINT32 bmpSize = 0;
23 BYTE* bmp = ClipboardGetData(clipboard, bmpId, &bmpSize);
24 if (!bmp)
25 goto fail;
26
27 wStream bmpBuffer = WINPR_C_ARRAY_INIT;
28 wStream* s = Stream_StaticConstInit(&bmpBuffer, bmp, bmpSize);
29 if (!s || (bmpSize < sizeof(WINPR_BITMAP_FILE_HEADER)))
30 goto fail_bmp;
31
32 Stream_Seek(s, 10);
33 UINT32 bitmapOffset = 0;
34 Stream_Read_UINT32(s, bitmapOffset);
35 if ((bitmapOffset != expectedOffset) ||
36 (bmpSize != sizeof(WINPR_BITMAP_FILE_HEADER) + dibSize) ||
37 (memcmp(&bmp[sizeof(WINPR_BITMAP_FILE_HEADER)], dib, dibSize) != 0))
38 goto fail_bmp;
39
40 /* The synthesized BMP must also be readable by the image conversion code. */
41 wImage* image = winpr_image_new();
42 if (!image)
43 goto fail_bmp;
44 rc = (winpr_image_read_buffer(image, bmp, bmpSize) > 0);
45 winpr_image_free(image, TRUE);
46
47fail_bmp:
48 free(bmp);
49fail:
50 ClipboardDestroy(clipboard);
51 return rc;
52}
53
54static void write_dib_info_header(wStream* s, UINT32 size, UINT16 bpp, UINT32 compression)
55{
56 WINPR_ASSERT(s);
57
58 Stream_Write_UINT32(s, size);
59 Stream_Write_INT32(s, 1); /* width */
60 Stream_Write_INT32(s, 1); /* height */
61 Stream_Write_UINT16(s, 1); /* planes */
62 Stream_Write_UINT16(s, bpp);
63 Stream_Write_UINT32(s, compression);
64 Stream_Write_UINT32(s, 4); /* image size */
65 Stream_Zero(s, 16); /* resolution and palette metadata */
66}
67
68static BOOL test_dib_offsets(void)
69{
70 BYTE v4[sizeof(BITMAPV4HEADER) + 4] = WINPR_C_ARRAY_INIT;
71 wStream sbuffer = WINPR_C_ARRAY_INIT;
72 wStream* s = Stream_StaticInit(&sbuffer, v4, sizeof(v4));
73 if (!s)
74 return FALSE;
75 write_dib_info_header(s, sizeof(BITMAPV4HEADER), 32, BI_BITFIELDS);
76
77 Stream_Write_UINT32(s, 0x00FF0000); /* red mask */
78 Stream_Write_UINT32(s, 0x0000FF00); /* green mask */
79 Stream_Write_UINT32(s, 0x000000FF); /* blue mask */
80 Stream_Write_UINT32(s, 0xFF000000); /* alpha mask */
81 Stream_Zero(s, sizeof(BITMAPV4HEADER) - Stream_GetPosition(s));
82 Stream_Write_UINT32(s, 0xFF123456); /* pixel */
83 if (!test_dib_to_bmp(v4, sizeof(v4), sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(BITMAPV4HEADER)))
84 return FALSE;
85
86 BYTE bitfields[sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD) + 4] = WINPR_C_ARRAY_INIT;
87 s = Stream_StaticInit(&sbuffer, bitfields, sizeof(bitfields));
88 if (!s)
89 return FALSE;
90 write_dib_info_header(s, sizeof(BITMAPINFOHEADER), 32, BI_BITFIELDS);
91 Stream_Write_UINT32(s, 0x00FF0000); /* red mask */
92 Stream_Write_UINT32(s, 0x0000FF00); /* green mask */
93 Stream_Write_UINT32(s, 0x000000FF); /* blue mask */
94 Stream_Write_UINT32(s, 0xFF123456); /* pixel */
95 if (!test_dib_to_bmp(bitfields, sizeof(bitfields),
97 3 * sizeof(DWORD)))
98 return FALSE;
99
100 BYTE paletted[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) + 4] = WINPR_C_ARRAY_INIT;
101 s = Stream_StaticInit(&sbuffer, paletted, sizeof(paletted));
102 if (!s)
103 return FALSE;
104 write_dib_info_header(s, sizeof(BITMAPINFOHEADER), 8, BI_RGB);
105 Stream_Zero(s, 256 * sizeof(RGBQUAD));
106 Stream_Write_UINT32(s, 0); /* pixel row */
107 return test_dib_to_bmp(paletted, sizeof(paletted),
109 256 * sizeof(RGBQUAD));
110}
111
112static BOOL test_text_leading_newline(void)
113{
114 const char* tests[][2] = { { "\nfoo", "\r\nfoo" }, { "\n", "\r\n" } };
115 BOOL rc = FALSE;
116
117 wClipboard* clipboard = ClipboardCreate();
118 if (!clipboard)
119 return FALSE;
120
121 const UINT32 textId = ClipboardRegisterFormat(clipboard, "text/plain");
122 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
123 {
124 /* local text/plain is set without a terminator */
125 if (!ClipboardSetData(clipboard, textId, tests[x][0], (UINT32)strlen(tests[x][0])))
126 goto fail;
127
128 UINT32 size = 0;
129 WCHAR* wstr = ClipboardGetData(clipboard, CF_UNICODETEXT, &size);
130 char* str = ConvertWCharNToUtf8Alloc(wstr, size / sizeof(WCHAR), nullptr);
131 const BOOL match = str && (strcmp(str, tests[x][1]) == 0);
132 free(wstr);
133 free(str);
134 if (!match)
135 {
136 (void)fprintf(stderr, "text/plain to CF_UNICODETEXT failed for case %" PRIuz "\n", x);
137 goto fail;
138 }
139 }
140 rc = TRUE;
141
142fail:
143 ClipboardDestroy(clipboard);
144 return rc;
145}
146
147int TestClipboardFormats(int argc, char* argv[])
148{
149 int rc = -1;
150 UINT32 count = 0;
151 UINT32* pFormatIds = nullptr;
152 const char* formatName = nullptr;
153 wClipboard* clipboard = nullptr;
154 UINT32 utf8StringFormatId = 0;
155
156 WINPR_UNUSED(argc);
157 WINPR_UNUSED(argv);
158
159 clipboard = ClipboardCreate();
160 if (!clipboard)
161 return -1;
162 if (!test_dib_offsets())
163 goto fail;
164 if (!test_text_leading_newline())
165 goto fail;
166
167 const char* mime_types[] = { "text/html", "text/html", "image/bmp",
168 "image/png", "image/webp", "image/jpeg" };
169 for (size_t x = 0; x < ARRAYSIZE(mime_types); x++)
170 {
171 const char* mime = mime_types[x];
172 UINT32 id = ClipboardRegisterFormat(clipboard, mime);
173 (void)fprintf(stderr, "ClipboardRegisterFormat(%s) -> 0x%08" PRIx32 "\n", mime, id);
174 if (id == 0)
175 goto fail;
176 }
177
178 utf8StringFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING");
179 pFormatIds = nullptr;
180 count = ClipboardGetRegisteredFormatIds(clipboard, &pFormatIds);
181
182 for (UINT32 index = 0; index < count; index++)
183 {
184 UINT32 formatId = pFormatIds[index];
185 formatName = ClipboardGetFormatName(clipboard, formatId);
186 (void)fprintf(stderr, "Format: 0x%08" PRIX32 " %s\n", formatId, formatName);
187 }
188
189 free(pFormatIds);
190
191 if (1)
192 {
193 BOOL bSuccess = 0;
194 UINT32 SrcSize = 0;
195 UINT32 DstSize = 0;
196 const char pSrcData[] = "this is a test string";
197 char* pDstData = nullptr;
198
199 SrcSize = (UINT32)(strnlen(pSrcData, ARRAYSIZE(pSrcData)) + 1);
200 bSuccess = ClipboardSetData(clipboard, utf8StringFormatId, pSrcData, SrcSize);
201 (void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
202 DstSize = 0;
203 pDstData = (char*)ClipboardGetData(clipboard, utf8StringFormatId, &DstSize);
204 (void)fprintf(stderr, "ClipboardGetData: %s\n", pDstData);
205 free(pDstData);
206 }
207
208 if (1)
209 {
210 UINT32 DstSize = 0;
211 char* pSrcData = nullptr;
212 WCHAR* pDstData = nullptr;
213 DstSize = 0;
214 pDstData = (WCHAR*)ClipboardGetData(clipboard, CF_UNICODETEXT, &DstSize);
215 pSrcData = ConvertWCharNToUtf8Alloc(pDstData, DstSize / sizeof(WCHAR), nullptr);
216
217 (void)fprintf(stderr, "ClipboardGetData (synthetic): %s\n", pSrcData);
218 free(pDstData);
219 free(pSrcData);
220 }
221
222 pFormatIds = nullptr;
223 count = ClipboardGetFormatIds(clipboard, &pFormatIds);
224
225 for (UINT32 index = 0; index < count; index++)
226 {
227 UINT32 formatId = pFormatIds[index];
228 formatName = ClipboardGetFormatName(clipboard, formatId);
229 (void)fprintf(stderr, "Format: 0x%08" PRIX32 " %s\n", formatId, formatName);
230 }
231
232 if (1)
233 {
234 const char* name = TEST_CLIP_BMP;
235 BOOL bSuccess = FALSE;
236 UINT32 idBmp = ClipboardRegisterFormat(clipboard, "image/bmp");
237
238 wImage* img = winpr_image_new();
239 if (!img)
240 goto fail;
241
242 if (winpr_image_read(img, name) <= 0)
243 {
244 winpr_image_free(img, TRUE);
245 goto fail;
246 }
247
248 size_t bmpsize = 0;
249 void* data = winpr_image_write_buffer(img, WINPR_IMAGE_BITMAP, &bmpsize);
250 bSuccess = ClipboardSetData(clipboard, idBmp, data, bmpsize);
251 (void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
252
253 free(data);
254 winpr_image_free(img, TRUE);
255 if (!bSuccess)
256 goto fail;
257
258 {
259 UINT32 id = CF_DIB;
260
261 UINT32 DstSize = 0;
262 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
263 (void)fprintf(stderr, "ClipboardGetData: [CF_DIB] %p [%" PRIu32 "]\n", pDstData,
264 DstSize);
265 if (!pDstData)
266 goto fail;
267 bSuccess = ClipboardSetData(clipboard, id, pDstData, DstSize);
268 free(pDstData);
269 if (!bSuccess)
270 goto fail;
271 }
272 {
273 const uint32_t id = ClipboardGetFormatId(clipboard, "HTML Format");
274 UINT32 DstSize = 0;
275 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
276 if (!pDstData)
277 goto fail;
278 {
279 FILE* fp = fopen("test.html", "w");
280 if (fp)
281 {
282 (void)fwrite(pDstData, 1, DstSize, fp);
283 (void)fclose(fp);
284 }
285 }
286 free(pDstData);
287 }
288 {
289 UINT32 id = ClipboardRegisterFormat(clipboard, "image/bmp");
290
291 UINT32 DstSize = 0;
292 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
293 (void)fprintf(stderr, "ClipboardGetData: [image/bmp] %p [%" PRIu32 "]\n", pDstData,
294 DstSize);
295 if (!pDstData)
296 goto fail;
297 free(pDstData);
298 if (DstSize != bmpsize)
299 goto fail;
300 }
301
302#if defined(WINPR_UTILS_IMAGE_PNG)
303 {
304 UINT32 id = ClipboardRegisterFormat(clipboard, "image/png");
305
306 UINT32 DstSize = 0;
307 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
308 (void)fprintf(stderr, "ClipboardGetData: [image/png] %p\n", pDstData);
309 if (!pDstData)
310 goto fail;
311 free(pDstData);
312 }
313 {
314 const char* name = TEST_CLIP_PNG;
315 BOOL bSuccess = FALSE;
316 UINT32 idBmp = ClipboardRegisterFormat(clipboard, "image/png");
317
318 wImage* img = winpr_image_new();
319 if (!img)
320 goto fail;
321
322 if (winpr_image_read(img, name) <= 0)
323 {
324 winpr_image_free(img, TRUE);
325 goto fail;
326 }
327
328 size_t bmpsize = 0;
329 void* data = winpr_image_write_buffer(img, WINPR_IMAGE_PNG, &bmpsize);
330 bSuccess = ClipboardSetData(clipboard, idBmp, data, bmpsize);
331 (void)fprintf(stderr, "ClipboardSetData: %" PRId32 "\n", bSuccess);
332
333 free(data);
334 winpr_image_free(img, TRUE);
335 if (!bSuccess)
336 goto fail;
337 }
338 {
339 UINT32 id = CF_DIB;
340
341 UINT32 DstSize = 0;
342 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
343 (void)fprintf(stderr, "ClipboardGetData: [CF_DIB] %p [%" PRIu32 "]\n", pDstData,
344 DstSize);
345 if (!pDstData)
346 goto fail;
347 bSuccess = ClipboardSetData(clipboard, id, pDstData, DstSize);
348 free(pDstData);
349 if (!bSuccess)
350 goto fail;
351 }
352#endif
353
354#if defined(WINPR_UTILS_IMAGE_WEBP)
355 {
356 UINT32 id = ClipboardRegisterFormat(clipboard, "image/webp");
357
358 UINT32 DstSize = 0;
359 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
360 (void)fprintf(stderr, "ClipboardGetData: [image/webp] %p\n", pDstData);
361 if (!pDstData)
362 goto fail;
363 free(pDstData);
364 }
365#endif
366
367#if defined(WINPR_UTILS_IMAGE_JPEG)
368 {
369 UINT32 id = ClipboardRegisterFormat(clipboard, "image/jpeg");
370
371 UINT32 DstSize = 0;
372 void* pDstData = ClipboardGetData(clipboard, id, &DstSize);
373 (void)fprintf(stderr, "ClipboardGetData: [image/jpeg] %p\n", pDstData);
374 if (!pDstData)
375 goto fail;
376 free(pDstData);
377 }
378#endif
379 }
380
381 rc = 0;
382
383fail:
384 free(pFormatIds);
385 ClipboardDestroy(clipboard);
386 return rc;
387}