- Timestamp:
- Sep 6, 2019 10:05:11 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 133152
- Location:
- trunk/src/VBox
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r80444 r80623 702 702 HANDLE hClip = NULL; 703 703 704 LogFlowFunc(("VBOX_ WM_SHCLPB_READ_DATA: uFormat=0x%x\n", uFormat));704 LogFlowFunc(("VBOX_CLIPBOARD_WM_READ_DATA: uFormat=0x%x\n", uFormat)); 705 705 706 706 int rc = VBoxClipboardWinOpen(hwnd); … … 844 844 845 845 if (RT_FAILURE(rc)) 846 LogFunc((" Failed with rc=%Rrc\n", rc));846 LogFunc(("VBOX_CLIPBOARD_WM_READ_DATA: Failed with rc=%Rrc\n", rc)); 847 847 } 848 848 #endif … … 850 850 if (hClip == NULL) 851 851 { 852 LogFunc(("VBOX_ WM_SHCLPB_READ_DATA: hClip=NULL, lastError=%ld\n", GetLastError()));852 LogFunc(("VBOX_CLIPBOARD_WM_READ_DATA: hClip=NULL, lastError=%ld\n", GetLastError())); 853 853 854 854 /* Requested clipboard format is not available, send empty data. */ … … 1222 1222 switch (uMsg) 1223 1223 { 1224 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:1224 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 1225 1225 { 1226 1226 pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS; -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
r80450 r80623 168 168 VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, 3); 169 169 170 Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE);170 Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT); 171 171 Msg.uFormats.SetUInt32(0); 172 172 Msg.fFlags.SetUInt32(0); … … 1477 1477 switch (uMsg) 1478 1478 { 1479 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:1479 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 1480 1480 { 1481 1481 rc = VbglR3ClipboardFormatsWriteRecv(&pEvent->cmdCtx, &pEvent->u.ReportFormats); … … 1649 1649 if (pCtx->uProtocolVer == 0) 1650 1650 { 1651 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_ WRITE, 1);1651 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT, 1); 1652 1652 VbglHGCMParmUInt32Set(&Msg.uFormats, pFormats->uFormats); 1653 1653 } 1654 1654 else 1655 1655 { 1656 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_ WRITE, 3);1656 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT, 3); 1657 1657 1658 1658 Msg.uContext.SetUInt32(pCtx->uContextID); … … 1680 1680 VBoxClipboardFormatsMsg Msg; 1681 1681 1682 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_ WRITE, 1);1682 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT, 1); 1683 1683 VbglHGCMParmUInt32Set(&Msg.uFormats, fFormats); 1684 1684 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceClipboard-os2.cpp
r80444 r80623 775 775 * Listener message - the host has new formats to offer. 776 776 */ 777 case WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:777 case WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 778 778 vgsvcClipboardOs2AdvertiseHostFormats(LONGFROMMP(mp1)); 779 779 break; … … 895 895 * respond do WM_RENDERFORMAT message. 896 896 */ 897 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:898 if (!WinPostMsg(g_hwndWorker, WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE,897 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 898 if (!WinPostMsg(g_hwndWorker, WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT, 899 899 MPFROMLONG(fFormats), 0)) 900 900 VGSvcError("WinPostMsg(%lx, FORMATS,,) failed, lasterr=%#lx\n", -
trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.cpp
r80444 r80623 380 380 switch (u32Msg) 381 381 { 382 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:382 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 383 383 { 384 384 /* -
trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
r80444 r80623 166 166 * @param cb the size of the data in @a pv 167 167 */ 168 void Clip CompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)168 void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 169 169 { 170 170 RT_NOREF1(pCtx); … … 192 192 rc = VERR_NO_MEMORY; 193 193 if (RT_SUCCESS(rc)) 194 rc = ClipStartX11(g_ctx.pBackend );194 rc = ClipStartX11(g_ctx.pBackend, false /* grab */); 195 195 if (RT_SUCCESS(rc)) 196 196 { … … 229 229 switch (Msg) 230 230 { 231 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE:231 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 232 232 { 233 233 /* The host has announced available clipboard formats. -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp
r80468 r80623 183 183 RTMemFree(pEvIt); 184 184 } 185 186 pSource->uID = 0; 187 pSource->uEventIDNext = 0; 185 188 } 186 189 … … 216 219 217 220 return NULL; 221 } 222 223 /** 224 * Returns the last (newest) event ID which has been registered for an event source. 225 * 226 * @returns Last registered event ID, or 0 if not found. 227 * @param pSource Event source to get last registered event from. 228 */ 229 VBOXCLIPBOARDEVENTID SharedClipboardEventGetLast(PSHAREDCLIPBOARDEVENTSOURCE pSource) 230 { 231 AssertPtrReturn(pSource, 0); 232 PSHAREDCLIPBOARDEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHAREDCLIPBOARDEVENT, Node); 233 if (pEvent) 234 return pEvent->uID; 235 236 return 0; 218 237 } 219 238 … … 281 300 LogFlowFunc(("Event %RU16\n", pEvent->uID)); 282 301 302 RTListNodeRemove(&pEvent->Node); 303 283 304 SharedClipboardEventDestroy(pEvent); 305 284 306 RTMemFree(pEvent); 285 286 RTListNodeRemove(&pEvent->Node); 307 pEvent = NULL; 287 308 288 309 rc = VINF_SUCCESS; … … 290 311 else 291 312 rc = VERR_NOT_FOUND; 292 293 AssertRC(rc);294 313 295 314 LogFlowFuncLeaveRC(rc); … … 362 381 else 363 382 rc = VERR_NOT_FOUND; 364 365 #ifdef DEBUG_andy366 AssertRC(rc);367 #endif368 383 369 384 LogFlowFuncLeaveRC(rc); … … 787 802 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT); 788 803 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); 789 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE);804 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT); 790 805 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START); 791 806 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_READ); … … 820 835 { 821 836 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD); 822 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_ WRITE);837 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT); 823 838 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_READ); 824 839 RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_WRITE); -
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp
r80444 r80623 1893 1893 else 1894 1894 rc = VERR_NOT_IMPLEMENTED; 1895 Clip CompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,1896 pvDest, cbDest);1895 ClipRequestFromX11CompleteCallback(pReq->mCtx->pFrontend, rc, pReq->mReq, 1896 pvDest, cbDest); 1897 1897 RTMemFree(pvDest); 1898 1898 RTMemFree(pReq); … … 2010 2010 /* The clipboard callback was never scheduled, so we must signal 2011 2011 * that the request processing is finished and clean up ourselves. */ 2012 Clip CompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,2013 NULL, 0);2012 ClipRequestFromX11CompleteCallback(pReq->mCtx->pFrontend, rc, pReq->mReq, 2013 NULL, 0); 2014 2014 RTMemFree(pReq); 2015 2015 } … … 2037 2037 if (!pCtx->fHaveX11) 2038 2038 return VERR_NO_DATA; 2039 2039 2040 int rc = VINF_SUCCESS; 2040 CLIPREADX11CBREQ *pX11Req; 2041 pX11Req = (CLIPREADX11CBREQ *)RTMemAllocZ(sizeof(*pX11Req)); 2042 if (!pX11Req) 2043 rc = VERR_NO_MEMORY; 2044 else 2041 2042 CLIPREADX11CBREQ *pX11Req = (CLIPREADX11CBREQ *)RTMemAllocZ(sizeof(CLIPREADX11CBREQ)); 2043 if (pX11Req) 2045 2044 { 2046 2045 pX11Req->mFormat = u32Format; 2047 2046 pX11Req->mCtx = pCtx; 2048 2047 pX11Req->mReq = pReq; 2048 2049 2049 /* We use this to schedule a worker function on the event thread. */ 2050 clipQueueToEventThread(pCtx, vboxClipboardReadX11Worker, 2051 (XtPointer) pX11Req); 2052 } 2050 clipQueueToEventThread(pCtx, vboxClipboardReadX11Worker, (XtPointer) pX11Req); 2051 } 2052 else 2053 rc = VERR_NO_MEMORY; 2054 2053 2055 return rc; 2054 2056 } … … 2387 2389 static char g_completedBuf[MAX_BUF_SIZE]; 2388 2390 2389 void Clip CompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)2391 void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 2390 2392 { 2391 2393 RT_NOREF1(pCtx); … … 2646 2648 uint32_t cbActual; 2647 2649 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL; 2648 rc = ClipStartX11(pCtx );2650 rc = ClipStartX11(pCtx, false /* fGrab */); 2649 2651 AssertRCReturn(rc, 1); 2650 2652 … … 2843 2845 2844 2846 pCtx = ClipConstructX11(NULL, true); 2845 rc = ClipStartX11(pCtx );2847 rc = ClipStartX11(pCtx, false /* fGrab */); 2846 2848 AssertRCReturn(rc, 1); 2847 2849 … … 2894 2896 } 2895 2897 2896 void Clip CompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)2898 void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 2897 2899 { 2898 2900 RT_NOREF5(pCtx, rc, pReq, pv, cb); … … 2924 2926 CLIPBACKEND *pCtx = ClipConstructX11(NULL, false); 2925 2927 AssertReturn(pCtx, 1); 2926 rc = ClipStartX11(pCtx );2928 rc = ClipStartX11(pCtx, false /* fGrab */); 2927 2929 AssertRCReturn(rc, 1); 2928 2930 /* Give the clipboard time to synchronise. */ -
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r79631 r80623 85 85 -framework ApplicationServices -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxSharedClipboard.dylib 86 86 87 if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK) 87 if 0 ## Disabled for now; needs to be adapted to the new protocol first. 88 if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK) 88 89 if1of ($(KBUILD_TARGET), freebsd linux netbsd openbsd solaris) 89 90 # … … 102 103 export VBOX_LOG_DEST=nofile; $(tstClipboardX11-2_1_STAGE_TARGET) quiet 103 104 $(QUIET)$(APPEND) -t "$@" "done" 104 endif # 1of ($(KBUILD_TARGET),freebsd linux netbsd openbsd solaris) 105 endif # 1of ($(KBUILD_TARGET),freebsd linux netbsd openbsd solaris) 106 endif 105 107 endif 106 108 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp
r80447 r80623 38 38 { 39 39 /** We have a separate thread to poll for new clipboard content */ 40 RTTHREAD thread; 41 bool volatile fTerminate; 42 40 RTTHREAD thread; 41 bool volatile fTerminate; 43 42 /** The reference to the current pasteboard */ 44 PasteboardRef pasteboard; 45 46 PVBOXCLIPBOARDCLIENT pClient; 43 PasteboardRef pasteboard; 44 PVBOXCLIPBOARDCLIENT pClient; 47 45 }; 48 46 … … 70 68 /* Retrieve the formats currently in the clipboard and supported by vbox */ 71 69 int rc = queryNewPasteboardFormats(pCtx->pasteboard, &fFormats, &fChanged); 72 if (RT_SUCCESS(rc) && fChanged) 73 { 74 vboxSvcClipboardOldReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, fFormats); 75 Log(("vboxClipboardChanged fFormats %02X\n", fFormats)); 76 } 77 78 return rc; 79 } 80 70 if ( RT_SUCCESS(rc) 71 && fChanged) 72 { 73 SHAREDCLIPBOARDFORMATDATA formatData; 74 RT_ZERO(formatData); 75 76 formatData.uFormats = fFormats; 77 78 rc = vboxSvcClipboardFormatsReport(pCtx->pClient, &formatData); 79 } 80 81 LogFlowFuncLeaveRC(rc); 82 return rc; 83 } 81 84 82 85 /** … … 92 95 static int vboxClipboardThread(RTTHREAD ThreadSelf, void *pvUser) 93 96 { 94 Log (("vboxClipboardThread: starting clipboard thread\n"));97 LogFlowFuncEnter(); 95 98 96 99 AssertPtrReturn(pvUser, VERR_INVALID_PARAMETER); … … 109 112 } 110 113 111 Log (("vboxClipboardThread: clipboard thread terminated successfully with return code %Rrc\n", VINF_SUCCESS));114 LogFlowFuncLeaveRC(VINF_SUCCESS); 112 115 return VINF_SUCCESS; 113 116 } 114 117 115 /* 116 * Public platform dependent functions. 117 */ 118 119 /** Initialise the host side of the shared clipboard - called by the hgcm layer. */ 118 120 119 int VBoxClipboardSvcImplInit(void) 121 120 { … … 138 137 } 139 138 140 /** Terminate the host side of the shared clipboard - called by the hgcm layer. */141 139 void VBoxClipboardSvcImplDestroy(void) 142 140 { 143 Log(("vboxClipboardDestroy\n"));144 145 141 /* 146 142 * Signal the termination of the polling thread and wait for it to respond. … … 186 182 /* Sync the host clipboard content with the client. */ 187 183 VBoxSvcClipboardLock(); 184 188 185 int rc = vboxClipboardChanged(pClient->State.pCtx); 186 189 187 VBoxSvcClipboardUnlock(); 190 188 … … 195 193 { 196 194 VBoxSvcClipboardLock(); 195 197 196 pClient->State.pCtx->pClient = NULL; 197 198 198 VBoxSvcClipboardUnlock(); 199 199 … … 201 201 } 202 202 203 int VBoxClipboardSvcImplFormatAnnounce(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx,204 P SHAREDCLIPBOARDFORMATDATA pFormats)203 int VBoxClipboardSvcImplFormatAnnounce(PVBOXCLIPBOARDCLIENT pClient, 204 PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDFORMATDATA pFormats) 205 205 { 206 206 RT_NOREF(pCmdCtx); … … 208 208 LogFlowFunc(("uFormats=%02X\n", pFormats->uFormats)); 209 209 210 if (pFormats->uFormats == 0)210 if (pFormats->uFormats == VBOX_SHARED_CLIPBOARD_FMT_NONE) 211 211 { 212 212 /* This is just an automatism, not a genuine announcement */ … … 219 219 #endif 220 220 221 return vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, pFormats->uFormats); 221 SHAREDCLIPBOARDDATAREQ dataReq; 222 RT_ZERO(dataReq); 223 224 dataReq.uFmt = pFormats->uFormats; 225 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 226 227 return vboxSvcClipboardDataReadRequest(pClient, &dataReq, NULL /* puEvent */); 222 228 } 223 229 … … 256 262 * @param pData Data block to write to clipboard. 257 263 */ 258 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData) 264 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, 265 PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData) 259 266 { 260 267 RT_NOREF(pCmdCtx); -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
r80562 r80623 136 136 uint32_t cbChunkSize; 137 137 SHAREDCLIPBOARDSOURCE enmSource; 138 /** Old cruft (needed for VBox Guest Additions <= 6.0), remove this some time later. */139 VBOXCLIPBOARDCLIENTSTATEOLD Old;140 138 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 141 139 /** The client's URI state. */ … … 227 225 * The service functions. Locking is between the service thread and the platform-dependent (window) thread. 228 226 */ 229 int vboxSvcClipboardSendFormatsWrite(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats); 230 231 int vboxSvcClipboardOldCompleteReadData(PVBOXCLIPBOARDCLIENT pClient, int rc, uint32_t cbActual); 232 int vboxSvcClipboardOldReportMsg(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t uFormats); 233 void vboxSvcClipboardOldClientStateResetData(PVBOXCLIPBOARDCLIENTSTATE pClientState); 234 void vboxSvcClipboardOldClientStateReset(PVBOXCLIPBOARDCLIENTSTATE pClientState); 227 int vboxSvcClipboardDataReadRequest(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDDATAREQ pDataReq, PVBOXCLIPBOARDEVENTID puEvent); 228 int vboxSvcClipboardDataReadSignal(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData); 229 int vboxSvcClipboardFormatsReport(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats); 235 230 236 231 uint32_t vboxSvcClipboardGetMode(void); … … 307 302 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer); 308 303 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer); 309 #endif 304 #endif /*VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 310 305 311 306 /* Host unit testing interface */ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
r80563 r80623 55 55 static int vboxClipboardSvcWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx); 56 56 57 typedef struct _VBOXCLIPBOARDCONTEXTOLD58 {59 /** Event which gets triggered if the host clipboard needs to render its data. */60 RTSEMEVENT hRenderEvent;61 } VBOXCLIPBOARDCONTEXTOLD;62 63 57 struct _VBOXCLIPBOARDCONTEXT 64 58 { … … 69 63 /** Windows-specific context data. */ 70 64 VBOXCLIPBOARDWINCTX Win; 71 /** Old cruft, needed for the legacy protocol (v0). */72 VBOXCLIPBOARDCONTEXTOLD Old;73 65 }; 74 66 75 67 76 68 /** @todo Someone please explain the protocol wrt overflows... */ 77 static void vboxClipboard GetData(uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,78 void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)69 static void vboxClipboardSvcWinGetData(uint32_t u32Format, const void *pvSrc, uint32_t cbSrc, 70 void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst) 79 71 { 80 72 LogFlowFunc(("cbSrc = %d, cbDst = %d\n", cbSrc, cbDst)); … … 175 167 } 176 168 177 /**178 * Requests data of a specific format from the guest, optionally waiting for its arrival via VBoxClipboardSvcImplWriteData()179 * and copying the retrieved data into the OS' clipboard.180 *181 * Legacy protocol, do not use anymore.182 *183 * @returns VBox status code.184 * @param pCtx Clipboard context to use.185 * @param cfFormat Windows clipboard format to receive data in.186 * @param uTimeoutMs Timeout (in ms) to wait until the render event has been triggered.187 * Specify 0 if no waiting is required.188 */189 static int vboxClipboardSvcWinOldRequestData(PVBOXCLIPBOARDCONTEXT pCtx, UINT cfFormat,190 RTMSINTERVAL uTimeoutMs)191 {192 Assert(pCtx->Old.hRenderEvent);193 Assert(pCtx->pClient->State.Old.data.pv == NULL && pCtx->pClient->State.Old.data.cb == 0 && pCtx->pClient->State.Old.data.u32Format == 0);194 195 LogFlowFunc(("cfFormat=%u, uTimeoutMs=%RU32\n", cfFormat, uTimeoutMs));196 197 const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat);198 199 int rc = vboxSvcClipboardOldReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, fFormat);200 if ( RT_SUCCESS(rc)201 && uTimeoutMs)202 {203 rc = RTSemEventWait(pCtx->Old.hRenderEvent, uTimeoutMs /* Timeout in ms */);204 if (RT_SUCCESS(rc))205 {206 LogFlowFunc(("rc=%Rrc, pv=%p, cb=%RU32, u32Format=%RU32\n",207 rc, pCtx->pClient->State.Old.data.pv, pCtx->pClient->State.Old.data.cb,208 pCtx->pClient->State.Old.data.u32Format));209 210 if ( RT_SUCCESS (rc)211 && pCtx->pClient->State.Old.data.pv != NULL212 && pCtx->pClient->State.Old.data.cb > 0213 && pCtx->pClient->State.Old.data.u32Format == fFormat)214 {215 rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat,216 pCtx->pClient->State.Old.data.pv, pCtx->pClient->State.Old.data.cb);217 218 vboxSvcClipboardOldClientStateResetData(&pCtx->pClient->State);219 }220 221 if (RT_FAILURE(rc))222 {223 vboxSvcClipboardOldClientStateReset(&pCtx->pClient->State);224 225 /* Something went wrong. */226 VBoxClipboardWinClear();227 }228 }229 }230 231 LogFlowFuncLeaveRC(rc);232 return rc;233 }234 235 169 static int vboxClipboardSvcWinDataRead(PVBOXCLIPBOARDCONTEXT pCtx, UINT cfFormat, 236 170 void **ppvData, uint32_t *pcbData) … … 238 172 LogFlowFunc(("cfFormat=%u\n", cfFormat)); 239 173 240 int rc; 241 242 PVBOXCLIPBOARDCLIENTMSG pMsgReadData = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, 243 VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA); 244 if (pMsgReadData) 245 { 246 const uint16_t uEvent = SharedClipboardEventIDGenerate(&pCtx->pClient->Events); 247 248 const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat); 249 const uint32_t uCID = VBOX_SHARED_CLIPBOARD_CONTEXTID_MAKE(pCtx->pClient->Events.uID, uEvent); 250 251 HGCMSvcSetU32(&pMsgReadData->m_paParms[0], uCID); 252 HGCMSvcSetU32(&pMsgReadData->m_paParms[1], fFormat); 253 HGCMSvcSetU32(&pMsgReadData->m_paParms[2], pCtx->pClient->State.cbChunkSize); 254 255 LogFlowFunc(("CID=%RU32\n", uCID)); 256 257 rc = vboxSvcClipboardMsgAdd(pCtx->pClient, pMsgReadData, true /* fAppend */); 174 SHAREDCLIPBOARDDATAREQ dataReq; 175 RT_ZERO(dataReq); 176 177 dataReq.uFmt = VBoxClipboardWinClipboardFormatToVBox(cfFormat); 178 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 179 180 VBOXCLIPBOARDEVENTID uEvent = 0; 181 int rc = vboxSvcClipboardDataReadRequest(pCtx->pClient, &dataReq, &uEvent); 182 if (RT_SUCCESS(rc)) 183 { 184 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload; 185 rc = SharedClipboardEventWait(&pCtx->pClient->Events, uEvent, 30 * 1000, &pPayload); 258 186 if (RT_SUCCESS(rc)) 259 187 { 260 int rc2 = SharedClipboardEventRegister(&pCtx->pClient->Events, uEvent); 261 AssertRC(rc2); 262 263 rc = vboxSvcClipboardClientWakeup(pCtx->pClient); 264 if (RT_SUCCESS(rc)) 265 { 266 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload; 267 rc = SharedClipboardEventWait(&pCtx->pClient->Events, uEvent, 268 30 * 1000, &pPayload); 269 if (RT_SUCCESS(rc)) 270 { 271 *ppvData = pPayload->pvData; 272 *pcbData = pPayload->cbData; 273 274 /* Detach the payload, as the caller then will own the data. */ 275 SharedClipboardEventPayloadDetach(&pCtx->pClient->Events, uEvent); 276 } 277 } 278 279 SharedClipboardEventUnregister(&pCtx->pClient->Events, uEvent); 280 } 281 } 282 else 283 rc = VERR_NO_MEMORY; 188 *ppvData = pPayload->pvData; 189 *pcbData = pPayload->cbData; 190 191 /* Detach the payload, as the caller then will own the data. */ 192 SharedClipboardEventPayloadDetach(&pCtx->pClient->Events, uEvent); 193 } 194 195 SharedClipboardEventUnregister(&pCtx->pClient->Events, uEvent); 196 } 284 197 285 198 LogFlowFuncLeaveRC(rc); … … 366 279 else 367 280 { 368 int rc; 369 370 if (pCtx->pClient->State.uProtocolVer == 0) 281 void *pvData = NULL; 282 uint32_t cbData = 0; 283 int rc = vboxClipboardSvcWinDataRead(pCtx, cfFormat, &pvData, &cbData); 284 if ( RT_SUCCESS(rc) 285 && pvData 286 && cbData) 371 287 { 372 rc = vboxClipboardSvcWinOldRequestData(pCtx, cfFormat, 30 * 1000 /* 30s timeout */); 288 rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat, pvData, cbData); 289 290 RTMemFree(pvData); 291 cbData = 0; 373 292 } 374 else 375 { 376 void *pvData = NULL; 377 uint32_t cbData = 0; 378 rc = vboxClipboardSvcWinDataRead(pCtx, cfFormat, &pvData, &cbData); 379 if ( RT_SUCCESS(rc) 380 && pvData 381 && cbData) 382 { 383 rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat, pvData, cbData); 384 385 RTMemFree(pvData); 386 } 387 else 388 AssertFailed(); 389 } 293 294 if (RT_FAILURE(rc)) 295 VBoxClipboardWinClear(); 390 296 } 391 297 … … 406 312 { 407 313 LogFunc(("VBOX_CLIPBOARD_WM_REPORT_FORMATS\n")); 408 409 /* Some legcay protocol checks. */410 if ( pCtx->pClient->State.uProtocolVer == 0411 && ( pCtx->pClient == NULL412 || pCtx->pClient->State.Old.fHostMsgFormats))413 {414 /* Host has pending formats message. Ignore the guest announcement,415 * because host clipboard has more priority.416 */417 LogFunc(("VBOX_CLIPBOARD_WM_REPORT_FORMATS ignored; pClient=%p\n", pCtx->pClient));418 break;419 }420 314 421 315 /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT. */ … … 640 534 && Formats.uFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) 641 535 { 642 if (pCtx->pClient->State.uProtocolVer == 0) 643 { 644 rc = vboxSvcClipboardOldReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, Formats.uFormats); 645 } 646 else /* Protocol v1 and up. */ 647 { 648 rc = vboxSvcClipboardSendFormatsWrite(pCtx->pClient, &Formats); 649 } 536 rc = vboxSvcClipboardFormatsReport(pCtx->pClient, &Formats); 650 537 } 651 538 } … … 687 574 if (RT_SUCCESS(rc)) 688 575 { 689 rc = RTSemEventCreate(&pCtx->Old.hRenderEvent); 576 rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */, 577 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 690 578 if (RT_SUCCESS(rc)) 691 579 { 692 rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */, 693 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 694 if (RT_SUCCESS(rc)) 695 { 696 int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */); 697 AssertRC(rc2); 698 } 699 } 700 701 if (RT_FAILURE(rc)) 702 RTSemEventDestroy(pCtx->Old.hRenderEvent); 580 int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */); 581 AssertRC(rc2); 582 } 703 583 } 704 584 … … 736 616 PostMessage(pCtx->Win.hWnd, WM_DESTROY, 0 /* wParam */, 0 /* lParam */); 737 617 738 rc = RTSemEventDestroy(pCtx->Old.hRenderEvent); 739 if (RT_SUCCESS(rc)) 740 { 741 if (pCtx->hThread != NIL_RTTHREAD) 742 { 743 LogFunc(("Waiting for thread to terminate ...\n")); 744 745 /* Wait for the window thread to terminate. */ 746 rc = RTThreadWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */, NULL); 747 if (RT_FAILURE(rc)) 748 LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc)); 749 750 pCtx->hThread = NIL_RTTHREAD; 751 } 618 if (pCtx->hThread != NIL_RTTHREAD) 619 { 620 LogFunc(("Waiting for thread to terminate ...\n")); 621 622 /* Wait for the window thread to terminate. */ 623 rc = RTThreadWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */, NULL); 624 if (RT_FAILURE(rc)) 625 LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc)); 626 627 pCtx->hThread = NIL_RTTHREAD; 752 628 } 753 629 … … 809 685 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 810 686 } 811 812 else813 rc = VERR_NOT_SUPPORTED;814 687 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 815 688 … … 850 723 LogFunc(("CF_DIB\n")); 851 724 852 vboxClipboard GetData(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, lp, GlobalSize(hClip),853 pData->pvData, pData->cbData, pcbActual);725 vboxClipboardSvcWinGetData(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, lp, GlobalSize(hClip), 726 pData->pvData, pData->cbData, pcbActual); 854 727 855 728 GlobalUnlock(hClip); … … 872 745 LogFunc(("CF_UNICODETEXT\n")); 873 746 874 vboxClipboard GetData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, uniString, (lstrlenW(uniString) + 1) * 2,875 pData->pvData, pData->cbData, pcbActual);747 vboxClipboardSvcWinGetData(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, uniString, (lstrlenW(uniString) + 1) * 2, 748 pData->pvData, pData->cbData, pcbActual); 876 749 877 750 GlobalUnlock(hClip); … … 895 768 { 896 769 /** @todo r=andy Add data overflow handling. */ 897 vboxClipboard GetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip),898 pData->pvData, pData->cbData, pcbActual);770 vboxClipboardSvcWinGetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip), 771 pData->pvData, pData->cbData, pcbActual); 899 772 #ifdef VBOX_STRICT 900 773 LogFlowFunc(("Raw HTML clipboard data from host:")); … … 922 795 { 923 796 /* Reply with empty data. */ 924 vboxClipboard GetData(0, NULL, 0, pData->pvData, pData->cbData, pcbActual);797 vboxClipboardSvcWinGetData(0, NULL, 0, pData->pvData, pData->cbData, pcbActual); 925 798 } 926 799 … … 929 802 } 930 803 931 static int vboxClipboardSvcWinOldWriteData(PVBOXCLIPBOARDCLIENT pClient,932 void *pv, uint32_t cb, uint32_t u32Format)804 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, 805 PSHAREDCLIPBOARDDATABLOCK pData) 933 806 { 934 807 LogFlowFuncEnter(); 935 808 936 const PVBOXCLIPBOARDCLIENTSTATE pState = &pClient->State; 937 938 /* 939 * The guest returns data that was requested in the WM_RENDERFORMAT handler. 940 */ 941 Assert( pState->Old.data.pv == NULL 942 && pState->Old.data.cb == 0 943 && pState->Old.data.u32Format == 0); 944 945 #ifdef LOG_ENABLED 946 VBoxClipboardDbgDumpData(pv, cb, u32Format); 947 #endif 948 949 if (cb > 0) 950 { 951 char *pszResult = NULL; 952 953 if ( u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML 954 && !VBoxClipboardWinIsCFHTML((const char*)pv)) 955 { 956 /* check that this is not already CF_HTML */ 957 uint32_t cbResult; 958 int rc = VBoxClipboardWinConvertMIMEToCFHTML((const char *)pv, cb, &pszResult, &cbResult); 959 if (RT_SUCCESS(rc)) 960 { 961 if (pszResult != NULL && cbResult != 0) 962 { 963 pState->Old.data.pv = pszResult; 964 pState->Old.data.cb = cbResult; 965 pState->Old.data.u32Format = u32Format; 966 } 967 } 968 } 969 else 970 { 971 pState->Old.data.pv = RTMemDup(pv, cb); 972 if (pState->Old.data.pv) 973 { 974 pState->Old.data.cb = cb; 975 pState->Old.data.u32Format = u32Format; 976 } 977 } 978 } 979 980 AssertPtr(pState->pCtx); 981 int rc = RTSemEventSignal(pState->pCtx->Old.hRenderEvent); 982 AssertRC(rc); 809 int rc = vboxSvcClipboardDataReadSignal(pClient, pCmdCtx, pData); 983 810 984 811 LogFlowFuncLeaveRC(rc); … … 986 813 } 987 814 988 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx,989 PSHAREDCLIPBOARDDATABLOCK pData)990 {991 LogFlowFuncEnter();992 993 int rc;994 995 if (pClient->State.uProtocolVer == 0)996 {997 rc = vboxClipboardSvcWinOldWriteData(pClient, pData->pvData, pData->cbData, pData->uFormat);998 }999 else1000 {1001 const uint16_t uEvent = VBOX_SHARED_CLIPBOARD_CONTEXTID_GET_EVENT(pCmdCtx->uContextID);1002 1003 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload;1004 rc = SharedClipboardPayloadAlloc(uEvent, pData->pvData, pData->cbData, &pPayload);1005 if (RT_SUCCESS(rc))1006 {1007 rc = SharedClipboardEventSignal(&pClient->Events, uEvent, pPayload);1008 if (RT_FAILURE(rc))1009 SharedClipboardPayloadFree(pPayload);1010 }1011 }1012 1013 LogFlowFuncLeaveRC(rc);1014 return rc;1015 }1016 1017 815 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1018 816 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer) -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11-stubs.cpp
r80473 r80623 128 128 } 129 129 130 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST131 int VBoxClipboardSvcImplURIReadDir(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDDIRDATA pDirData)132 {133 RT_NOREF(pClient, pDirData);134 return VERR_NOT_IMPLEMENTED;135 }136 137 int VBoxClipboardSvcImplURIWriteDir(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDDIRDATA pDirData)138 {139 RT_NOREF(pClient, pDirData);140 return VERR_NOT_IMPLEMENTED;141 }142 143 int VBoxClipboardSvcImplURIReadFileHdr(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEHDR pFileHdr)144 {145 RT_NOREF(pClient, pFileHdr);146 return VERR_NOT_IMPLEMENTED;147 }148 149 int VBoxClipboardSvcImplURIWriteFileHdr(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEHDR pFileHdr)150 {151 RT_NOREF(pClient, pFileHdr);152 return VERR_NOT_IMPLEMENTED;153 }154 155 int VBoxClipboardSvcImplURIReadFileData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEDATA pFileData)156 {157 RT_NOREF(pClient, pFileData);158 return VERR_NOT_IMPLEMENTED;159 }160 161 int VBoxClipboardSvcImplURIWriteFileData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEDATA pFileData)162 {163 RT_NOREF(pClient, pFileData);164 return VERR_NOT_IMPLEMENTED;165 }166 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */167 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
r80473 r80623 38 38 * Structures and Typedefs * 39 39 *********************************************************************************************************************************/ 40 struct _VBOXCLIPBOARDREQFROMVBOX; 41 typedef struct _VBOXCLIPBOARDREQFROMVBOX VBOXCLIPBOARDREQFROMVBOX; 42 43 /** Global context information used by the host glue for the X11 clipboard 44 * backend */ 40 41 /** 42 * Global context information used by the host glue for the X11 clipboard backend. 43 */ 45 44 struct _VBOXCLIPBOARDCONTEXT 46 45 { 47 46 /** This mutex is grabbed during any critical operations on the clipboard 48 47 * which might clash with others. */ 49 RTCRITSECT clipboardMutex; 50 /** The currently pending request for data from VBox. NULL if there is 51 * no request pending. The protocol for completing a request is to grab 52 * the critical section, check that @a pReq is not NULL, fill in the data 53 * fields and set @a pReq to NULL. The protocol for cancelling a pending 54 * request is to grab the critical section and set pReq to NULL. 55 * It is an error if a request arrives while another one is pending, and 56 * the backend is responsible for ensuring that this does not happen. */ 57 VBOXCLIPBOARDREQFROMVBOX *pReq; 48 RTCRITSECT CritSect; 58 49 /** Pointer to the opaque X11 backend structure */ 59 CLIPBACKEND *pBackend;50 CLIPBACKEND *pBackend; 60 51 /** Pointer to the VBox host client data structure. */ 61 52 PVBOXCLIPBOARDCLIENT pClient; 62 53 /** We set this when we start shutting down as a hint not to post any new 63 54 * requests. */ 64 bool fShuttingDown;55 bool fShuttingDown; 65 56 }; 66 67 57 68 58 … … 77 67 LogFlowFunc(("pCtx=%p, u32Formats=%02X\n", pCtx, u32Formats)); 78 68 79 vboxSvcClipboardOldReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, u32Formats); 69 SHAREDCLIPBOARDFORMATDATA formatData; 70 RT_ZERO(formatData); 71 72 formatData.uFormats = u32Formats; 73 74 int rc2 = vboxSvcClipboardFormatsReport(pCtx->pClient, &formatData); 75 AssertRC(rc2); 80 76 } 81 77 … … 86 82 int VBoxClipboardSvcImplInit(void) 87 83 { 84 LogFlowFuncEnter(); 88 85 return VINF_SUCCESS; 89 86 } … … 95 92 void VBoxClipboardSvcImplDestroy(void) 96 93 { 97 94 LogFlowFuncEnter(); 98 95 } 99 96 100 97 /** 101 98 * Connect a guest to the shared clipboard. 102 * @note host glue code103 99 * @note on the host, we assume that some other application already owns 104 100 * the clipboard and leave ownership to X11. … … 108 104 int rc = VINF_SUCCESS; 109 105 110 LogRel(("Starting host clipboard service\n"));111 112 106 PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT)); 113 if ( !pCtx)107 if (pCtx) 114 108 { 115 rc = VERR_NO_MEMORY; 116 } 117 else 118 { 119 RTCritSectInit(&pCtx->clipboardMutex); 109 RTCritSectInit(&pCtx->CritSect); 120 110 CLIPBACKEND *pBackend = ClipConstructX11(pCtx, fHeadless); 121 111 if (!pBackend) … … 136 126 if (RT_FAILURE(rc)) 137 127 { 138 RTCritSectDelete(&pCtx-> clipboardMutex);128 RTCritSectDelete(&pCtx->CritSect); 139 129 RTMemFree(pCtx); 140 130 } 141 131 } 142 143 if (RT_FAILURE(rc)) 144 LogRel(("Failed to initialize the Shared Clipboard host service, rc=%Rrc\n", rc)); 132 else 133 rc = VERR_NO_MEMORY; 145 134 146 135 LogFlowFuncLeaveRC(rc); … … 160 149 * there is data in the host clipboard it will automatically be sent to 161 150 * the guest when the clipboard starts up. */ 162 return vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, 0); 151 SHAREDCLIPBOARDFORMATDATA formatData; 152 RT_ZERO(formatData); 153 154 formatData.uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE; 155 156 return vboxSvcClipboardFormatsReport(pClient, &formatData); 163 157 } 164 158 … … 170 164 { 171 165 LogFlowFuncEnter(); 172 173 LogRel(("Stopping the host clipboard service\n"));174 166 175 167 PVBOXCLIPBOARDCONTEXT pCtx = pClient->State.pCtx; … … 192 184 { 193 185 ClipDestructX11(pCtx->pBackend); 194 RTCritSectDelete(&pCtx-> clipboardMutex);186 RTCritSectDelete(&pCtx->CritSect); 195 187 RTMemFree(pCtx); 196 188 } … … 225 217 struct _CLIPREADCBREQ 226 218 { 227 /** Where to write the returned data to. */ 228 void *pv; 229 /** The size of the buffer in pv */ 230 uint32_t cb; 231 /** The actual size of the data written */ 232 uint32_t *pcbActual; 219 /** Where to write the returned data to. Weak pointer! */ 220 void *pv; 221 /** The size of the buffer in pv. */ 222 uint32_t cb; 223 /** The actual size of the data written. */ 224 uint32_t *pcbActual; 225 /** The request's event ID. */ 226 VBOXCLIPBOARDEVENTID uEvent; 233 227 }; 234 228 235 229 /** 236 * Called when VBox wants to read the X11 clipboard. 237 * 238 * @returns VINF_SUCCESS on successful completion 239 * @returns VINF_HGCM_ASYNC_EXECUTE if the operation will complete 240 * asynchronously 241 * @returns iprt status code on failure 242 * 243 * @param pClient Context information about the guest VM 230 * Called when the host service wants to read the X11 clipboard. 231 * 232 * @returns VINF_SUCCESS on successful completion. 233 * @returns VINF_HGCM_ASYNC_EXECUTE if the operation will complete asynchronously. 234 * @returns IPRT status code on failure. 235 * 236 * @param pClient Context information about the guest VM. 244 237 * @param pCmdCtx Command context to use. 245 238 * @param pData Data block to put read data into. 246 * @param pcbActual Where to write the actual size of the written data 239 * @param pcbActual Where to write the actual size of the written data. 247 240 * 248 241 * @note We always fail or complete asynchronously. … … 262 255 int rc = VINF_SUCCESS; 263 256 264 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAlloc (sizeof(CLIPREADCBREQ));265 if ( !pReq)257 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ)); 258 if (pReq) 266 259 { 267 rc = VERR_NO_MEMORY; 260 const VBOXCLIPBOARDEVENTID uEvent = SharedClipboardEventIDGenerate(&pClient->Events); 261 262 pReq->pv = pData->pvData; 263 pReq->cb = pData->cbData; 264 pReq->pcbActual = pcbActual; 265 pReq->uEvent = uEvent; 266 267 rc = ClipRequestDataFromX11(pClient->State.pCtx->pBackend, pData->uFormat, pReq); 268 if (RT_SUCCESS(rc)) 269 { 270 rc = SharedClipboardEventRegister(&pClient->Events, uEvent); 271 if (RT_SUCCESS(rc)) 272 { 273 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload; 274 rc = SharedClipboardEventWait(&pClient->Events, uEvent, 30 * 1000, &pPayload); 275 if (RT_SUCCESS(rc)) 276 { 277 memcpy(pData->pvData, pPayload->pvData, RT_MIN(pData->cbData, pPayload->cbData)); 278 pData->cbData = pPayload->cbData; 279 280 Assert(pData->cbData == pPayload->cbData); /* Sanity. */ 281 } 282 283 SharedClipboardEventUnregister(&pClient->Events, uEvent); 284 } 285 } 268 286 } 269 287 else 270 { 271 pReq->pv = pData->pvData; 272 pReq->cb = pData->cbData; 273 pReq->pcbActual = pcbActual; 274 rc = ClipRequestDataFromX11(pClient->State.pCtx->pBackend, pData->uFormat, pReq); 275 if (RT_SUCCESS(rc)) 276 rc = VINF_HGCM_ASYNC_EXECUTE; 277 } 288 rc = VERR_NO_MEMORY; 278 289 279 290 LogFlowFuncLeaveRC(rc); … … 282 293 283 294 /** 284 * Complete a request from VBox for the X11 clipboard data. The data should 285 * be written to the buffer provided in the initial request. 286 * @param pCtx request context information 287 * @param rc the completion status of the request 288 * @param pReq request 289 * @param pv address 290 * @param cb size 291 * 292 * @todo change this to deal with the buffer issues rather than offloading 293 * them onto the caller 294 */ 295 void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, 296 CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 297 { 298 if (cb <= pReq->cb && cb != 0) 299 memcpy(pReq->pv, pv, cb); 300 301 RTMemFree(pReq); 302 303 vboxSvcClipboardOldCompleteReadData(pCtx->pClient, rc, cb); 304 } 305 306 /** A request for clipboard data from VBox */ 307 struct _VBOXCLIPBOARDREQFROMVBOX 308 { 309 /** Data received */ 310 void *pv; 311 /** The size of the data */ 312 uint32_t cb; 313 /** Format of the data */ 314 uint32_t format; 315 /** A semaphore for waiting for the data */ 316 RTSEMEVENT finished; 317 }; 318 319 /** Wait for clipboard data requested from VBox to arrive. */ 320 static int clipWaitForDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx, 321 VBOXCLIPBOARDREQFROMVBOX *pReq, 322 uint32_t u32Format) 323 { 324 int rc = VINF_SUCCESS; 325 326 LogFlowFunc(("pCtx=%p, pReq=%p, u32Format=%02X\n", pCtx, pReq, u32Format)); 327 328 /* Request data from VBox */ 329 vboxSvcClipboardOldReportMsg(pCtx->pClient, 330 VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, 331 u32Format); 332 /* Which will signal us when it is ready. We use a timeout here 333 * because we can't be sure that the guest will behave correctly. 334 */ 335 rc = RTSemEventWait(pReq->finished, CLIPBOARD_TIMEOUT); 336 337 /* If the request hasn't yet completed then we cancel it. We use 338 * the critical section to prevent these operations colliding. */ 339 RTCritSectEnter(&pCtx->clipboardMutex); 340 341 /* The data may have arrived between the semaphore timing out and 342 * our grabbing the mutex. */ 343 if (rc == VERR_TIMEOUT && pReq->pv != NULL) 344 rc = VINF_SUCCESS; 345 if (pCtx->pReq == pReq) 346 pCtx->pReq = NULL; 347 Assert(pCtx->pReq == NULL); 348 349 RTCritSectLeave(&pCtx->clipboardMutex); 350 351 if (RT_SUCCESS(rc) && (pReq->pv == NULL)) 352 rc = VERR_NO_DATA; 295 * Called when writing guest clipboard data to the host service. 296 * 297 * @param pClient Context information about the guest VM. 298 * @param pCmdCtx Pointer to the clipboard command context. 299 * @param pData Data block to write to clipboard. 300 */ 301 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, 302 PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData) 303 { 304 LogFlowFunc(("pClient=%p, pv=%p, cb=%RU32, uFormat=%02X\n", 305 pClient, pData->pvData, pData->cbData, pData->uFormat)); 306 307 int rc = vboxSvcClipboardDataReadSignal(pClient, pCmdCtx, pData); 353 308 354 309 LogFlowFuncLeaveRC(rc); … … 356 311 } 357 312 358 /** Post a request for clipboard data to VBox/the guest and wait for it to be 359 * completed. */ 360 static int clipRequestDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx, VBOXCLIPBOARDREQFROMVBOX *pReq, uint32_t u32Format) 361 { 362 int rc = VINF_SUCCESS; 363 364 LogFlowFunc(("pCtx=%p, pReq=%p, u32Format=%02X\n", pCtx, pReq, u32Format)); 365 366 /* Start by "posting" the request for the next invocation of 367 * vboxClipboardWriteData. */ 368 RTCritSectEnter(&pCtx->clipboardMutex); 369 370 if (pCtx->pReq != NULL) 371 { 372 /* This would be a violation of the protocol, see the comments in the 373 * context structure definition. */ 374 Assert(false); 375 rc = VERR_WRONG_ORDER; 376 } 377 else 378 pCtx->pReq = pReq; 379 380 RTCritSectLeave(&pCtx->clipboardMutex); 381 382 if (RT_SUCCESS(rc)) 383 rc = clipWaitForDataFromVBox(pCtx, pReq, u32Format); 384 385 LogFlowFuncLeaveRC(rc); 386 return rc; 387 } 388 389 /** 390 * Send a request to VBox to transfer the contents of its clipboard to X11. 313 /** 314 * Completes a request from the host service for reading the X11 clipboard data. 315 * The data should be written to the buffer provided in the initial request. 316 * 317 * @param pCtx Request context information. 318 * @param rc The completion status of the request. 319 * @param pReq Request. 320 * @param pv Address. 321 * @param cb Size. 322 * 323 * @todo Change this to deal with the buffer issues rather than offloading them onto the caller. 324 */ 325 void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, 326 CLIPREADCBREQ *pReq, void *pv, uint32_t cb) 327 { 328 AssertMsgRC(rc, ("Clipboard data completion from X11 failed with %Rrc\n", rc)); 329 330 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload; 331 int rc2 = SharedClipboardPayloadAlloc(pReq->uEvent, pv, cb, &pPayload); 332 if (RT_SUCCESS(rc2)) 333 rc2 = SharedClipboardEventSignal(&pCtx->pClient->Events, pReq->uEvent, pPayload); 334 335 AssertRC(rc); 336 337 RTMemFree(pReq); 338 } 339 340 /** 341 * Reads clipboard data from the guest and passes it to the X11 clipboard. 391 342 * 392 343 * @param pCtx Pointer to the host clipboard structure … … 400 351 int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void **ppv, uint32_t *pcb) 401 352 { 402 VBOXCLIPBOARDREQFROMVBOX request = { NULL, 0, 0, NIL_RTSEMEVENT }; 403 404 LogFlowFunc(("pCtx=%p, u32Format=%02X, ppv=%p, pcb=%p\n", pCtx, u32Format, ppv, pcb)); 353 LogFlowFunc(("pCtx=%p, u32Format=%02X, ppv=%p\n", pCtx, u32Format, ppv)); 405 354 406 355 if (pCtx->fShuttingDown) 407 356 { 408 357 /* The shared clipboard is disconnecting. */ 409 LogRel((" Clipboard: Host requested guest clipboard data after guest had disconnected\n"));358 LogRel(("Shared Clipboard: Host requested guest clipboard data after guest had disconnected\n")); 410 359 return VERR_WRONG_ORDER; 411 360 } 412 361 413 int rc = RTSemEventCreate(&request.finished); 362 /* Request data from the guest. */ 363 SHAREDCLIPBOARDDATAREQ dataReq; 364 RT_ZERO(dataReq); 365 366 dataReq.uFmt = u32Format; 367 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 368 369 VBOXCLIPBOARDEVENTID uEvent; 370 int rc = vboxSvcClipboardDataReadRequest(pCtx->pClient, &dataReq, &uEvent); 414 371 if (RT_SUCCESS(rc)) 415 372 { 416 rc = clipRequestDataFromVBox(pCtx, &request, u32Format); 417 RTSemEventDestroy(request.finished); 418 } 419 420 if (RT_SUCCESS(rc)) 421 { 422 *ppv = request.pv; 423 *pcb = request.cb; 373 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload; 374 rc = SharedClipboardEventWait(&pCtx->pClient->Events, uEvent, 30 * 1000, &pPayload); 375 if (RT_SUCCESS(rc)) 376 { 377 *ppv = pPayload->pvData; 378 *pcb = pPayload->cbData; 379 380 /* Detach the payload, as the caller then will own the data. */ 381 SharedClipboardEventPayloadDetach(&pCtx->pClient->Events, uEvent); 382 } 383 384 SharedClipboardEventUnregister(&pCtx->pClient->Events, uEvent); 424 385 } 425 386 … … 428 389 } 429 390 430 /** 431 * Called when we have requested data from VBox and that data has arrived. 432 * 433 * @param pClient Context information about the guest VM. 434 * @param pCmdCtx Pointer to the clipboard command context. 435 * @param pData Data block to write to clipboard. 436 */ 437 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, 438 PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData) 439 { 440 RT_NOREF(pCmdCtx); 441 442 LogFlowFunc(("pClient=%p, pv=%p (%.*ls), cb=%u, uFormat=%02X\n", 443 pClient, pData->pvData, pData->cbData / 2, pData->pvData, pData->cbData, pData->uFormat)); 444 445 PVBOXCLIPBOARDCONTEXT pCtx = pClient->State.pCtx; 446 447 /* Grab the mutex and check whether there is a pending request for data. */ 448 RTCritSectEnter(&pCtx->clipboardMutex); 449 450 VBOXCLIPBOARDREQFROMVBOX *pReq = pCtx->pReq; 451 if (pReq != NULL) 452 { 453 if (pData->cbData > 0) 454 { 455 pReq->pv = RTMemDup(pData->pvData, pData->cbData); 456 if (pReq->pv != NULL) /* NULL may also mean no memory... */ 457 { 458 pReq->cb = pData->cbData; 459 pReq->format = pData->uFormat; 460 } 461 } 462 463 /* Signal that the request has been completed. */ 464 RTSemEventSignal(pReq->finished); 465 pCtx->pReq = NULL; 466 } 467 468 RTCritSectLeave(&pCtx->clipboardMutex); 469 391 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 392 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer) 393 { 394 RT_NOREF(pClient, pTransfer); 470 395 return VINF_SUCCESS; 471 396 } 472 397 473 #if 0 474 int VBoxClipboardSvcImplURIReadDir(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDDIRDATA pDirData) 475 { 476 RT_NOREF(pClient, pDirData); 477 return VERR_NOT_IMPLEMENTED; 478 } 479 480 int VBoxClipboardSvcImplURIWriteDir(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDDIRDATA pDirData) 481 { 482 RT_NOREF(pClient, pDirData); 483 return VERR_NOT_IMPLEMENTED; 484 } 485 486 int VBoxClipboardSvcImplURIReadFileHdr(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEHDR pFileHdr) 487 { 488 RT_NOREF(pClient, pFileHdr); 489 return VERR_NOT_IMPLEMENTED; 490 } 491 492 int VBoxClipboardSvcImplURIWriteFileHdr(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEHDR pFileHdr) 493 { 494 RT_NOREF(pClient, pFileHdr); 495 return VERR_NOT_IMPLEMENTED; 496 } 497 498 int VBoxClipboardSvcImplURIReadFileData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEDATA pFileData) 499 { 500 RT_NOREF(pClient, pFileData); 501 return VERR_NOT_IMPLEMENTED; 502 } 503 504 int VBoxClipboardSvcImplURIWriteFileData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDFILEDATA pFileData) 505 { 506 RT_NOREF(pClient, pFileData); 507 return VERR_NOT_IMPLEMENTED; 508 } 509 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */ 510 511 #ifdef TESTCASE 512 # include <iprt/initterm.h> 513 # include <iprt/stream.h> 514 515 # define TEST_NAME "tstClipboardX11-2" 516 517 struct _CLIPBACKEND 518 { 519 uint32_t formats; 520 struct _READDATA 521 { 522 uint32_t format; 523 int rc; 524 CLIPREADCBREQ *pReq; 525 } readData; 526 struct _COMPLETEREAD 527 { 528 int rc; 529 uint32_t cbActual; 530 } completeRead; 531 struct _WRITEDATA 532 { 533 void *pv; 534 uint32_t cb; 535 uint32_t format; 536 bool timeout; 537 } writeData; 538 struct _REPORTDATA 539 { 540 uint32_t format; 541 } reportData; 542 }; 543 544 int vboxSvcClipboardOldReportMsg(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t uFormats) 545 { 546 RT_NOREF(uFormats); 547 CLIPBACKEND *pBackend = pClient->State.pCtx->pBackend; 548 549 int rc; 550 551 if ( (uMsg == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA) 552 && !pBackend->writeData.timeout) 553 { 554 SHAREDCLIPBOARDDATABLOCK dataBlock; 555 RT_ZERO(dataBlock); 556 557 dataBlock.pvData = pBackend->writeData.pv; 558 dataBlock.cbData = pBackend->writeData.cb; 559 dataBlock.uFormat = pBackend->writeData.format; 560 561 rc = VBoxClipboardSvcImplWriteData(pClient, NULL /* pCmdCtx */, &dataBlock); 562 } 563 else 564 rc = VERR_NOT_SUPPORTED; 565 566 return rc; 567 } 568 569 int vboxSvcClipboardOldCompleteReadData(PVBOXCLIPBOARDCLIENT pClient, int rc, uint32_t cbActual) 570 { 571 CLIPBACKEND *pBackend = pClient->State.pCtx->pBackend; 572 pBackend->completeRead.rc = rc; 573 pBackend->completeRead.cbActual = cbActual; 574 398 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer) 399 { 400 RT_NOREF(pClient, pTransfer); 575 401 return VINF_SUCCESS; 576 402 } 577 578 CLIPBACKEND* ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend, bool) 579 { 580 RT_NOREF(pFrontend); 581 return (CLIPBACKEND *)RTMemAllocZ(sizeof(CLIPBACKEND)); 582 } 583 584 void ClipDestructX11(CLIPBACKEND *pBackend) 585 { 586 RTMemFree(pBackend); 587 } 588 589 int ClipStartX11(CLIPBACKEND *pBackend, bool) 590 { 591 RT_NOREF(pBackend); 592 return VINF_SUCCESS; 593 } 594 595 int ClipStopX11(CLIPBACKEND *pBackend) 596 { 597 RT_NOREF1(pBackend); 598 return VINF_SUCCESS; 599 } 600 601 int ClipAnnounceFormatToX11(CLIPBACKEND *pBackend, VBOXCLIPBOARDFORMATS vboxFormats) 602 { 603 pBackend->formats = vboxFormats; 604 return VINF_SUCCESS; 605 } 606 607 extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, VBOXCLIPBOARDFORMAT vboxFormat, 608 CLIPREADCBREQ *pReq) 609 { 610 pBackend->readData.format = vboxFormat; 611 pBackend->readData.pReq = pReq; 612 return pBackend->readData.rc; 613 } 614 615 int main() 616 { 617 VBOXCLIPBOARDCLIENT client; 618 unsigned cErrors = 0; 619 int rc = RTR3InitExeNoArguments(0); 620 RTPrintf(TEST_NAME ": TESTING\n"); 621 AssertRCReturn(rc, 1); 622 rc = VBoxClipboardSvcImplConnect(&client, false); 623 CLIPBACKEND *pBackend = client.State.pCtx->pBackend; 624 AssertRCReturn(rc, 1); 625 626 SHAREDCLIPBOARDFORMATDATA formatData; 627 RT_ZERO(formatData); 628 formatData.uFormats = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 629 630 VBoxClipboardSvcImplFormatAnnounce(&client, NULL /* pCmdCtx */, &formatData); 631 632 if (pBackend->formats != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 633 { 634 RTPrintf(TEST_NAME ": vboxClipboardFormatAnnounce failed with VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"); 635 ++cErrors; 636 } 637 pBackend->readData.rc = VINF_SUCCESS; 638 639 client.State.Old.asyncRead.callHandle = (VBOXHGCMCALLHANDLE)pBackend; 640 client.State.Old.asyncRead.paParms = (VBOXHGCMSVCPARM *)&client; 641 642 uint32_t u32Dummy; 643 644 SHAREDCLIPBOARDDATABLOCK dataBlock; 645 RT_ZERO(dataBlock); 646 dataBlock.pvData = &u32Dummy; 647 dataBlock.cbData = 42; 648 dataBlock.uFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 649 650 rc = VBoxClipboardSvcImplReadData(&client, NULL /* pCmdCtx */, &dataBlock, &u32Dummy); 651 if (rc != VINF_HGCM_ASYNC_EXECUTE) 652 { 653 RTPrintf(TEST_NAME ": vboxClipboardReadData returned %Rrc\n", rc); 654 ++cErrors; 655 } 656 else 657 { 658 if ( pBackend->readData.format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT 659 || pBackend->readData.pReq->pv != &u32Dummy 660 || pBackend->readData.pReq->cb != 42 661 || pBackend->readData.pReq->pcbActual != &u32Dummy) 662 { 663 RTPrintf(TEST_NAME ": format=%u, pReq->pv=%p, pReq->cb=%u, pReq->pcbActual=%p\n", 664 pBackend->readData.format, pBackend->readData.pReq->pv, 665 pBackend->readData.pReq->cb, 666 pBackend->readData.pReq->pcbActual); 667 ++cErrors; 668 } 669 else 670 { 671 ClipCompleteDataRequestFromX11(client.State.pCtx, VERR_NO_DATA, 672 pBackend->readData.pReq, NULL, 43); 673 if ( pBackend->completeRead.rc != VERR_NO_DATA 674 || pBackend->completeRead.cbActual != 43) 675 { 676 RTPrintf(TEST_NAME ": rc=%Rrc, cbActual=%u\n", 677 pBackend->completeRead.rc, 678 pBackend->completeRead.cbActual); 679 ++cErrors; 680 } 681 } 682 } 683 void *pv; 684 uint32_t cb; 685 pBackend->writeData.pv = (void *)"testing"; 686 pBackend->writeData.cb = sizeof("testing"); 687 pBackend->writeData.format = 1234; 688 pBackend->reportData.format = 4321; /* XX this should be handled! */ 689 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb); 690 if ( rc != VINF_SUCCESS 691 || strcmp((const char *)pv, "testing") != 0 692 || cb != sizeof("testing")) 693 { 694 RTPrintf("rc=%Rrc, pv=%p, cb=%u\n", rc, pv, cb); 695 ++cErrors; 696 } 697 else 698 RTMemFree(pv); 699 pBackend->writeData.timeout = true; 700 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb); 701 if (rc != VERR_TIMEOUT) 702 { 703 RTPrintf("rc=%Rrc, expected VERR_TIMEOUT\n", rc); 704 ++cErrors; 705 } 706 pBackend->writeData.pv = NULL; 707 pBackend->writeData.cb = 0; 708 pBackend->writeData.timeout = false; 709 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb); 710 if (rc != VERR_NO_DATA) 711 { 712 RTPrintf("rc=%Rrc, expected VERR_NO_DATA\n", rc); 713 ++cErrors; 714 } 715 /* Data arriving after a timeout should *not* cause any segfaults or 716 * memory leaks. Check with Valgrind! */ 717 RT_ZERO(dataBlock); 718 719 const char *pszString = "tested"; 720 721 dataBlock.pvData = (void *)pszString; 722 dataBlock.cbData = (uint32_t)(strlen(pszString) + 1); 723 dataBlock.uFormat = 999; 724 725 VBoxClipboardSvcImplWriteData(&client, NULL /* pCmdCtx */, &dataBlock); 726 727 VBoxClipboardSvcImplDisconnect(&client); 728 729 RTPrintf(TEST_NAME ": errors: %u\n", cErrors); 730 731 return cErrors > 0 ? 1 : 0; 732 } 733 #endif /* TESTCASE */ 734 403 #endif -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r80562 r80623 41 41 * There are currently four messages defined. The first is 42 42 * VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, which waits for a message from the 43 * host. Host messages currently defined are 44 * VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT (unused), 45 * VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA (request that the guest send the 46 * contents of its clipboard to the host) and 47 * VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS (to notify the guest that new 48 * clipboard data is available). If a host message is sent while the guest is 49 * not waiting, it will be queued until the guest requests it. At most one 50 * host message of each type will be kept in the queue. The host code only 51 * supports a single simultaneous VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG call 52 * from the guest. 43 * host. If a host message is sent while the guest is not waiting, it will be 44 * queued until the guest requests it. The host code only supports a single 45 * simultaneous VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG call from one guest. 53 46 * 54 47 * The second guest message is VBOX_SHARED_CLIPBOARD_FN_FORMATS, which tells … … 56 49 * VBOX_SHARED_CLIPBOARD_FN_READ_DATA, which asks the host to send its 57 50 * clipboard data and waits until it arrives. The host supports at most one 58 * simultaneous VBOX_SHARED_CLIPBOARD_FN_READ_DATA call from theguest - if a51 * simultaneous VBOX_SHARED_CLIPBOARD_FN_READ_DATA call from a guest - if a 59 52 * second call is made before the first has returned, the first will be 60 53 * aborted. … … 68 61 * 69 62 * The initial protocol implementation (called protocol v0) was very simple, 70 * and could only handle simple data (like copied text and so on). 63 * and could only handle simple data (like copied text and so on). It also 64 * was limited to two (2) fixed parameters at all times. 71 65 * 72 66 * Since VBox 6.1 a newer protocol (v1) has been established to also support 73 * file transfers. This protocol does not rely on the old ReportMsg() / ReturnMsg() 74 * mechanism anymore and uses a (per-client) message queue instead 67 * file transfers. This protocol uses a (per-client) message queue instead 75 68 * (see VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD vs. VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG). 76 69 * 77 70 * To distinguish the old (legacy) or new(er) protocol, the VBOX_SHARED_CLIPBOARD_GUEST_FN_CONNECT 78 71 * message has been introduced. If an older guest does not send this message, 79 * protocol v0 will be used by the host by default.72 * an appropriate translation will be done to serve older Guest Additions (< 6.1). 80 73 * 81 74 * The protocol also support out-of-order messages by using so-called "context IDs", … … 431 424 case VBOX_HGCM_SVC_PARM_PTR: paDstParms[i].u.uint32 = pMsg->m_paParms[i - 2].u.pointer.size; break; 432 425 } 426 } 427 428 /** 429 * Sets the VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD return parameters. 430 * 431 * This function does the necessary translation between the legacy protocol (v0) and the new protocols (>= v1), 432 * as messages are always stored as >= v1 messages in the message queue. 433 * 434 * @returns VBox status code. 435 * @param pMsg Message to set return parameters to. 436 * @param paDstParms The peek parameter vector. 437 * @param cDstParms The number of peek parameters (at least two). 438 */ 439 int vboxSvcClipboardMsgSetGetHostMsgOldReturn(PVBOXCLIPBOARDCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms) 440 { 441 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 442 AssertPtrReturn(paDstParms, VERR_INVALID_POINTER); 443 AssertReturn (cDstParms >= 2, VERR_INVALID_PARAMETER); 444 445 int rc = VINF_SUCCESS; 446 447 switch (pMsg->m_uMsg) 448 { 449 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT: 450 { 451 HGCMSvcSetU32(&paDstParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT); 452 HGCMSvcSetU32(&paDstParms[1], 0 /* Not used */); 453 break; 454 } 455 456 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA: 457 { 458 HGCMSvcSetU32(&paDstParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); 459 AssertBreakStmt(pMsg->m_cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */ 460 uint32_t uFmt; 461 rc = HGCMSvcGetU32(&pMsg->m_paParms[1] /* uFormat */, &uFmt); 462 if (RT_SUCCESS(rc)) 463 HGCMSvcSetU32(&paDstParms[1], uFmt); 464 break; 465 } 466 467 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT: 468 { 469 HGCMSvcSetU32(&paDstParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT); 470 AssertBreakStmt(pMsg->m_cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */ 471 uint32_t uFmts; 472 rc = HGCMSvcGetU32(&pMsg->m_paParms[1] /* uFormats */, &uFmts); 473 if (RT_SUCCESS(rc)) 474 HGCMSvcSetU32(&paDstParms[1], uFmts); 475 break; 476 } 477 478 default: 479 AssertFailed(); /* Not supported by legacy protocol. */ 480 rc = VERR_NOT_SUPPORTED; 481 break; 482 } 483 484 LogFlowFuncLeaveRC(rc); 485 return rc; 433 486 } 434 487 … … 549 602 LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->uClientID)); 550 603 return VINF_HGCM_ASYNC_EXECUTE; 604 } 605 606 /** 607 * Implements VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD. 608 * 609 * @returns VBox status code. 610 * @retval VINF_SUCCESS if a message was pending and is being returned. 611 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 612 * 613 * @param pClient The client state. 614 * @param hCall The client's call handle. 615 * @param cParms Number of parameters. 616 * @param paParms Array of parameters. 617 */ 618 int vboxSvcClipboardMsgGetOld(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 619 { 620 int rc; 621 622 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD) 623 { 624 rc = VERR_INVALID_PARAMETER; 625 } 626 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* msg */ 627 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT) /* formats */ 628 { 629 rc = VERR_INVALID_PARAMETER; 630 } 631 else 632 { 633 if (!pClient->queueMsg.isEmpty()) 634 { 635 PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->queueMsg.first(); 636 AssertPtr(pFirstMsg); 637 638 LogFlowFunc(("[Client %RU32] uMsg=%RU32 (%s), cParms=%RU32\n", 639 pClient->uClientID, pFirstMsg->m_uMsg, VBoxClipboardHostMsgToStr(pFirstMsg->m_uMsg), 640 pFirstMsg->m_cParms)); 641 642 rc = vboxSvcClipboardMsgSetGetHostMsgOldReturn(pFirstMsg, paParms, cParms); 643 if (RT_SUCCESS(rc)) 644 { 645 AssertPtr(g_pHelpers); 646 rc = g_pHelpers->pfnCallComplete(hCall, rc); 647 if (rc != VERR_CANCELLED) 648 { 649 pClient->queueMsg.removeFirst(); 650 vboxSvcClipboardMsgFree(pFirstMsg); 651 652 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 653 } 654 } 655 } 656 else 657 { 658 ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n", 659 pClient->uClientID), VERR_RESOURCE_BUSY); 660 661 pClient->Pending.hHandle = hCall; 662 pClient->Pending.cParms = cParms; 663 pClient->Pending.paParms = paParms; 664 pClient->Pending.uType = VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD; 665 666 rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 667 668 LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->uClientID)); 669 } 670 } 671 672 LogFlowFunc(("[Client %RU32] rc=%Rrc\n", pClient->uClientID, rc)); 673 return rc; 551 674 } 552 675 … … 676 799 } 677 800 801 /** 802 * Wakes up a pending client (i.e. waiting for new messages). 803 * 804 * @returns VBox status code. 805 * @retval VINF_NO_CHANGE if the client is not in pending mode. 806 * 807 * @param pClient Client to wake up. 808 */ 678 809 int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient) 679 810 { … … 682 813 if (pClient->Pending.uType) 683 814 { 684 LogF lowFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID));815 LogFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID)); 685 816 686 817 rc = VINF_SUCCESS; … … 691 822 if (pFirstMsg) 692 823 { 693 LogFlowFunc(("[Client %RU32] Current host message is %RU32 (%s), cParms=%RU32\n", 694 pClient->uClientID, pFirstMsg->m_uMsg, VBoxClipboardHostMsgToStr(pFirstMsg->m_uMsg), 695 pFirstMsg->m_cParms)); 824 LogFunc(("[Client %RU32] Current host message is %RU32 (%s), cParms=%RU32\n", 825 pClient->uClientID, pFirstMsg->m_uMsg, VBoxClipboardHostMsgToStr(pFirstMsg->m_uMsg), 826 pFirstMsg->m_cParms)); 827 828 bool fDonePending = false; 696 829 697 830 if (pClient->Pending.uType == VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT) 698 831 { 699 832 vboxSvcClipboardMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms); 833 fDonePending = true; 834 } 835 else if (pClient->Pending.uType == VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD) /* Legacy */ 836 { 837 rc = vboxSvcClipboardMsgSetGetHostMsgOldReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms); 838 if (RT_SUCCESS(rc)) 839 { 840 /* The old (legacy) protocol gets the message right when returning from peeking, so 841 * remove the actual message from our queue right now. */ 842 pClient->queueMsg.removeFirst(); 843 vboxSvcClipboardMsgFree(pFirstMsg); 844 845 fDonePending = true; 846 } 847 } 848 849 if (fDonePending) 850 { 700 851 rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS); 701 852 … … 703 854 pClient->Pending.paParms = NULL; 704 855 pClient->Pending.cParms = 0; 705 pClient->Pending.uType = false;856 pClient->Pending.uType = 0; 706 857 } 707 858 } … … 714 865 return rc; 715 866 } 867 else 868 LogFunc(("[Client %RU32] Not in pending state, skipping wakeup\n", pClient->uClientID)); 716 869 717 870 return VINF_NO_CHANGE; … … 719 872 720 873 /** 721 * Set the HGCM parameters according to pending messages. 722 * Executed under the clipboard lock. 723 * 724 * Legacy protocol, do not use anymore. 874 * Requests to read clipboard data from the guest. 875 * 876 * @returns VBox status code. 877 * @param pClient Client to request to read data form. 878 * @param pDataReq Data request to send to the guest. 879 * @param puEvent Event ID for waiting for new data. Optional. 725 880 */ 726 static bool vboxSvcClipboardOldReturnMsg(PVBOXCLIPBOARDCLIENT pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 727 { 728 /** @todo r=andy The client at the moment supplies two parameters, which we can 729 * use by filling in the next message type sent by the host service. 730 * Make this more flexible later, as I don't want to break the existing protocol right now. */ 731 if (cParms < 2) 732 { 733 AssertFailed(); /* Should never happen. */ 734 return false; 735 } 736 737 /* Message priority is taken into account. */ 738 if (pClient->State.Old.fHostMsgQuit) 739 { 740 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT\n")); 741 HGCMSvcSetU32(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT); 742 HGCMSvcSetU32(&paParms[1], 0); 743 pClient->State.Old.fHostMsgQuit = false; 744 } 745 else if (pClient->State.Old.fHostMsgReadData) 746 { 747 uint32_t fFormat = 0; 748 749 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA: u32RequestedFormat=%02X\n", 750 pClient->State.Old.u32RequestedFormat)); 751 752 if (pClient->State.Old.u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 753 fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 754 else if (pClient->State.Old.u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 755 fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 756 else if (pClient->State.Old.u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML) 757 fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML; 758 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 759 else if (pClient->State.Old.u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 760 fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST; 761 #endif 762 else 763 { 764 LogRel2(("Clipboard: Unsupported format from guest (0x%x), skipping\n", fFormat)); 765 pClient->State.Old.u32RequestedFormat = 0; 766 } 767 pClient->State.Old.u32RequestedFormat &= ~fFormat; 768 HGCMSvcSetU32(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA); 769 HGCMSvcSetU32(&paParms[1], fFormat); 770 if (pClient->State.Old.u32RequestedFormat == 0) 771 pClient->State.Old.fHostMsgReadData = false; 772 } 773 else if (pClient->State.Old.fHostMsgFormats) 774 { 775 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS: u32AvailableFormats=%02X\n", 776 pClient->State.Old.u32AvailableFormats)); 777 778 HGCMSvcSetU32(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE); 779 HGCMSvcSetU32(&paParms[1], pClient->State.Old.u32AvailableFormats); 780 pClient->State.Old.fHostMsgFormats = false; 881 int vboxSvcClipboardDataReadRequest(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDDATAREQ pDataReq, 882 PVBOXCLIPBOARDEVENTID puEvent) 883 { 884 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 885 AssertPtrReturn(pDataReq, VERR_INVALID_POINTER); 886 /* puEvent is optional. */ 887 888 int rc; 889 890 PVBOXCLIPBOARDCLIENTMSG pMsgReadData = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, 891 VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA); 892 if (pMsgReadData) 893 { 894 const VBOXCLIPBOARDEVENTID uEvent = SharedClipboardEventIDGenerate(&pClient->Events); 895 896 HGCMSvcSetU32(&pMsgReadData->m_paParms[0], VBOX_SHARED_CLIPBOARD_CONTEXTID_MAKE(pClient->Events.uID, uEvent)); 897 HGCMSvcSetU32(&pMsgReadData->m_paParms[1], pDataReq->uFmt); 898 HGCMSvcSetU32(&pMsgReadData->m_paParms[2], pClient->State.cbChunkSize); 899 900 rc = vboxSvcClipboardMsgAdd(pClient, pMsgReadData, true /* fAppend */); 901 if (RT_SUCCESS(rc)) 902 { 903 rc = SharedClipboardEventRegister(&pClient->Events, uEvent); 904 if (RT_SUCCESS(rc)) 905 { 906 rc = vboxSvcClipboardClientWakeup(pClient); 907 if (RT_SUCCESS(rc)) 908 { 909 if (puEvent) 910 *puEvent = uEvent; 911 } 912 else 913 SharedClipboardEventUnregister(&pClient->Events, uEvent); 914 } 915 } 781 916 } 782 917 else 783 { 784 /* No pending messages. */ 785 LogFlowFunc(("No pending message\n")); 786 return false; 787 } 788 789 /* Message information assigned. */ 790 return true; 791 } 792 793 int vboxSvcClipboardSendFormatsWrite(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats) 794 { 795 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 918 rc = VERR_NO_MEMORY; 919 920 LogFlowFuncLeaveRC(rc); 921 return rc; 922 } 923 924 int vboxSvcClipboardDataReadSignal(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, 925 PSHAREDCLIPBOARDDATABLOCK pData) 926 { 927 VBOXCLIPBOARDEVENTID uEvent; 928 if (pClient->State.uProtocolVer == 0) 929 { 930 /* Protocol v0 did not have any context ID handling, so we ASSUME that the last event registered 931 * is the one we want to handle (as this all was a synchronous protocol anyway). */ 932 uEvent = SharedClipboardEventGetLast(&pClient->Events); 933 } 934 else 935 uEvent = VBOX_SHARED_CLIPBOARD_CONTEXTID_GET_EVENT(pCmdCtx->uContextID); 936 937 int rc = VINF_SUCCESS; 938 939 PSHAREDCLIPBOARDEVENTPAYLOAD pPayload = NULL; 940 if (pData->cbData) 941 rc = SharedClipboardPayloadAlloc(uEvent, pData->pvData, pData->cbData, &pPayload); 942 943 if (RT_SUCCESS(rc)) 944 { 945 rc = SharedClipboardEventSignal(&pClient->Events, uEvent, pPayload); 946 if (RT_FAILURE(rc)) 947 SharedClipboardPayloadFree(pPayload); 948 } 949 950 LogFlowFuncLeaveRC(rc); 951 return rc; 952 } 953 954 int vboxSvcClipboardFormatsReport(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats) 955 { 956 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 957 AssertPtrReturn(pFormats, VERR_INVALID_POINTER); 796 958 797 959 int rc; 798 960 799 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_ WRITE, 3);961 PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT, 3); 800 962 if (pMsg) 801 963 { … … 808 970 rc = vboxSvcClipboardMsgAdd(pClient, pMsg, true /* fAppend */); 809 971 if (RT_SUCCESS(rc)) 810 {811 972 rc = vboxSvcClipboardClientWakeup(pClient); 812 }813 973 } 814 974 else … … 900 1060 return rc; 901 1061 } 902 903 /**904 * Reports a cached message back to the guest.905 *906 * Legacy protocol, do not use anymore.907 */908 int vboxSvcClipboardOldReportMsg(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t uFormats)909 {910 AssertPtrReturn(pClient, VERR_INVALID_POINTER);911 912 int rc = VINF_SUCCESS;913 914 LogFlowFunc(("uMsg=%RU32 (%s), fIsAsync=%RTbool\n",915 uMsg, VBoxClipboardHostMsgToStr(uMsg), pClient->State.Old.fAsync));916 917 if (VBoxSvcClipboardLock())918 {919 switch (uMsg)920 {921 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:922 {923 pClient->State.Old.fHostMsgQuit = true;924 } break;925 926 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:927 {928 if ( vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST929 && vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)930 {931 /* Skip the message. */932 break;933 }934 935 LogFlowFunc(("uFormats=%02X\n", uFormats));936 937 pClient->State.Old.u32RequestedFormat = uFormats;938 pClient->State.Old.fHostMsgReadData = true;939 } break;940 941 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:942 {943 if ( vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST944 && vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)945 {946 /* Skip the message. */947 break;948 }949 950 LogFlowFunc(("uFormats=%02X\n", uFormats));951 952 pClient->State.Old.u32AvailableFormats = uFormats;953 pClient->State.Old.fHostMsgFormats = true;954 } break;955 956 default:957 {958 AssertMsgFailed(("Invalid message %RU32\n", uMsg));959 rc = VERR_INVALID_PARAMETER;960 break;961 }962 }963 964 if (RT_SUCCESS(rc))965 {966 if (pClient->State.Old.fAsync)967 {968 /* The client waits for a response. */969 bool fMessageReturned = vboxSvcClipboardOldReturnMsg(pClient,970 pClient->State.Old.async.cParms,971 pClient->State.Old.async.paParms);972 973 /* Make a copy of the handle. */974 VBOXHGCMCALLHANDLE callHandle = pClient->State.Old.async.callHandle;975 976 if (fMessageReturned)977 {978 /* There is a response. */979 pClient->State.Old.fAsync = false;980 }981 982 VBoxSvcClipboardUnlock();983 984 if (fMessageReturned)985 {986 LogFlowFunc(("CallComplete\n"));987 g_pHelpers->pfnCallComplete(callHandle, VINF_SUCCESS);988 }989 }990 else991 VBoxSvcClipboardUnlock();992 }993 else994 VBoxSvcClipboardUnlock();995 }996 997 LogFlowFuncLeaveRC(rc);998 return rc;999 }1000 1001 1062 1002 1063 int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENT pClient, SHAREDCLIPBOARDSOURCE enmSource) … … 1143 1204 } 1144 1205 1145 /**1146 * Disconnect the host side of the shared clipboard and send a "host disconnected" message1147 * to the guest side.1148 */1149 1206 static DECLCALLBACK(int) svcDisconnect(void *, uint32_t u32ClientID, void *pvClient) 1150 1207 { … … 1155 1212 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient; 1156 1213 AssertPtr(pClient); 1157 1158 vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0); /** @todo r=andy Why is this necessary? The client already disconnected ... */1159 vboxSvcClipboardOldCompleteReadData(pClient, VERR_NO_DATA, 0);1160 1214 1161 1215 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST … … 1171 1225 vboxSvcClipboardClientStateReset(&pClient->State); 1172 1226 vboxSvcClipboardClientStateDestroy(&pClient->State); 1227 1228 SharedClipboardEventSourceDestroy(&pClient->Events); 1173 1229 1174 1230 ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID); … … 1262 1318 #endif 1263 1319 1264 bool fD efer = false;1320 bool fDoCallComplete = true; 1265 1321 1266 1322 switch (u32Function) … … 1268 1324 case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD: 1269 1325 { 1270 if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD) 1271 { 1272 rc = VERR_INVALID_PARAMETER; 1273 } 1274 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* msg */ 1275 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT) /* formats */ 1276 { 1277 rc = VERR_INVALID_PARAMETER; 1278 } 1279 else 1280 { 1281 /* Atomically verify the client's state. */ 1282 if (VBoxSvcClipboardLock()) 1283 { 1284 bool fMessageReturned = vboxSvcClipboardOldReturnMsg(pClient, cParms, paParms); 1285 if (fMessageReturned) 1286 { 1287 /* Just return to the caller. */ 1288 pClient->State.Old.fAsync = false; 1289 } 1290 else 1291 { 1292 /* No event available at the time. Process asynchronously. */ 1293 fDefer = true; 1294 1295 pClient->State.Old.fAsync = true; 1296 pClient->State.Old.async.callHandle = callHandle; 1297 pClient->State.Old.async.cParms = cParms; 1298 pClient->State.Old.async.paParms = paParms; 1299 } 1300 1301 VBoxSvcClipboardUnlock(); 1302 } 1303 else 1304 { 1305 rc = VERR_NOT_SUPPORTED; 1306 } 1307 } 1308 1326 rc = vboxSvcClipboardMsgGetOld(pClient, callHandle, cParms, paParms); 1327 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1328 fDoCallComplete = false; 1309 1329 break; 1310 1330 } … … 1357 1377 rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/); 1358 1378 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1359 fD efer = true;1379 fDoCallComplete = false; 1360 1380 break; 1361 1381 } … … 1364 1384 { 1365 1385 rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms); 1366 if ( RT_SUCCESS(rc)) /* vboxSvcClipboardMsgGet did the completion already. */1367 fD efer = true;1386 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1387 fDoCallComplete = false; 1368 1388 break; 1369 1389 } 1370 1390 1371 case VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_ WRITE:1391 case VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT: 1372 1392 { 1373 1393 uint32_t uFormats = 0; … … 1468 1488 } 1469 1489 1470 uint32_t u 32Format;1471 rc = HGCMSvcGetU32(&paParms[0], &u 32Format);1490 uint32_t uFormat; 1491 rc = HGCMSvcGetU32(&paParms[0], &uFormat); 1472 1492 if (RT_SUCCESS(rc)) 1473 1493 { 1474 1494 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1475 if (u 32Format == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)1495 if (uFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST) 1476 1496 { 1477 1497 if (!SharedClipboardURICtxTransfersMaximumReached(&pClient->URI)) … … 1540 1560 RT_ZERO(parms); 1541 1561 1542 parms.uFormat = u 32Format;1562 parms.uFormat = uFormat; 1543 1563 parms.u.pvData = pv; 1544 1564 parms.cbData = cb; … … 1557 1577 if (g_ExtState.fDelayedAnnouncement) 1558 1578 { 1559 vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, 1560 g_ExtState.uDelayedFormats); 1579 SHAREDCLIPBOARDFORMATDATA formatData; 1580 RT_ZERO(formatData); 1581 1582 formatData.uFormats = g_ExtState.uDelayedFormats; 1583 1584 int rc2 = vboxSvcClipboardFormatsReport(pClient, &formatData); 1585 AssertRC(rc2); 1561 1586 1562 1587 g_ExtState.fDelayedAnnouncement = false; … … 1575 1600 * so data which has been read above might get overridden by the host clipboard eventually. */ 1576 1601 1602 VBOXCLIPBOARDCLIENTCMDCTX cmdCtx; 1603 RT_ZERO(cmdCtx); 1604 1577 1605 /* Release any other pending read, as we only 1578 1606 * support one pending read at one time. */ 1579 rc = vboxSvcClipboardOldCompleteReadData(pClient, VERR_NO_DATA, 0);1580 1607 if (RT_SUCCESS(rc)) 1581 1608 { 1582 VBOXCLIPBOARDCLIENTCMDCTX cmdCtx;1583 RT_ZERO(cmdCtx);1584 1585 1609 SHAREDCLIPBOARDDATABLOCK dataBlock; 1586 1610 RT_ZERO(dataBlock); … … 1588 1612 dataBlock.pvData = pv; 1589 1613 dataBlock.cbData = cb; 1590 dataBlock.uFormat = u 32Format;1614 dataBlock.uFormat = uFormat; 1591 1615 1592 1616 rc = VBoxClipboardSvcImplReadData(pClient, &cmdCtx, &dataBlock, &cbActual); 1593 } 1594 1595 /* 1596 * Remember our read request until it is completed. 1597 * See the protocol description above for more information. 1598 */ 1599 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1600 { 1601 if (VBoxSvcClipboardLock()) 1602 { 1603 pClient->State.Old.asyncRead.callHandle = callHandle; 1604 pClient->State.Old.asyncRead.cParms = cParms; 1605 pClient->State.Old.asyncRead.paParms = paParms; 1606 pClient->State.Old.fReadPending = true; 1607 fDefer = true; 1608 VBoxSvcClipboardUnlock(); 1609 } 1610 else 1611 rc = VERR_NOT_SUPPORTED; 1612 } 1613 else if (RT_SUCCESS (rc)) 1614 { 1615 HGCMSvcSetU32(&paParms[2], cbActual); 1617 if (RT_SUCCESS(rc)) 1618 HGCMSvcSetU32(&paParms[2], cbActual); 1616 1619 } 1617 1620 } … … 1635 1638 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST 1636 1639 rc = vboxSvcClipboardURIHandler(pClient, callHandle, u32Function, cParms, paParms, tsArrival); 1637 1638 /* The URI handler does deferring on its own, so never do any call completion here. */1639 fDefer = true;1640 1640 #else 1641 1641 rc = VERR_NOT_IMPLEMENTED; … … 1645 1645 } 1646 1646 1647 LogFlowFunc(("u32ClientID=%RU32, fD efer=%RTbool\n", pClient->uClientID, fDefer));1648 1649 if ( !fDefer)1647 LogFlowFunc(("u32ClientID=%RU32, fDoCallComplete=%RTbool, rc=%Rrc\n", pClient->uClientID, fDoCallComplete, rc)); 1648 1649 if (fDoCallComplete) 1650 1650 g_pHelpers->pfnCallComplete(callHandle, rc); 1651 1651 1652 1652 LogFlowFuncLeaveRC(rc); 1653 }1654 1655 /** If the client in the guest is waiting for a read operation to complete1656 * then complete it, otherwise return. See the protocol description in the1657 * shared clipboard module description. */1658 int vboxSvcClipboardOldCompleteReadData(PVBOXCLIPBOARDCLIENT pClient, int rc, uint32_t cbActual)1659 {1660 VBOXHGCMCALLHANDLE callHandle = NULL;1661 VBOXHGCMSVCPARM *paParms = NULL;1662 bool fReadPending = false;1663 if (VBoxSvcClipboardLock()) /* if not can we do anything useful? */1664 {1665 callHandle = pClient->State.Old.asyncRead.callHandle;1666 paParms = pClient->State.Old.asyncRead.paParms;1667 fReadPending = pClient->State.Old.fReadPending;1668 pClient->State.Old.fReadPending = false;1669 VBoxSvcClipboardUnlock();1670 }1671 if (fReadPending)1672 {1673 HGCMSvcSetU32(&paParms[2], cbActual);1674 g_pHelpers->pfnCallComplete(callHandle, rc);1675 }1676 1677 return VINF_SUCCESS;1678 1653 } 1679 1654 … … 1715 1690 1716 1691 /** 1717 * Resets the Shared Clipboard data reading porition of the old client state.1718 *1719 * Legacy protocol, do not use anymore.1720 *1721 * @param pClientState Client state to reset data reading portion for.1722 */1723 void vboxSvcClipboardOldClientStateResetData(PVBOXCLIPBOARDCLIENTSTATE pClientState)1724 {1725 if (pClientState->Old.data.pv)1726 {1727 RTMemFree(pClientState->Old.data.pv);1728 pClientState->Old.data.pv = NULL;1729 }1730 1731 pClientState->Old.data.cb = 0;1732 pClientState->Old.data.u32Format = 0;1733 }1734 1735 /**1736 * Resets a Shared Clipboard service's old client state.1737 * Legacy protocol, do not use anymore.1738 *1739 * @param pClientState Client state to reset.1740 */1741 void vboxSvcClipboardOldClientStateReset(PVBOXCLIPBOARDCLIENTSTATE pClientState)1742 {1743 LogFlowFuncEnter();1744 1745 pClientState->Old.fAsync = false;1746 pClientState->Old.fReadPending = false;1747 1748 pClientState->Old.fHostMsgQuit = false;1749 pClientState->Old.fHostMsgReadData = false;1750 pClientState->Old.fHostMsgFormats = false;1751 1752 pClientState->Old.u32AvailableFormats = 0;1753 pClientState->Old.u32RequestedFormat = 0;1754 1755 vboxSvcClipboardOldClientStateResetData(pClientState);1756 }1757 1758 /**1759 1692 * Resets a Shared Clipboard service's client state. 1760 1693 * … … 1769 1702 pClientState->URI.enmTransferDir = SHAREDCLIPBOARDURITRANSFERDIR_UNKNOWN; 1770 1703 #endif 1771 1772 vboxSvcClipboardOldClientStateReset(pClientState);1773 1704 } 1774 1705 … … 1840 1771 } 1841 1772 1842 #ifndef UNIT_TEST1843 1773 /** 1844 * SSM descriptor table for the VBOXCLIPBOARDCLIENTDATA structure. 1774 * SSM descriptor table for the VBOXCLIPBOARDCLIENTSTATEOLD structure. 1775 * Legacy, do not use anymore. 1845 1776 */ 1846 static SSMFIELD const g_aClipboard ClientDataFields[] =1847 { 1848 SSMFIELD_ENTRY (VBOXCLIPBOARDCLIENTSTATE, u32ClientID), /* for validation purposes */1849 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATE , Old.fHostMsgQuit),1850 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATE , Old.fHostMsgReadData),1851 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATE , Old.fHostMsgFormats),1852 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATE , Old.u32RequestedFormat),1777 static SSMFIELD const g_aClipboardSSMFieldsV0[] = 1778 { 1779 SSMFIELD_ENTRY_OLD(uClientID, sizeof(uint32_t)), 1780 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATEOLD, fHostMsgQuit), 1781 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATEOLD, fHostMsgReadData), 1782 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATEOLD, fHostMsgFormats), 1783 SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTSTATEOLD, u32RequestedFormat), 1853 1784 SSMFIELD_ENTRY_TERM() 1854 1785 }; 1855 #endif1856 1786 1857 1787 static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM) … … 1868 1798 LogFunc(("u32ClientID=%RU32\n", u32ClientID)); 1869 1799 1870 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient; 1800 //PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient; 1801 RT_NOREF(pvClient); 1871 1802 1872 1803 /* This field used to be the length. We're using it as a version field 1873 1804 with the high bit set. */ 1874 1805 SSMR3PutU32(pSSM, UINT32_C(0x80000002)); 1875 int rc = SSMR3PutStructEx(pSSM, &pClient->State, sizeof(pClient->State), 1876 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL); 1806 1807 VBOXCLIPBOARDCLIENTSTATEOLD Dummy; 1808 RT_ZERO(Dummy); 1809 1810 int rc = SSMR3PutStructEx(pSSM, &Dummy, sizeof(Dummy), 1811 0 /*fFlags*/, &g_aClipboardSSMFieldsV0[0], NULL); 1877 1812 AssertRCReturn(rc, rc); 1878 1813 … … 1892 1827 PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient; 1893 1828 AssertPtr(pClient); 1894 1895 /* Existing client can not be in async state yet. */1896 Assert(!pClient->State.Old.fAsync);1897 1829 1898 1830 /* Save the client ID for data validation. */ … … 1906 1838 if (lenOrVer == UINT32_C(0x80000002)) 1907 1839 { 1908 rc = SSMR3GetStructEx(pSSM, &pClient->State, sizeof(pClient->State), 1909 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL); 1840 uint32_t uMarker; 1841 rc = SSMR3GetU32(pSSM, &uMarker); /* Begin marker. */ 1842 AssertRC(rc); 1843 Assert(uMarker == UINT32_C(0x19200102) /* SSMR3STRUCT_BEGIN */); 1844 1845 rc = SSMR3Skip(pSSM, sizeof(uint32_t) + (3 * sizeof(bool)) + sizeof(uint32_t)); 1910 1846 AssertRCReturn(rc, rc); 1847 1848 rc = SSMR3GetU32(pSSM, &uMarker); /* End marker. */ 1849 AssertRC(rc); 1850 Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */); 1911 1851 } 1912 1852 else … … 1927 1867 VBoxClipboardSvcImplSync(pClient); 1928 1868 1929 #else /* UNIT_TEST */1869 #else /* UNIT_TEST */ 1930 1870 RT_NOREF(u32ClientID, pvClient, pSSM, uVersion); 1931 1871 #endif /* UNIT_TEST */ … … 1961 1901 else 1962 1902 { 1963 rc = vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, u32Format); 1903 SHAREDCLIPBOARDFORMATDATA formatData; 1904 RT_ZERO(formatData); 1905 1906 formatData.uFormats = u32Format; 1907 1908 rc = vboxSvcClipboardFormatsReport(pClient, &formatData); 1964 1909 } 1965 1910 … … 1970 1915 case VBOX_CLIPBOARD_EXT_FN_DATA_READ: 1971 1916 { 1972 rc = vboxSvcClipboardOldReportMsg(pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format); 1917 SHAREDCLIPBOARDDATAREQ dataReq; 1918 RT_ZERO(dataReq); 1919 1920 dataReq.uFmt = u32Format; 1921 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */ 1922 1923 rc = vboxSvcClipboardDataReadRequest(pClient, &dataReq, NULL /* puEvent */); 1973 1924 break; 1974 1925 } … … 2016 1967 } 2017 1968 2018 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *p table)1969 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable) 2019 1970 { 2020 1971 int rc = VINF_SUCCESS; 2021 1972 2022 LogFlowFunc(("ptable=%p\n", p table));2023 2024 if (!p table)1973 LogFlowFunc(("ptable=%p\n", pTable)); 1974 1975 if (!pTable) 2025 1976 { 2026 1977 rc = VERR_INVALID_PARAMETER; … … 2028 1979 else 2029 1980 { 2030 LogFunc(("ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", p table->cbSize, ptable->u32Version));2031 2032 if ( p table->cbSize != sizeof (VBOXHGCMSVCFNTABLE)2033 || p table->u32Version != VBOX_HGCM_SVC_VERSION)1981 LogFunc(("ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", pTable->cbSize, pTable->u32Version)); 1982 1983 if ( pTable->cbSize != sizeof (VBOXHGCMSVCFNTABLE) 1984 || pTable->u32Version != VBOX_HGCM_SVC_VERSION) 2034 1985 { 2035 1986 rc = VERR_INVALID_PARAMETER; … … 2037 1988 else 2038 1989 { 2039 g_pHelpers = p table->pHelpers;2040 2041 p table->cbClient = sizeof(VBOXCLIPBOARDCLIENT);2042 2043 p table->pfnUnload = svcUnload;2044 p table->pfnConnect = svcConnect;2045 p table->pfnDisconnect = svcDisconnect;2046 p table->pfnCall = svcCall;2047 p table->pfnHostCall = svcHostCall;2048 p table->pfnSaveState = svcSaveState;2049 p table->pfnLoadState = svcLoadState;2050 p table->pfnRegisterExtension = svcRegisterExtension;2051 p table->pfnNotify = NULL;2052 p table->pvService = NULL;1990 g_pHelpers = pTable->pHelpers; 1991 1992 pTable->cbClient = sizeof(VBOXCLIPBOARDCLIENT); 1993 1994 pTable->pfnUnload = svcUnload; 1995 pTable->pfnConnect = svcConnect; 1996 pTable->pfnDisconnect = svcDisconnect; 1997 pTable->pfnCall = svcCall; 1998 pTable->pfnHostCall = svcHostCall; 1999 pTable->pfnSaveState = svcSaveState; 2000 pTable->pfnLoadState = svcLoadState; 2001 pTable->pfnRegisterExtension = svcRegisterExtension; 2002 pTable->pfnNotify = NULL; 2003 pTable->pvService = NULL; 2053 2004 2054 2005 /* Service specific initialization. */ -
trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp
r80446 r80623 97 97 } 98 98 99 #if 0 /* Disabled for now. */ 99 100 static void testGetHostMsg(void) 100 101 { … … 198 199 table.pfnUnload(NULL); 199 200 } 201 #endif 200 202 201 203 static void testSetHeadless(void) … … 267 269 */ 268 270 testHostCall(); 269 testGetHostMsg();271 /* testGetHostMsg(); Disabled */ 270 272 271 273 /* -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r79347 r80623 252 252 { 253 253 #ifdef DEBUG_andy 254 uMaxClipboardAreas = ULONG_MAX;254 uMaxClipboardAreas = 9999; 255 255 #endif 256 256 int rc2 = RTCritSectInit(&CritSect);
Note:
See TracChangeset
for help on using the changeset viewer.