1a84601801d5bd045712787a3ef59313795389a1vboxsync * VBoxClient - Shared Clipboard Guest -> Host copying, Darwin.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Copyright (C) 2007-2013 Oracle Corporation
1a84601801d5bd045712787a3ef59313795389a1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1a84601801d5bd045712787a3ef59313795389a1vboxsync * available from http://www.virtualbox.org. This file is free software;
1a84601801d5bd045712787a3ef59313795389a1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1a84601801d5bd045712787a3ef59313795389a1vboxsync * General Public License (GPL) as published by the Free Software
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1a84601801d5bd045712787a3ef59313795389a1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1a84601801d5bd045712787a3ef59313795389a1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Header Files *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Walk through pasteboard items and report currently available item types.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pPasteboard Reference to guest Pasteboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @returns Available formats bit field.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncuint32_t vbclClipboardGetAvailableFormats(PasteboardRef pPasteboard)
1a84601801d5bd045712787a3ef59313795389a1vboxsync#define VBOXCL_ADD_FORMAT_IF_PRESENT(a_kDarwinFmt, a_fVBoxFmt) \
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (PasteboardCopyItemFlavorData(pPasteboard, iItemID, a_kDarwinFmt, &flavorData) == noErr) \
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn((rc == noErr) && (cItems > 0), fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemIdentifier(pPasteboard, iItem, &iItemID);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeUTF16PlainText, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeUTF8PlainText, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeBMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP );
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeHTML, VBOX_SHARED_CLIPBOARD_FMT_HTML );
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavors(pPasteboard, iItemID, &flavorTypeArray);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN (%d)..\n", (int)flavorCount);
1a84601801d5bd045712787a3ef59313795389a1vboxsync for(CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN #%d..\n", (int)flavorIndex);
1a84601801d5bd045712787a3ef59313795389a1vboxsync flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavorData(pPasteboard, iItemID, flavorType, &flavorData1);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "Found: %s, size: %d\n", (char *)CFStringGetCStringPtr(flavorType, kCFStringEncodingMacRoman), (int)CFDataGetLength(flavorData1));
1a84601801d5bd045712787a3ef59313795389a1vboxsync#endif /* CLIPBOARD_DUMP_CONTENT_FORMATS */
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Search for content of specified type in guest clipboard buffer and put
1a84601801d5bd045712787a3ef59313795389a1vboxsync * it into newly allocated buffer.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pPasteboard Guest PasteBoard reference.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param fFormat Data formats we are looking for.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param ppvData Where to return pointer to the received data. M
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pcbData Where to return the size of the data.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pcbAlloc Where to return the size of the memory block
1a84601801d5bd045712787a3ef59313795389a1vboxsync * *ppvData pointes to. (Usually greater than *cbData
1a84601801d5bd045712787a3ef59313795389a1vboxsync * because the allocation is page aligned.)
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @returns IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardReadGuestData(PasteboardRef pPasteboard, CFStringRef sFormat, void **ppvData, uint32_t *pcbData,
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Walk through all the items in PasteBoard in order to find
1a84601801d5bd045712787a3ef59313795389a1vboxsync that one that correcponds to requested data format. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Now, get the item's flavors that corresponds to requested type. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemIdentifier(pPasteboard, iItem, &iItemID);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavorData(pPasteboard, iItemID, sFormat, &flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync void *flavorDataPtr = (void *)CFDataGetBytePtr(flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Found first matching item, no more search. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Found match */
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Release resources occupied by vbclClipboardReadGuestData().
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic void vbclClipboardReleaseGuestData(void **ppvData, uint32_t cbAlloc)
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Pass data to host.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteData(uint32_t u32ClientId, uint32_t u32Format, const void *pvData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Allow empty buffers */
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VbglR3ClipboardWriteData(u32ClientId, u32Format, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VbglR3ClipboardWriteData(u32ClientId, u32Format, (void *)pvData, cbData); /** @todo r=bird: Why on earth does a write function like VbglR3ClipboardWriteData take a non-const parameter? */
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Paste text data into host clipboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param u32ClientId Host clipboard connection.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pwszData UTF-16 encoded string.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param cbData The length of the string, in bytes, probably
1a84601801d5bd045712787a3ef59313795389a1vboxsync * including a terminating zero.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteText(uint32_t u32ClientId, PRTUTF16 pwszData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync size_t cwcActual; /* (includes a schwarzenegger character) */
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc = vboxClipboardUtf16GetWinSize(pwszData, cbData / sizeof(RTUTF16), &cwcActual);
1a84601801d5bd045712787a3ef59313795389a1vboxsync PRTUTF16 pwszWinTmp = (PRTUTF16)RTMemAlloc(cwcActual * sizeof(RTUTF16));
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vboxClipboardUtf16LinToWin(pwszData, cbData / sizeof(RTUTF16), pwszWinTmp, cwcActual);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Paste a bitmap onto the host clipboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param u32ClientId Host clipboard connection.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pvData The bitmap data.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param cbData The size of the bitmap.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteBitmap(uint32_t u32ClientId, void *pvData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc = vboxClipboardBmpGetDib(pvData, cbData, &pvDib, &cbDib);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, pvDib, cbDib);
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Read guest's clipboard buffer and forward its content to host.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param u32ClientId Host clipboard connection.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pPasteboard Guest PasteBoard reference.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param fFormats List of data formats (bit field) received from host.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @returns IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsyncint vbclClipboardForwardToHost(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats)
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "vbclClipboardForwardToHost: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Walk across all item(s) formats */
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* First, try to get UTF16 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF16PlainText, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTUtf16DupEx(&pUtf16Str, (PRTUTF16)pvData, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync else /* Failed to get UTF16 buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Then, try to get UTF8 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF8PlainText, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTStrToUtf16((const char *)pvData, &pUtf16Str);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Finally, we got UTF16 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteText(u32ClientId, (PRTUTF16)pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
1a84601801d5bd045712787a3ef59313795389a1vboxsync else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_BITMAP: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeBMP, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteBitmap(u32ClientId, pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
1a84601801d5bd045712787a3ef59313795389a1vboxsync else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_HTML)
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_HTML: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeHTML, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_HTML;
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested data in unsupported format: %#x\n", fFormatsLeft);
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc; /** @todo r=bird: If there are multiple formats available, which rc is returned here? Does it matter? */