VirtualBox

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

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

Shared Clipboard/URI: Update; more work on root list handling.

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 16.9 KB
Line 
1/* $Id: clipboard-common.cpp 80283 2019-08-15 08:47: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/path.h>
25
26#include <iprt/errcore.h>
27#include <VBox/log.h>
28#include <VBox/GuestHost/clipboard-helper.h>
29#ifdef LOG_ENABLED
30# include <VBox/HostServices/VBoxClipboardSvc.h>
31#endif
32
33/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
34
35int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
36{
37 size_t cwDest, i;
38
39 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
40 AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
41 if (cwSrc == 0)
42 {
43 *pcwDest = 0;
44 LogFlowFunc(("empty source string, returning\n"));
45 return VINF_SUCCESS;
46 }
47/** @todo convert the remainder of the Assert stuff to AssertLogRel. */
48 /* We only take little endian Utf16 */
49 if (pwszSrc[0] == UTF16BEMARKER)
50 {
51 LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
52 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
53 }
54 cwDest = 0;
55 /* Calculate the size of the destination text string. */
56 /* Is this Utf16 or Utf16-LE? */
57 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
58 {
59 /* Check for a single line feed */
60 if (pwszSrc[i] == LINEFEED)
61 ++cwDest;
62#ifdef RT_OS_DARWIN
63 /* Check for a single carriage return (MacOS) */
64 if (pwszSrc[i] == CARRIAGERETURN)
65 ++cwDest;
66#endif
67 if (pwszSrc[i] == 0)
68 {
69 /* Don't count this, as we do so below. */
70 break;
71 }
72 }
73 /* Count the terminating null byte. */
74 ++cwDest;
75 LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
76 *pcwDest = cwDest;
77 return VINF_SUCCESS;
78}
79
80int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
81 size_t cwDest)
82{
83 size_t i, j;
84 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
85 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
86 {
87 LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
88 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
89 }
90 if (cwSrc == 0)
91 {
92 if (cwDest == 0)
93 {
94 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
95 return VERR_BUFFER_OVERFLOW;
96 }
97 pu16Dest[0] = 0;
98 LogFlowFunc(("empty source string, returning\n"));
99 return VINF_SUCCESS;
100 }
101 /* We only take little endian Utf16 */
102 if (pwszSrc[0] == UTF16BEMARKER)
103 {
104 LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
105 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
106 }
107 /* Don't copy the endian marker. */
108 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
109 {
110 /* Don't copy the null byte, as we add it below. */
111 if (pwszSrc[i] == 0)
112 break;
113 if (j == cwDest)
114 {
115 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
116 return VERR_BUFFER_OVERFLOW;
117 }
118 if (pwszSrc[i] == LINEFEED)
119 {
120 pu16Dest[j] = CARRIAGERETURN;
121 ++j;
122 if (j == cwDest)
123 {
124 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
125 return VERR_BUFFER_OVERFLOW;
126 }
127 }
128#ifdef RT_OS_DARWIN
129 /* Check for a single carriage return (MacOS) */
130 else if (pwszSrc[i] == CARRIAGERETURN)
131 {
132 /* set cr */
133 pu16Dest[j] = CARRIAGERETURN;
134 ++j;
135 if (j == cwDest)
136 {
137 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
138 return VERR_BUFFER_OVERFLOW;
139 }
140 /* add the lf */
141 pu16Dest[j] = LINEFEED;
142 continue;
143 }
144#endif
145 pu16Dest[j] = pwszSrc[i];
146 }
147 /* Add the trailing null. */
148 if (j == cwDest)
149 {
150 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
151 return VERR_BUFFER_OVERFLOW;
152 }
153 pu16Dest[j] = 0;
154 LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
155 return VINF_SUCCESS;
156}
157
158int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
159{
160 size_t cwDest;
161
162 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
163 if (!VALID_PTR(pwszSrc))
164 {
165 LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc));
166 AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER);
167 }
168 if (cwSrc == 0)
169 {
170 LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
171 *pcwDest = 0;
172 return VINF_SUCCESS;
173 }
174 /* We only take little endian Utf16 */
175 if (pwszSrc[0] == UTF16BEMARKER)
176 {
177 LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
178 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
179 }
180 /* Calculate the size of the destination text string. */
181 /* Is this Utf16 or Utf16-LE? */
182 if (pwszSrc[0] == UTF16LEMARKER)
183 cwDest = 0;
184 else
185 cwDest = 1;
186 for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
187 {
188 if ( (i + 1 < cwSrc)
189 && (pwszSrc[i] == CARRIAGERETURN)
190 && (pwszSrc[i + 1] == LINEFEED))
191 {
192 ++i;
193 }
194 if (pwszSrc[i] == 0)
195 {
196 break;
197 }
198 }
199 /* Terminating zero */
200 ++cwDest;
201 LogFlowFunc(("returning %d\n", cwDest));
202 *pcwDest = cwDest;
203 return VINF_SUCCESS;
204}
205
206int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
207 size_t cwDest)
208{
209 size_t cwDestPos;
210
211 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
212 cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest));
213 /* A buffer of size 0 may not be an error, but it is not a good idea either. */
214 Assert(cwDest > 0);
215 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
216 {
217 LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
218 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
219 }
220 /* We only take little endian Utf16 */
221 if (pwszSrc[0] == UTF16BEMARKER)
222 {
223 LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
224 AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
225 }
226 if (cwDest == 0)
227 {
228 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
229 return VERR_BUFFER_OVERFLOW;
230 }
231 if (cwSrc == 0)
232 {
233 pu16Dest[0] = 0;
234 LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n"));
235 return VINF_SUCCESS;
236 }
237 /* Prepend the Utf16 byte order marker if it is missing. */
238 if (pwszSrc[0] == UTF16LEMARKER)
239 {
240 cwDestPos = 0;
241 }
242 else
243 {
244 pu16Dest[0] = UTF16LEMARKER;
245 cwDestPos = 1;
246 }
247 for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
248 {
249 if (pwszSrc[i] == 0)
250 {
251 break;
252 }
253 if (cwDestPos == cwDest)
254 {
255 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
256 return VERR_BUFFER_OVERFLOW;
257 }
258 if ( (i + 1 < cwSrc)
259 && (pwszSrc[i] == CARRIAGERETURN)
260 && (pwszSrc[i + 1] == LINEFEED))
261 {
262 ++i;
263 }
264 pu16Dest[cwDestPos] = pwszSrc[i];
265 }
266 /* Terminating zero */
267 if (cwDestPos == cwDest)
268 {
269 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
270 return VERR_BUFFER_OVERFLOW;
271 }
272 pu16Dest[cwDestPos] = 0;
273 LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1));
274 return VINF_SUCCESS;
275}
276
277int vboxClipboardDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDest, size_t *pcbDest)
278{
279 size_t cb = sizeof(BMFILEHEADER) + cbSrc;
280 PBMFILEHEADER pFileHeader = NULL;
281 void *pvDest = NULL;
282 size_t offPixel = 0;
283
284 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
285 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
286 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
287
288 PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pvSrc;
289 /** @todo Support all the many versions of the DIB headers. */
290 if ( cbSrc < sizeof(BMINFOHEADER)
291 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) < sizeof(BMINFOHEADER)
292 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
293 {
294 Log(("vboxClipboardDibToBmp: invalid or unsupported bitmap data.\n"));
295 return VERR_INVALID_PARAMETER;
296 }
297
298 offPixel = sizeof(BMFILEHEADER)
299 + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
300 + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
301 if (cbSrc < offPixel)
302 {
303 Log(("vboxClipboardDibToBmp: invalid bitmap data.\n"));
304 return VERR_INVALID_PARAMETER;
305 }
306
307 pvDest = RTMemAlloc(cb);
308 if (!pvDest)
309 {
310 Log(("writeToPasteboard: cannot allocate memory for bitmap.\n"));
311 return VERR_NO_MEMORY;
312 }
313
314 pFileHeader = (PBMFILEHEADER)pvDest;
315 pFileHeader->u16Type = BITMAPHEADERMAGIC;
316 pFileHeader->u32Size = (uint32_t)RT_H2LE_U32(cb);
317 pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
318 pFileHeader->u32OffBits = (uint32_t)RT_H2LE_U32(offPixel);
319 memcpy((uint8_t *)pvDest + sizeof(BMFILEHEADER), pvSrc, cbSrc);
320 *ppvDest = pvDest;
321 *pcbDest = cb;
322 return VINF_SUCCESS;
323}
324
325int vboxClipboardBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDest, size_t *pcbDest)
326{
327 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
328 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
329 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
330
331 PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvSrc;
332 if ( cbSrc < sizeof(BMFILEHEADER)
333 || pFileHeader->u16Type != BITMAPHEADERMAGIC
334 || RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
335 {
336 Log(("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
337 return VERR_INVALID_PARAMETER;
338 }
339
340 *ppvDest = ((uint8_t *)pvSrc) + sizeof(BMFILEHEADER);
341 *pcbDest = cbSrc - sizeof(BMFILEHEADER);
342 return VINF_SUCCESS;
343}
344
345#ifdef LOG_ENABLED
346int VBoxClipboardDbgDumpHtml(const char *pszSrc, size_t cbSrc)
347{
348 size_t cchIgnored = 0;
349 int rc = RTStrNLenEx(pszSrc, cbSrc, &cchIgnored);
350 if (RT_SUCCESS(rc))
351 {
352 char *pszBuf = (char *)RTMemAllocZ(cbSrc + 1);
353 if (pszBuf)
354 {
355 rc = RTStrCopy(pszBuf, cbSrc + 1, (const char *)pszSrc);
356 if (RT_SUCCESS(rc))
357 {
358 for (size_t i = 0; i < cbSrc; ++i)
359 if (pszBuf[i] == '\n' || pszBuf[i] == '\r')
360 pszBuf[i] = ' ';
361 }
362 else
363 LogFunc(("Error in copying string\n"));
364 LogFunc(("Removed \\r\\n: %s\n", pszBuf));
365 RTMemFree(pszBuf);
366 }
367 else
368 rc = VERR_NO_MEMORY;
369 }
370
371 return rc;
372}
373
374void VBoxClipboardDbgDumpData(const void *pv, size_t cb, VBOXCLIPBOARDFORMAT u32Format)
375{
376 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
377 {
378 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));
379 if (pv && cb)
380 LogFunc(("%ls\n", pv));
381 else
382 LogFunc(("%p %zu\n", pv, cb));
383 }
384 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
385 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
386 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
387 {
388 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));
389 if (pv && cb)
390 {
391 LogFunc(("%s\n", pv));
392
393 //size_t cb = RTStrNLen(pv, );
394 char *pszBuf = (char *)RTMemAllocZ(cb + 1);
395 RTStrCopy(pszBuf, cb + 1, (const char *)pv);
396 for (size_t off = 0; off < cb; ++off)
397 {
398 if (pszBuf[off] == '\n' || pszBuf[off] == '\r')
399 pszBuf[off] = ' ';
400 }
401
402 LogFunc(("%s\n", pszBuf));
403 RTMemFree(pszBuf);
404 }
405 else
406 LogFunc(("%p %zu\n", pv, cb));
407 }
408 else
409 LogFunc(("Invalid format %02X\n", u32Format));
410}
411
412/**
413 * Translates a Shared Clipboard host message enum to a string.
414 *
415 * @returns Message ID string name.
416 * @param uMsg The message to translate.
417 */
418const char *VBoxClipboardHostMsgToStr(uint32_t uMsg)
419{
420 switch (uMsg)
421 {
422 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
423 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
424 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
425 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
426 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_READ);
427 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_WRITE);
428 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_ENTRY_READ);
429 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_ENTRY_WRITE);
430 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN);
431 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE);
432 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ);
433 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE);
434 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ);
435 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE);
436 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN);
437 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE);
438 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ);
439 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE);
440 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL);
441 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR);
442 }
443 return "Unknown";
444}
445
446/**
447 * Translates a Shared Clipboard guest message enum to a string.
448 *
449 * @returns Message ID string name.
450 * @param uMsg The message to translate.
451 */
452const char *VBoxClipboardGuestMsgToStr(uint32_t uMsg)
453{
454 switch (uMsg)
455 {
456 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPORT_FORMATS);
457 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA);
458 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA);
459 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT);
460 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT);
461 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET);
462 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS);
463 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY);
464 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_HDR_READ);
465 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_HDR_WRITE);
466 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_ENTRY_READ);
467 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOT_LIST_ENTRY_WRITE);
468 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN);
469 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE);
470 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ);
471 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE);
472 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ);
473 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE);
474 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN);
475 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE);
476 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ);
477 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE);
478 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL);
479 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR);
480 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
481 }
482 return "Unknown";
483}
484#endif /* LOG_ENABLED */
485
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