VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp@ 80444

Last change on this file since 80444 was 80444, checked in by vboxsync, 5 years ago

Shared Clipboard/URI: Added protocol versioning support plus enhanced versions of existing commands (to also provide context IDs, among other stuff). So far only the host service(s) and the Windows guest is using the new(er) protocol.

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 25.5 KB
Line 
1/* $Id: clipboard-common.cpp 80444 2019-08-27 17:47:44Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Some helper function for converting between the various eol.
4 */
5
6/*
7 * Includes contributions from François Revol
8 *
9 * Copyright (C) 2006-2019 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
21
22#include <iprt/alloc.h>
23#include <iprt/assert.h>
24#include <iprt/semaphore.h>
25#include <iprt/path.h>
26
27#include <iprt/errcore.h>
28#include <VBox/log.h>
29#include <VBox/GuestHost/clipboard-helper.h>
30#include <VBox/HostServices/VBoxClipboardSvc.h>
31
32
33/**
34 * Allocates a new event payload.
35 *
36 * @returns VBox status code.
37 * @param uID Event ID to associate payload to.
38 * @param pvData Data block to associate to this payload.
39 * @param cbData Size (in bytes) of data block to associate.
40 * @param ppPayload Where to store the allocated event payload on success.
41 */
42int SharedClipboardPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData,
43 PSHAREDCLIPBOARDEVENTPAYLOAD *ppPayload)
44{
45 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
46 AssertReturn (cbData, VERR_INVALID_PARAMETER);
47
48 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload =
49 (PSHAREDCLIPBOARDEVENTPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDEVENTPAYLOAD));
50 if (!pPayload)
51 return VERR_NO_MEMORY;
52
53 pPayload->pvData = RTMemAlloc(cbData);
54 if (pPayload->pvData)
55 {
56 memcpy(pPayload->pvData, pvData, cbData);
57
58 pPayload->cbData = cbData;
59 pPayload->uID = uID;
60
61 *ppPayload = pPayload;
62
63 return VINF_SUCCESS;
64 }
65
66 RTMemFree(pPayload);
67 return VERR_NO_MEMORY;
68}
69
70/**
71 * Frees an event payload.
72 *
73 * @returns VBox status code.
74 * @param pPayload Event payload to free.
75 */
76void SharedClipboardPayloadFree(PSHAREDCLIPBOARDEVENTPAYLOAD pPayload)
77{
78 if (!pPayload)
79 return;
80
81 if (pPayload->pvData)
82 {
83 Assert(pPayload->cbData);
84 RTMemFree(pPayload->pvData);
85 pPayload->pvData = NULL;
86 }
87
88 pPayload->cbData = 0;
89
90 RTMemFree(pPayload);
91 pPayload = NULL;
92}
93
94int SharedClipboardEventCreate(PSHAREDCLIPBOARDEVENT pEvent, uint16_t uID)
95{
96 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
97
98 LogFlowFunc(("Event %RU16\n", uID));
99
100 int rc = RTSemEventCreate(&pEvent->hEventSem);
101 if (RT_SUCCESS(rc))
102 {
103 pEvent->uID = uID;
104 pEvent->pPayload = NULL;
105 }
106
107 return rc;
108}
109
110void SharedClipboardEventDestroy(PSHAREDCLIPBOARDEVENT pEvent)
111{
112 if (!pEvent)
113 return;
114
115 LogFlowFunc(("Event %RU16\n", pEvent->uID));
116
117 if (pEvent->hEventSem != NIL_RTSEMEVENT)
118 {
119 RTSemEventDestroy(pEvent->hEventSem);
120 pEvent->hEventSem = NIL_RTSEMEVENT;
121 }
122
123 SharedClipboardPayloadFree(pEvent->pPayload);
124
125 pEvent->uID = 0;
126}
127
128int SharedClipboardEventSourceCreate(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
129{
130 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
131
132 LogFlowFunc(("pSource=%p, uID=%RU16\n", pSource, uID));
133
134 int rc = VINF_SUCCESS;
135
136 RTListInit(&pSource->lstEvents);
137
138 pSource->uID = uID;
139 pSource->uEventIDNext = 1; /* Event ID 0 always is reserved (marks "unused"). */
140
141 LogFlowFuncLeaveRC(rc);
142 return rc;
143}
144
145void SharedClipboardEventSourceDestroy(PSHAREDCLIPBOARDEVENTSOURCE pSource)
146{
147 if (!pSource)
148 return;
149
150 LogFlowFunc(("ID=%RU16\n", pSource->uID));
151
152 PSHAREDCLIPBOARDEVENT pEvIt;
153 PSHAREDCLIPBOARDEVENT pEvItNext;
154 RTListForEachSafe(&pSource->lstEvents, pEvIt, pEvItNext, SHAREDCLIPBOARDEVENT, Node)
155 {
156 SharedClipboardEventDestroy(pEvIt);
157 RTMemFree(pEvIt);
158 }
159}
160
161/**
162 * Generates a new event ID for a specific event source.
163 *
164 * @returns New event ID generated, or 0 on error.
165 * @param pSource Event source to generate event for.
166 */
167uint16_t SharedClipboardEventIDGenerate(PSHAREDCLIPBOARDEVENTSOURCE pSource)
168{
169 AssertPtrReturn(pSource, 0);
170
171 LogFlowFunc(("uSource=%RU16: New event: %RU16\n", pSource->uID, pSource->uEventIDNext));
172 return pSource->uEventIDNext++; /** @todo Improve this. */
173}
174
175/**
176 * Returns a specific event of a event source.
177 *
178 * @returns Pointer to event if found, or NULL if not found.
179 * @param pSource Event source to get event from.
180 * @param uID Event ID to get.
181 */
182inline PSHAREDCLIPBOARDEVENT sharedClipboardEventGet(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
183{
184 PSHAREDCLIPBOARDEVENT pEvIt;
185 RTListForEach(&pSource->lstEvents, pEvIt, SHAREDCLIPBOARDEVENT, Node)
186 {
187 if (pEvIt->uID == uID)
188 return pEvIt;
189 }
190
191 return NULL;
192}
193
194/**
195 * Registers an event.
196 *
197 * @returns VBox status code.
198 * @param pSource Event source to register event for.
199 * @param uID Event ID to register.
200 */
201int SharedClipboardEventRegister(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
202{
203 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
204
205 int rc;
206
207 LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
208
209 if (sharedClipboardEventGet(pSource, uID) == NULL)
210 {
211 PSHAREDCLIPBOARDEVENT pEvent
212 = (PSHAREDCLIPBOARDEVENT)RTMemAllocZ(sizeof(SHAREDCLIPBOARDEVENT));
213 if (pEvent)
214 {
215 rc = SharedClipboardEventCreate(pEvent, uID);
216 if (RT_SUCCESS(rc))
217 {
218 RTListAppend(&pSource->lstEvents, &pEvent->Node);
219
220 LogFlowFunc(("Event %RU16\n", uID));
221 }
222 }
223 else
224 rc = VERR_NO_MEMORY;
225 }
226 else
227 rc = VERR_ALREADY_EXISTS;
228
229#ifdef DEBUG_andy
230 AssertRC(rc);
231#endif
232
233 LogFlowFuncLeaveRC(rc);
234 return rc;
235}
236
237/**
238 * Unregisters an event.
239 *
240 * @returns VBox status code.
241 * @param pSource Event source to unregister event for.
242 * @param uID Event ID to unregister.
243 */
244int SharedClipboardEventUnregister(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
245{
246 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
247
248 int rc;
249
250 LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
251
252 PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
253 if (pEvent)
254 {
255 LogFlowFunc(("Event %RU16\n", pEvent->uID));
256
257 SharedClipboardEventDestroy(pEvent);
258 RTMemFree(pEvent);
259
260 RTListNodeRemove(&pEvent->Node);
261
262 rc = VINF_SUCCESS;
263 }
264 else
265 rc = VERR_NOT_FOUND;
266
267 AssertRC(rc);
268
269 LogFlowFuncLeaveRC(rc);
270 return rc;
271}
272
273/**
274 * Waits for an event to get signalled.
275 *
276 * @returns VBox status code.
277 * @param pSource Event source that contains the event to wait for.
278 * @param uID Event ID to wait for.
279 * @param uTimeoutMs Timeout (in ms) to wait.
280 * @param ppPayload Where to store the (allocated) event payload on success. Needs to be free'd with
281 * SharedClipboardPayloadFree().
282 */
283int SharedClipboardEventWait(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID, RTMSINTERVAL uTimeoutMs,
284 PSHAREDCLIPBOARDEVENTPAYLOAD* ppPayload)
285{
286 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
287
288 LogFlowFuncEnter();
289
290 int rc;
291
292 PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
293 if (pEvent)
294 {
295 rc = RTSemEventWait(pEvent->hEventSem, uTimeoutMs);
296 if (RT_SUCCESS(rc))
297 {
298 *ppPayload = pEvent->pPayload;
299
300 pEvent->pPayload = NULL;
301 }
302 }
303 else
304 rc = VERR_NOT_FOUND;
305
306 LogFlowFuncLeaveRC(rc);
307 return rc;
308}
309
310/**
311 * Signals an event.
312 *
313 * @returns VBox status code.
314 * @param pSource Event source of event to signal.
315 * @param uID Event ID to signal.
316 * @param pPayload Event payload to associate. Takes ownership. Optional.
317 */
318int SharedClipboardEventSignal(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID,
319 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload)
320{
321 AssertPtrReturn(pSource, VERR_INVALID_POINTER);
322
323 int rc;
324
325 LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
326
327 PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
328 if (pEvent)
329 {
330 Assert(pEvent->pPayload == NULL);
331
332 pEvent->pPayload = pPayload;
333
334 rc = RTSemEventSignal(pEvent->hEventSem);
335 }
336 else
337 rc = VERR_NOT_FOUND;
338
339#ifdef DEBUG_andy
340 AssertRC(rc);
341#endif
342
343 LogFlowFuncLeaveRC(rc);
344 return rc;
345}
346
347/**
348 * Detaches a payload from an event.
349 *
350 * @returns VBox status code.
351 * @param pSource Event source of event to detach payload for.
352 * @param uID Event ID to detach payload for.
353 */
354void SharedClipboardEventPayloadDetach(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
355{
356 AssertPtrReturnVoid(pSource);
357
358 LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
359
360 PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
361 if (pEvent)
362 {
363 pEvent->pPayload = NULL;
364 }
365#ifdef DEBUG_andy
366 else
367 AssertMsgFailed(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
368#endif
369}
370
371/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
372
373int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
374{
375 size_t cwDest, i;
376
377 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
378 AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
379 if (cwSrc == 0)
380 {
381 *pcwDest = 0;
382 LogFlowFunc(("empty source string, returning\n"));
383 return VINF_SUCCESS;
384 }
385/** @todo convert the remainder of the Assert stuff to AssertLogRel. */
386 /* We only take little endian Utf16 */
387 if (pwszSrc[0] == UTF16BEMARKER)
388 {
389 LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
390 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
391 }
392 cwDest = 0;
393 /* Calculate the size of the destination text string. */
394 /* Is this Utf16 or Utf16-LE? */
395 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
396 {
397 /* Check for a single line feed */
398 if (pwszSrc[i] == LINEFEED)
399 ++cwDest;
400#ifdef RT_OS_DARWIN
401 /* Check for a single carriage return (MacOS) */
402 if (pwszSrc[i] == CARRIAGERETURN)
403 ++cwDest;
404#endif
405 if (pwszSrc[i] == 0)
406 {
407 /* Don't count this, as we do so below. */
408 break;
409 }
410 }
411 /* Count the terminating null byte. */
412 ++cwDest;
413 LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
414 *pcwDest = cwDest;
415 return VINF_SUCCESS;
416}
417
418int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
419 size_t cwDest)
420{
421 size_t i, j;
422 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
423 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
424 {
425 LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
426 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
427 }
428 if (cwSrc == 0)
429 {
430 if (cwDest == 0)
431 {
432 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
433 return VERR_BUFFER_OVERFLOW;
434 }
435 pu16Dest[0] = 0;
436 LogFlowFunc(("empty source string, returning\n"));
437 return VINF_SUCCESS;
438 }
439 /* We only take little endian Utf16 */
440 if (pwszSrc[0] == UTF16BEMARKER)
441 {
442 LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
443 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
444 }
445 /* Don't copy the endian marker. */
446 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
447 {
448 /* Don't copy the null byte, as we add it below. */
449 if (pwszSrc[i] == 0)
450 break;
451 if (j == cwDest)
452 {
453 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
454 return VERR_BUFFER_OVERFLOW;
455 }
456 if (pwszSrc[i] == LINEFEED)
457 {
458 pu16Dest[j] = CARRIAGERETURN;
459 ++j;
460 if (j == cwDest)
461 {
462 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
463 return VERR_BUFFER_OVERFLOW;
464 }
465 }
466#ifdef RT_OS_DARWIN
467 /* Check for a single carriage return (MacOS) */
468 else if (pwszSrc[i] == CARRIAGERETURN)
469 {
470 /* set cr */
471 pu16Dest[j] = CARRIAGERETURN;
472 ++j;
473 if (j == cwDest)
474 {
475 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
476 return VERR_BUFFER_OVERFLOW;
477 }
478 /* add the lf */
479 pu16Dest[j] = LINEFEED;
480 continue;
481 }
482#endif
483 pu16Dest[j] = pwszSrc[i];
484 }
485 /* Add the trailing null. */
486 if (j == cwDest)
487 {
488 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
489 return VERR_BUFFER_OVERFLOW;
490 }
491 pu16Dest[j] = 0;
492 LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
493 return VINF_SUCCESS;
494}
495
496int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
497{
498 size_t cwDest;
499
500 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
501 if (!VALID_PTR(pwszSrc))
502 {
503 LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc));
504 AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER);
505 }
506 if (cwSrc == 0)
507 {
508 LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
509 *pcwDest = 0;
510 return VINF_SUCCESS;
511 }
512 /* We only take little endian Utf16 */
513 if (pwszSrc[0] == UTF16BEMARKER)
514 {
515 LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
516 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
517 }
518 /* Calculate the size of the destination text string. */
519 /* Is this Utf16 or Utf16-LE? */
520 if (pwszSrc[0] == UTF16LEMARKER)
521 cwDest = 0;
522 else
523 cwDest = 1;
524 for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
525 {
526 if ( (i + 1 < cwSrc)
527 && (pwszSrc[i] == CARRIAGERETURN)
528 && (pwszSrc[i + 1] == LINEFEED))
529 {
530 ++i;
531 }
532 if (pwszSrc[i] == 0)
533 {
534 break;
535 }
536 }
537 /* Terminating zero */
538 ++cwDest;
539 LogFlowFunc(("returning %d\n", cwDest));
540 *pcwDest = cwDest;
541 return VINF_SUCCESS;
542}
543
544int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
545 size_t cwDest)
546{
547 size_t cwDestPos;
548
549 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
550 cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest));
551 /* A buffer of size 0 may not be an error, but it is not a good idea either. */
552 Assert(cwDest > 0);
553 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
554 {
555 LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
556 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
557 }
558 /* We only take little endian Utf16 */
559 if (pwszSrc[0] == UTF16BEMARKER)
560 {
561 LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
562 AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
563 }
564 if (cwDest == 0)
565 {
566 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
567 return VERR_BUFFER_OVERFLOW;
568 }
569 if (cwSrc == 0)
570 {
571 pu16Dest[0] = 0;
572 LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n"));
573 return VINF_SUCCESS;
574 }
575 /* Prepend the Utf16 byte order marker if it is missing. */
576 if (pwszSrc[0] == UTF16LEMARKER)
577 {
578 cwDestPos = 0;
579 }
580 else
581 {
582 pu16Dest[0] = UTF16LEMARKER;
583 cwDestPos = 1;
584 }
585 for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
586 {
587 if (pwszSrc[i] == 0)
588 {
589 break;
590 }
591 if (cwDestPos == cwDest)
592 {
593 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
594 return VERR_BUFFER_OVERFLOW;
595 }
596 if ( (i + 1 < cwSrc)
597 && (pwszSrc[i] == CARRIAGERETURN)
598 && (pwszSrc[i + 1] == LINEFEED))
599 {
600 ++i;
601 }
602 pu16Dest[cwDestPos] = pwszSrc[i];
603 }
604 /* Terminating zero */
605 if (cwDestPos == cwDest)
606 {
607 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
608 return VERR_BUFFER_OVERFLOW;
609 }
610 pu16Dest[cwDestPos] = 0;
611 LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1));
612 return VINF_SUCCESS;
613}
614
615int vboxClipboardDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDest, size_t *pcbDest)
616{
617 size_t cb = sizeof(BMFILEHEADER) + cbSrc;
618 PBMFILEHEADER pFileHeader = NULL;
619 void *pvDest = NULL;
620 size_t offPixel = 0;
621
622 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
623 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
624 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
625
626 PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pvSrc;
627 /** @todo Support all the many versions of the DIB headers. */
628 if ( cbSrc < sizeof(BMINFOHEADER)
629 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) < sizeof(BMINFOHEADER)
630 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
631 {
632 Log(("vboxClipboardDibToBmp: invalid or unsupported bitmap data.\n"));
633 return VERR_INVALID_PARAMETER;
634 }
635
636 offPixel = sizeof(BMFILEHEADER)
637 + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
638 + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
639 if (cbSrc < offPixel)
640 {
641 Log(("vboxClipboardDibToBmp: invalid bitmap data.\n"));
642 return VERR_INVALID_PARAMETER;
643 }
644
645 pvDest = RTMemAlloc(cb);
646 if (!pvDest)
647 {
648 Log(("writeToPasteboard: cannot allocate memory for bitmap.\n"));
649 return VERR_NO_MEMORY;
650 }
651
652 pFileHeader = (PBMFILEHEADER)pvDest;
653 pFileHeader->u16Type = BITMAPHEADERMAGIC;
654 pFileHeader->u32Size = (uint32_t)RT_H2LE_U32(cb);
655 pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
656 pFileHeader->u32OffBits = (uint32_t)RT_H2LE_U32(offPixel);
657 memcpy((uint8_t *)pvDest + sizeof(BMFILEHEADER), pvSrc, cbSrc);
658 *ppvDest = pvDest;
659 *pcbDest = cb;
660 return VINF_SUCCESS;
661}
662
663int vboxClipboardBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDest, size_t *pcbDest)
664{
665 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
666 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
667 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
668
669 PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvSrc;
670 if ( cbSrc < sizeof(BMFILEHEADER)
671 || pFileHeader->u16Type != BITMAPHEADERMAGIC
672 || RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
673 {
674 Log(("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
675 return VERR_INVALID_PARAMETER;
676 }
677
678 *ppvDest = ((uint8_t *)pvSrc) + sizeof(BMFILEHEADER);
679 *pcbDest = cbSrc - sizeof(BMFILEHEADER);
680 return VINF_SUCCESS;
681}
682
683#ifdef LOG_ENABLED
684int VBoxClipboardDbgDumpHtml(const char *pszSrc, size_t cbSrc)
685{
686 size_t cchIgnored = 0;
687 int rc = RTStrNLenEx(pszSrc, cbSrc, &cchIgnored);
688 if (RT_SUCCESS(rc))
689 {
690 char *pszBuf = (char *)RTMemAllocZ(cbSrc + 1);
691 if (pszBuf)
692 {
693 rc = RTStrCopy(pszBuf, cbSrc + 1, (const char *)pszSrc);
694 if (RT_SUCCESS(rc))
695 {
696 for (size_t i = 0; i < cbSrc; ++i)
697 if (pszBuf[i] == '\n' || pszBuf[i] == '\r')
698 pszBuf[i] = ' ';
699 }
700 else
701 LogFunc(("Error in copying string\n"));
702 LogFunc(("Removed \\r\\n: %s\n", pszBuf));
703 RTMemFree(pszBuf);
704 }
705 else
706 rc = VERR_NO_MEMORY;
707 }
708
709 return rc;
710}
711
712void VBoxClipboardDbgDumpData(const void *pv, size_t cb, VBOXCLIPBOARDFORMAT u32Format)
713{
714 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
715 {
716 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));
717 if (pv && cb)
718 LogFunc(("%ls\n", pv));
719 else
720 LogFunc(("%p %zu\n", pv, cb));
721 }
722 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
723 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
724 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
725 {
726 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));
727 if (pv && cb)
728 {
729 LogFunc(("%s\n", pv));
730
731 //size_t cb = RTStrNLen(pv, );
732 char *pszBuf = (char *)RTMemAllocZ(cb + 1);
733 RTStrCopy(pszBuf, cb + 1, (const char *)pv);
734 for (size_t off = 0; off < cb; ++off)
735 {
736 if (pszBuf[off] == '\n' || pszBuf[off] == '\r')
737 pszBuf[off] = ' ';
738 }
739
740 LogFunc(("%s\n", pszBuf));
741 RTMemFree(pszBuf);
742 }
743 else
744 LogFunc(("%p %zu\n", pv, cb));
745 }
746 else
747 LogFunc(("Invalid format %02X\n", u32Format));
748}
749#endif /* LOG_ENABLED */
750
751/**
752 * Translates a Shared Clipboard host message enum to a string.
753 *
754 * @returns Message ID string name.
755 * @param uMsg The message to translate.
756 */
757const char *VBoxClipboardHostMsgToStr(uint32_t uMsg)
758{
759 switch (uMsg)
760 {
761 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
762 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
763 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE);
764 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
765 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_READ);
766 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_WRITE);
767 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_ENTRY_READ);
768 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_ENTRY_WRITE);
769 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN);
770 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE);
771 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ);
772 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE);
773 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ);
774 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE);
775 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN);
776 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE);
777 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ);
778 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE);
779 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL);
780 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR);
781 }
782 return "Unknown";
783}
784
785/**
786 * Translates a Shared Clipboard guest message enum to a string.
787 *
788 * @returns Message ID string name.
789 * @param uMsg The message to translate.
790 */
791const char *VBoxClipboardGuestMsgToStr(uint32_t uMsg)
792{
793 switch (uMsg)
794 {
795 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD);
796 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_WRITE);
797 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_READ);
798 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_WRITE);
799 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CONNECT);
800 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT);
801 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT);
802 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET);
803 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS);
804 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY);
805 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_HDR_READ);
806 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_HDR_WRITE);
807 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_ENTRY_READ);
808 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_ENTRY_WRITE);
809 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN);
810 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE);
811 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ);
812 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE);
813 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ);
814 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE);
815 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN);
816 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE);
817 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ);
818 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE);
819 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL);
820 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR);
821 }
822 return "Unknown";
823}
824
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette