/** * Stop registered services. * * @return IPRT status code. */ static void vbclStopServices(void) { unsigned int iServiceId = 0; VBoxClientVerbose(1, "Stopping services...\n"); for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++) { VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName); int rc = (g_aServices[iServiceId].pfnStop)(); if (RT_FAILURE(rc)) VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc); } VBoxClientVerbose(1, "Services stop completed\n"); }
/** * Paste buffer into guest clipboard. * * @param pPasteboard Guest PasteBoard reference. * @param pData Data to be pasted. * @param cbDataSize The size of *pData. * @param fFormat Buffer data format. * @param fClear Whether or not clear guest clipboard before insert data. * * @returns IPRT status code. */ static int vbclClipboardGuestPasteData(PasteboardRef pPasteboard, UInt8 *pData, CFIndex cbDataSize, CFStringRef sFormat, bool fClear) { PasteboardItemID itemId = (PasteboardItemID)1; CFDataRef textData = NULL; OSStatus rc; /* Ignoring sunchronization flags here */ PasteboardSynchronize(pPasteboard); if (fClear) { rc = PasteboardClear(pPasteboard); AssertReturn(rc == noErr, VERR_NOT_SUPPORTED); } /* Create a CData object which we could pass to the pasteboard */ if ((textData = CFDataCreate(kCFAllocatorDefault, pData, cbDataSize))) { /* Put the Utf-8 version to the pasteboard */ rc = PasteboardPutItemFlavor(pPasteboard, itemId, sFormat, textData, 0); CFRelease(textData); if (rc != noErr) { VBoxClientVerbose(3, "unable to put data into guest's clipboard: %d\n", rc); return VERR_GENERAL_FAILURE; } } else return VERR_NO_MEMORY; /* Synchronize updated content */ PasteboardSynchronize(pPasteboard); return VINF_SUCCESS; }
/** * Start registered services. * * @return IPRT status code. */ static int vbclStartServices(void) { int rc; unsigned int iServiceId = 0; VBoxClientVerbose(1, "Starting services...\n"); for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++) { VBoxClientVerbose(1, "Starting service: %s\n", g_aServices[iServiceId].pszName); rc = (g_aServices[iServiceId].pfnStart)(); if (RT_FAILURE(rc)) { VBoxClientVerbose(1, "unable to start service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc); VBoxClientVerbose(1, "Rolling back..\n"); /* Stop running services */ do { VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName); int rcStop = (g_aServices[iServiceId].pfnStop)(); if (RT_FAILURE(rcStop)) VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rcStop); } while (--iServiceId != 0); break; } } if (RT_SUCCESS(rc)) VBoxClientVerbose(1, "Services start completed.\n"); return rc; }
/** * Read host's clipboard buffer and put its content to guest clipboard. * * @param u32ClientId Host connection. * @param pPasteboard Guest PasteBoard reference. * @param fFormats List of data formats (bit field) received from host. * * @returns IPRT status code. */ int vbclClipboardForwardToGuest(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats) { int rc = VERR_INVALID_PARAMETER; void *pData; uint32_t cbDataSize, cbMemSize; uint32_t fFormatsInternal = fFormats; /* Walk across all item(s) formats */ while (fFormatsInternal) { if (fFormatsInternal & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { VBoxClientVerbose(3, "found VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT: %d\n", fFormatsInternal); rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &pData, &cbDataSize, &cbMemSize); if (RT_SUCCESS(rc)) { /* Store data in guest buffer */ rc = vbclClipboardGuestPasteText(pPasteboard, pData, cbDataSize); /* Release occupied resources */ vbclClipboardReleaseHostData(&pData, cbMemSize); } fFormatsInternal &= ~((uint32_t)VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT); } else if (fFormatsInternal & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { VBoxClientVerbose(3, "found VBOX_SHARED_CLIPBOARD_FMT_BITMAP: %d\n", fFormatsInternal); rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &pData, &cbDataSize, &cbMemSize); if (RT_SUCCESS(rc)) { /* Store data in guest buffer */ rc = vbclClipboardGuestPastePicture(pPasteboard, pData, cbDataSize); /* Release occupied resources */ vbclClipboardReleaseHostData(&pData, cbMemSize); } fFormatsInternal &= ~((uint32_t)VBOX_SHARED_CLIPBOARD_FMT_BITMAP); } else if (fFormatsInternal & VBOX_SHARED_CLIPBOARD_FMT_HTML) { VBoxClientVerbose(3, "found VBOX_SHARED_CLIPBOARD_FMT_HTML: %d\n", fFormatsInternal); rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, &pData, &cbDataSize, &cbMemSize); if (RT_SUCCESS(rc)) { /* Store data in guest buffer */ rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pData, cbDataSize, kUTTypeHTML, true); /* Release occupied resources */ vbclClipboardReleaseHostData(&pData, cbMemSize); } fFormatsInternal &= ~((uint32_t)VBOX_SHARED_CLIPBOARD_FMT_HTML); } else { VBoxClientVerbose(3, "received data in unsupported format: %d\n", fFormats); break; } } return rc; }
/** * Walk through pasteboard items and report currently available item types. * * @param pPasteboard Reference to guest Pasteboard. * @returns Available formats bit field. */ uint32_t vbclClipboardGetAvailableFormats(PasteboardRef pPasteboard) { uint32_t fFormats = 0; ItemCount cItems = 0; ItemCount iItem; OSStatus rc; #define VBOXCL_ADD_FORMAT_IF_PRESENT(a_kDarwinFmt, a_fVBoxFmt) \ if (PasteboardCopyItemFlavorData(pPasteboard, iItemID, a_kDarwinFmt, &flavorData) == noErr) \ { \ fFormats |= (uint32_t)a_fVBoxFmt; \ CFRelease(flavorData); \ } rc = PasteboardGetItemCount(pPasteboard, &cItems); AssertReturn((rc == noErr) && (cItems > 0), fFormats); for (iItem = 1; iItem <= cItems; iItem++) { PasteboardItemID iItemID; CFDataRef flavorData; rc = PasteboardGetItemIdentifier(pPasteboard, iItem, &iItemID); if (rc == noErr) { VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeUTF16PlainText, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT); VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeUTF8PlainText, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT); VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeBMP, VBOX_SHARED_CLIPBOARD_FMT_BITMAP ); VBOXCL_ADD_FORMAT_IF_PRESENT(kUTTypeHTML, VBOX_SHARED_CLIPBOARD_FMT_HTML ); #ifdef CLIPBOARD_DUMP_CONTENT_FORMATS CFArrayRef flavorTypeArray; CFIndex flavorCount; CFStringRef flavorType; rc = PasteboardCopyItemFlavors(pPasteboard, iItemID, &flavorTypeArray); if (rc == noErr) { VBoxClientVerbose(3, "SCAN..\n"); flavorCount = CFArrayGetCount(flavorTypeArray); VBoxClientVerbose(3, "SCAN (%d)..\n", (int)flavorCount); for(CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++) { VBoxClientVerbose(3, "SCAN #%d..\n", (int)flavorIndex); flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex); CFDataRef flavorData1; rc = PasteboardCopyItemFlavorData(pPasteboard, iItemID, flavorType, &flavorData1); if (rc == noErr) { VBoxClientVerbose(3, "Found: %s, size: %d\n", (char *)CFStringGetCStringPtr(flavorType, kCFStringEncodingMacRoman), (int)CFDataGetLength(flavorData1)); CFRelease(flavorData1); } } VBoxClientVerbose(3, "SCAN COMPLETE\n"); CFRelease(flavorTypeArray); } #endif /* CLIPBOARD_DUMP_CONTENT_FORMATS */ } } #undef VBOXCL_ADD_FORMAT_IF_PRESENT return fFormats; }
/** * Read guest's clipboard buffer and forward its content to host. * * @param u32ClientId Host clipboard connection. * @param pPasteboard Guest PasteBoard reference. * @param fFormats List of data formats (bit field) received from host. * * @returns IPRT status code. */ int vbclClipboardForwardToHost(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats) { int rc = VINF_SUCCESS; void *pvData = NULL; uint32_t cbData = 0; uint32_t cbAlloc = 0; VBoxClientVerbose(3, "vbclClipboardForwardToHost: %d\n", fFormats); /* Walk across all item(s) formats */ uint32_t fFormatsLeft = fFormats; while (fFormatsLeft) { if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT: %d\n", fFormats); RTUTF16 *pUtf16Str = NULL; /* First, try to get UTF16 encoded buffer */ rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF16PlainText, &pvData, &cbData, &cbAlloc); if (RT_SUCCESS(rc)) { rc = RTUtf16DupEx(&pUtf16Str, (PRTUTF16)pvData, 0); if (RT_FAILURE(rc)) pUtf16Str = NULL; } else /* Failed to get UTF16 buffer */ { /* Then, try to get UTF8 encoded buffer */ rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF8PlainText, &pvData, &cbData, &cbAlloc); if (RT_SUCCESS(rc)) { rc = RTStrToUtf16((const char *)pvData, &pUtf16Str); if (RT_FAILURE(rc)) pUtf16Str = NULL; } } /* Finally, we got UTF16 encoded buffer */ if (RT_SUCCESS(rc)) { rc = vbclClipboardHostPasteText(u32ClientId, (PRTUTF16)pvData, cbData); if (pUtf16Str) { RTUtf16Free(pUtf16Str); pUtf16Str = NULL; } vbclClipboardReleaseGuestData(&pvData, cbAlloc); } else { /* No data found or error occurred: send empty buffer */ rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, NULL, 0); } fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; } else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_BITMAP: %d\n", fFormats); rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeBMP, &pvData, &cbData, &cbAlloc); if (RT_SUCCESS(rc)) { rc = vbclClipboardHostPasteBitmap(u32ClientId, pvData, cbData); vbclClipboardReleaseGuestData(&pvData, cbAlloc); } else { /* No data found or error occurred: send empty buffer */ rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, NULL, 0); } fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_BITMAP; } else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_HTML) { VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_HTML: %d\n", fFormats); rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeHTML, &pvData, &cbData, &cbAlloc); if (RT_SUCCESS(rc)) { rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, pvData, cbData); vbclClipboardReleaseGuestData(&pvData, cbAlloc); } else { /* No data found or error occurred: send empty buffer */ rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, NULL, 0); } fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_HTML; } else { VBoxClientVerbose(3, "requested data in unsupported format: %#x\n", fFormatsLeft); break; } } return rc; /** @todo r=bird: If there are multiple formats available, which rc is returned here? Does it matter? */ }