linux.cpp revision 039cd2c4871a00e51af909222a34695d9cec3000
ece9652d971886b99a269656ea4782319637e75avboxsync * Shared Clipboard:
ece9652d971886b99a269656ea4782319637e75avboxsync * Linux host.
ece9652d971886b99a269656ea4782319637e75avboxsync * Copyright (C) 2006-2007 innotek GmbH
ece9652d971886b99a269656ea4782319637e75avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ece9652d971886b99a269656ea4782319637e75avboxsync * available from http://www.virtualbox.org. This file is free software;
ece9652d971886b99a269656ea4782319637e75avboxsync * you can redistribute it and/or modify it under the terms of the GNU
ece9652d971886b99a269656ea4782319637e75avboxsync * General Public License as published by the Free Software Foundation,
ece9652d971886b99a269656ea4782319637e75avboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
ece9652d971886b99a269656ea4782319637e75avboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
ece9652d971886b99a269656ea4782319637e75avboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
ece9652d971886b99a269656ea4782319637e75avboxsync * If you received this file as part of a commercial VirtualBox
ece9652d971886b99a269656ea4782319637e75avboxsync * distribution, then only the terms of your commercial VirtualBox
ece9652d971886b99a269656ea4782319637e75avboxsync * license agreement apply instead of the previous paragraph.
ece9652d971886b99a269656ea4782319637e75avboxsync/** The different clipboard formats which we support. */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/** The X11 clipboard uses several names for the same format. This structure maps an X11
ece9652d971886b99a269656ea4782319637e75avboxsync name to a format. */
ece9652d971886b99a269656ea4782319637e75avboxsynctypedef struct {
ece9652d971886b99a269656ea4782319637e75avboxsync/** Does the host or the guest currently own the clipboard? */
ece9652d971886b99a269656ea4782319637e75avboxsynctypedef struct {
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** BMP file type marker - must always contain 'BM' */
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** The size of the BMP file in bytes (the MS docs say that this is not reliable) */
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** Reserved, must always be zero */
ece9652d971886b99a269656ea4782319637e75avboxsync /** Reserved, must always be zero */
ece9652d971886b99a269656ea4782319637e75avboxsync /** Offset from the beginning of this header to the actual image bits */
ece9652d971886b99a269656ea4782319637e75avboxsync/** Global clipboard context information */
ece9652d971886b99a269656ea4782319637e75avboxsync /** The X Toolkit application context structure */
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync /** We have a separate thread to wait for Window and Clipboard events */
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** The X Toolkit widget which we use as our clipboard client. It is never made visible. */
ece9652d971886b99a269656ea4782319637e75avboxsync /** X11 atom refering to the clipboard: CLIPBOARD */
ece9652d971886b99a269656ea4782319637e75avboxsync /** X11 atom refering to the clipboard targets: TARGETS */
ece9652d971886b99a269656ea4782319637e75avboxsync /** X11 atom refering to the clipboard multiple target: MULTIPLE */
ece9652d971886b99a269656ea4782319637e75avboxsync /** X11 atom refering to the clipboard timestamp target: TIMESTAMP */
0be1c98f1388ddc063a7e830f53e2018f658b348vboxsync /** X11 atom refering to the clipboard utf16 text format: text/plain;charset=ISO-10646-UCS-2 */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** X11 atom refering to the clipboard utf8 text format: UTF8_STRING */
79c6e4760808b57244846404a5a799fedba4353bvboxsync /** X11 atom refering to the clipboard compound text format: COMPOUND_TEXT */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** A list of the X11 formats which we support, mapped to our identifier for them, in the
6d2267c67854347b52e4353b8f69d32ce9179924vboxsync order we prefer to have them in. */
0be1c98f1388ddc063a7e830f53e2018f658b348vboxsync /** Does the host or the guest currently own the clipboard? */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** What is the best text format the host has to offer? INVALID for none. */
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** Atom corresponding to the host text format */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** What is the best bitmap format the host has to offer? INVALID for none. */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** Atom corresponding to the host Bitmap format */
e7f5b62e52275099a4d14501306063e23876b771vboxsync /** What formats does the guest have on offer? */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** Windows caches the clipboard data it receives. Since we have no way of knowing whether
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync that data is still valid, we always send a "data changed" message after a successful
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync transfer to invalidate the cache. */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** Since the clipboard data moves asynchronously, we use an event semaphore to wait for
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync it. When a function issues a request for clipboard data it must wait for this
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync semaphore, which is triggered when the data arrives. */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** And because it would not do for the guest to be waiting for the host while the host
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync is waiting for the guest, we set a flag and assert horribly if we spot a deadlock. */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** This mutex is held while an asynchronous operation completes (i.e. the host clipboard is
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync being queried) to make sure that the clipboard is not disconnected during that time. It
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync is also grabbed when the clipboard client disconnects. When an asynchronous operation
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync starts completing, it checks that the same client is still connected immediately after
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync grabbing the mutex. */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** Format which we are reading from the host clipboard (valid during a request for the
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync host clipboard) */
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync /** The guest buffer to write host clipboard data to (valid during a request for the host
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync clipboard) */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** The size of the guest buffer to write host clipboard data to (valid during a request for
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync the host clipboard) */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** The size of the host clipboard data written to the guest buffer (valid during a request
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync for the host clipboard) */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync /** Pointer to the client data structure */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync/* Only one client is supported. There seems to be no need for more clients. */
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * Get the size of the buffer needed to hold a Utf16-LE zero terminated string with Windows EOLs
e7f5b62e52275099a4d14501306063e23876b771vboxsync * converted from a Utf16 string with Linux EOLs.
e7f5b62e52275099a4d14501306063e23876b771vboxsync * @returns RT error code
e7f5b62e52275099a4d14501306063e23876b771vboxsync * @param pu16Src The source Utf16 string
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param cwSrc The length in 16 bit words of the source string
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @retval pcwDest The length of the destination string in 16 bit words
36ec4b6f42e209d010ade084a96f46ce763345eavboxsyncstatic int vboxClipboardUtf16GetWinSize(PRTUTF16 pu16Src, size_t cwSrc, size_t *pcwDest)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u\n", cwSrc, pu16Src, cwSrc));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"));
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync AssertReturn(pu16Src != 0, VERR_INVALID_PARAMETER);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /* We only take little endian Utf16 */
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync AssertReturn(pu16Src[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync /* Calculate the size of the destination text string. */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync /* Is this Utf16 or Utf16-LE? */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync for (i = (pu16Src[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync if (pu16Src[i] == 0)
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync /* Don't count this, as we do so below. */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync /* Count the terminating null byte. */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync * Convert a Utf16 text with Linux EOLs to null-terminated Utf16-LE with Windows EOLs. Does no
1cc6d0ca9b70d90116a4fb8f7e60869cc98ad57cvboxsync * checking for validity.
1cc6d0ca9b70d90116a4fb8f7e60869cc98ad57cvboxsync * @returns VBox status code
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param pu16Src Source Utf16 text to convert
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param cwSrc Size of the source text in 16 bit words
ece9652d971886b99a269656ea4782319637e75avboxsync * @retval pu16Dest Buffer to store the converted text to.
ece9652d971886b99a269656ea4782319637e75avboxsync * @retval pcwDest Size of the buffer for the converted text in 16 bit words
ece9652d971886b99a269656ea4782319637e75avboxsyncstatic int vboxClipboardUtf16LinToWin(PRTUTF16 pu16Src, size_t cwSrc, PRTUTF16 pu16Dest,
ece9652d971886b99a269656ea4782319637e75avboxsync LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u\n", cwSrc, pu16Src, cwSrc));
e7f5b62e52275099a4d14501306063e23876b771vboxsync LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pu16Src=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pu16Src, pu16Dest));
ece9652d971886b99a269656ea4782319637e75avboxsync AssertReturn(VALID_PTR(pu16Src) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
e7f5b62e52275099a4d14501306063e23876b771vboxsync /* We only take little endian Utf16 */
e7f5b62e52275099a4d14501306063e23876b771vboxsync LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
e7f5b62e52275099a4d14501306063e23876b771vboxsync AssertReturn(pu16Src[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync /* Don't copy the endian marker. */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync for (i = (pu16Src[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync /* Don't copy the null byte, as we add it below. */
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync if (pu16Src[i] == 0)
ece9652d971886b99a269656ea4782319637e75avboxsync /* Add the trailing null. */
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * Get the size of the buffer needed to hold a zero-terminated Utf16 string with Linux EOLs
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * converted from a Utf16 string with Windows EOLs.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @returns RT status code
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param pu16Src The source Utf16 string
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param cwSrc The length in 16 bit words of the source string
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @retval pcwDest The length of the destination string in 16 bit words
992ef02987d71b2b9f73a50265997c7f8e384886vboxsyncstatic int vboxClipboardUtf16GetLinSize(PRTUTF16 pu16Src, size_t cwSrc, size_t *pcwDest)
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync LogFlowFunc(("pu16Src=%.*ls, cwSrc=%u\n", cwSrc, pu16Src, cwSrc));
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pu16Src));
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync AssertReturn(VALID_PTR(pu16Src), VERR_INVALID_PARAMETER);
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync /* We only take little endian Utf16 */
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync AssertReturn(pu16Src[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync /* Calculate the size of the destination text string. */
cwDest = 0;
if (pu16Src[i] == 0)
++cwDest;
return VINF_SUCCESS;
LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pu16Src=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pu16Src, pu16Dest));
LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
if (cwDest == 0)
return VERR_BUFFER_OVERFLOW;
if (cwSrc == 0)
pu16Dest[0] = 0;
return VINF_SUCCESS;
cwDestPos = 0;
if (pu16Src[i] == 0)
return VERR_BUFFER_OVERFLOW;
return VERR_BUFFER_OVERFLOW;
return VINF_SUCCESS;
if (pClient == 0)
Log(("vboxClipboardReadDataFromClient: host requested guest clipboard data after guest had disconnected.\n"));
return VERR_TIMEOUT;
LogRel(("vboxClipboardReadDataFromClient: a guest to host clipboard transfer has been requested, but another is in progress, or has not cleaned up properly.\n"));
AssertMsgFailed(("A guest to host clipboard transfer has been requested, but another is in progress, or has not cleaned up properly.\n"));
LogRel(("vboxClipboardReadDataFromClient: deadlock situation - the host and the guest are both waiting for data from the other."));
return VERR_DEADLOCK;
LogRel (("vboxClipboardReadDataFromClient: vboxSvcClipboardReportMsg failed to complete within %d milliseconds\n", CLIPBOARDTIMEOUT));
return VERR_TIMEOUT;
return VINF_SUCCESS;
int rc;
LogRel(("vboxClipboardGetUtf16: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
LogRel(("vboxClipboardGetUtf16: clipboard conversion failed. vboxClipboardUtf16LinToWin returned %Vrc. Abandoning.\n", rc));
*pcbActual = 0;
int rc;
LogRel(("vboxClipboardGetUtf8: clipboard conversion failed. RTStrToUtf16Ex returned %Vrc. Abandoning.\n", rc));
*pcbActual = 0;
LogRel(("vboxClipboardGetUtf8: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
LogRel(("vboxClipboardGetUtf8: clipboard conversion failed. vboxClipboardUtf16LinToWin returned %Vrc. Abandoning.\n", rc));
*pcbActual = 0;
char **ppu8SrcText;
if (rc < 0)
const char *pcReason;
switch(rc)
case XNoMemory:
case XLocaleNotSupported:
case XConverterNotFound:
pcReason));
*pcbActual = 0;
LogRel(("vboxClipboardGetCText: clipboard conversion failed. RTStrToUtf16Ex returned %Vrc. Abandoning.\n", rc));
*pcbActual = 0;
LogRel(("vboxClipboardGetCText: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
LogRel(("vboxClipboardGetCText: clipboard conversion failed. vboxClipboardUtf16LinToWin returned %Vrc. Abandoning.\n", rc));
*pcbActual = 0;
for (unsigned i = 0; i < cbSourceLen; i++)
++cwDestLen;
for (unsigned i = 0, j = 0; i < cbSourceLen; ++i, ++j)
int *piFormat)
case UTF16:
case CTEXT:
case UTF8:
case LATIN1:
int *piFormat)
Log (("vboxClipboardTargetsProc: reading clipboard from host, X toolkit failed to convert the selection\n"));
for (unsigned i = 0; i < cAtoms; ++i)
#ifdef DEBUG
if (szAtomName != 0)
#ifdef DEBUG
szAtomName));
for (unsigned i = 0; i < cAtoms; ++i)
if (szAtomName != 0)
unsigned guestFormat)
int cArgc = 0;
char *pcArgv = 0;
if (pDisplay == 0)
LogRel(("vboxClipboardThread: failed to connect to the host clipboard - the window system may not be running.\n"));
return VERR_NOT_SUPPORTED;
g_ctx.atomClipboard = XInternAtom(XtDisplay(g_ctx.widget), "CLIPBOARD", false /* only_if_exists */);
#ifdef USE_UTF16
#ifdef USE_UTF8
#ifdef USE_CTEXT
#ifdef USE_LATIN1
LogRel (("vboxClipboardThread: clipboard thread terminated successfully with return code %Vrc\n", rc));
return rc;
int vboxClipboardInit (void)
int rc;
void vboxClipboardDestroy (void)
LogRel(("vboxClipboardConnect: attempted to connect, but a client appears to be already running.\n"));
return VINF_SUCCESS;
/* On a Linux host, the guest should never synchronise/cache its clipboard contents, as
return VINF_SUCCESS;
unsigned cTargets = 0;
for (unsigned i = 0; i < uListSize; ++i)
++cTargets;
#ifdef DEBUG
if (szAtomName != 0)
static void vboxClipboardEmptyGuestBuffer(void)
int rc;
LogRel (("vboxClipboardConvertUtf16: vboxClipboardReadDataFromClient returned %Vrc, %d bytes of data\n", rc, g_ctx.pClient->data.cb));
LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRel(("vboxClipboardConvertUtf16: clipboard conversion failed. vboxClipboardUtf16WinToLin returned %Vrc. Abandoning.\n", rc));
char *pu8DestText;
int rc;
LogRel (("vboxClipboardConvertUtf8: vboxClipboardReadDataFromClient returned %Vrc, %d bytes of data\n", rc, g_ctx.pClient->data.cb));
LogRel(("vboxClipboardConvertUtf8: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRel(("vboxClipboardConvertUtf8: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Vrc. Abandoning.\n", rc));
return rc;
if (pu8DestText == 0)
&cbDestLen);
LogRel(("vboxClipboardConvertUtf8: clipboard conversion failed. RTUtf16ToUtf8Ex() returned %Vrc. Abandoning.\n", rc));
return rc;
char *pu8DestText = 0;
int rc;
LogRel (("vboxClipboardConvertUtf8: vboxClipboardReadDataFromClient returned %Vrc, %d bytes of data\n", rc, g_ctx.pClient->data.cb));
LogRel(("vboxClipboardConvertCText: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
if (cwDestLen == 0)
if (pu16DestText == 0)
LogRel(("vboxClipboardConvertCText: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Vrc. Abandoning.\n", rc));
LogRel(("vboxClipboardConvertCText: clipboard conversion failed. RTUtf16ToUtf8Ex() returned %Vrc. Abandoning.\n", rc));
if (rc < 0)
const char *pcReason;
switch(rc)
case XNoMemory:
case XLocaleNotSupported:
case XConverterNotFound:
pcReason));
unsigned char *pcHostText;
int rc;
Log (("vboxClipboardConvertLatin1: vboxClipboardReadDataFromClient returned %Vrc, %d bytes of data\n", rc, g_ctx.pClient->data.cb));
if (pcHostText == 0)
pcHostText));
#ifdef DEBUG
if (szAtomName != 0)
switch (eFormat)
case TARGETS:
case UTF16:
case UTF8:
case CTEXT:
case LATIN1:
if (u32Formats == 0)
*pcbActual = 0;
return VINF_SUCCESS;
LogRel(("vboxClipboardReadData: detected a deadlock situation - the host and the guest are waiting for each other.\n"));
return VERR_DEADLOCK;
LogRel (("vboxClipboardReadDataFromClient: XtGetSelectionValue failed to complete within %d milliseconds\n", CLIPBOARDTIMEOUT));
return VERR_TIMEOUT;
return VERR_NOT_IMPLEMENTED;
return VINF_SUCCESS;
void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format)
LogRel(("vboxClipboardWriteData: clipboard data has arrived from the guest, but another transfer is in process or has not cleaned up properly.\n"));
AssertMsgFailed(("vboxClipboardWriteData: clipboard data has arrived from the guest, but another transfer is in process or has not cleaned up properly.\n"));
if (cb > 0)