VirtualBox

Ignore:
Timestamp:
Jul 9, 2019 8:14:01 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131932
Message:

Shared Clipboard/URI: Update.

Location:
trunk/src/VBox/HostServices/SharedClipboard
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r79503 r79630  
    150150    /** Optional protocol version the client uses. Set to 0 by default. */
    151151    uint32_t                 uProtocolVer;
    152     /** Flag indicating whether this client currently is deferred mode,
    153      *  meaning that it did not return to the caller yet. */
    154     bool                     fDeferred;
    155     /** Structure for keeping the client's deferred state.
     152    /** Structure for keeping the client's pending (deferred return) state.
    156153     *  A client is in a deferred state when it asks for the next HGCM message,
    157154     *  but the service can't provide it yet. That way a client will block (on the guest side, does not return)
     
    161158        /** The client's HGCM call handle. Needed for completing a deferred call. */
    162159        VBOXHGCMCALLHANDLE hHandle;
    163         /** Message type (function number) to use when completing the deferred call. */
     160        /** Message type (function number) to use when completing the deferred call.
     161         *  A non-0 value means the client is in pending mode. */
    164162        uint32_t           uType;
    165163        /** Parameter count to use when completing the deferred call. */
     
    167165        /** Parameters to use when completing the deferred call. */
    168166        PVBOXHGCMSVCPARM   paParms;
    169     } Deferred;
     167    } Pending;
    170168} VBOXCLIPBOARDCLIENT, *PVBOXCLIPBOARDCLIENT;
    171169
     
    184182int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENTDATA pClientData, SHAREDCLIPBOARDSOURCE enmSource);
    185183
    186 int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
    187                                 VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    188 int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc);
    189 int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rc);
    190 int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms);
    191 
    192184void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTDATA pClientData);
    193185PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms);
    194186void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg);
     187void vboxSvcClipboardMsgSetPeekReturn(PVBOXCLIPBOARDCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms);
    195188int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend);
    196 int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t *puType, uint32_t *pcParms);
    197 int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTDATA pClientData,
    198                                uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     189int vboxSvcClipboardMsgPeek(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait);
     190int vboxSvcClipboardMsgGet(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     191
     192int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient);
    199193
    200194# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     
    226220
    227221int vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    228                                 PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList);
    229 int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList);
    230 int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     222                                PVBOXCLIPBOARDLISTHDR pListHdr, PSHAREDCLIPBOARDLISTHANDLE phList);
     223int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList);
     224int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
    231225                                   PVBOXCLIPBOARDLISTHDR pListHdr);
    232 int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     226int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
    233227                                    PVBOXCLIPBOARDLISTHDR pListHdr);
    234 int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     228int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
    235229                                     PVBOXCLIPBOARDLISTENTRY pListEntry);
    236 int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     230int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
    237231                                      PVBOXCLIPBOARDLISTENTRY pListEntry);
    238232
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp

    r79497 r79630  
    4141extern PFNHGCMSVCEXT g_pfnExtension;
    4242extern void *g_pvExtension;
     43extern PVBOXHGCMSVCHELPERS g_pHelpers;
    4344
    4445extern ClipboardClientQueue g_listClientsDeferred;
     46
     47
     48/*********************************************************************************************************************************
     49*   Prototypes                                                                                                                   *
     50*********************************************************************************************************************************/
     51int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     52                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms);
    4553
    4654
     
    6674
    6775DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    68                                               PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList)
    69 {
    70     RT_NOREF(pCtx, pListHdr, phList);
    71 
    72     LogFlowFuncEnter();
    73 
    74     int rc = VINF_SUCCESS;
    75 
    76     LogFlowFuncLeaveRC(rc);
    77     return rc;
    78 }
    79 
    80 DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList)
    81 {
    82     RT_NOREF(pCtx, hList);
    83 
    84     LogFlowFuncEnter();
    85 
    86     int rc = VINF_SUCCESS;
    87 
    88     LogFlowFuncLeaveRC(rc);
    89     return rc;
    90 }
    91 
    92 DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    93                                                  VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
    94 {
    95     RT_NOREF(pCtx, hList, pListHdr);
     76                                              PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
     77{
     78    RT_NOREF(phList);
    9679
    9780    LogFlowFuncEnter();
     
    10285    int rc;
    10386
    104     PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
    105                                                             VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
     87    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN,
     88                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
    10689    if (pMsg)
    10790    {
    108         rc = vboxSvcClipboardMsgAdd(&pClient->pData->State, pMsg, true /* fAppend */);
    109         if (RT_SUCCESS(rc))
    110             rc = vboxSvcClipboardClientDeferredComplete(pClient, VINF_SUCCESS);
     91        rc = VBoxSvcClipboardURISetListOpen(pMsg->m_cParms, pMsg->m_paParms, pOpenParms);
     92        if (RT_SUCCESS(rc))
     93        {
     94            rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
     95            if (RT_SUCCESS(rc))
     96            {
     97                int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN);
     98                AssertRC(rc2);
     99
     100                vboxSvcClipboardClientWakeup(pClient);
     101            }
     102        }
    111103    }
    112104    else
     
    116108    {
    117109        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    118         rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
     110        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN,
    119111                                                 30 * 1000 /* Timeout in ms */, &pPayload);
    120112        if (RT_SUCCESS(rc))
    121113        {
     114            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDREPLY));
     115
     116            PVBOXCLIPBOARDREPLY pReply = (PVBOXCLIPBOARDREPLY)pPayload->pvData;
     117            AssertPtr(pReply);
     118
     119            Assert(pReply->uType == VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN);
     120
     121            *phList = pReply->u.ListOpen.uHandle;
     122
     123            SharedClipboardURITransferPayloadFree(pPayload);
     124        }
     125    }
     126
     127    LogFlowFuncLeaveRC(rc);
     128    return rc;
     129}
     130
     131DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList)
     132{
     133    RT_NOREF(pCtx, hList);
     134
     135    LogFlowFuncEnter();
     136
     137    int rc = VINF_SUCCESS;
     138
     139    LogFlowFuncLeaveRC(rc);
     140    return rc;
     141}
     142
     143DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     144                                                 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
     145{
     146    LogFlowFuncEnter();
     147
     148    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
     149    AssertPtr(pClient);
     150
     151    int rc;
     152
     153    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
     154                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ_REQ);
     155    if (pMsg)
     156    {
     157        HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
     158        HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
     159        HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fFlags */);
     160
     161        rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
     162        if (RT_SUCCESS(rc))
     163        {
     164            int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE);
     165            AssertRC(rc2);
     166
     167            vboxSvcClipboardClientWakeup(pClient);
     168        }
     169    }
     170    else
     171        rc = VERR_NO_MEMORY;
     172
     173    if (RT_SUCCESS(rc))
     174    {
     175        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
     176        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
     177                                                 30 * 1000 /* Timeout in ms */, &pPayload);
     178        if (RT_SUCCESS(rc))
     179        {
    122180            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR));
    123             //*ppListHdr = (PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
    124 
    125             RTMemFree(pPayload);
     181
     182            *pListHdr = *(PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
     183
     184            SharedClipboardURITransferPayloadFree(pPayload);
    126185        }
    127186    }
     
    132191
    133192DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    134                                                   VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
     193                                                  SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
    135194{
    136195    RT_NOREF(pCtx, hList, pListHdr);
     
    142201
    143202DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    144                                                    VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
    145 {
    146     RT_NOREF(pCtx, hList, pListEntry);
    147 
    148     LogFlowFuncEnter();
    149 
    150     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
    151     AssertPtr(pClientData);
    152 
    153     PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    154     int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
     203                                                   SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     204{
     205    LogFlowFuncEnter();
     206
     207    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
     208    AssertPtr(pClient);
     209
     210    int rc;
     211
     212    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ,
     213                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ_REQ);
     214    if (pMsg)
     215    {
     216        HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
     217        HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
     218        HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fInfo */);
     219
     220        rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
     221        if (RT_SUCCESS(rc))
     222        {
     223            int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE);
     224            if (rc2 == VERR_ALREADY_EXISTS)
     225                rc2 = VINF_SUCCESS;
     226            AssertRC(rc2);
     227
     228            vboxSvcClipboardClientWakeup(pClient);
     229        }
     230    }
     231    else
     232        rc = VERR_NO_MEMORY;
     233
     234    if (RT_SUCCESS(rc))
     235    {
     236        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
     237        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
    155238                                                 30 * 1000 /* Timeout in ms */, &pPayload);
    156     if (RT_SUCCESS(rc))
    157     {
    158         Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
    159 
    160         PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData;
    161         AssertPtr(pListEntry);
    162 
    163    /*     const uint32_t cbToRead = RT_MIN(cbChunk, pListEntry->cbData);
    164 
    165         memcpy(pvChunk, pListEntry->pvData, cbToRead);*/
    166 
    167         SharedClipboardURITransferPayloadFree(pPayload);
    168 
    169 /*        if (pcbRead)
    170             *pcbRead = cbToRead;*/
     239        if (RT_SUCCESS(rc))
     240        {
     241            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
     242
     243            rc = SharedClipboardURIListEntryCopy(pListEntry, (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData);
     244
     245            SharedClipboardURITransferPayloadFree(pPayload);
     246        }
    171247    }
    172248
     
    176252
    177253DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
    178                                                     VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     254                                                    SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
    179255{
    180256    RT_NOREF(pCtx, hList, pListEntry);
     
    237313DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
    238314{
    239     LogFlowFuncEnter();
    240 
    241     AssertPtrReturnVoid(pData);
    242 
    243     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pData->pvUser;
    244     AssertPtrReturnVoid(pClientData);
    245 
    246     PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer;
    247     AssertPtrReturnVoid(pTransfer);
    248 
    249     /* Register needed events. */
    250     int rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ);
    251     AssertRC(rc2);
    252     rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ);
    253     AssertRC(rc2);
    254 
    255 #if 0
    256     /* Tell the guest that it can start sending URI data. */
    257     rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START,
    258                                     0 /* u32Formats == 0 means reading data */);
    259     AssertRC(rc2);
    260 #endif
     315    RT_NOREF(pData);
     316
     317    LogFlowFuncEnter();
    261318}
    262319
    263320DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
    264321{
    265     LogFlowFuncEnter();
    266 
    267322    RT_NOREF(pData, rc);
    268323
     324    LogFlowFuncEnter();
     325
    269326    LogRel2(("Shared Clipboard: Transfer complete\n"));
    270327}
     
    286343
    287344    LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
     345}
     346
     347/**
     348 * Gets an URI message reply from HGCM service parameters.
     349 *
     350 * @returns VBox status code.
     351 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
     352 * @param   paParms             Array of HGCM parameters.
     353 * @param   pReply              Where to store the reply.
     354 */
     355int VBoxSvcClipboardURIGetReply(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     356                                PVBOXCLIPBOARDREPLY pReply)
     357{
     358    int rc;
     359
     360    if (cParms >= VBOX_SHARED_CLIPBOARD_CPARMS_REPLY_MIN)
     361    {
     362        uint32_t cbPayload = 0;
     363
     364        /* Note: Context ID (paParms[0]) not used yet. */
     365        rc = HGCMSvcGetU32(&paParms[1], &pReply->uType);
     366        if (RT_SUCCESS(rc))
     367            rc = HGCMSvcGetU32(&paParms[2], &pReply->rc);
     368        if (RT_SUCCESS(rc))
     369            rc = HGCMSvcGetU32(&paParms[3], &cbPayload);
     370        if (RT_SUCCESS(rc))
     371        {
     372            rc = HGCMSvcGetPv(&paParms[4], &pReply->pvPayload, &pReply->cbPayload);
     373            AssertReturn(cbPayload == pReply->cbPayload, VERR_INVALID_PARAMETER);
     374        }
     375
     376        if (RT_SUCCESS(rc))
     377        {
     378            switch (pReply->uType)
     379            {
     380                case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
     381                {
     382                    if (cParms >= 6)
     383                    {
     384                        rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ListOpen.uHandle);
     385                    }
     386                    else
     387                        rc = VERR_INVALID_PARAMETER;
     388                    break;
     389                }
     390
     391                case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
     392                {
     393                    if (cParms >= 6)
     394                    {
     395                        rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ObjOpen.uHandle);
     396                    }
     397                    else
     398                        rc = VERR_INVALID_PARAMETER;
     399                    break;
     400                }
     401
     402                default:
     403                    break;
     404            }
     405        }
     406    }
     407    else
     408        rc = VERR_INVALID_PARAMETER;
     409
     410    LogFlowFuncLeaveRC(rc);
     411    return rc;
     412}
     413
     414/**
     415 * Gets an URI list open request from HGCM service parameters.
     416 *
     417 * @returns VBox status code.
     418 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
     419 * @param   paParms             Array of HGCM parameters.
     420 * @param   pOpenParms          Where to store the open parameters of the request.
     421 */
     422int VBoxSvcClipboardURIGetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     423                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
     424{
     425    int rc;
     426
     427    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
     428    {
     429        uint32_t cbPath   = 0;
     430        uint32_t cbFilter = 0;
     431
     432        /* Note: Context ID (paParms[0]) not used yet. */
     433        rc = HGCMSvcGetU32(&paParms[1], &pOpenParms->fList);
     434        if (RT_SUCCESS(rc))
     435            rc = HGCMSvcGetU32(&paParms[2], &cbPath);
     436        if (RT_SUCCESS(rc))
     437        {
     438            rc = HGCMSvcGetStr(&paParms[3], &pOpenParms->pszPath, &pOpenParms->cbPath);
     439            AssertReturn(cbPath == pOpenParms->cbPath, VERR_INVALID_PARAMETER);
     440        }
     441        if (RT_SUCCESS(rc))
     442            rc = HGCMSvcGetU32(&paParms[4], &cbFilter);
     443        if (RT_SUCCESS(rc))
     444        {
     445            rc = HGCMSvcGetStr(&paParms[5], &pOpenParms->pszFilter, &pOpenParms->cbFilter);
     446            AssertReturn(cbFilter == pOpenParms->cbFilter, VERR_INVALID_PARAMETER);
     447        }
     448
     449        if (RT_SUCCESS(rc))
     450        {
     451            /** @todo Some more validation. */
     452        }
     453    }
     454    else
     455        rc = VERR_INVALID_PARAMETER;
     456
     457    LogFlowFuncLeaveRC(rc);
     458    return rc;
     459}
     460
     461int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     462                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
     463{
     464    int rc;
     465
     466    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
     467    {
     468        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
     469        HGCMSvcSetU32(&paParms[1], pOpenParms->fList);
     470        HGCMSvcSetU32(&paParms[2], pOpenParms->cbFilter);
     471        HGCMSvcSetPv (&paParms[3], pOpenParms->pszFilter, pOpenParms->cbFilter);
     472        HGCMSvcSetU32(&paParms[4], pOpenParms->cbPath);
     473        HGCMSvcSetPv (&paParms[5], pOpenParms->pszPath, pOpenParms->cbPath);
     474        HGCMSvcSetU64(&paParms[6], 0); /* OUT: uHandle */
     475
     476        rc = VINF_SUCCESS;
     477    }
     478    else
     479        rc = VERR_INVALID_PARAMETER;
     480
     481    LogFlowFuncLeaveRC(rc);
     482    return rc;
    288483}
    289484
     
    298493 */
    299494int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
    300                                   PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
     495                                  PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
    301496{
    302497    int rc;
    303498
    304     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE)
     499    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
    305500    {
    306501        /* Note: Context ID (paParms[0]) not used yet. */
    307502        rc = HGCMSvcGetU64(&paParms[1], phList);
    308         if (RT_SUCCESS(rc))
    309             rc = HGCMSvcGetU64(&paParms[2], &pListHdr->cTotalObjects);
    310         if (RT_SUCCESS(rc))
    311             rc = HGCMSvcGetU64(&paParms[3], &pListHdr->cbTotalSize);
    312         if (RT_SUCCESS(rc))
    313             rc = HGCMSvcGetU32(&paParms[4], &pListHdr->enmCompression);
    314         if (RT_SUCCESS(rc))
    315             rc = HGCMSvcGetU32(&paParms[5], (uint32_t *)&pListHdr->enmChecksumType);
     503        /* Note: Flags (paParms[2]) not used here. */
     504        if (RT_SUCCESS(rc))
     505            rc = HGCMSvcGetU32(&paParms[3], &pListHdr->fFeatures);
     506        if (RT_SUCCESS(rc))
     507            rc = HGCMSvcGetU64(&paParms[4], &pListHdr->cTotalObjects);
     508        if (RT_SUCCESS(rc))
     509            rc = HGCMSvcGetU64(&paParms[5], &pListHdr->cbTotalSize);
     510        if (RT_SUCCESS(rc))
     511            rc = HGCMSvcGetU32(&paParms[6], &pListHdr->enmCompression);
     512        if (RT_SUCCESS(rc))
     513            rc = HGCMSvcGetU32(&paParms[7], (uint32_t *)&pListHdr->enmChecksumType);
    316514
    317515        if (RT_SUCCESS(rc))
     
    340538    int rc;
    341539
    342     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ)
     540    if (   cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR
     541        || cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
    343542    {
    344543        /** @todo Set pvMetaFmt + cbMetaFmt. */
    345544        /** @todo Calculate header checksum. */
    346545
    347         /* Note: Context ID (paParms[0]) not used yet. */
    348         HGCMSvcSetU32(&paParms[1], pListHdr->fList);
    349         HGCMSvcSetU32(&paParms[2], pListHdr->fFeatures);
    350         HGCMSvcSetU32(&paParms[3], pListHdr->cbFilter);
    351         HGCMSvcSetPv (&paParms[4], pListHdr->pszFilter, pListHdr->cbFilter);
    352         HGCMSvcSetU64(&paParms[5], pListHdr->cTotalObjects);
    353         HGCMSvcSetU64(&paParms[6], pListHdr->cbTotalSize);
    354         HGCMSvcSetU32(&paParms[7], pListHdr->enmCompression);
    355         HGCMSvcSetU32(&paParms[8], (uint32_t)pListHdr->enmChecksumType);
     546        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
     547        HGCMSvcSetU32(&paParms[1], pListHdr->fFeatures);
     548        HGCMSvcSetU32(&paParms[2], 0 /* Features, will be returned on success */);
     549        HGCMSvcSetU64(&paParms[3], pListHdr->cTotalObjects);
     550        HGCMSvcSetU64(&paParms[4], pListHdr->cbTotalSize);
     551        HGCMSvcSetU32(&paParms[5], pListHdr->enmCompression);
     552        HGCMSvcSetU32(&paParms[6], pListHdr->enmChecksumType);
    356553
    357554        rc = VINF_SUCCESS;
     
    374571 */
    375572int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
    376                                     PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     573                                    PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
    377574{
    378575    int rc;
    379576
    380     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE)
     577    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
    381578    {
    382579        /* Note: Context ID (paParms[0]) not used yet. */
     
    414611    int rc;
    415612
    416     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ)
     613    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
    417614    {
    418615        /** @todo Calculate chunk checksum. */
    419616
    420         /* Note: Context ID (paParms[0]) not used yet. */
     617        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
    421618        HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
    422619        HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
     
    432629}
    433630
     631/**
     632 * Gets an URI error from HGCM service parameters.
     633 *
     634 * @returns VBox status code.
     635 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
     636 * @param   paParms             Array of HGCM parameters.
     637 * @param   pRc                 Where to store the received error code.
     638 */
    434639int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
    435640{
     
    446651    else
    447652        rc = VERR_INVALID_PARAMETER;
     653
     654    LogFlowFuncLeaveRC(rc);
     655    return rc;
     656}
     657
     658int VBoxSvcClipboardURITransferHandleReply(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer,
     659                                           uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     660{
     661    RT_NOREF(pClient);
     662
     663    int rc;
     664
     665    uint32_t            cbReply = sizeof(VBOXCLIPBOARDREPLY);
     666    PVBOXCLIPBOARDREPLY pReply  = (PVBOXCLIPBOARDREPLY)RTMemAlloc(cbReply);
     667    if (pReply)
     668    {
     669        rc = VBoxSvcClipboardURIGetReply(cParms, paParms, pReply);
     670        if (RT_SUCCESS(rc))
     671        {
     672            PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload
     673                = (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
     674            if (pPayload)
     675            {
     676                pPayload->pvData = pReply;
     677                pPayload->cbData = cbReply;
     678
     679                switch (pReply->uType)
     680                {
     681                    case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
     682                    {
     683                        rc = SharedClipboardURITransferEventSignal(pTransfer,
     684                                                                   SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN, pPayload);
     685                        break;
     686                    }
     687
     688                    default:
     689                        rc = VERR_NOT_FOUND;
     690                        break;
     691                }
     692
     693                if (RT_FAILURE(rc))
     694                {
     695                    if (pPayload)
     696                        RTMemFree(pPayload);
     697                }
     698            }
     699            else
     700                rc = VERR_NO_MEMORY;
     701        }
     702    }
     703    else
     704        rc = VERR_NO_MEMORY;
     705
     706    if (RT_FAILURE(rc))
     707    {
     708        if (pReply)
     709            RTMemFree(pReply);
     710    }
    448711
    449712    LogFlowFuncLeaveRC(rc);
     
    471734    RT_NOREF(paParms, tsArrival);
    472735
    473     LogFlowFunc(("uClient=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
    474                  pClient->uClientID, u32Function, cParms, g_pfnExtension));
     736    LogFlowFunc(("uClient=%RU32, u32Function=%RU32 (%s), cParms=%RU32, g_pfnExtension=%p\n",
     737                 pClient->uClientID, u32Function, VBoxSvcClipboardGuestMsgToStr(u32Function), cParms, g_pfnExtension));
    475738
    476739    const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
     
    503766    switch (u32Function)
    504767    {
    505         case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     768        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
    506769            RT_FALL_THROUGH();
    507         case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
     770        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
     771            RT_FALL_THROUGH();
     772        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
     773            RT_FALL_THROUGH();
     774        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
    508775            break;
    509776        default:
     
    535802    switch (u32Function)
    536803    {
    537         case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
    538         {
    539             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT\n"));
    540 
    541             if (!SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
     804        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
     805        {
     806            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS\n", pClient->uClientID));
     807
     808            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_STATUS)
     809                break;
     810
     811            SHAREDCLIPBOARDURITRANSFERSTATUS uStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
     812            rc = HGCMSvcGetU32(&paParms[1], &uStatus);
     813            if (RT_FAILURE(rc))
     814                break;
     815
     816            LogFlowFunc(("uStatus: %RU32\n", uStatus));
     817
     818            if (   uStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING
     819                && !SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
    542820            {
    543821                SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
     
    592870                        SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
    593871
    594                         rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     872                        rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
    595873                        if (RT_SUCCESS(rc))
    596874                            rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
     
    614892                rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
    615893
    616             LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: %Rrc\n", rc));
     894            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS: %Rrc\n", pClient->uClientID, rc));
    617895
    618896            if (RT_FAILURE(rc))
     
    622900        }
    623901
    624         case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
    625         {
    626             if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG)
    627             {
    628                 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n"));
    629                 rc = vboxSvcClipboardMsgGetNextInfo(&pClientData->State,
    630                                                     &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
    631 
    632                 /* No (new) messages available or some error occurred? */
    633                 if (   rc == VERR_NO_DATA
    634                     || RT_FAILURE(rc))
     902        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
     903        {
     904            rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, false /*fWait*/);
     905            break;
     906        }
     907
     908        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
     909        {
     910            rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/);
     911            break;
     912        }
     913
     914        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
     915        {
     916            rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms);
     917            break;
     918        }
     919
     920        case VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY:
     921        {
     922            rc = VBoxSvcClipboardURITransferHandleReply(pClient, pTransfer, cParms, paParms);
     923            break;
     924        }
     925
     926        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
     927        {
     928            VBOXCLIPBOARDLISTOPENPARMS listOpenParms;
     929            rc = VBoxSvcClipboardURIGetListOpen(cParms, paParms, &listOpenParms);
     930            if (RT_SUCCESS(rc))
     931            {
     932                SHAREDCLIPBOARDLISTHANDLE hList;
     933                rc = SharedClipboardURITransferListOpen(pTransfer, &listOpenParms, &hList);
     934                if (RT_SUCCESS(rc))
    635935                {
    636                     uint32_t fFlags = 0;
    637                     int rc2 = HGCMSvcGetU32(&paParms[2], &fFlags);
    638                     if (   RT_SUCCESS(rc2)
    639                         && fFlags) /* Blocking flag set? */
    640                     {
    641                         /* Defer client returning. */
    642                         rc = VINF_HGCM_ASYNC_EXECUTE;
    643                     }
    644                     else
    645                         rc = VERR_INVALID_PARAMETER;
    646 
    647                     LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc));
     936                    /* Return list handle. */
     937                    HGCMSvcSetU32(&paParms[1], hList);
    648938                }
    649939            }
     
    651941        }
    652942
    653         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
    654         {
    655             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN\n"));
    656             rc = VINF_SUCCESS;
    657             break;
    658         }
    659 
    660943        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
    661944        {
    662             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE\n"));
    663             rc = VINF_SUCCESS;
     945            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
     946                break;
     947
     948            SHAREDCLIPBOARDLISTHANDLE hList;
     949            /* Note: Context ID (paParms[0]) not used yet. */
     950            rc = HGCMSvcGetU64(&paParms[1], &hList);
     951            if (RT_SUCCESS(rc))
     952            {
     953                rc = SharedClipboardURITransferListClose(pTransfer, hList);
     954            }
    664955            break;
    665956        }
     
    667958        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
    668959        {
    669             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_HDR\n"));
    670 
    671             VBOXCLIPBOARDLISTHANDLE hList;
    672             VBOXCLIPBOARDLISTHDR    hdrList;
    673             rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
     960            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
     961                break;
     962
     963            SHAREDCLIPBOARDLISTHANDLE hList;
     964            /* Note: Context ID (paParms[0]) not used yet. */
     965            rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
    674966            if (RT_SUCCESS(rc))
    675967            {
     968                VBOXCLIPBOARDLISTHDR hdrList;
     969                rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
    676970                if (RT_SUCCESS(rc))
    677971                    rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
     
    682976        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
    683977        {
    684             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_HDR\n"));
    685 
    686978            VBOXCLIPBOARDLISTHDR hdrList;
    687979            rc = SharedClipboardURIListHdrInit(&hdrList);
    688980            if (RT_SUCCESS(rc))
    689981            {
    690                 VBOXCLIPBOARDLISTHANDLE hList;
     982                SHAREDCLIPBOARDLISTHANDLE hList;
    691983                rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
    692984                if (RT_SUCCESS(rc))
     
    696988
    697989                    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    698                     rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
     990                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
    699991                                                                pvData, cbData, &pPayload);
    700992                    if (RT_SUCCESS(rc))
    701993                    {
    702                         rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
     994                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
    703995                                                                   pPayload);
    704996                    }
     
    7101002        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
    7111003        {
    712             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_ENTRY\n"));
     1004            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
     1005                break;
     1006
     1007            SHAREDCLIPBOARDLISTHANDLE hList;
     1008            /* Note: Context ID (paParms[0]) not used yet. */
     1009            rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
     1010            if (RT_SUCCESS(rc))
     1011            {
     1012                VBOXCLIPBOARDLISTENTRY entryList;
     1013                rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
     1014            }
    7131015            break;
    7141016        }
     
    7161018        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
    7171019        {
    718             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_ENTRY\n"));
    719 
    7201020            VBOXCLIPBOARDLISTENTRY entryList;
    7211021            rc = SharedClipboardURIListEntryInit(&entryList);
    7221022            if (RT_SUCCESS(rc))
    7231023            {
    724                 VBOXCLIPBOARDLISTHANDLE hList;
     1024                SHAREDCLIPBOARDLISTHANDLE hList;
    7251025                rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
    7261026                if (RT_SUCCESS(rc))
     
    7301030
    7311031                    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    732                     rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
     1032                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
    7331033                                                                pvData, cbData, &pPayload);
    7341034                    if (RT_SUCCESS(rc))
    7351035                    {
    736                         rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
     1036                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
    7371037                                                                   pPayload);
    7381038                    }
     
    7421042            break;
    7431043        }
    744 #if 0
     1044
     1045    #if 0
    7451046        case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
    7461047        {
     
    9131214#endif
    9141215        case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
    915             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_CANCEL\n"));
    916 
     1216        {
    9171217            LogRel2(("Shared Clipboard: Transfer canceled\n"));
    9181218            break;
     1219        }
    9191220
    9201221        case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
    9211222        {
    922             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_ERROR\n"));
    923 
    9241223            int rcGuest;
    9251224            rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
     
    9301229
    9311230        default:
    932             AssertMsgFailed(("Not implemented\n"));
    933             break;
    934     }
    935 
    936     if (rc == VINF_HGCM_ASYNC_EXECUTE)
    937     {
    938         try
    939         {
    940             vboxSvcClipboardClientDefer(pClient, callHandle, u32Function, cParms, paParms);
    941             g_listClientsDeferred.push_back(pClient->uClientID);
    942         }
    943         catch (std::bad_alloc &)
    944         {
    945             rc = VERR_NO_MEMORY;
    946             /* Don't report to guest. */
    947         }
    948     }
    949     else if (pClient)
    950     {
    951         int rc2 = vboxSvcClipboardClientComplete(pClient, callHandle, rc);
    952         AssertRC(rc2);
    953     }
    954 
    955     LogFlowFunc(("Returning uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
     1231            LogFunc(("Not implemented\n"));
     1232            break;
     1233    }
     1234
     1235    if (rc != VINF_HGCM_ASYNC_EXECUTE)
     1236    {
     1237        /* Tell the client that the call is complete (unblocks waiting). */
     1238        LogFlowFunc(("[Client %RU32] Calling pfnCallComplete w/ rc=%Rrc\n", pClient->uClientID, rc));
     1239        AssertPtr(g_pHelpers);
     1240        g_pHelpers->pfnCallComplete(callHandle, rc);
     1241    }
     1242
     1243    LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->uClientID, rc));
    9561244    return rc;
    9571245}
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp

    r79497 r79630  
    6868            break;
    6969
    70         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
    71             RT_FALL_THROUGH();
    72         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
    73             RT_FALL_THROUGH();
    74         case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE:
    75             fAllowed = fGuestToHost;
    76             break;
    77 
    78         case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
    79             RT_FALL_THROUGH();
    80         case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     70        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
     71            RT_FALL_THROUGH();
     72        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
     73            RT_FALL_THROUGH();
     74        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
     75            RT_FALL_THROUGH();
     76        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
    8177            RT_FALL_THROUGH();
    8278        case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
     
    8985            break;
    9086    }
     87
     88    fAllowed = true; /** @todo FIX !!!! */
    9189
    9290    LogFlowFunc(("uMsg=%RU32, uMode=%RU32 -> fAllowed=%RTbool\n", uMsg, uMode, fAllowed));
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r79497 r79630  
    646646    {
    647647        if (pCtx->Win.hWnd)
    648             PostMessage(pCtx->Win.hWnd, WM_CLOSE, 0 /* wParam */, 0 /* lParam */);
     648            PostMessage(pCtx->Win.hWnd, WM_DESTROY, 0 /* wParam */, 0 /* lParam */);
    649649
    650650        rc = RTSemEventDestroy(pCtx->hRenderEvent);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r79505 r79630  
    127127 * the rest of the code stays the same.
    128128 *
     129 * @section sec_uri_protocol            URI protocol.
     130 *
     131 * The host service issues commands which the guest has to respond with an own
     132 * message to. The protocol itself is designed so that it has primitives to list
     133 * directories and open/close/read/write file system objects.
     134 *
     135 * The protocol does not rely on the old ReportMsg() / ReturnMsg() mechanism anymore
     136 * and uses a (per-client) message queue instead (see VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD
     137 * vs. VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG).
     138 *
     139 * Note that this is different from the DnD approach, as Shared Clipboard transfers
     140 * need to be deeper integrated within the host / guest OS (i.e. for progress UI),
     141 * and this might require non-monolithic / random access APIs to achieve.
     142 *
     143 * One transfer always is handled by an own (HGCM) client, so for multiple transfers
     144 * at the same time, multiple clients (client IDs) are being used. How this transfer
     145 * is implemented on the guest (and / or host) side depends upon the actual implementation,
     146 * e.g. via an own thread per transfer.
    129147 */
    130148
     
    136154#include <VBox/log.h>
    137155
     156#include <VBox/AssertGuest.h>
    138157#include <VBox/HostServices/Service.h>
    139158#include <VBox/HostServices/VBoxClipboardSvc.h>
     
    167186*   Global Variables                                                                                                             *
    168187*********************************************************************************************************************************/
    169 static PVBOXHGCMSVCHELPERS g_pHelpers;
     188PVBOXHGCMSVCHELPERS g_pHelpers;
    170189
    171190static RTCRITSECT g_CritSect;
     
    183202static bool g_fHeadless = false;
    184203
    185 /** Map of all connected clients. */
     204/** Global map of all connected clients. */
    186205ClipboardClientMap g_mapClients;
    187206
    188 /** List of all clients which are queued up (deferred return) and ready
     207/** Global list of all clients which are queued up (deferred return) and ready
    189208 *  to process new commands. The key is the (unique) client ID. */
    190209ClipboardClientQueue g_listClientsDeferred;
    191210
    192 
    193 #if 0
    194 static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
    195 {
    196     pParm->type             = VBOX_HGCM_SVC_PARM_PTR;
    197     pParm->u.pointer.size   = cb;
    198     pParm->u.pointer.addr   = pv;
    199 }
    200 #endif
    201211
    202212static int VBoxHGCMParmPtrGet(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
     
    323333
    324334/**
     335 * Sets the GUEST_MSG_PEEK_WAIT GUEST_MSG_PEEK_NOWAIT return parameters.
     336 *
     337 * @param   paDstParms  The peek parameter vector.
     338 * @param   cDstParms   The number of peek parameters (at least two).
     339 * @remarks ASSUMES the parameters has been cleared by clientMsgPeek.
     340 */
     341void vboxSvcClipboardMsgSetPeekReturn(PVBOXCLIPBOARDCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
     342{
     343    Assert(cDstParms >= 2);
     344    if (paDstParms[0].type == VBOX_HGCM_SVC_PARM_32BIT)
     345        paDstParms[0].u.uint32 = pMsg->m_uMsg;
     346    else
     347        paDstParms[0].u.uint64 = pMsg->m_uMsg;
     348    paDstParms[1].u.uint32 = pMsg->m_cParms;
     349
     350    uint32_t i = RT_MIN(cDstParms, pMsg->m_cParms + 2);
     351    while (i-- > 2)
     352        switch (pMsg->m_paParms[i - 2].type)
     353        {
     354            case VBOX_HGCM_SVC_PARM_32BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
     355            case VBOX_HGCM_SVC_PARM_64BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
     356            case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = pMsg->m_paParms[i - 2].u.pointer.size; break;
     357        }
     358}
     359
     360/**
    325361 * Adds a new message to a client'S message queue.
    326362 *
     
    347383
    348384/**
    349  * Retrieves information about the next message in the queue.
    350  *
    351  * @returns IPRT status code. VERR_NO_DATA if no next message is available.
    352  * @param   pClientData         Pointer to the client data structure to get message info for.
    353  * @param   puType              Where to store the message type.
    354  * @param   pcParms             Where to store the message parameter count.
     385 * Implements VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT and VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT.
     386 *
     387 * @returns VBox status code.
     388 * @retval  VINF_SUCCESS if a message was pending and is being returned.
     389 * @retval  VERR_TRY_AGAIN if no message pending and not blocking.
     390 * @retval  VERR_RESOURCE_BUSY if another read already made a waiting call.
     391 * @retval  VINF_HGCM_ASYNC_EXECUTE if message wait is pending.
     392 *
     393 * @param   pClient     The client state.
     394 * @param   hCall       The client's call handle.
     395 * @param   cParms      Number of parameters.
     396 * @param   paParms     Array of parameters.
     397 * @param   fWait       Set if we should wait for a message, clear if to return
     398 *                      immediately.
    355399 */
    356 int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t *puType, uint32_t *pcParms)
    357 {
    358     AssertPtrReturn(puType, VERR_INVALID_POINTER);
    359     AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
    360 
    361     int rc;
    362 
    363     if (pClientData->queueMsg.isEmpty())
    364     {
    365         rc = VERR_NO_DATA;
    366     }
    367     else
    368     {
    369         PVBOXCLIPBOARDCLIENTMSG pMsg = pClientData->queueMsg.first();
    370         AssertPtr(pMsg);
    371 
    372         *puType  = pMsg->m_uMsg;
    373         *pcParms = pMsg->m_cParms;
     400int vboxSvcClipboardMsgPeek(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     401                            bool fWait)
     402{
     403    /*
     404     * Validate the request.
     405     */
     406    ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_WRONG_PARAMETER_COUNT);
     407
     408    uint64_t idRestoreCheck = 0;
     409    uint32_t i              = 0;
     410    if (paParms[i].type == VBOX_HGCM_SVC_PARM_64BIT)
     411    {
     412        idRestoreCheck = paParms[0].u.uint64;
     413        paParms[0].u.uint64 = 0;
     414        i++;
     415    }
     416    for (; i < cParms; i++)
     417    {
     418        ASSERT_GUEST_MSG_RETURN(paParms[i].type == VBOX_HGCM_SVC_PARM_32BIT, ("#%u type=%u\n", i, paParms[i].type),
     419                                VERR_WRONG_PARAMETER_TYPE);
     420        paParms[i].u.uint32 = 0;
     421    }
     422
     423    /*
     424     * Check restore session ID.
     425     */
     426    if (idRestoreCheck != 0)
     427    {
     428        uint64_t idRestore = g_pHelpers->pfnGetVMMDevSessionId(g_pHelpers);
     429        if (idRestoreCheck != idRestore)
     430        {
     431            paParms[0].u.uint64 = idRestore;
     432            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_XXX -> VERR_VM_RESTORED (%#RX64 -> %#RX64)\n",
     433                         pClient->uClientID, idRestoreCheck, idRestore));
     434            return VERR_VM_RESTORED;
     435        }
     436        Assert(!g_pHelpers->pfnIsCallRestored(hCall));
     437    }
     438
     439    /*
     440     * Return information about the first message if one is pending in the list.
     441     */
     442    if (!pClient->pData->queueMsg.isEmpty())
     443    {
     444        PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
     445        if (pFirstMsg)
     446        {
     447            vboxSvcClipboardMsgSetPeekReturn(pFirstMsg, paParms, cParms);
     448            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n",
     449                         pClient->uClientID, pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg),
     450                         pFirstMsg->m_cParms));
     451            return VINF_SUCCESS;
     452        }
     453    }
     454
     455    /*
     456     * If we cannot wait, fail the call.
     457     */
     458    if (!fWait)
     459    {
     460        LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", pClient->uClientID));
     461        return VERR_TRY_AGAIN;
     462    }
     463
     464    /*
     465     * Wait for the host to queue a message for this client.
     466     */
     467    ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n",
     468                                                           pClient->uClientID), VERR_RESOURCE_BUSY);
     469    pClient->Pending.hHandle = hCall;
     470    pClient->Pending.cParms  = cParms;
     471    pClient->Pending.paParms = paParms;
     472    pClient->Pending.uType   = VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT;
     473    LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->uClientID));
     474    return VINF_HGCM_ASYNC_EXECUTE;
     475}
     476
     477/**
     478 * Implements VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET.
     479 *
     480 * @returns VBox status code.
     481 * @retval  VINF_SUCCESS if message retrieved and removed from the pending queue.
     482 * @retval  VERR_TRY_AGAIN if no message pending.
     483 * @retval  VERR_BUFFER_OVERFLOW if a parmeter buffer is too small.  The buffer
     484 *          size was updated to reflect the required size, though this isn't yet
     485 *          forwarded to the guest.  (The guest is better of using peek with
     486 *          parameter count + 2 parameters to get the sizes.)
     487 * @retval  VERR_MISMATCH if the incoming message ID does not match the pending.
     488 * @retval  VINF_HGCM_ASYNC_EXECUTE if message was completed already.
     489 *
     490 * @param   pClient      The client state.
     491 * @param   hCall        The client's call handle.
     492 * @param   cParms       Number of parameters.
     493 * @param   paParms      Array of parameters.
     494 */
     495int vboxSvcClipboardMsgGet(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     496{
     497    /*
     498     * Validate the request.
     499     */
     500    uint32_t const idMsgExpected = cParms > 0 && paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT ? paParms[0].u.uint32
     501                                 : cParms > 0 && paParms[0].type == VBOX_HGCM_SVC_PARM_64BIT ? paParms[0].u.uint64
     502                                 : UINT32_MAX;
     503
     504    /*
     505     * Return information about the first message if one is pending in the list.
     506     */
     507    PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
     508    if (pFirstMsg)
     509    {
     510        LogFlowFunc(("First message is: %RU32 %s (%RU32 parms)\n",
     511                     pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms));
     512
     513        ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_uMsg == idMsgExpected || idMsgExpected == UINT32_MAX,
     514                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
     515                                 pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_uMsg,
     516                                 idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
     517                                VERR_MISMATCH);
     518        ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_cParms == cParms,
     519                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
     520                                 pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms,
     521                                 idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
     522                                VERR_WRONG_PARAMETER_COUNT);
     523
     524        /* Check the parameter types. */
     525        for (uint32_t i = 0; i < cParms; i++)
     526            ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_paParms[i].type == paParms[i].type,
     527                                    ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->m_paParms[i].type,
     528                                     paParms[i].type, pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg)),
     529                                    VERR_WRONG_PARAMETER_TYPE);
     530        /*
     531         * Copy out the parameters.
     532         *
     533         * No assertions on buffer overflows, and keep going till the end so we can
     534         * communicate all the required buffer sizes.
     535         */
     536        int rc = VINF_SUCCESS;
     537        for (uint32_t i = 0; i < cParms; i++)
     538            switch (pFirstMsg->m_paParms[i].type)
     539            {
     540                case VBOX_HGCM_SVC_PARM_32BIT:
     541                    paParms[i].u.uint32 = pFirstMsg->m_paParms[i].u.uint32;
     542                    break;
     543
     544                case VBOX_HGCM_SVC_PARM_64BIT:
     545                    paParms[i].u.uint64 = pFirstMsg->m_paParms[i].u.uint64;
     546                    break;
     547
     548                case VBOX_HGCM_SVC_PARM_PTR:
     549                {
     550                    uint32_t const cbSrc = pFirstMsg->m_paParms[i].u.pointer.size;
     551                    uint32_t const cbDst = paParms[i].u.pointer.size;
     552                    paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
     553                                                        * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
     554                    if (cbSrc <= cbDst)
     555                        memcpy(paParms[i].u.pointer.addr, pFirstMsg->m_paParms[i].u.pointer.addr, cbSrc);
     556                    else
     557                        rc = VERR_BUFFER_OVERFLOW;
     558                    break;
     559                }
     560
     561                default:
     562                    AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->m_paParms[i].type));
     563                    rc = VERR_INTERNAL_ERROR;
     564                    break;
     565            }
     566        if (RT_SUCCESS(rc))
     567        {
     568            /*
     569             * Complete the message and remove the pending message unless the
     570             * guest raced us and cancelled this call in the meantime.
     571             */
     572            AssertPtr(g_pHelpers);
     573            rc = g_pHelpers->pfnCallComplete(hCall, rc);
     574
     575            LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->uClientID, rc));
     576
     577            if (rc != VERR_CANCELLED)
     578            {
     579                pClient->pData->queueMsg.removeFirst();
     580                vboxSvcClipboardMsgFree(pFirstMsg);
     581            }
     582
     583            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     584        }
     585
     586        LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->uClientID, rc));
     587        return rc;
     588    }
     589
     590    paParms[0].u.uint32 = 0;
     591    paParms[1].u.uint32 = 0;
     592    LogFlowFunc(("[Client %RU32] -> VERR_TRY_AGAIN\n", pClient->uClientID));
     593    return VERR_TRY_AGAIN;
     594}
     595
     596int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient)
     597{
     598    int rc = VINF_NO_CHANGE;
     599
     600    if (pClient->Pending.uType)
     601    {
     602        LogFlowFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID));
    374603
    375604        rc = VINF_SUCCESS;
    376     }
    377 
    378     LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puType, *pcParms, rc));
    379     return rc;
    380 }
    381 
    382 /**
    383  * Retrieves the next queued up message and removes it from the queue on success.
    384  * Will return VERR_NO_DATA if no next message is available.
    385  *
    386  * @returns IPRT status code.
    387  * @param   pClientData         Pointer to the client data structure to get message for.
    388  * @param   uMsg                Message type to retrieve.
    389  * @param   cParms              Number of parameters the \@a paParms array can store.
    390  * @param   paParms             Where to store the message parameters.
    391  */
    392 int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTDATA pClientData,
    393                                uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    394 {
    395     LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
    396 
    397     /* Check for pending messages in our queue. */
    398     if (pClientData->queueMsg.isEmpty())
    399         return VERR_NO_DATA;
    400 
    401     /* Get the current message. */
    402     PVBOXCLIPBOARDCLIENTMSG pMsg = pClientData->queueMsg.first();
    403     AssertPtr(pMsg);
    404 
    405     int rc = VINF_SUCCESS;
    406 
    407     /* Fetch the current message info. */
    408     if (pMsg->m_uMsg != uMsg)
    409     {
    410         LogFunc(("Stored message type (%RU32) does not match request (%RU32)\n", pMsg->m_uMsg, uMsg));
    411         rc = VERR_INVALID_PARAMETER;
    412     }
    413     else if (pMsg->m_cParms > cParms)
    414     {
    415         LogFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", pMsg->m_cParms, cParms));
    416         rc = VERR_INVALID_PARAMETER;
    417     }
    418 
    419     if (RT_SUCCESS(rc))
    420     {
    421         rc = Message::CopyParms(paParms, cParms, pMsg->m_paParms, pMsg->m_cParms, true /* fDeepCopy */);
    422 
    423         /** @todo Only remove on success? */
    424         pClientData->queueMsg.removeFirst(); /* Remove the current message from the queue. */
    425     }
    426     else
    427     {
    428         vboxSvcClipboardMsgQueueReset(pClientData);
    429         /** @todo Cleanup, send notification to guest. */
    430     }
    431 
    432     LogFlowFunc(("Message processed with rc=%Rrc\n", rc));
    433     return rc;
     605
     606        if (!pClient->pData->queueMsg.isEmpty())
     607        {
     608            PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
     609            if (pFirstMsg)
     610            {
     611                LogFlowFunc(("[Client %RU32] Current host message is %RU32 (cParms=%RU32)\n",
     612                             pClient->uClientID, pFirstMsg->m_uMsg, pFirstMsg->m_cParms));
     613
     614                if (pClient->Pending.uType == VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT)
     615                {
     616                    vboxSvcClipboardMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms);
     617                    rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS);
     618
     619                    pClient->Pending.hHandle = NULL;
     620                    pClient->Pending.paParms = NULL;
     621                    pClient->Pending.cParms  = 0;
     622                    pClient->Pending.uType   = false;
     623                }
     624            }
     625            else
     626                AssertFailed();
     627        }
     628        else
     629            AssertMsgFailed(("Waking up client ID=%RU32 with no host message in queue is a bad idea\n", pClient->uClientID));
     630
     631        return rc;
     632    }
     633
     634    return VINF_NO_CHANGE;
    434635}
    435636
     
    9191120                                        SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
    9201121
    921                                         rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     1122                                        rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
    9221123                                        if (RT_SUCCESS(rc))
    9231124                                            rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
     
    10361237                                    creationCtx.pvUser = pClientData;
    10371238
    1038                                     rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     1239                                    rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
    10391240                                    if (RT_SUCCESS(rc))
    10401241                                        rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
     
    12331434
    12341435/**
    1235  * Defers a client from returning back to the caller (guest side).
    1236  *
    1237  * @returns VBox status code.
    1238  * @param   pClient             Client to defer.
    1239  * @param   hHandle             The call handle to defer.
    1240  * @param   u32Function         Function ID to save.
    1241  * @param   cParms              Number of parameters to save.
    1242  * @param   paParms             Parameter arrray to save.
    1243  */
    1244 int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
    1245                                 VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    1246 {
    1247     LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
    1248 
    1249     AssertMsgReturn(pClient->fDeferred == false, ("Client already in deferred mode\n"),
    1250                     VERR_WRONG_ORDER);
    1251 
    1252     pClient->fDeferred = true;
    1253 
    1254     pClient->Deferred.hHandle = hHandle;
    1255     pClient->Deferred.uType   = u32Function;
    1256     pClient->Deferred.cParms  = cParms;
    1257     pClient->Deferred.paParms = paParms;
    1258 
    1259     return false;
    1260 }
    1261 
    1262 /**
    1263  * Completes a call of a client, which in turn will return the result to the caller on
    1264  * the guest side.
    1265  *
    1266  * @returns VBox status code.
    1267  * @param   pClient             Client to complete.
    1268  * @param   hHandle             Call handle to complete.
    1269  * @param   rc                  Return code to set for the client.
    1270  */
    1271 int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc)
    1272 {
    1273     RT_NOREF(pClient);
    1274 
    1275     LogFlowFunc(("uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
    1276 
    1277     g_pHelpers->pfnCallComplete(hHandle, rc);
    1278 
    1279     return VINF_SUCCESS;
    1280 }
    1281 
    1282 /**
    1283  * Completes a deferred client.
    1284  *
    1285  * @returns VBox status code.
    1286  * @param   pClient             Client to complete.
    1287  * @param   rcComplete          Return code to set for the client.
    1288  */
    1289 int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rcComplete)
    1290 {
    1291     LogFlowFunc(("uClient=%RU32, fDeferred=%RTbool\n", pClient->uClientID, pClient->fDeferred));
    1292 
    1293     int rc = VINF_SUCCESS;
    1294 
    1295     if (pClient->fDeferred) /* Not deferred? Bail out early. */
    1296     {
    1297         LogFlowFunc(("Completing call\n"));
    1298 
    1299         rc = vboxSvcClipboardClientComplete(pClient, pClient->Deferred.hHandle, rcComplete);
    1300 
    1301         pClient->fDeferred = false;
    1302         RT_ZERO(pClient->Deferred);
    1303     }
    1304 
    1305     return rc;
    1306 }
    1307 
    1308 /**
    1309  * Sets a deferred client's next message info -- when returning to the client, it then
    1310  * can retrieve the actual message sent by the host.
    1311  *
    1312  * @returns VBox status code.
    1313  * @param   pClient             Client to set the next message information for.
    1314  * @param   uMsg                Message ID to set.
    1315  * @param   cParms              Number of parameters of message required.
    1316  */
    1317 int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms)
    1318 {
    1319     int rc;
    1320 
    1321     LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
    1322 
    1323     if (pClient->fDeferred)
    1324     {
    1325         if (pClient->Deferred.cParms >= 2)
    1326         {
    1327             AssertPtrReturn(pClient->Deferred.paParms, VERR_BUFFER_OVERFLOW);
    1328 
    1329             HGCMSvcSetU32(&pClient->Deferred.paParms[0], uMsg);
    1330             HGCMSvcSetU32(&pClient->Deferred.paParms[1], cParms);
    1331 
    1332             rc = VINF_SUCCESS;
    1333         }
    1334         else
    1335             rc = VERR_INVALID_PARAMETER;
    1336     }
    1337     else
    1338         rc = VERR_INVALID_STATE;
    1339 
    1340     LogFlowFuncLeaveRC(rc);
    1341     return rc;
    1342 }
    1343 
    1344 /**
    13451436 * Initializes a Shared Clipboard service's client state.
    13461437 *
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