VirtualBox

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

Last change on this file since 80468 was 80468, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Made the event source and event IDs more non-deterministic.

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