VirtualBox

Changeset 80623 in vbox for trunk/src


Ignore:
Timestamp:
Sep 6, 2019 10:05:11 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133152
Message:

Shared Clipboard: Removed old protocol handling cruft on the host side and added message translation support for serving older Guest Additions. Updated docs / protocol changelog.

Location:
trunk/src/VBox
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r80444 r80623  
    702702           HANDLE hClip = NULL;
    703703
    704            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: uFormat=0x%x\n", uFormat));
     704           LogFlowFunc(("VBOX_CLIPBOARD_WM_READ_DATA: uFormat=0x%x\n", uFormat));
    705705
    706706           int rc = VBoxClipboardWinOpen(hwnd);
     
    844844
    845845                   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));
    847847               }
    848848#endif
     
    850850               if (hClip == NULL)
    851851               {
    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()));
    853853
    854854                   /* Requested clipboard format is not available, send empty data. */
     
    12221222                switch (uMsg)
    12231223                {
    1224                     case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:
     1224                    case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT:
    12251225                    {
    12261226                        pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS;
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp

    r80450 r80623  
    168168                           VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, 3);
    169169
    170         Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE);
     170        Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT);
    171171        Msg.uFormats.SetUInt32(0);
    172172        Msg.fFlags.SetUInt32(0);
     
    14771477        switch (uMsg)
    14781478        {
    1479             case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:
     1479            case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT:
    14801480            {
    14811481                rc = VbglR3ClipboardFormatsWriteRecv(&pEvent->cmdCtx, &pEvent->u.ReportFormats);
     
    16491649    if (pCtx->uProtocolVer == 0)
    16501650    {
    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);
    16521652        VbglHGCMParmUInt32Set(&Msg.uFormats, pFormats->uFormats);
    16531653    }
    16541654    else
    16551655    {
    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);
    16571657
    16581658        Msg.uContext.SetUInt32(pCtx->uContextID);
     
    16801680    VBoxClipboardFormatsMsg Msg;
    16811681
    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);
    16831683    VbglHGCMParmUInt32Set(&Msg.uFormats, fFormats);
    16841684
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceClipboard-os2.cpp

    r80444 r80623  
    775775         * Listener message - the host has new formats to offer.
    776776         */
    777         case WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:
     777        case WM_USER + VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT:
    778778            vgsvcClipboardOs2AdvertiseHostFormats(LONGFROMMP(mp1));
    779779            break;
     
    895895                         * respond do WM_RENDERFORMAT message.
    896896                         */
    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,
    899899                                            MPFROMLONG(fFormats), 0))
    900900                                VGSvcError("WinPostMsg(%lx, FORMATS,,) failed, lasterr=%#lx\n",
  • trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.cpp

    r80444 r80623  
    380380            switch (u32Msg)
    381381            {
    382                 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:
     382                case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT:
    383383                {
    384384                    /*
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp

    r80444 r80623  
    166166 * @param  cb        the size of the data in @a pv
    167167 */
    168 void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
     168void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
    169169{
    170170    RT_NOREF1(pCtx);
     
    192192        rc = VERR_NO_MEMORY;
    193193    if (RT_SUCCESS(rc))
    194         rc = ClipStartX11(g_ctx.pBackend);
     194        rc = ClipStartX11(g_ctx.pBackend, false /* grab */);
    195195    if (RT_SUCCESS(rc))
    196196    {
     
    229229            switch (Msg)
    230230            {
    231                 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE:
     231                case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT:
    232232                {
    233233                    /* The host has announced available clipboard formats.
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp

    r80468 r80623  
    183183        RTMemFree(pEvIt);
    184184    }
     185
     186    pSource->uID          = 0;
     187    pSource->uEventIDNext = 0;
    185188}
    186189
     
    216219
    217220    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 */
     229VBOXCLIPBOARDEVENTID 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;
    218237}
    219238
     
    281300        LogFlowFunc(("Event %RU16\n", pEvent->uID));
    282301
     302        RTListNodeRemove(&pEvent->Node);
     303
    283304        SharedClipboardEventDestroy(pEvent);
     305
    284306        RTMemFree(pEvent);
    285 
    286         RTListNodeRemove(&pEvent->Node);
     307        pEvent = NULL;
    287308
    288309        rc = VINF_SUCCESS;
     
    290311    else
    291312        rc = VERR_NOT_FOUND;
    292 
    293     AssertRC(rc);
    294313
    295314    LogFlowFuncLeaveRC(rc);
     
    362381    else
    363382        rc = VERR_NOT_FOUND;
    364 
    365 #ifdef DEBUG_andy
    366     AssertRC(rc);
    367 #endif
    368383
    369384    LogFlowFuncLeaveRC(rc);
     
    787802        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
    788803        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);
    790805        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
    791806        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_READ);
     
    820835    {
    821836        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);
    823838        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_READ);
    824839        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_WRITE);
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp

    r80444 r80623  
    18931893    else
    18941894        rc = VERR_NOT_IMPLEMENTED;
    1895     ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,
    1896                                    pvDest, cbDest);
     1895    ClipRequestFromX11CompleteCallback(pReq->mCtx->pFrontend, rc, pReq->mReq,
     1896                                       pvDest, cbDest);
    18971897    RTMemFree(pvDest);
    18981898    RTMemFree(pReq);
     
    20102010        /* The clipboard callback was never scheduled, so we must signal
    20112011         * that the request processing is finished and clean up ourselves. */
    2012         ClipCompleteDataRequestFromX11(pReq->mCtx->pFrontend, rc, pReq->mReq,
    2013                                        NULL, 0);
     2012        ClipRequestFromX11CompleteCallback(pReq->mCtx->pFrontend, rc, pReq->mReq,
     2013                                           NULL, 0);
    20142014        RTMemFree(pReq);
    20152015    }
     
    20372037    if (!pCtx->fHaveX11)
    20382038        return VERR_NO_DATA;
     2039
    20392040    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)
    20452044    {
    20462045        pX11Req->mFormat = u32Format;
    20472046        pX11Req->mCtx = pCtx;
    20482047        pX11Req->mReq = pReq;
     2048
    20492049        /* 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
    20532055    return rc;
    20542056}
     
    23872389static char g_completedBuf[MAX_BUF_SIZE];
    23882390
    2389 void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
     2391void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
    23902392{
    23912393    RT_NOREF1(pCtx);
     
    26462648    uint32_t cbActual;
    26472649    CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL;
    2648     rc = ClipStartX11(pCtx);
     2650    rc = ClipStartX11(pCtx, false /* fGrab */);
    26492651    AssertRCReturn(rc, 1);
    26502652
     
    28432845
    28442846    pCtx = ClipConstructX11(NULL, true);
    2845     rc = ClipStartX11(pCtx);
     2847    rc = ClipStartX11(pCtx, false /* fGrab */);
    28462848    AssertRCReturn(rc, 1);
    28472849
     
    28942896}
    28952897
    2896 void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
     2898void ClipRequestFromX11CompleteCallback(VBOXCLIPBOARDCONTEXT *pCtx, int rc, CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
    28972899{
    28982900    RT_NOREF5(pCtx, rc, pReq, pv, cb);
     
    29242926    CLIPBACKEND *pCtx = ClipConstructX11(NULL, false);
    29252927    AssertReturn(pCtx, 1);
    2926     rc = ClipStartX11(pCtx);
     2928    rc = ClipStartX11(pCtx, false /* fGrab */);
    29272929    AssertRCReturn(rc, 1);
    29282930    /* Give the clipboard time to synchronise. */
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r79631 r80623  
    8585        -framework ApplicationServices -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxSharedClipboard.dylib
    8686
    87 if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK)
     87if 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)
    8889 if1of ($(KBUILD_TARGET), freebsd linux netbsd openbsd solaris)
    8990 #
     
    102103        export VBOX_LOG_DEST=nofile; $(tstClipboardX11-2_1_STAGE_TARGET) quiet
    103104        $(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
    105107endif
    106108
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp

    r80447 r80623  
    3838{
    3939    /** 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;
    4342    /** The reference to the current pasteboard */
    44     PasteboardRef pasteboard;
    45 
    46     PVBOXCLIPBOARDCLIENT pClient;
     43    PasteboardRef           pasteboard;
     44    PVBOXCLIPBOARDCLIENT    pClient;
    4745};
    4846
     
    7068    /* Retrieve the formats currently in the clipboard and supported by vbox */
    7169    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}
    8184
    8285/**
     
    9295static int vboxClipboardThread(RTTHREAD ThreadSelf, void *pvUser)
    9396{
    94     Log(("vboxClipboardThread: starting clipboard thread\n"));
     97    LogFlowFuncEnter();
    9598
    9699    AssertPtrReturn(pvUser, VERR_INVALID_PARAMETER);
     
    109112    }
    110113
    111     Log(("vboxClipboardThread: clipboard thread terminated successfully with return code %Rrc\n", VINF_SUCCESS));
     114    LogFlowFuncLeaveRC(VINF_SUCCESS);
    112115    return VINF_SUCCESS;
    113116}
    114117
    115 /*
    116  * Public platform dependent functions.
    117  */
    118 
    119 /** Initialise the host side of the shared clipboard - called by the hgcm layer. */
     118
    120119int VBoxClipboardSvcImplInit(void)
    121120{
     
    138137}
    139138
    140 /** Terminate the host side of the shared clipboard - called by the hgcm layer. */
    141139void VBoxClipboardSvcImplDestroy(void)
    142140{
    143     Log(("vboxClipboardDestroy\n"));
    144 
    145141    /*
    146142     * Signal the termination of the polling thread and wait for it to respond.
     
    186182    /* Sync the host clipboard content with the client. */
    187183    VBoxSvcClipboardLock();
     184
    188185    int rc = vboxClipboardChanged(pClient->State.pCtx);
     186
    189187    VBoxSvcClipboardUnlock();
    190188
     
    195193{
    196194    VBoxSvcClipboardLock();
     195
    197196    pClient->State.pCtx->pClient = NULL;
     197
    198198    VBoxSvcClipboardUnlock();
    199199
     
    201201}
    202202
    203 int VBoxClipboardSvcImplFormatAnnounce(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx,
    204                                        PSHAREDCLIPBOARDFORMATDATA pFormats)
     203int VBoxClipboardSvcImplFormatAnnounce(PVBOXCLIPBOARDCLIENT pClient,
     204                                       PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDFORMATDATA pFormats)
    205205{
    206206    RT_NOREF(pCmdCtx);
     
    208208    LogFlowFunc(("uFormats=%02X\n", pFormats->uFormats));
    209209
    210     if (pFormats->uFormats == 0)
     210    if (pFormats->uFormats == VBOX_SHARED_CLIPBOARD_FMT_NONE)
    211211    {
    212212        /* This is just an automatism, not a genuine announcement */
     
    219219#endif
    220220
    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 */);
    222228}
    223229
     
    256262 * @param pData                 Data block to write to clipboard.
    257263 */
    258 int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData)
     264int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient,
     265                                  PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData)
    259266{
    260267    RT_NOREF(pCmdCtx);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r80562 r80623  
    136136    uint32_t                         cbChunkSize;
    137137    SHAREDCLIPBOARDSOURCE            enmSource;
    138     /** Old cruft (needed for VBox Guest Additions <= 6.0), remove this some time later. */
    139     VBOXCLIPBOARDCLIENTSTATEOLD      Old;
    140138#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    141139    /** The client's URI state. */
     
    227225 * The service functions. Locking is between the service thread and the platform-dependent (window) thread.
    228226 */
    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);
     227int vboxSvcClipboardDataReadRequest(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDDATAREQ pDataReq, PVBOXCLIPBOARDEVENTID puEvent);
     228int vboxSvcClipboardDataReadSignal(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx, PSHAREDCLIPBOARDDATABLOCK pData);
     229int vboxSvcClipboardFormatsReport(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats);
    235230
    236231uint32_t vboxSvcClipboardGetMode(void);
     
    307302int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer);
    308303int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer);
    309 #endif
     304#endif /*VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
    310305
    311306/* Host unit testing interface */
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r80563 r80623  
    5555static int vboxClipboardSvcWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
    5656
    57 typedef struct _VBOXCLIPBOARDCONTEXTOLD
    58 {
    59     /** Event which gets triggered if the host clipboard needs to render its data. */
    60     RTSEMEVENT               hRenderEvent;
    61 } VBOXCLIPBOARDCONTEXTOLD;
    62 
    6357struct _VBOXCLIPBOARDCONTEXT
    6458{
     
    6963    /** Windows-specific context data. */
    7064    VBOXCLIPBOARDWINCTX      Win;
    71     /** Old cruft, needed for the legacy protocol (v0). */
    72     VBOXCLIPBOARDCONTEXTOLD  Old;
    7365};
    7466
    7567
    7668/** @todo Someone please explain the protocol wrt overflows...  */
    77 static void vboxClipboardGetData(uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,
    78                                  void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)
     69static void vboxClipboardSvcWinGetData(uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,
     70                                       void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)
    7971{
    8072    LogFlowFunc(("cbSrc = %d, cbDst = %d\n", cbSrc, cbDst));
     
    175167}
    176168
    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 != NULL
    212                 && pCtx->pClient->State.Old.data.cb > 0
    213                 && 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 
    235169static int vboxClipboardSvcWinDataRead(PVBOXCLIPBOARDCONTEXT pCtx, UINT cfFormat,
    236170                                       void **ppvData, uint32_t *pcbData)
     
    238172    LogFlowFunc(("cfFormat=%u\n", cfFormat));
    239173
    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);
    258186        if (RT_SUCCESS(rc))
    259187        {
    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    }
    284197
    285198    LogFlowFuncLeaveRC(rc);
     
    366279            else
    367280            {
    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)
    371287                {
    372                     rc = vboxClipboardSvcWinOldRequestData(pCtx, cfFormat, 30 * 1000 /* 30s timeout */);
     288                    rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat, pvData, cbData);
     289
     290                    RTMemFree(pvData);
     291                    cbData = 0;
    373292                }
    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();
    390296            }
    391297
     
    406312        {
    407313            LogFunc(("VBOX_CLIPBOARD_WM_REPORT_FORMATS\n"));
    408 
    409             /* Some legcay protocol checks. */
    410             if (   pCtx->pClient->State.uProtocolVer == 0
    411                 && (   pCtx->pClient == NULL
    412                     || 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             }
    420314
    421315            /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT. */
     
    640534            && Formats.uFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE)
    641535        {
    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);
    650537        }
    651538    }
     
    687574        if (RT_SUCCESS(rc))
    688575        {
    689             rc = RTSemEventCreate(&pCtx->Old.hRenderEvent);
     576            rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */,
     577                                RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
    690578            if (RT_SUCCESS(rc))
    691579            {
    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            }
    703583        }
    704584
     
    736616            PostMessage(pCtx->Win.hWnd, WM_DESTROY, 0 /* wParam */, 0 /* lParam */);
    737617
    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;
    752628        }
    753629
     
    809685#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    810686    }
    811 
    812     else
    813         rc = VERR_NOT_SUPPORTED;
    814687#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
    815688
     
    850723                    LogFunc(("CF_DIB\n"));
    851724
    852                     vboxClipboardGetData(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);
    854727
    855728                    GlobalUnlock(hClip);
     
    872745                    LogFunc(("CF_UNICODETEXT\n"));
    873746
    874                     vboxClipboardGetData(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);
    876749
    877750                    GlobalUnlock(hClip);
     
    895768                    {
    896769                        /** @todo r=andy Add data overflow handling. */
    897                         vboxClipboardGetData(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);
    899772#ifdef VBOX_STRICT
    900773                        LogFlowFunc(("Raw HTML clipboard data from host:"));
     
    922795    {
    923796        /* Reply with empty data. */
    924         vboxClipboardGetData(0, NULL, 0, pData->pvData, pData->cbData, pcbActual);
     797        vboxClipboardSvcWinGetData(0, NULL, 0, pData->pvData, pData->cbData, pcbActual);
    925798    }
    926799
     
    929802}
    930803
    931 static int vboxClipboardSvcWinOldWriteData(PVBOXCLIPBOARDCLIENT pClient,
    932                                            void *pv, uint32_t cb, uint32_t u32Format)
     804int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENT pClient, PVBOXCLIPBOARDCLIENTCMDCTX pCmdCtx,
     805                                  PSHAREDCLIPBOARDDATABLOCK pData)
    933806{
    934807    LogFlowFuncEnter();
    935808
    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);
    983810
    984811    LogFlowFuncLeaveRC(rc);
     
    986813}
    987814
    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     else
    1000     {
    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 
    1017815#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    1018816int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer)
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11-stubs.cpp

    r80473 r80623  
    128128}
    129129
    130 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    131 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  
    3838*   Structures and Typedefs                                                                                                      *
    3939*********************************************************************************************************************************/
    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 */
    4544struct _VBOXCLIPBOARDCONTEXT
    4645{
    4746    /** This mutex is grabbed during any critical operations on the clipboard
    4847     * 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;
    5849    /** Pointer to the opaque X11 backend structure */
    59     CLIPBACKEND *pBackend;
     50    CLIPBACKEND         *pBackend;
    6051    /** Pointer to the VBox host client data structure. */
    6152    PVBOXCLIPBOARDCLIENT pClient;
    6253    /** We set this when we start shutting down as a hint not to post any new
    6354     * requests. */
    64     bool fShuttingDown;
     55    bool                 fShuttingDown;
    6556};
    66 
    6757
    6858
     
    7767    LogFlowFunc(("pCtx=%p, u32Formats=%02X\n", pCtx, u32Formats));
    7868
    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);
    8076}
    8177
     
    8682int VBoxClipboardSvcImplInit(void)
    8783{
     84    LogFlowFuncEnter();
    8885    return VINF_SUCCESS;
    8986}
     
    9592void VBoxClipboardSvcImplDestroy(void)
    9693{
    97 
     94    LogFlowFuncEnter();
    9895}
    9996
    10097/**
    10198 * Connect a guest to the shared clipboard.
    102  * @note  host glue code
    10399 * @note  on the host, we assume that some other application already owns
    104100 *        the clipboard and leave ownership to X11.
     
    108104    int rc = VINF_SUCCESS;
    109105
    110     LogRel(("Starting host clipboard service\n"));
    111 
    112106    PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT));
    113     if (!pCtx)
     107    if (pCtx)
    114108    {
    115         rc = VERR_NO_MEMORY;
    116     }
    117     else
    118     {
    119         RTCritSectInit(&pCtx->clipboardMutex);
     109        RTCritSectInit(&pCtx->CritSect);
    120110        CLIPBACKEND *pBackend = ClipConstructX11(pCtx, fHeadless);
    121111        if (!pBackend)
     
    136126        if (RT_FAILURE(rc))
    137127        {
    138             RTCritSectDelete(&pCtx->clipboardMutex);
     128            RTCritSectDelete(&pCtx->CritSect);
    139129            RTMemFree(pCtx);
    140130        }
    141131    }
    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;
    145134
    146135    LogFlowFuncLeaveRC(rc);
     
    160149     * there is data in the host clipboard it will automatically be sent to
    161150     * 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);
    163157}
    164158
     
    170164{
    171165    LogFlowFuncEnter();
    172 
    173     LogRel(("Stopping the host clipboard service\n"));
    174166
    175167    PVBOXCLIPBOARDCONTEXT pCtx = pClient->State.pCtx;
     
    192184    {
    193185        ClipDestructX11(pCtx->pBackend);
    194         RTCritSectDelete(&pCtx->clipboardMutex);
     186        RTCritSectDelete(&pCtx->CritSect);
    195187        RTMemFree(pCtx);
    196188    }
     
    225217struct _CLIPREADCBREQ
    226218{
    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;
    233227};
    234228
    235229/**
    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.
    244237 * @param pCmdCtx               Command context to use.
    245238 * @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.
    247240 *
    248241 * @note   We always fail or complete asynchronously.
     
    262255    int rc = VINF_SUCCESS;
    263256
    264     CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAlloc(sizeof(CLIPREADCBREQ));
    265     if (!pReq)
     257    CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ));
     258    if (pReq)
    266259    {
    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        }
    268286    }
    269287    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;
    278289
    279290    LogFlowFuncLeaveRC(rc);
     
    282293
    283294/**
    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 */
     301int 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);
    353308
    354309    LogFlowFuncLeaveRC(rc);
     
    356311}
    357312
    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 */
     325void 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.
    391342 *
    392343 * @param  pCtx      Pointer to the host clipboard structure
     
    400351int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void **ppv, uint32_t *pcb)
    401352{
    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));
    405354
    406355    if (pCtx->fShuttingDown)
    407356    {
    408357        /* 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"));
    410359        return VERR_WRONG_ORDER;
    411360    }
    412361
    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);
    414371    if (RT_SUCCESS(rc))
    415372    {
    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);
    424385    }
    425386
     
    428389}
    429390
    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
     392int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer)
     393{
     394    RT_NOREF(pClient, pTransfer);
    470395    return VINF_SUCCESS;
    471396}
    472397
    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 
     398int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer)
     399{
     400    RT_NOREF(pClient, pTransfer);
    575401    return VINF_SUCCESS;
    576402}
    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  
    4141 * There are currently four messages defined.  The first is
    4242 * 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.
    5346 *
    5447 * The second guest message is VBOX_SHARED_CLIPBOARD_FN_FORMATS, which tells
     
    5649 * VBOX_SHARED_CLIPBOARD_FN_READ_DATA, which asks the host to send its
    5750 * clipboard data and waits until it arrives.  The host supports at most one
    58  * simultaneous VBOX_SHARED_CLIPBOARD_FN_READ_DATA call from the guest - if a
     51 * simultaneous VBOX_SHARED_CLIPBOARD_FN_READ_DATA call from a guest - if a
    5952 * second call is made before the first has returned, the first will be
    6053 * aborted.
     
    6861 *
    6962 * 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.
    7165 *
    7266 * 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
    7568 * (see VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD vs. VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG).
    7669 *
    7770 * To distinguish the old (legacy) or new(er) protocol, the VBOX_SHARED_CLIPBOARD_GUEST_FN_CONNECT
    7871 * 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).
    8073 *
    8174 * The protocol also support out-of-order messages by using so-called "context IDs",
     
    431424            case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = pMsg->m_paParms[i - 2].u.pointer.size; break;
    432425        }
     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 */
     439int 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;
    433486}
    434487
     
    549602    LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->uClientID));
    550603    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 */
     618int 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;
    551674}
    552675
     
    676799}
    677800
     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 */
    678809int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient)
    679810{
     
    682813    if (pClient->Pending.uType)
    683814    {
    684         LogFlowFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID));
     815        LogFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID));
    685816
    686817        rc = VINF_SUCCESS;
     
    691822            if (pFirstMsg)
    692823            {
    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;
    696829
    697830                if (pClient->Pending.uType == VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT)
    698831                {
    699832                    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                {
    700851                    rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS);
    701852
     
    703854                    pClient->Pending.paParms = NULL;
    704855                    pClient->Pending.cParms  = 0;
    705                     pClient->Pending.uType   = false;
     856                    pClient->Pending.uType   = 0;
    706857                }
    707858            }
     
    714865        return rc;
    715866    }
     867    else
     868        LogFunc(("[Client %RU32] Not in pending state, skipping wakeup\n", pClient->uClientID));
    716869
    717870    return VINF_NO_CHANGE;
     
    719872
    720873/**
    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.
    725880 */
    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;
     881int 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        }
    781916    }
    782917    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
     924int 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
     954int vboxSvcClipboardFormatsReport(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDFORMATDATA pFormats)
     955{
     956    AssertPtrReturn(pClient,  VERR_INVALID_POINTER);
     957    AssertPtrReturn(pFormats, VERR_INVALID_POINTER);
    796958
    797959    int rc;
    798960
    799     PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE, 3);
     961    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_REPORT, 3);
    800962    if (pMsg)
    801963    {
     
    808970        rc = vboxSvcClipboardMsgAdd(pClient, pMsg, true /* fAppend */);
    809971        if (RT_SUCCESS(rc))
    810         {
    811972            rc = vboxSvcClipboardClientWakeup(pClient);
    812         }
    813973    }
    814974    else
     
    9001060    return rc;
    9011061}
    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_HOST
    929                     && 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_GUEST
    944                     && 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             else
    991                 VBoxSvcClipboardUnlock();
    992         }
    993         else
    994             VBoxSvcClipboardUnlock();
    995     }
    996 
    997     LogFlowFuncLeaveRC(rc);
    998     return rc;
    999 }
    1000 
    10011062
    10021063int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENT pClient, SHAREDCLIPBOARDSOURCE enmSource)
     
    11431204}
    11441205
    1145 /**
    1146  * Disconnect the host side of the shared clipboard and send a "host disconnected" message
    1147  * to the guest side.
    1148  */
    11491206static DECLCALLBACK(int) svcDisconnect(void *, uint32_t u32ClientID, void *pvClient)
    11501207{
     
    11551212    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient;
    11561213    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);
    11601214
    11611215#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     
    11711225    vboxSvcClipboardClientStateReset(&pClient->State);
    11721226    vboxSvcClipboardClientStateDestroy(&pClient->State);
     1227
     1228    SharedClipboardEventSourceDestroy(&pClient->Events);
    11731229
    11741230    ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID);
     
    12621318#endif
    12631319
    1264     bool fDefer = false;
     1320    bool fDoCallComplete = true;
    12651321
    12661322    switch (u32Function)
     
    12681324        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD:
    12691325        {
    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;
    13091329            break;
    13101330        }
     
    13571377            rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/);
    13581378            if (rc == VINF_HGCM_ASYNC_EXECUTE)
    1359                 fDefer = true;
     1379                fDoCallComplete = false;
    13601380            break;
    13611381        }
     
    13641384        {
    13651385            rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms);
    1366             if (RT_SUCCESS(rc)) /* vboxSvcClipboardMsgGet did the completion already. */
    1367                 fDefer = true;
     1386            if (rc == VINF_HGCM_ASYNC_EXECUTE)
     1387                fDoCallComplete = false;
    13681388            break;
    13691389        }
    13701390
    1371         case VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_WRITE:
     1391        case VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_REPORT:
    13721392        {
    13731393            uint32_t uFormats = 0;
     
    14681488                }
    14691489
    1470                 uint32_t u32Format;
    1471                 rc = HGCMSvcGetU32(&paParms[0], &u32Format);
     1490                uint32_t uFormat;
     1491                rc = HGCMSvcGetU32(&paParms[0], &uFormat);
    14721492                if (RT_SUCCESS(rc))
    14731493                {
    14741494#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    1475                     if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     1495                    if (uFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    14761496                    {
    14771497                        if (!SharedClipboardURICtxTransfersMaximumReached(&pClient->URI))
     
    15401560                                RT_ZERO(parms);
    15411561
    1542                                 parms.uFormat  = u32Format;
     1562                                parms.uFormat  = uFormat;
    15431563                                parms.u.pvData = pv;
    15441564                                parms.cbData   = cb;
     
    15571577                                if (g_ExtState.fDelayedAnnouncement)
    15581578                                {
    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);
    15611586
    15621587                                    g_ExtState.fDelayedAnnouncement = false;
     
    15751600                             *       so data which has been read above might get overridden by the host clipboard eventually. */
    15761601
     1602                            VBOXCLIPBOARDCLIENTCMDCTX cmdCtx;
     1603                            RT_ZERO(cmdCtx);
     1604
    15771605                            /* Release any other pending read, as we only
    15781606                             * support one pending read at one time. */
    1579                             rc = vboxSvcClipboardOldCompleteReadData(pClient, VERR_NO_DATA, 0);
    15801607                            if (RT_SUCCESS(rc))
    15811608                            {
    1582                                 VBOXCLIPBOARDCLIENTCMDCTX cmdCtx;
    1583                                 RT_ZERO(cmdCtx);
    1584 
    15851609                                SHAREDCLIPBOARDDATABLOCK dataBlock;
    15861610                                RT_ZERO(dataBlock);
     
    15881612                                dataBlock.pvData  = pv;
    15891613                                dataBlock.cbData  = cb;
    1590                                 dataBlock.uFormat = u32Format;
     1614                                dataBlock.uFormat = uFormat;
    15911615
    15921616                                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);
    16161619                            }
    16171620                        }
     
    16351638#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    16361639            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;
    16401640#else
    16411641            rc = VERR_NOT_IMPLEMENTED;
     
    16451645    }
    16461646
    1647     LogFlowFunc(("u32ClientID=%RU32, fDefer=%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)
    16501650        g_pHelpers->pfnCallComplete(callHandle, rc);
    16511651
    16521652    LogFlowFuncLeaveRC(rc);
    1653 }
    1654 
    1655 /** If the client in the guest is waiting for a read operation to complete
    1656  * then complete it, otherwise return.  See the protocol description in the
    1657  * 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;
    16781653}
    16791654
     
    17151690
    17161691/**
    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 /**
    17591692 * Resets a Shared Clipboard service's client state.
    17601693 *
     
    17691702    pClientState->URI.enmTransferDir = SHAREDCLIPBOARDURITRANSFERDIR_UNKNOWN;
    17701703#endif
    1771 
    1772     vboxSvcClipboardOldClientStateReset(pClientState);
    17731704}
    17741705
     
    18401771}
    18411772
    1842 #ifndef UNIT_TEST
    18431773/**
    1844  * SSM descriptor table for the VBOXCLIPBOARDCLIENTDATA structure.
     1774 * SSM descriptor table for the VBOXCLIPBOARDCLIENTSTATEOLD structure.
     1775 * Legacy, do not use anymore.
    18451776 */
    1846 static SSMFIELD const g_aClipboardClientDataFields[] =
    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),
     1777static 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),
    18531784    SSMFIELD_ENTRY_TERM()
    18541785};
    1855 #endif
    18561786
    18571787static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
     
    18681798    LogFunc(("u32ClientID=%RU32\n", u32ClientID));
    18691799
    1870     PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient;
     1800    //PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient;
     1801    RT_NOREF(pvClient);
    18711802
    18721803    /* This field used to be the length. We're using it as a version field
    18731804       with the high bit set. */
    18741805    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);
    18771812    AssertRCReturn(rc, rc);
    18781813
     
    18921827    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pvClient;
    18931828    AssertPtr(pClient);
    1894 
    1895     /* Existing client can not be in async state yet. */
    1896     Assert(!pClient->State.Old.fAsync);
    18971829
    18981830    /* Save the client ID for data validation. */
     
    19061838    if (lenOrVer == UINT32_C(0x80000002))
    19071839    {
    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));
    19101846        AssertRCReturn(rc, rc);
     1847
     1848        rc = SSMR3GetU32(pSSM, &uMarker);      /* End marker. */
     1849        AssertRC(rc);
     1850        Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */);
    19111851    }
    19121852    else
     
    19271867    VBoxClipboardSvcImplSync(pClient);
    19281868
    1929 #else  /* UNIT_TEST*/
     1869#else  /* UNIT_TEST */
    19301870    RT_NOREF(u32ClientID, pvClient, pSSM, uVersion);
    19311871#endif /* UNIT_TEST */
     
    19611901                else
    19621902                {
    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);
    19641909                }
    19651910
     
    19701915            case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
    19711916            {
    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 */);
    19731924                break;
    19741925            }
     
    20161967}
    20171968
    2018 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable)
     1969extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *pTable)
    20191970{
    20201971    int rc = VINF_SUCCESS;
    20211972
    2022     LogFlowFunc(("ptable=%p\n", ptable));
    2023 
    2024     if (!ptable)
     1973    LogFlowFunc(("ptable=%p\n", pTable));
     1974
     1975    if (!pTable)
    20251976    {
    20261977        rc = VERR_INVALID_PARAMETER;
     
    20281979    else
    20291980    {
    2030         LogFunc(("ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
    2031 
    2032         if (   ptable->cbSize     != sizeof (VBOXHGCMSVCFNTABLE)
    2033             || ptable->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)
    20341985        {
    20351986            rc = VERR_INVALID_PARAMETER;
     
    20371988        else
    20381989        {
    2039             g_pHelpers = ptable->pHelpers;
    2040 
    2041             ptable->cbClient = sizeof(VBOXCLIPBOARDCLIENT);
    2042 
    2043             ptable->pfnUnload     = svcUnload;
    2044             ptable->pfnConnect    = svcConnect;
    2045             ptable->pfnDisconnect = svcDisconnect;
    2046             ptable->pfnCall       = svcCall;
    2047             ptable->pfnHostCall   = svcHostCall;
    2048             ptable->pfnSaveState  = svcSaveState;
    2049             ptable->pfnLoadState  = svcLoadState;
    2050             ptable->pfnRegisterExtension  = svcRegisterExtension;
    2051             ptable->pfnNotify     = NULL;
    2052             ptable->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;
    20532004
    20542005            /* Service specific initialization. */
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp

    r80446 r80623  
    9797}
    9898
     99#if 0 /* Disabled for now. */
    99100static void testGetHostMsg(void)
    100101{
     
    198199    table.pfnUnload(NULL);
    199200}
     201#endif
    200202
    201203static void testSetHeadless(void)
     
    267269     */
    268270    testHostCall();
    269     testGetHostMsg();
     271    /* testGetHostMsg(); Disabled */
    270272
    271273    /*
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r79347 r80623  
    252252    {
    253253#ifdef DEBUG_andy
    254         uMaxClipboardAreas = ULONG_MAX;
     254        uMaxClipboardAreas = 9999;
    255255#endif
    256256        int rc2 = RTCritSectInit(&CritSect);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette