32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync/* $Id$ */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync/** @file
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync * Shared Clipboard: Mac OS X host implementation.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync/*
c29fe1f686f1a78237986fbb030e3020cdbbfb77vboxsync * Includes contributions from Fran�ois Revol
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync *
7f8c3a19fc6774798746c0782be09b88e54bf960vboxsync * Copyright (C) 2008-2012 Oracle Corporation
7f8c3a19fc6774798746c0782be09b88e54bf960vboxsync *
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * available from http://www.virtualbox.org. This file is free software;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * you can redistribute it and/or modify it under the terms of the GNU
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * General Public License (GPL) as published by the Free Software
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
7d9e0d289e799c0ee5b9307fe7358ddc53bd34ddvboxsync#define LOG_GROUP LOG_GROUP_HGCM
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#include <Carbon/Carbon.h>
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#include <iprt/mem.h>
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#include <iprt/assert.h>
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#include "iprt/err.h"
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#include "VBox/log.h"
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync#include "VBox/HostServices/VBoxClipboardSvc.h"
af1bd0025dd5d8be5f1468689d0d77d4839a3be5vboxsync#include "VBox/GuestHost/clipboard-helper.h"
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/* For debugging */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync//#define SHOW_CLIPBOARD_CONTENT
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/**
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Initialize the global pasteboard and return a reference to it.
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pPasteboardRef Reference to the global pasteboard.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @returns IPRT status code.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsyncint initPasteboard(PasteboardRef *pPasteboardRef)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync{
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync int rc = VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (PasteboardCreate(kPasteboardClipboard, pPasteboardRef))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync rc = VERR_NOT_SUPPORTED;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return rc;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync}
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/**
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Release the reference to the global pasteboard.
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pPasteboardRef Reference to the global pasteboard.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsyncvoid destroyPasteboard(PasteboardRef *pPasteboardRef)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync{
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync CFRelease(*pPasteboardRef);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync *pPasteboardRef = NULL;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync}
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/**
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Inspect the global pasteboard for new content. Check if there is some type
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * that is supported by vbox and return it.
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pPasteboardRef Reference to the global pasteboard.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pfFormats Pointer for the bit combination of the
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * supported types.
be641d8f2dc377d6a4403f3822d8bed08f51e28avboxsync * @param pbChanged True if something has changed after the
be641d8f2dc377d6a4403f3822d8bed08f51e28avboxsync * last call.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync *
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync * @returns IPRT status code. (Always VINF_SUCCESS atm.)
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsyncint queryNewPasteboardFormats(PasteboardRef pPasteboard, uint32_t *pfFormats, bool *pfChanged)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync{
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("queryNewPasteboardFormats\n"));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync OSStatus err = noErr;
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *pfChanged = true;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PasteboardSyncFlags syncFlags;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Make sure all is in sync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync syncFlags = PasteboardSynchronize(pPasteboard);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* If nothing changed return */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (!(syncFlags & kPasteboardModified))
be641d8f2dc377d6a4403f3822d8bed08f51e28avboxsync {
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *pfChanged = false;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VINF_SUCCESS;
be641d8f2dc377d6a4403f3822d8bed08f51e28avboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Are some items in the pasteboard? */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync ItemCount itemCount;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync err = PasteboardGetItemCount(pPasteboard, &itemCount);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (itemCount < 1)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* The id of the first element in the pasteboard */
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync int rc = VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PasteboardItemID itemID;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /* Retrieve all flavors in the pasteboard, maybe there
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * is something we can use. */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync CFArrayRef flavorTypeArray;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardCopyItemFlavors(pPasteboard, itemID, &flavorTypeArray)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync CFIndex flavorCount;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync flavorCount = CFArrayGetCount(flavorTypeArray);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync CFStringRef flavorType;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync flavorType = static_cast <CFStringRef>(CFArrayGetValueAtIndex(flavorTypeArray,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync flavorIndex));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Currently only unicode supported */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (UTTypeConformsTo(flavorType, kUTTypeUTF8PlainText) ||
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync UTTypeConformsTo(flavorType, kUTTypeUTF16PlainText))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("Unicode flavor detected.\n"));
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync else if (UTTypeConformsTo(flavorType, kUTTypeBMP))
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("BMP flavor detected.\n"));
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync CFRelease(flavorTypeArray);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("queryNewPasteboardFormats: rc = %02X\n", rc));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return rc;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync}
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/**
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Read content from the host clipboard and write it to the internal clipboard
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * structure for further processing.
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pPasteboardRef Reference to the global pasteboard.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param fFormats The format type which should be read.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pv The destination buffer.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param cb The size of the destination buffer.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pcbActual The size which is needed to transfer the content.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @returns IPRT status code.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsyncint readFromPasteboard(PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync{
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: fFormat = %02X\n", fFormat));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync OSStatus err = noErr;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Make sure all is in sync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PasteboardSynchronize(pPasteboard);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Are some items in the pasteboard? */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync ItemCount itemCount;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync err = PasteboardGetItemCount(pPasteboard, &itemCount);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (itemCount < 1)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* The id of the first element in the pasteboard */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync int rc = VERR_NOT_SUPPORTED;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PasteboardItemID itemID;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* The guest request unicode */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync CFDataRef outData;
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync PRTUTF16 pwszTmp = NULL;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Try utf-16 first */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("Clipboard content is utf-16\n"));
54ab180f75bcb8c750d0d7d59e39aca6eb59e848vboxsync
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData);
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync if (pwszString)
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync rc = RTUtf16DupEx(&pwszTmp, pwszString, 0);
54ab180f75bcb8c750d0d7d59e39aca6eb59e848vboxsync else
54ab180f75bcb8c750d0d7d59e39aca6eb59e848vboxsync rc = VERR_INVALID_PARAMETER;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Second try is utf-8 */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync else
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: clipboard content is utf-8\n"));
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync const char *pszString = (const char *)CFDataGetBytePtr(outData);
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync if (pszString)
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync rc = RTStrToUtf16(pszString, &pwszTmp);
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync else
04582cbe4711c5c860680c6cb8d8df1800de2019vboxsync rc = VERR_INVALID_PARAMETER;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync if (pwszTmp)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Check how much longer will the converted text will be. */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync size_t cwSrc = RTUtf16Len(pwszTmp);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync size_t cwDest;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardUtf16GetWinSize(pwszTmp, cwSrc, &cwDest);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_FAILURE(rc))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTUtf16Free(pwszTmp);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Rrc. Abandoning.\n", rc));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync AssertRCReturn(rc, rc);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Set the actually needed data size */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync *pcbActual = cwDest * 2;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Return success state */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync rc = VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Do not copy data if the dst buffer is not big enough. */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (*pcbActual <= cb)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_FAILURE(rc))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTUtf16Free(pwszTmp);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Rrc. Abandoning.\n", rc));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync AssertRCReturn(rc, rc);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#ifdef SHOW_CLIPBOARD_CONTENT
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv)));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync#endif
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Free the temp string */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTUtf16Free(pwszTmp);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* The guest request BITMAP */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync CFDataRef outData;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync const void *pTmp = NULL;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync size_t cbTmpSize;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Get the data from the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData)))
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("Clipboard content is BMP\n"));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync pTmp = CFDataGetBytePtr(outData);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync cbTmpSize = CFDataGetLength(outData);
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync if (pTmp)
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync const void *pDib;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync size_t cbDibSize;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_FAILURE(rc))
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync rc = VERR_NOT_SUPPORTED;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc. Abandoning.\n", rc));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync AssertRCReturn(rc, rc);
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync *pcbActual = cbDibSize;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Return success state */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync rc = VINF_SUCCESS;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Do not copy data if the dst buffer is not big enough. */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync if (*pcbActual <= cb)
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync memcpy(pv, pDib, cbDibSize);
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync#ifdef SHOW_CLIPBOARD_CONTENT
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize));
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync#endif
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("readFromPasteboard: rc = %02X\n", rc));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return rc;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync}
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/**
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Write clipboard content to the host clipboard from the internal clipboard
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * structure.
295a2ae5a4db2c930f7096c6cf55b5fa4ee5b018vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pPasteboardRef Reference to the global pasteboard.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param pv The source buffer.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param cb The size of the source buffer.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @param fFormats The format type which should be written.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * @returns IPRT status code.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsyncint writeToPasteboard(PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync{
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: fFormat = %02X\n", fFormat));
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* Clear the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (PasteboardClear(pPasteboard))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VERR_NOT_SUPPORTED;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Make sure all is in sync */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PasteboardSynchronize(pPasteboard);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync int rc = VERR_NOT_SUPPORTED;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Handle the unicode text */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PRTUTF16 pwszSrcText = static_cast <PRTUTF16>(pv);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync size_t cwSrc = cb / 2;
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync size_t cwDest = 0;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* How long will the converted text be? */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardUtf16GetLinSize(pwszSrcText, cwSrc, &cwDest);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_FAILURE(rc))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync AssertRCReturn(rc, rc);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Empty clipboard? Not critical */
6a30d0e9d748ecb8a0c62b4233a97fed255a8a4cvboxsync if (cwDest == 0)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: received empty clipboard data from the guest, returning false.\n"));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Allocate the necessary memory */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PRTUTF16 pwszDestText = static_cast <PRTUTF16>(RTMemAlloc(cwDest * 2));
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync if (pwszDestText == NULL)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VERR_NO_MEMORY;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Convert the EOL */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardUtf16WinToLin(pwszSrcText, cwSrc, pwszDestText, cwDest);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_FAILURE(rc))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTMemFree(pwszDestText);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync AssertRCReturn(rc, rc);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync CFDataRef textData = NULL;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Item id is 1. Nothing special here. */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PasteboardItemID itemId = (PasteboardItemID)1;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create a CData object which we could pass to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if ((textData = CFDataCreate(kCFAllocatorDefault,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync reinterpret_cast<UInt8*>(pwszDestText), cwDest * 2)))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Put the Utf-16 version to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PasteboardPutItemFlavor(pPasteboard, itemId,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync kUTTypeUTF16PlainText,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync textData, 0);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create a Utf-8 version */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync char *pszDestText;
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = RTUtf16ToUtf8(pwszDestText, &pszDestText);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_SUCCESS(rc))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create a CData object which we could pass to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if ((textData = CFDataCreate(kCFAllocatorDefault,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync reinterpret_cast<UInt8*>(pszDestText), strlen(pszDestText))))
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync {
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Put the Utf-8 version to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PasteboardPutItemFlavor(pPasteboard, itemId,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync kUTTypeUTF8PlainText,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync textData, 0);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTStrFree(pszDestText);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTMemFree(pwszDestText);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync rc = VINF_SUCCESS;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Handle the bitmap */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Create a full BMP from it */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync void *pBmp;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync size_t cbBmpSize;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync CFDataRef bmpData = NULL;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Item id is 1. Nothing special here. */
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync PasteboardItemID itemId = (PasteboardItemID)1;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmpSize);
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if (RT_SUCCESS(rc))
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Create a CData object which we could pass to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync if ((bmpData = CFDataCreate(kCFAllocatorDefault,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync reinterpret_cast<UInt8*>(pBmp), cbBmpSize)))
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync {
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync /* Put the Utf-8 version to the pasteboard */
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync PasteboardPutItemFlavor(pPasteboard, itemId,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync kUTTypeBMP,
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync bmpData, 0);
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync RTMemFree(pBmp);
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync rc = VINF_SUCCESS;
e6317c5fa1f3ac24b7d86f42d2b11bcb0733609evboxsync }
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync else
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync rc = VERR_NOT_IMPLEMENTED;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync
1731b00e118d691438a0c8b1f1b4c6e29a0d5bb6vboxsync Log(("writeToPasteboard: rc = %02X\n", rc));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return rc;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync}
7d9e0d289e799c0ee5b9307fe7358ddc53bd34ddvboxsync