/** * Paste picture data into guest clipboard. * * @param pPasteboard Guest PasteBoard reference. * @param pData Data to be pasted. * @param cbDataSize The size of *pData. * * @returns IPRT status code. */ static int vbclClipboardGuestPastePicture(PasteboardRef pPasteboard, void *pData, uint32_t cbDataSize) { int rc; void *pBmp; size_t cbBmpSize; AssertReturn(pData, VERR_INVALID_PARAMETER); /* Skip zero-sized buffer */ AssertReturn(cbDataSize > 0, VINF_SUCCESS); rc = vboxClipboardDibToBmp(pData, cbDataSize, &pBmp, &cbBmpSize); AssertReturn(RT_SUCCESS(rc), rc); rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pBmp, cbBmpSize, kUTTypeBMP, true); RTMemFree(pBmp); return rc; }
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); } }
/** * Write clipboard content to the host clipboard from the internal clipboard * structure. * * @param pPasteboardRef Reference to the global pasteboard. * @param pv The source buffer. * @param cb The size of the source buffer. * @param fFormats The format type which should be written. * * @returns IPRT status code. */ int writeToPasteboard(PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat) { Log(("writeToPasteboard: fFormat = %02X\n", fFormat)); /* Clear the pasteboard */ if (PasteboardClear(pPasteboard)) return VERR_NOT_SUPPORTED; /* Make sure all is in sync */ PasteboardSynchronize(pPasteboard); int rc = VERR_NOT_SUPPORTED; /* Handle the unicode text */ if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { PRTUTF16 pwszSrcText = static_cast <PRTUTF16>(pv); size_t cwSrc = cb / 2; size_t cwDest = 0; /* How long will the converted text be? */ rc = vboxClipboardUtf16GetLinSize(pwszSrcText, cwSrc, &cwDest); if (RT_FAILURE(rc)) { Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } /* Empty clipboard? Not critical */ if (cwDest == 0) { Log(("writeToPasteboard: received empty clipboard data from the guest, returning false.\n")); return VINF_SUCCESS; } /* Allocate the necessary memory */ PRTUTF16 pwszDestText = static_cast <PRTUTF16>(RTMemAlloc(cwDest * 2)); if (pwszDestText == NULL) { Log(("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2)); return VERR_NO_MEMORY; } /* Convert the EOL */ rc = vboxClipboardUtf16WinToLin(pwszSrcText, cwSrc, pwszDestText, cwDest); if (RT_FAILURE(rc)) { Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc)); RTMemFree(pwszDestText); AssertRCReturn(rc, rc); } CFDataRef textData = NULL; /* Item id is 1. Nothing special here. */ PasteboardItemID itemId = (PasteboardItemID)1; /* Create a CData object which we could pass to the pasteboard */ if ((textData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pwszDestText), cwDest * 2))) { /* Put the Utf-16 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeUTF16PlainText, textData, 0); } /* Create a Utf-8 version */ char *pszDestText; rc = RTUtf16ToUtf8(pwszDestText, &pszDestText); if (RT_SUCCESS(rc)) { /* Create a CData object which we could pass to the pasteboard */ if ((textData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pszDestText), strlen(pszDestText)))) { /* Put the Utf-8 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeUTF8PlainText, textData, 0); } RTStrFree(pszDestText); } RTMemFree(pwszDestText); rc = VINF_SUCCESS; } /* Handle the bitmap */ else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { /* Create a full BMP from it */ void *pBmp; size_t cbBmpSize; CFDataRef bmpData = NULL; /* Item id is 1. Nothing special here. */ PasteboardItemID itemId = (PasteboardItemID)1; rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmpSize); if (RT_SUCCESS(rc)) { /* Create a CData object which we could pass to the pasteboard */ if ((bmpData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pBmp), cbBmpSize))) { /* Put the Utf-8 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeBMP, bmpData, 0); } RTMemFree(pBmp); } rc = VINF_SUCCESS; } else rc = VERR_NOT_IMPLEMENTED; Log(("writeToPasteboard: rc = %02X\n", rc)); return rc; }