1a84601801d5bd045712787a3ef59313795389a1vboxsync/** $Id$ */
1a84601801d5bd045712787a3ef59313795389a1vboxsync/** @file
1a84601801d5bd045712787a3ef59313795389a1vboxsync * VBoxClient - Shared Clipboard Guest -> Host copying, Darwin.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Copyright (C) 2007-2013 Oracle Corporation
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
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
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Header Files *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <Carbon/Carbon.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <signal.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <stdlib.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/thread.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/mem.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/stream.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/initterm.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/message.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/VBoxGuestLib.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/HostServices/VBoxClipboardSvc.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/GuestHost/clipboard-helper.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include "VBoxClientInternal.h"
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Walk through pasteboard items and report currently available item types.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pPasteboard Reference to guest Pasteboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @returns Available formats bit field.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncuint32_t vbclClipboardGetAvailableFormats(PasteboardRef pPasteboard)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t fFormats = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync ItemCount cItems = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync ItemCount iItem;
1a84601801d5bd045712787a3ef59313795389a1vboxsync OSStatus rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync#define VBOXCL_ADD_FORMAT_IF_PRESENT(a_kDarwinFmt, a_fVBoxFmt) \
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (PasteboardCopyItemFlavorData(pPasteboard, iItemID, a_kDarwinFmt, &flavorData) == noErr) \
1a84601801d5bd045712787a3ef59313795389a1vboxsync { \
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormats |= (uint32_t)a_fVBoxFmt; \
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(flavorData); \
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemCount(pPasteboard, &cItems);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn((rc == noErr) && (cItems > 0), fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync for (iItem = 1; iItem <= cItems; iItem++)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync PasteboardItemID iItemID;
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFDataRef flavorData;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemIdentifier(pPasteboard, iItem, &iItemID);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (rc == noErr)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
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
1a84601801d5bd045712787a3ef59313795389a1vboxsync#ifdef CLIPBOARD_DUMP_CONTENT_FORMATS
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFArrayRef flavorTypeArray;
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFIndex flavorCount;
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFStringRef flavorType;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavors(pPasteboard, iItemID, &flavorTypeArray);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (rc == noErr)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN..\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync flavorCount = CFArrayGetCount(flavorTypeArray);
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN (%d)..\n", (int)flavorCount);
1a84601801d5bd045712787a3ef59313795389a1vboxsync for(CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN #%d..\n", (int)flavorIndex);
1a84601801d5bd045712787a3ef59313795389a1vboxsync flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFDataRef flavorData1;
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavorData(pPasteboard, iItemID, flavorType, &flavorData1);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (rc == noErr)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "Found: %s, size: %d\n", (char *)CFStringGetCStringPtr(flavorType, kCFStringEncodingMacRoman), (int)CFDataGetLength(flavorData1));
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(flavorData1);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "SCAN COMPLETE\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(flavorTypeArray);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync#endif /* CLIPBOARD_DUMP_CONTENT_FORMATS */
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync#undef VBOXCL_ADD_FORMAT_IF_PRESENT
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return fFormats;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Search for content of specified type in guest clipboard buffer and put
1a84601801d5bd045712787a3ef59313795389a1vboxsync * it into newly allocated buffer.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
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.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardReadGuestData(PasteboardRef pPasteboard, CFStringRef sFormat, void **ppvData, uint32_t *pcbData,
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t *pcbAlloc)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync ItemCount cItems, iItem;
1a84601801d5bd045712787a3ef59313795389a1vboxsync OSStatus rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync void *pvData = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t cbData = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t cbAlloc = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertPtrReturn(ppvData, VERR_INVALID_POINTER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertPtrReturn(pcbData, VERR_INVALID_POINTER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertPtrReturn(pcbAlloc, VERR_INVALID_POINTER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemCount(pPasteboard, &cItems);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(rc == noErr, VERR_INVALID_PARAMETER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(cItems > 0, VERR_INVALID_PARAMETER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Walk through all the items in PasteBoard in order to find
1a84601801d5bd045712787a3ef59313795389a1vboxsync that one that correcponds to requested data format. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync for (iItem = 1; iItem <= cItems; iItem++)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync PasteboardItemID iItemID;
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFDataRef flavorData;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Now, get the item's flavors that corresponds to requested type. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardGetItemIdentifier(pPasteboard, iItem, &iItemID);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(rc == noErr, VERR_INVALID_PARAMETER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCopyItemFlavorData(pPasteboard, iItemID, sFormat, &flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (rc == noErr)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync void *flavorDataPtr = (void *)CFDataGetBytePtr(flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync cbData = CFDataGetLength(flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (flavorDataPtr && cbData > 0)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync cbAlloc = RT_ALIGN_32(cbData, PAGE_SIZE);
1a84601801d5bd045712787a3ef59313795389a1vboxsync pvData = RTMemPageAllocZ(cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (pvData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync memcpy(pvData, flavorDataPtr, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(flavorData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Found first matching item, no more search. */
1a84601801d5bd045712787a3ef59313795389a1vboxsync break;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Found match */
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (pvData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync *ppvData = pvData;
1a84601801d5bd045712787a3ef59313795389a1vboxsync *pcbData = cbData;
1a84601801d5bd045712787a3ef59313795389a1vboxsync *pcbAlloc = cbAlloc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VINF_SUCCESS;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VERR_INVALID_PARAMETER;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Release resources occupied by vbclClipboardReadGuestData().
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic void vbclClipboardReleaseGuestData(void **ppvData, uint32_t cbAlloc)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturnVoid(ppvData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTMemPageFree(*ppvData, cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync *ppvData = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Pass data to host.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteData(uint32_t u32ClientId, uint32_t u32Format, const void *pvData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Allow empty buffers */
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (cbData == 0)
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VbglR3ClipboardWriteData(u32ClientId, u32Format, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(pvData, VERR_INVALID_PARAMETER);
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}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Paste text data into host clipboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
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.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteText(uint32_t u32ClientId, PRTUTF16 pwszData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(cbData > 0, VERR_INVALID_PARAMETER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertPtrReturn(pwszData, VERR_INVALID_POINTER);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync size_t cwcActual; /* (includes a schwarzenegger character) */
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc = vboxClipboardUtf16GetWinSize(pwszData, cbData / sizeof(RTUTF16), &cwcActual);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(RT_SUCCESS(rc), rc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync PRTUTF16 pwszWinTmp = (PRTUTF16)RTMemAlloc(cwcActual * sizeof(RTUTF16));
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(pwszWinTmp, VERR_NO_MEMORY);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vboxClipboardUtf16LinToWin(pwszData, cbData / sizeof(RTUTF16), pwszWinTmp, cwcActual);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
1a84601801d5bd045712787a3ef59313795389a1vboxsync pwszWinTmp, cwcActual * sizeof(RTUTF16));
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTMemFree(pwszWinTmp);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Paste a bitmap onto the host clipboard.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param u32ClientId Host clipboard connection.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pvData The bitmap data.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param cbData The size of the bitmap.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardHostPasteBitmap(uint32_t u32ClientId, void *pvData, uint32_t cbData)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync const void *pvDib;
1a84601801d5bd045712787a3ef59313795389a1vboxsync size_t cbDib;
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc = vboxClipboardBmpGetDib(pvData, cbData, &pvDib, &cbDib);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertRCReturn(rc, rc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, pvDib, cbDib);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Read guest's clipboard buffer and forward its content to host.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
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 *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @returns IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncint vbclClipboardForwardToHost(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc = VINF_SUCCESS;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync void *pvData = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t cbData = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t cbAlloc = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "vbclClipboardForwardToHost: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Walk across all item(s) formats */
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t fFormatsLeft = fFormats;
1a84601801d5bd045712787a3ef59313795389a1vboxsync while (fFormatsLeft)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTUTF16 *pUtf16Str = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* First, try to get UTF16 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF16PlainText, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTUtf16DupEx(&pUtf16Str, (PRTUTF16)pvData, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync pUtf16Str = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else /* Failed to get UTF16 buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Then, try to get UTF8 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF8PlainText, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTStrToUtf16((const char *)pvData, &pUtf16Str);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync pUtf16Str = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Finally, we got UTF16 encoded buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteText(u32ClientId, (PRTUTF16)pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (pUtf16Str)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTUtf16Free(pUtf16Str);
1a84601801d5bd045712787a3ef59313795389a1vboxsync pUtf16Str = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardReleaseGuestData(&pvData, cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_BITMAP: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeBMP, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteBitmap(u32ClientId, pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardReleaseGuestData(&pvData, cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_HTML)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_HTML: %d\n", fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeHTML, &pvData, &cbData, &cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, pvData, cbData);
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardReleaseGuestData(&pvData, cbAlloc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* No data found or error occurred: send empty buffer */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, NULL, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_HTML;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(3, "requested data in unsupported format: %#x\n", fFormatsLeft);
1a84601801d5bd045712787a3ef59313795389a1vboxsync break;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc; /** @todo r=bird: If there are multiple formats available, which rc is returned here? Does it matter? */
1a84601801d5bd045712787a3ef59313795389a1vboxsync}