/**
 * Paste a bitmap onto the host clipboard.
 *
 * @param   u32ClientId     Host clipboard connection.
 * @param   pvData          The bitmap data.
 * @param   cbData          The size of the bitmap.
 */
static int vbclClipboardHostPasteBitmap(uint32_t u32ClientId, void *pvData, uint32_t cbData)
{
    const void   *pvDib;
    size_t        cbDib;
    int rc = vboxClipboardBmpGetDib(pvData, cbData, &pvDib, &cbDib);
    AssertRCReturn(rc, rc);

    rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, pvDib, cbDib);

    return rc;
}
Ejemplo n.º 2
0
void VBoxClipboardService::MessageReceived(BMessage *message)
{
    uint32_t formats = 0;
    message->PrintToStream();
    switch (message->what)
    {
        case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS:
        {
            int rc;
            uint32_t cb;
            void *pv;
            bool commit = false;

            if (message->FindInt32("Formats", (int32 *)&formats) != B_OK)
                break;

            if (!formats)
                break;

            if (!be_clipboard->Lock())
                break;

            be_clipboard->Clear();
            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
            {
                pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb);
                if (pv)
                {
                    char *text;
                    rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text);
                    if (RT_SUCCESS(rc))
                    {
                        BString str(text);
                        /** @todo user vboxClipboardUtf16WinToLin() */
                        // convert Windows CRLF to LF
                        str.ReplaceAll("\r\n", "\n");
                        // don't include the \0
                        clip->AddData("text/plain", B_MIME_TYPE, str.String(), str.Length());
                        RTStrFree(text);
                        commit = true;
                    }
                    free(pv);
                }
            }

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
            {
                pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb);
                if (pv)
                {
                    void  *pBmp  = NULL;
                    size_t cbBmp = 0;
                    rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp);
                    if (RT_SUCCESS(rc))
                    {
                        BMemoryIO mio(pBmp, cbBmp);
                        BBitmap *bitmap = BTranslationUtils::GetBitmap(&mio);
                        if (bitmap)
                        {
                            BMessage bitmapArchive;

                            /** @todo r=ramshankar: split this into functions with error checking as
                             *        neccessary. */
                            if (   bitmap->IsValid()
                                && bitmap->Archive(&bitmapArchive) == B_OK
                                && clip->AddMessage("image/bitmap", &bitmapArchive) == B_OK)
                            {
                                commit = true;
                            }
                            delete bitmap;
                        }
                        RTMemFree(pBmp);
                    }
                    free(pv);
                }
            }

            /*
             * Make sure we don't bounce this data back to the host, it's impolite. It can also
             * be used as a hint to applications probably.
             */
            clip->AddBool("FromVirtualBoxHost", true);
            if (commit)
                be_clipboard->Commit();
            be_clipboard->Unlock();
            break;
        }

        case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA:
        {
            int rc;

            if (message->FindInt32("Formats", (int32 *)&formats) != B_OK)
                break;

            if (!formats)
                break;
            if (!be_clipboard->Lock())
                break;

            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }
            clip->PrintToStream();

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
            {
                const char *text;
                int32 textLen;
                if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK)
                {
                    // usually doesn't include the \0 so be safe
                    BString str(text, textLen);
                    // convert from LF to Windows CRLF
                    str.ReplaceAll("\n", "\r\n");
                    PRTUTF16 pwsz;
                    rc = RTStrToUtf16(str.String(), &pwsz);
                    if (RT_SUCCESS(rc))
                    {
                        uint32_t cb = (RTUtf16Len(pwsz) + 1) * sizeof(RTUTF16);

                        rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, pwsz, cb);
                        //printf("VbglR3ClipboardWriteData: %d\n", rc);
                        RTUtf16Free(pwsz);
                    }
                }
            }
            else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
            {
                BMessage archivedBitmap;
                if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK ||
                    clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK)
                {
                    BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap);
                    if (bitmap)
                    {
                        // Don't delete bitmap, BBitmapStream will.
                        BBitmapStream stream(bitmap);
                        BTranslatorRoster *roster = BTranslatorRoster::Default();
                        if (roster && bitmap->IsValid())
                        {
                            BMallocIO bmpStream;
                            if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK)
                            {
                                const void *pDib;
                                size_t cbDibSize;
                                /* Strip out the BM header */
                                rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize);
                                if (RT_SUCCESS(rc))
                                {
                                    rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib,
                                                                  cbDibSize);
                                }
                            }
                        }
                    }
                }
            }

            be_clipboard->Unlock();
            break;
        }

        case B_CLIPBOARD_CHANGED:
        {
            printf("B_CLIPBOARD_CHANGED\n");
            const void *data;
            int32 dataLen;
            if (!be_clipboard->Lock())
                break;

            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }

            bool fromVBox;
            if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox)
            {
                // It already comes from the host, discard.
                be_clipboard->Unlock();
                break;
            }

            if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK)
                formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;

            if (   clip->HasMessage("image/bitmap")
                || clip->HasMessage("image/x-be-bitmap"))
            {
                formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
            }

            be_clipboard->Unlock();

            VbglR3ClipboardReportFormats(fClientId, formats);
            break;
        }

        case B_QUIT_REQUESTED:
            fExiting = true;
            break;

        default:
            BHandler::MessageReceived(message);
    }
}
Ejemplo n.º 3
0
/**
 * Read content from the host clipboard and write it to the internal clipboard
 * structure for further processing.
 *
 * @param   pPasteboardRef Reference to the global pasteboard.
 * @param   fFormats       The format type which should be read.
 * @param   pv             The destination buffer.
 * @param   cb             The size of the destination buffer.
 * @param   pcbActual      The size which is needed to transfer the content.
 *
 * @returns IPRT status code.
 */
int readFromPasteboard(PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
{
    Log(("readFromPasteboard: fFormat = %02X\n", fFormat));

    OSStatus err = noErr;

    /* Make sure all is in sync */
    PasteboardSynchronize(pPasteboard);

    /* Are some items in the pasteboard? */
    ItemCount itemCount;
    err = PasteboardGetItemCount(pPasteboard, &itemCount);
    if (itemCount < 1)
        return VINF_SUCCESS;

    /* The id of the first element in the pasteboard */
    int rc = VERR_NOT_SUPPORTED;
    PasteboardItemID itemID;
    if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID)))
    {
        /* The guest request unicode */
        if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
        {
            CFDataRef outData;
            PRTUTF16 pwszTmp = NULL;
            /* Try utf-16 first */
            if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData)))
            {
                Log(("Clipboard content is utf-16\n"));

                PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData);
                if (pwszString)
                    rc = RTUtf16DupEx(&pwszTmp, pwszString, 0);
                else
                    rc = VERR_INVALID_PARAMETER;
            }
            /* Second try is utf-8 */
            else
                if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData)))
                {
                    Log(("readFromPasteboard: clipboard content is utf-8\n"));
                    const char *pszString = (const char *)CFDataGetBytePtr(outData);
                    if (pszString)
                        rc = RTStrToUtf16(pszString, &pwszTmp);
                    else
                        rc = VERR_INVALID_PARAMETER;
                }
            if (pwszTmp)
            {
                /* Check how much longer will the converted text will be. */
                size_t cwSrc = RTUtf16Len(pwszTmp);
                size_t cwDest;
                rc = vboxClipboardUtf16GetWinSize(pwszTmp, cwSrc, &cwDest);
                if (RT_FAILURE(rc))
                {
                    RTUtf16Free(pwszTmp);
                    Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16GetWinSize returned %Rrc.  Abandoning.\n", rc));
                    AssertRCReturn(rc, rc);
                }
                /* Set the actually needed data size */
                *pcbActual = cwDest * 2;
                /* Return success state */
                rc = VINF_SUCCESS;
                /* Do not copy data if the dst buffer is not big enough. */
                if (*pcbActual <= cb)
                {
                    rc = vboxClipboardUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2);
                    if (RT_FAILURE(rc))
                    {
                        RTUtf16Free(pwszTmp);
                        Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16LinToWin() returned %Rrc.  Abandoning.\n", rc));
                        AssertRCReturn(rc, rc);
                    }
#ifdef SHOW_CLIPBOARD_CONTENT
                    Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv)));
#endif
                }
                /* Free the temp string */
                RTUtf16Free(pwszTmp);
            }
        }
        /* The guest request BITMAP */
        else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
        {
            CFDataRef outData;
            const void *pTmp = NULL;
            size_t cbTmpSize;
            /* Get the data from the pasteboard */
            if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData)))
            {
                Log(("Clipboard content is BMP\n"));
                pTmp = CFDataGetBytePtr(outData);
                cbTmpSize = CFDataGetLength(outData);
            }
            if (pTmp)
            {
                const void *pDib;
                size_t cbDibSize;
                rc = vboxClipboardBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize);
                if (RT_FAILURE(rc))
                {
                    rc = VERR_NOT_SUPPORTED;
                    Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc.  Abandoning.\n", rc));
                    AssertRCReturn(rc, rc);
                }

                *pcbActual = cbDibSize;
                /* Return success state */
                rc = VINF_SUCCESS;
                /* Do not copy data if the dst buffer is not big enough. */
                if (*pcbActual <= cb)
                {
                    memcpy(pv, pDib, cbDibSize);
#ifdef SHOW_CLIPBOARD_CONTENT
                    Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize));
#endif
                }
            }
        }
    }

    Log(("readFromPasteboard: rc = %02X\n", rc));
    return rc;
}