VirtualBox

Ignore:
Timestamp:
Dec 10, 2019 1:46:40 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
135389
Message:

SharedClipboardSvc,Vbgl: Worked over the host messages, taking locks when needed, not using C++ lists and a bunch of other simplifications. bugref:9437

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-darwin.cpp

    r82480 r82527  
    7070    if (   RT_SUCCESS(rc)
    7171        && fChanged)
    72     {
    73         SHCLFORMATDATA formatData;
    74         RT_ZERO(formatData);
    75 
    76         formatData.Formats = fFormats;
    77 
    78         rc = ShClSvcFormatsReport(pCtx->pClient, &formatData);
    79     }
     72        rc = ShClSvcHostReportFormats(pCtx->pClient, fFormats);
    8073
    8174    LogFlowFuncLeaveRC(rc);
     
    215208#endif
    216209
    217     SHCLDATAREQ dataReq;
    218     RT_ZERO(dataReq);
    219 
    220     dataReq.uFmt   = pFormats->Formats;
    221     dataReq.cbSize = _64K; /** @todo Make this more dynamic. */
    222 
    223     return ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */);
     210    return ShClSvcDataReadRequest(pClient, pFormats->Formats, NULL /* puEvent */);
    224211}
    225212
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r82526 r82527  
    5353
    5454/**
    55  * Structure for keeping a single HGCM message.
     55 * A queued message for the guest.
    5656 */
    5757typedef struct _SHCLCLIENTMSG
    5858{
    59     /** Stored message type. */
    60     uint32_t         uMsg;
    61     /** Number of stored HGCM parameters. */
    62     uint32_t         cParms;
    63     /** Stored HGCM parameters. */
    64     PVBOXHGCMSVCPARM paParms;
    65     /** Message context. */
    66     SHCLMSGCTX       Ctx;
    67 } SHCLCLIENTMSG, *PSHCLCLIENTMSG;
     59    /** The queue list entry. */
     60    RTLISTNODE          ListEntry;
     61    /** Stored message ID (VBOX_SHCL_HOST_MSG_XXX). */
     62    uint32_t            idMsg;
     63    /** Number of stored parameters. */
     64    uint32_t            cParms;
     65    /** The context ID for this message.
     66     * @todo r=bird: Why do we need this? */
     67    uint64_t            idContext;
     68    /** HGCM parameters. */
     69    VBOXHGCMSVCPARM     aParms[RT_FLEXIBLE_ARRAY];
     70} SHCLCLIENTMSG;
     71/** Pointer to a queue message for the guest.   */
     72typedef SHCLCLIENTMSG *PSHCLCLIENTMSG;
    6873
    6974typedef struct SHCLCLIENTTRANSFERSTATE
     
    141146{
    142147    /** General client state data. */
    143     SHCLCLIENTSTATE          State;
    144     RTCRITSECT               CritSect;
    145     /** The client's message queue (FIFO). */
    146     RTCList<SHCLCLIENTMSG *> queueMsg;
     148    SHCLCLIENTSTATE             State;
     149    /** The critical section protecting the queue, event source and whatnot.   */
     150    RTCRITSECT                  CritSect;
     151    /** The client's message queue (SHCLCLIENTMSG). */
     152    RTLISTANCHOR                MsgQueue;
     153    /** Number of allocated messages (updated atomically, not under critsect). */
     154    uint32_t volatile           cAllocatedMessages;
    147155    /** The client's own event source.
    148156     *  Needed for events which are not bound to a specific transfer. */
    149     SHCLEVENTSOURCE          EventSrc;
     157    SHCLEVENTSOURCE             EventSrc;
    150158#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    151159    /** Transfer contextdata. */
     
    210218    /** The actual clipboard formats announced while the host service
    211219     *  is reading clipboard data from the extension. */
    212     uint32_t       uDelayedFormats;
     220    uint32_t       fDelayedFormats;
    213221} SHCLEXTSTATE, *PSHCLEXTSTATE;
    214222
     
    216224
    217225void shClSvcMsgQueueReset(PSHCLCLIENT pClient);
    218 PSHCLCLIENTMSG shClSvcMsgAlloc(uint32_t uMsg, uint32_t cParms);
    219 void shClSvcMsgFree(PSHCLCLIENTMSG pMsg);
    220 void shClSvcMsgSetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms);
    221 int shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend);
     226PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t uMsg, uint32_t cParms);
     227void shClSvcMsgFree(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg);
     228void shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend);
     229int shClSvcMsgAddAndWakeupClient(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg);
    222230
    223231int shClSvcClientInit(PSHCLCLIENT pClient, uint32_t uClientID);
     
    243251 * @{
    244252 */
    245 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, PSHCLDATAREQ pDataReq, PSHCLEVENTID puEvent);
     253int ShClSvcDataReadRequest(PSHCLCLIENT pClient, SHCLFORMAT fFormat, PSHCLEVENTID puEvent);
    246254int ShClSvcDataReadSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, PSHCLDATABLOCK pData);
    247 int ShClSvcFormatsReport(PSHCLCLIENT pClient, PSHCLFORMATDATA pFormats);
     255int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats);
    248256uint32_t ShClSvcGetMode(void);
    249257bool ShClSvcGetHeadless(void);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp

    r82526 r82527  
    121121    int rc;
    122122
    123     PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ,
     123    PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ,
    124124                                             VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ);
    125125    if (pMsgHdr)
     
    162162                                for (uint32_t i = 0; i < pSrcRootListHdr->cRoots; i++)
    163163                                {
    164                                     PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ,
     164                                    PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ,
    165165                                                                               VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
    166166
     
    240240    int rc;
    241241
    242     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN,
     242    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN,
    243243                                          VBOX_SHCL_CPARMS_LIST_OPEN);
    244244    if (pMsg)
     
    300300    int rc;
    301301
    302     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE,
     302    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE,
    303303                                          VBOX_SHCL_CPARMS_LIST_CLOSE);
    304304    if (pMsg)
     
    348348    int rc;
    349349
    350     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ,
     350    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ,
    351351                                          VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ);
    352352    if (pMsg)
     
    409409    int rc;
    410410
    411     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ,
     411    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ,
    412412                                          VBOX_SHCL_CPARMS_LIST_ENTRY_READ);
    413413    if (pMsg)
     
    469469    int rc;
    470470
    471     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN,
     471    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN,
    472472                                          VBOX_SHCL_CPARMS_OBJ_OPEN);
    473473    if (pMsg)
     
    531531    int rc;
    532532
    533     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE,
     533    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE,
    534534                                          VBOX_SHCL_CPARMS_OBJ_CLOSE);
    535535    if (pMsg)
     
    587587    int rc;
    588588
    589     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ,
     589    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ,
    590590                                          VBOX_SHCL_CPARMS_OBJ_READ_REQ);
    591591    if (pMsg)
     
    646646    int rc;
    647647
    648     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_WRITE,
     648    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_WRITE,
    649649                                          VBOX_SHCL_CPARMS_OBJ_WRITE);
    650650    if (pMsg)
     
    19861986    /* puEvent is optional. */
    19871987
    1988     PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,
     1988    PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,
    19891989                                                  VBOX_SHCL_CPARMS_TRANSFER_STATUS);
    19901990    if (!pMsgReadData)
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r82526 r82527  
    167167}
    168168
    169 static int vboxClipboardSvcWinDataRead(PSHCLCONTEXT pCtx, UINT cfFormat,
    170                                        void **ppvData, uint32_t *pcbData)
    171 {
    172     SHCLDATAREQ dataReq;
    173     RT_ZERO(dataReq);
    174 
    175     dataReq.uFmt   = SharedClipboardWinClipboardFormatToVBox(cfFormat);
    176     dataReq.cbSize = _64K; /** @todo Make this more dynamic. */
    177 
    178     LogFlowFunc(("cfFormat=%u -> uFmt=0x%x\n", cfFormat, dataReq.uFmt));
    179 
    180     if (dataReq.uFmt == VBOX_SHCL_FMT_NONE)
    181     {
    182         LogRel2(("Shared Clipbaord: Windows format %u not supported, ingoring\n", cfFormat));
     169static int vboxClipboardSvcWinDataRead(PSHCLCONTEXT pCtx, UINT uFormat, void **ppvData, uint32_t *pcbData)
     170{
     171    SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(uFormat);
     172    LogFlowFunc(("uFormat=%u -> uFmt=0x%x\n", uFormat, fFormat));
     173
     174    if (fFormat == VBOX_SHCL_FMT_NONE)
     175    {
     176        LogRel2(("Shared Clipbaord: Windows format %u not supported, ingoring\n", uFormat));
    183177        return VERR_NOT_SUPPORTED;
    184178    }
    185179
    186180    SHCLEVENTID uEvent = 0;
    187     int rc = ShClSvcDataReadRequest(pCtx->pClient, &dataReq, &uEvent);
     181    int rc = ShClSvcDataReadRequest(pCtx->pClient, fFormat, &uEvent);
    188182    if (RT_SUCCESS(rc))
    189183    {
     
    310304
    311305            /* Insert the requested clipboard format data into the clipboard. */
    312             const UINT cfFormat = (UINT)wParam;
    313 
    314             const SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(cfFormat);
    315 
    316             LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
     306            const UINT       uFormat = (UINT)wParam;
     307            const SHCLFORMAT fFormat = SharedClipboardWinClipboardFormatToVBox(uFormat);
     308            LogFunc(("WM_RENDERFORMAT: uFormat=%u -> fFormat=0x%x\n", uFormat, fFormat));
    317309
    318310            if (   fFormat       == VBOX_SHCL_FMT_NONE
     
    327319                void    *pvData = NULL;
    328320                uint32_t cbData = 0;
    329                 int rc = vboxClipboardSvcWinDataRead(pCtx, cfFormat, &pvData, &cbData);
     321                int rc = vboxClipboardSvcWinDataRead(pCtx, uFormat, &pvData, &cbData);
    330322                if (   RT_SUCCESS(rc)
    331323                    && pvData
    332324                    && cbData)
    333325                {
    334                     rc = vboxClipboardSvcWinDataSet(pCtx, cfFormat, pvData, cbData);
     326                    rc = vboxClipboardSvcWinDataSet(pCtx, uFormat, pvData, cbData);
    335327
    336328                    RTMemFree(pvData);
     
    597589        rc = SharedClipboardWinGetFormats(&pCtx->Win, &Formats);
    598590        if (   RT_SUCCESS(rc)
    599             && Formats.Formats != VBOX_SHCL_FMT_NONE)
    600         {
    601             rc = ShClSvcFormatsReport(pCtx->pClient, &Formats);
    602         }
     591            && Formats.Formats != VBOX_SHCL_FMT_NONE) /** @todo r=bird: BUGBUG: revisit this. */
     592            rc = ShClSvcHostReportFormats(pCtx->pClient, Formats.Formats);
    603593    }
    604594    else /* If we don't have any client data (yet), bail out. */
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp

    r82526 r82527  
    113113     * there is data in the host clipboard it will automatically be sent to
    114114     * the guest when the clipboard starts up. */
    115     SHCLFORMATDATA formatData;
    116     RT_ZERO(formatData);
    117 
    118     formatData.Formats = VBOX_SHCL_FMT_NONE;
    119 
    120     return ShClSvcFormatsReport(pClient, &formatData);
     115    return ShClSvcHostReportFormats(pClient, VBOX_SHCL_FMT_NONE);
    121116}
    122117
     
    250245 *
    251246 * @param  pCtx                 Opaque context pointer for the glue code.
    252  * @param  Formats              The formats available.
    253  */
    254 DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t Formats)
    255 {
    256     LogFlowFunc(("pCtx=%p, Formats=%02X\n", pCtx, Formats));
    257 
    258     if (Formats == VBOX_SHCL_FMT_NONE) /* No formats to report? Bail out early. */
     247 * @param  fFormats             The formats available.
     248 */
     249DECLCALLBACK(void) ShClX11ReportFormatsCallback(PSHCLCONTEXT pCtx, uint32_t fFormats)
     250{
     251    LogFlowFunc(("pCtx=%p, fFormats=%#x\n", pCtx, fFormats));
     252
     253    /** @todo r=bird: BUGBUG: Revisit this   */
     254    if (fFormats == VBOX_SHCL_FMT_NONE) /* No formats to report? Bail out early. */
    259255        return;
    260256
    261     SHCLFORMATDATA formatData;
    262     RT_ZERO(formatData);
    263 
    264     formatData.Formats = Formats;
    265 
    266     int rc = ShClSvcFormatsReport(pCtx->pClient, &formatData);
     257    int rc = ShClSvcHostReportFormats(pCtx->pClient, fFormats);
    267258    RT_NOREF(rc);
    268259
     
    317308 *
    318309 * @param  pCtx      Pointer to the host clipboard structure.
    319  * @param  Format    The format in which the data should be transferred.
     310 * @param  fFormat   The format in which the data should be transferred
     311 *                   (VBOX_SHCL_FMT_XXX).
    320312 * @param  ppv       On success and if pcb > 0, this will point to a buffer
    321313 *                   to be freed with RTMemFree containing the data read.
     
    323315 *                   returned.
    324316 */
    325 DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT Format, void **ppv, uint32_t *pcb)
    326 {
    327     LogFlowFunc(("pCtx=%p, Format=0x%x\n", pCtx, Format));
     317DECLCALLBACK(int) ShClX11RequestDataForX11Callback(PSHCLCONTEXT pCtx, SHCLFORMAT fFormat, void **ppv, uint32_t *pcb)
     318{
     319    LogFlowFunc(("pCtx=%p, Format=0x%x\n", pCtx, fFormat));
    328320
    329321    if (pCtx->fShuttingDown)
     
    337329
    338330#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    339     if (Format == VBOX_SHCL_FMT_URI_LIST)
    340     {
    341         rc = 0;
    342     }
     331    if (fFormat == VBOX_SHCL_FMT_URI_LIST)
     332        rc = VINF_SUCCESS;
    343333    else
    344334#endif
    345335    {
    346336        /* Request data from the guest. */
    347         SHCLDATAREQ dataReq;
    348         RT_ZERO(dataReq);
    349 
    350         dataReq.uFmt   = Format;
    351         dataReq.cbSize = _64K; /** @todo Make this more dynamic. */
    352 
    353337        SHCLEVENTID uEvent;
    354         rc = ShClSvcDataReadRequest(pCtx->pClient, &dataReq, &uEvent);
     338        rc = ShClSvcDataReadRequest(pCtx->pClient, fFormat, &uEvent);
    355339        if (RT_SUCCESS(rc))
    356340        {
     
    375359
    376360#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     361
    377362int ShClSvcImplTransferCreate(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    378363{
     
    429414    return rc;
    430415}
    431 #endif
     416
     417#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r82526 r82527  
    368368 *
    369369 * @param   pClient             Pointer to the client data structure to reset message queue for.
     370 * @note    Caller enters pClient->CritSect.
    370371 */
    371372void shClSvcMsgQueueReset(PSHCLCLIENT pClient)
    372373{
     374    Assert(RTCritSectIsOwner(&pClient->CritSect));
    373375    LogFlowFuncEnter();
    374376
    375     while (!pClient->queueMsg.isEmpty())
    376     {
    377         RTMemFree(pClient->queueMsg.last());
    378         pClient->queueMsg.removeLast();
     377    while (!RTListIsEmpty(&pClient->MsgQueue))
     378    {
     379        PSHCLCLIENTMSG pMsg = RTListRemoveFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry);
     380        shClSvcMsgFree(pClient, pMsg);
    379381    }
    380382}
     
    384386 *
    385387 * @returns Allocated clipboard message, or NULL on failure.
    386  * @param   uMsg                Message type of message to allocate.
    387  * @param   cParms              Number of HGCM parameters to allocate.
    388  */
    389 PSHCLCLIENTMSG shClSvcMsgAlloc(uint32_t uMsg, uint32_t cParms)
    390 {
    391     PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAlloc(sizeof(SHCLCLIENTMSG));
     388 * @param   pClient     The client which is target of this message.
     389 * @param   idMsg       The message ID (VBOX_SHCL_HOST_MSG_XXX) to use
     390 * @param   cParms      The number of parameters the message takes.
     391 */
     392PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t idMsg, uint32_t cParms)
     393{
     394    RT_NOREF(pClient);
     395    PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAllocZ(RT_UOFFSETOF_DYN(SHCLCLIENTMSG, aParms[cParms]));
    392396    if (pMsg)
    393397    {
    394         pMsg->paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * cParms);
    395         if (pMsg->paParms)
    396         {
     398        uint32_t cAllocated = ASMAtomicIncU32(&pClient->cAllocatedMessages);
     399        if (cAllocated <= 4096)
     400        {
     401            RTListInit(&pMsg->ListEntry);
    397402            pMsg->cParms = cParms;
    398             pMsg->uMsg   = uMsg;
    399 
     403            pMsg->idMsg  = idMsg;
    400404            return pMsg;
    401405        }
    402     }
    403 
    404     RTMemFree(pMsg);
     406        AssertMsgFailed(("Too many messages allocated for client %u! (%u)\n", pClient->State.uClientID, cAllocated));
     407        ASMAtomicDecU32(&pClient->cAllocatedMessages);
     408        RTMemFree(pMsg);
     409    }
    405410    return NULL;
    406411}
     
    409414 * Frees a formerly allocated clipboard message.
    410415 *
    411  * @param   pMsg                Clipboard message to free.
    412  *                              The pointer will be invalid after calling this function.
    413  */
    414 void shClSvcMsgFree(PSHCLCLIENTMSG pMsg)
    415 {
    416     if (!pMsg)
    417         return;
    418 
    419     if (pMsg->paParms)
    420         RTMemFree(pMsg->paParms);
    421 
    422     RTMemFree(pMsg);
    423     pMsg = NULL;
     416 * @param   pClient     The client which was the target of this message.
     417 * @param   pMsg        Clipboard message to free.
     418 */
     419void shClSvcMsgFree(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg)
     420{
     421    RT_NOREF(pClient);
     422    /** @todo r=bird: Do accounting. */
     423    if (pMsg)
     424    {
     425        pMsg->idMsg = UINT32_C(0xdeadface);
     426        RTMemFree(pMsg);
     427
     428        uint32_t cAllocated = ASMAtomicDecU32(&pClient->cAllocatedMessages);
     429        Assert(cAllocated < UINT32_MAX / 2);
     430    }
    424431}
    425432
     
    433440 * @remarks ASSUMES the parameters has been cleared by clientMsgPeek.
    434441 */
    435 void shClSvcMsgSetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
     442static void shClSvcMsgSetPeekReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
    436443{
    437444    Assert(cDstParms >= 2);
    438445    if (paDstParms[0].type == VBOX_HGCM_SVC_PARM_32BIT)
    439         paDstParms[0].u.uint32 = pMsg->uMsg;
     446        paDstParms[0].u.uint32 = pMsg->idMsg;
    440447    else
    441         paDstParms[0].u.uint64 = pMsg->uMsg;
     448        paDstParms[0].u.uint64 = pMsg->idMsg;
    442449    paDstParms[1].u.uint32 = pMsg->cParms;
    443450
    444451    uint32_t i = RT_MIN(cDstParms, pMsg->cParms + 2);
    445452    while (i-- > 2)
    446         switch (pMsg->paParms[i - 2].type)
     453        switch (pMsg->aParms[i - 2].type)
    447454        {
    448455            case VBOX_HGCM_SVC_PARM_32BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
    449456            case VBOX_HGCM_SVC_PARM_64BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
    450             case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = pMsg->paParms[i - 2].u.pointer.size; break;
     457            case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = pMsg->aParms[i - 2].u.pointer.size; break;
    451458        }
    452459}
     
    455462 * Sets the VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT return parameters.
    456463 *
    457  * This function does the necessary translation between the legacy protocol (<= VBox 6.0) and the new protocols (>= VBox 6.1),
    458  * as messages are always stored as >= v1 messages in the message queue.
    459  *
    460464 * @returns VBox status code.
    461  * @param   pMsg        Message to set return parameters to.
     465 * @param   pMsg        The message which parameters to return to the guest.
    462466 * @param   paDstParms  The peek parameter vector.
    463  * @param   cDstParms   The number of peek parameters (at least two).
    464  * @param   pfRemove    Returns whether the message can be removed from the queue or not.
    465  *                      This is needed for certain messages which need to stay around for more than one (guest) call.
    466  */
    467 int shClSvcMsgSetGetHostMsgOldReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms,
    468                                      bool *pfRemove)
    469 {
    470     AssertPtrReturn(pMsg,           VERR_INVALID_POINTER);
    471     AssertPtrReturn(paDstParms,     VERR_INVALID_POINTER);
    472     AssertReturn   (cDstParms >= 2, VERR_INVALID_PARAMETER);
    473     AssertPtrReturn(pfRemove,       VERR_INVALID_POINTER);
    474 
    475     int rc = VINF_SUCCESS;
    476 
    477     bool fRemove = true;
    478 
    479     LogFlowFunc(("uMsg=%RU32 (%s), cParms=%RU32\n",
    480                  pMsg->uMsg, ShClHostMsgToStr(pMsg->uMsg), pMsg->cParms));
    481 
    482     switch (pMsg->uMsg)
    483     {
    484         case VBOX_SHCL_HOST_MSG_QUIT:
    485         {
    486             HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_QUIT);
    487             HGCMSvcSetU32(&paDstParms[1], 0 /* Not used */);
     467 * @param   cDstParms   The number of peek parameters should be exactly two
     468 */
     469static int shClSvcMsgSetOldWaitReturn(PSHCLCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
     470{
     471    /*
     472     * Assert sanity.
     473     */
     474    AssertPtr(pMsg);
     475    AssertPtrReturn(paDstParms, VERR_INVALID_POINTER);
     476    AssertReturn(cDstParms >= 2, VERR_INVALID_PARAMETER);
     477
     478    Assert(pMsg->cParms == 2);
     479    Assert(pMsg->aParms[0].u.uint32 == pMsg->idMsg);
     480    switch (pMsg->idMsg)
     481    {
     482        case VBOX_SHCL_HOST_MSG_READ_DATA:
     483        case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
    488484            break;
    489         }
    490 
    491         case VBOX_SHCL_HOST_MSG_READ_DATA:
    492         {
    493             HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_READ_DATA);
    494             AssertBreakStmt(pMsg->cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */
    495             uint32_t uSrcFmt = VBOX_SHCL_FMT_NONE;
    496             uint32_t uDstFmt = VBOX_SHCL_FMT_NONE;
    497             rc = HGCMSvcGetU32(&pMsg->paParms[2] /* uFormat */, &uSrcFmt);
    498             if (RT_SUCCESS(rc))
    499             {
    500                 if (uSrcFmt & VBOX_SHCL_FMT_UNICODETEXT)
    501                     uDstFmt = VBOX_SHCL_FMT_UNICODETEXT;
    502                 else if (uSrcFmt & VBOX_SHCL_FMT_BITMAP)
    503                     uDstFmt = VBOX_SHCL_FMT_BITMAP;
    504                 else if (uSrcFmt & VBOX_SHCL_FMT_HTML)
    505                     uDstFmt = VBOX_SHCL_FMT_HTML;
    506                 else
    507                     AssertStmt(uSrcFmt == VBOX_SHCL_FMT_NONE, uSrcFmt = VBOX_SHCL_FMT_NONE);
    508 
    509                 LogFlowFunc(("uSrcFmt=0x%x, uDstFmt=0x%x\n", uSrcFmt, uDstFmt));
    510 
    511                 /* Remove format we're going to return from the queued message. */
    512                 uSrcFmt &= ~uDstFmt;
    513                 HGCMSvcSetU32(&pMsg->paParms[2], uSrcFmt);
    514 
    515                 /* Only report back one format at a time. */
    516                 HGCMSvcSetU32(&paDstParms[1], uDstFmt);
    517 
    518                 /* If no more formats are left, the message can be removed finally. */
    519                 fRemove = uSrcFmt == VBOX_SHCL_FMT_NONE;
    520 
    521                 LogFlowFunc(("uSrcFmt=0x%x, fRemove=%RTbool\n", uSrcFmt, fRemove));
    522             }
    523             break;
    524         }
    525 
    526         case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
    527         {
    528             HGCMSvcSetU32(&paDstParms[0], VBOX_SHCL_HOST_MSG_FORMATS_REPORT);
    529             AssertBreakStmt(pMsg->cParms >= 2, rc = VERR_INVALID_PARAMETER); /* Paranoia. */
    530             uint32_t uFmts;
    531             rc = HGCMSvcGetU32(&pMsg->paParms[1] /* uFormats */, &uFmts);
    532             if (RT_SUCCESS(rc))
    533                 HGCMSvcSetU32(&paDstParms[1], uFmts);
    534             break;
    535         }
    536 
    537485        default:
    538             AssertFailed(); /* Not supported by legacy protocol. */
    539             rc = VERR_NOT_SUPPORTED;
    540             break;
    541     }
    542 
    543     *pfRemove = fRemove;
    544 
    545     LogFlowFuncLeaveRC(rc);
    546     return rc;
     486            AssertFailed();
     487    }
     488
     489    /*
     490     * Set the parameters.
     491     */
     492    if (pMsg->cParms > 0)
     493        paDstParms[0] = pMsg->aParms[0];
     494    if (pMsg->cParms > 1)
     495        paDstParms[1] = pMsg->aParms[1];
     496    return VINF_SUCCESS;
    547497}
    548498
     
    554504 * @param   pMsg                Pointer to message to add. The queue then owns the pointer.
    555505 * @param   fAppend             Whether to append or prepend the message to the queue.
    556  */
    557 int shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend)
    558 {
    559     AssertPtrReturn(pMsg, VERR_INVALID_POINTER);
    560 
    561     LogFlowFunc(("uMsg=%RU32 (%s), cParms=%RU32, fAppend=%RTbool\n",
    562                  pMsg->uMsg, ShClHostMsgToStr(pMsg->uMsg), pMsg->cParms, fAppend));
     506 *
     507 * @note    Caller must enter critical section.
     508 */
     509void shClSvcMsgAdd(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg, bool fAppend)
     510{
     511    Assert(RTCritSectIsOwned(&pClient->CritSect));
     512    AssertPtr(pMsg);
     513
     514    LogFlowFunc(("idMsg=%s (%RU32) cParms=%RU32 fAppend=%RTbool\n",
     515                 ShClHostMsgToStr(pMsg->idMsg), pMsg->idMsg, pMsg->cParms, fAppend));
    563516
    564517    if (fAppend)
    565         pClient->queueMsg.append(pMsg);
     518        RTListAppend(&pClient->MsgQueue, &pMsg->ListEntry);
    566519    else
    567         pClient->queueMsg.prepend(pMsg);
    568 
    569     /** @todo Catch / handle OOM? */
    570 
    571     return VINF_SUCCESS;
     520        RTListPrepend(&pClient->MsgQueue, &pMsg->ListEntry);
     521}
     522
     523
     524/**
     525 * Appends a message to the client's queue and wake it up.
     526 *
     527 * @returns VBox status code, though the message is consumed regardless of what
     528 *          is returned.
     529 * @param   pClient             The client to queue the message on.
     530 * @param   pMsg                The message to queue.  Ownership is always
     531 *                              transfered to the queue.
     532 *
     533 * @note    Caller must enter critical section.
     534 */
     535int shClSvcMsgAddAndWakeupClient(PSHCLCLIENT pClient, PSHCLCLIENTMSG pMsg)
     536{
     537    Assert(RTCritSectIsOwned(&pClient->CritSect));
     538    AssertPtr(pMsg);
     539    AssertPtr(pClient);
     540    LogFlowFunc(("idMsg=%s (%u) cParms=%u\n", ShClHostMsgToStr(pMsg->idMsg), pMsg->idMsg, pMsg->cParms));
     541
     542    RTListAppend(&pClient->MsgQueue, &pMsg->ListEntry);
     543    return shClSvcClientWakeup(pClient);
    572544}
    573545
     
    584556    /* Assign the client ID. */
    585557    pClient->State.uClientID = uClientID;
     558    RTListInit(&pClient->MsgQueue);
     559    pClient->cAllocatedMessages = 0;
    586560
    587561    LogFlowFunc(("[Client %RU32]\n", pClient->State.uClientID));
     
    669643
    670644    LogFlowFunc(("[Client %RU32]\n", pClient->State.uClientID));
     645    RTCritSectEnter(&pClient->CritSect);
    671646
    672647    /* Reset message queue. */
     
    684659
    685660    shclSvcClientStateReset(&pClient->State);
     661
     662    RTCritSectLeave(&pClient->CritSect);
    686663}
    687664
     
    824801     * Return information about the first message if one is pending in the list.
    825802     */
    826     if (!pClient->queueMsg.isEmpty())
    827     {
    828         PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first();
    829         if (pFirstMsg)
    830         {
    831             shClSvcMsgSetPeekReturn(pFirstMsg, paParms, cParms);
    832             LogFlowFunc(("[Client %RU32] VBOX_SHCL_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n",
    833                          pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg),
    834                          pFirstMsg->cParms));
    835             return VINF_SUCCESS;
    836         }
     803    PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry);
     804    if (pFirstMsg)
     805    {
     806        shClSvcMsgSetPeekReturn(pFirstMsg, paParms, cParms);
     807        LogFlowFunc(("[Client %RU32] VBOX_SHCL_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%s (%u), cParms=%u)\n",
     808                     pClient->State.uClientID, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms));
     809        return VINF_SUCCESS;
    837810    }
    838811
     
    875848static int shClSvcClientMsgOldGet(PSHCLCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    876849{
     850    /*
     851     * Validate input.
     852     */
     853    ASSERT_GUEST_RETURN(cParms == VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD, VERR_WRONG_PARAMETER_COUNT);
     854    ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* id32Msg */
     855    ASSERT_GUEST_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* f32Formats */
     856
     857    paParms[0].u.uint32 = 0;
     858    paParms[1].u.uint32 = 0;
     859
     860    /*
     861     * If there is a message pending we can return immediately.
     862     */
    877863    int rc;
    878 
    879     if (cParms != VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD)
    880     {
    881         rc = VERR_INVALID_PARAMETER;
    882     }
    883     else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT  /* msg */
    884              || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT) /* formats */
    885     {
    886         rc = VERR_INVALID_PARAMETER;
    887     }
     864    PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry);
     865    if (pFirstMsg)
     866    {
     867        LogFlowFunc(("[Client %RU32] uMsg=%s (%RU32), cParms=%RU32\n", pClient->State.uClientID,
     868                     ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms));
     869
     870        rc = shClSvcMsgSetOldWaitReturn(pFirstMsg, paParms, cParms);
     871        AssertPtr(g_pHelpers);
     872        rc = g_pHelpers->pfnCallComplete(hCall, rc);
     873        if (rc != VERR_CANCELLED)
     874        {
     875            RTListNodeRemove(&pFirstMsg->ListEntry);
     876            shClSvcMsgFree(pClient, pFirstMsg);
     877
     878            rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     879        }
     880    }
     881    /*
     882     * Otherwise we must wait.
     883     */
    888884    else
    889885    {
    890         if (!pClient->queueMsg.isEmpty())
    891         {
    892             PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first();
    893             AssertPtr(pFirstMsg);
    894 
    895             LogFlowFunc(("[Client %RU32] uMsg=%RU32 (%s), cParms=%RU32\n",
    896                          pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg),
    897                          pFirstMsg->cParms));
    898 
    899             bool fRemove;
    900             rc = shClSvcMsgSetGetHostMsgOldReturn(pFirstMsg, paParms, cParms, &fRemove);
    901             if (RT_SUCCESS(rc))
    902             {
    903                 AssertPtr(g_pHelpers);
    904                 rc = g_pHelpers->pfnCallComplete(hCall, rc);
    905                 if (   rc != VERR_CANCELLED
    906                     && fRemove)
    907                 {
    908                     pClient->queueMsg.removeFirst();
    909                     shClSvcMsgFree(pFirstMsg);
    910 
    911                     rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
    912                 }
    913             }
    914         }
    915         else
    916         {
    917             ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n",
    918                                                                    pClient->State.uClientID), VERR_RESOURCE_BUSY);
    919 
    920             pClient->Pending.hHandle = hCall;
    921             pClient->Pending.cParms  = cParms;
    922             pClient->Pending.paParms = paParms;
    923             pClient->Pending.uType   = VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT;
    924 
    925             rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
    926 
    927             LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->State.uClientID));
    928         }
     886        ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n", pClient->State.uClientID),
     887                                VERR_RESOURCE_BUSY);
     888
     889        pClient->Pending.hHandle = hCall;
     890        pClient->Pending.cParms  = cParms;
     891        pClient->Pending.paParms = paParms;
     892        pClient->Pending.uType   = VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT;
     893
     894        rc = VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     895
     896        LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->State.uClientID));
    929897    }
    930898
     
    965933     * Return information about the first message if one is pending in the list.
    966934     */
    967     if (!pClient->queueMsg.isEmpty())
    968     {
    969         PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first();
    970         if (pFirstMsg)
    971         {
    972             LogFlowFunc(("First message is: %RU32 (%s), cParms=%RU32\n",
    973                          pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms));
    974 
    975             ASSERT_GUEST_MSG_RETURN(pFirstMsg->uMsg == idMsgExpected || idMsgExpected == UINT32_MAX,
    976                                     ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
    977                                      pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms,
    978                                      idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms),
    979                                     VERR_MISMATCH);
    980             ASSERT_GUEST_MSG_RETURN(pFirstMsg->cParms == cParms,
    981                                     ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
    982                                      pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg), pFirstMsg->cParms,
    983                                      idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms),
    984                                     VERR_WRONG_PARAMETER_COUNT);
    985 
    986             /* Check the parameter types. */
    987             for (uint32_t i = 0; i < cParms; i++)
    988                 ASSERT_GUEST_MSG_RETURN(pFirstMsg->paParms[i].type == paParms[i].type,
    989                                         ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->paParms[i].type,
    990                                          paParms[i].type, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg)),
    991                                         VERR_WRONG_PARAMETER_TYPE);
     935    PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry);
     936    if (pFirstMsg)
     937    {
     938        LogFlowFunc(("First message is: %s (%u), cParms=%RU32\n", ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms));
     939
     940        ASSERT_GUEST_MSG_RETURN(pFirstMsg->idMsg == idMsgExpected || idMsgExpected == UINT32_MAX,
     941                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
     942                                 pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->cParms,
     943                                 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms),
     944                                VERR_MISMATCH);
     945        ASSERT_GUEST_MSG_RETURN(pFirstMsg->cParms == cParms,
     946                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
     947                                 pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->cParms,
     948                                 idMsgExpected, ShClHostMsgToStr(idMsgExpected), cParms),
     949                                VERR_WRONG_PARAMETER_COUNT);
     950
     951        /* Check the parameter types. */
     952        for (uint32_t i = 0; i < cParms; i++)
     953            ASSERT_GUEST_MSG_RETURN(pFirstMsg->aParms[i].type == paParms[i].type,
     954                                    ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->aParms[i].type,
     955                                     paParms[i].type, pFirstMsg->idMsg, ShClHostMsgToStr(pFirstMsg->idMsg)),
     956                                    VERR_WRONG_PARAMETER_TYPE);
     957        /*
     958         * Copy out the parameters.
     959         *
     960         * No assertions on buffer overflows, and keep going till the end so we can
     961         * communicate all the required buffer sizes.
     962         */
     963        int rc = VINF_SUCCESS;
     964        for (uint32_t i = 0; i < cParms; i++)
     965            switch (pFirstMsg->aParms[i].type)
     966            {
     967                case VBOX_HGCM_SVC_PARM_32BIT:
     968                    paParms[i].u.uint32 = pFirstMsg->aParms[i].u.uint32;
     969                    break;
     970
     971                case VBOX_HGCM_SVC_PARM_64BIT:
     972                    paParms[i].u.uint64 = pFirstMsg->aParms[i].u.uint64;
     973                    break;
     974
     975                case VBOX_HGCM_SVC_PARM_PTR:
     976                {
     977                    uint32_t const cbSrc = pFirstMsg->aParms[i].u.pointer.size;
     978                    uint32_t const cbDst = paParms[i].u.pointer.size;
     979                    paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
     980                                                        * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
     981                    if (cbSrc <= cbDst)
     982                        memcpy(paParms[i].u.pointer.addr, pFirstMsg->aParms[i].u.pointer.addr, cbSrc);
     983                    else
     984                    {
     985                        AssertMsgFailed(("#%u: cbSrc=%RU32 is bigger than cbDst=%RU32\n", i, cbSrc, cbDst));
     986                        rc = VERR_BUFFER_OVERFLOW;
     987                    }
     988                    break;
     989                }
     990
     991                default:
     992                    AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->aParms[i].type));
     993                    rc = VERR_INTERNAL_ERROR;
     994                    break;
     995            }
     996        if (RT_SUCCESS(rc))
     997        {
    992998            /*
    993              * Copy out the parameters.
    994              *
    995              * No assertions on buffer overflows, and keep going till the end so we can
    996              * communicate all the required buffer sizes.
     999             * Complete the message and remove the pending message unless the
     1000             * guest raced us and cancelled this call in the meantime.
    9971001             */
    998             int rc = VINF_SUCCESS;
    999             for (uint32_t i = 0; i < cParms; i++)
    1000                 switch (pFirstMsg->paParms[i].type)
    1001                 {
    1002                     case VBOX_HGCM_SVC_PARM_32BIT:
    1003                         paParms[i].u.uint32 = pFirstMsg->paParms[i].u.uint32;
    1004                         break;
    1005 
    1006                     case VBOX_HGCM_SVC_PARM_64BIT:
    1007                         paParms[i].u.uint64 = pFirstMsg->paParms[i].u.uint64;
    1008                         break;
    1009 
    1010                     case VBOX_HGCM_SVC_PARM_PTR:
    1011                     {
    1012                         uint32_t const cbSrc = pFirstMsg->paParms[i].u.pointer.size;
    1013                         uint32_t const cbDst = paParms[i].u.pointer.size;
    1014                         paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
    1015                                                             * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
    1016                         if (cbSrc <= cbDst)
    1017                             memcpy(paParms[i].u.pointer.addr, pFirstMsg->paParms[i].u.pointer.addr, cbSrc);
    1018                         else
    1019                         {
    1020                             AssertMsgFailed(("#%u: cbSrc=%RU32 is bigger than cbDst=%RU32\n", i, cbSrc, cbDst));
    1021                             rc = VERR_BUFFER_OVERFLOW;
    1022                         }
    1023                         break;
    1024                     }
    1025 
    1026                     default:
    1027                         AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->paParms[i].type));
    1028                         rc = VERR_INTERNAL_ERROR;
    1029                         break;
    1030                 }
    1031             if (RT_SUCCESS(rc))
     1002            AssertPtr(g_pHelpers);
     1003            rc = g_pHelpers->pfnCallComplete(hCall, rc);
     1004
     1005            LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->State.uClientID, rc));
     1006
     1007            if (rc != VERR_CANCELLED)
    10321008            {
    1033                 /*
    1034                  * Complete the message and remove the pending message unless the
    1035                  * guest raced us and cancelled this call in the meantime.
    1036                  */
    1037                 AssertPtr(g_pHelpers);
    1038                 rc = g_pHelpers->pfnCallComplete(hCall, rc);
    1039 
    1040                 LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->State.uClientID, rc));
    1041 
    1042                 if (rc != VERR_CANCELLED)
    1043                 {
    1044                     pClient->queueMsg.removeFirst();
    1045                     shClSvcMsgFree(pFirstMsg);
    1046                 }
    1047 
    1048                 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     1009                RTListNodeRemove(&pFirstMsg->ListEntry);
     1010                shClSvcMsgFree(pClient, pFirstMsg);
    10491011            }
    10501012
    1051             LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->State.uClientID, rc));
    1052             return rc;
    1053         }
     1013            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     1014        }
     1015
     1016        LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->State.uClientID, rc));
     1017        return rc;
    10541018    }
    10551019
     
    10961060        {
    10971061            Assert(pClient->Pending.cParms >= 2);
    1098             HGCMSvcSetU32(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED);
     1062            if (pClient->Pending.paParms[0].type == VBOX_HGCM_SVC_PARM_64BIT)
     1063                HGCMSvcSetU64(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED);
     1064            else
     1065                HGCMSvcSetU32(&pClient->Pending.paParms[0], VBOX_SHCL_HOST_MSG_CANCELED);
    10991066            rcComplete = VINF_TRY_AGAIN;
    11001067        }
     
    11331100 *
    11341101 * @param   pClient             Client to wake up.
     1102 * @note    Caller must enter pClient->CritSect.
    11351103 */
    11361104int shClSvcClientWakeup(PSHCLCLIENT pClient)
    11371105{
     1106    Assert(RTCritSectIsOwner(&pClient->CritSect));
    11381107    int rc = VINF_NO_CHANGE;
    11391108
    1140     if (pClient->Pending.uType)
     1109    if (pClient->Pending.uType != 0)
    11411110    {
    11421111        LogFunc(("[Client %RU32] Waking up ...\n", pClient->State.uClientID));
    11431112
    1144         rc = VINF_SUCCESS;
    1145 
    1146         if (!pClient->queueMsg.isEmpty())
    1147         {
    1148             PSHCLCLIENTMSG pFirstMsg = pClient->queueMsg.first();
    1149             if (pFirstMsg)
    1150             {
    1151                 LogFunc(("[Client %RU32] Current host message is %RU32 (%s), cParms=%RU32\n",
    1152                          pClient->State.uClientID, pFirstMsg->uMsg, ShClHostMsgToStr(pFirstMsg->uMsg),
    1153                          pFirstMsg->cParms));
    1154 
    1155                 bool fDonePending = false;
    1156 
    1157                 if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT)
    1158                 {
    1159                     shClSvcMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms);
    1160                     fDonePending = true;
    1161                 }
    1162                 else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT) /* Legacy, Guest Additions < 6.1. */
    1163                 {
    1164                     bool fRemove;
    1165                     rc = shClSvcMsgSetGetHostMsgOldReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms,
    1166                                                           &fRemove);
    1167                     if (RT_SUCCESS(rc))
    1168                     {
    1169                         if (fRemove)
    1170                         {
    1171                             /* The old (legacy) protocol gets the message right when returning from peeking, so
    1172                              * remove the actual message from our queue right now. */
    1173                             pClient->queueMsg.removeFirst();
    1174                             shClSvcMsgFree(pFirstMsg);
    1175                         }
    1176 
    1177                         fDonePending = true;
    1178                     }
    1179                 }
    1180 
    1181                 if (fDonePending)
    1182                 {
    1183                     rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS);
    1184 
    1185                     pClient->Pending.hHandle = NULL;
    1186                     pClient->Pending.paParms = NULL;
    1187                     pClient->Pending.cParms  = 0;
    1188                     pClient->Pending.uType   = 0;
    1189                 }
    1190             }
    1191             else
    1192                 AssertFailed();
    1193         }
     1113        PSHCLCLIENTMSG pFirstMsg = RTListGetFirst(&pClient->MsgQueue, SHCLCLIENTMSG, ListEntry);
     1114        AssertReturn(pFirstMsg, VERR_INTERNAL_ERROR);
     1115
     1116        LogFunc(("[Client %RU32] Current host message is %s (%RU32), cParms=%RU32\n",
     1117                 pClient->State.uClientID, ShClHostMsgToStr(pFirstMsg->idMsg), pFirstMsg->idMsg, pFirstMsg->cParms));
     1118
     1119        if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT)
     1120            shClSvcMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms);
     1121        else if (pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT) /* Legacy, Guest Additions < 6.1. */
     1122            shClSvcMsgSetOldWaitReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms);
    11941123        else
    1195             AssertMsgFailed(("Waking up client ID=%RU32 with no host message in queue is a bad idea\n", pClient->State.uClientID));
    1196 
    1197         return rc;
     1124            AssertMsgFailedReturn(("pClient->Pending.uType=%u\n", pClient->Pending.uType), VERR_INTERNAL_ERROR_3);
     1125
     1126        rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS);
     1127
     1128        if (   rc != VERR_CANCELLED
     1129            && pClient->Pending.uType == VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT)
     1130        {
     1131            RTListNodeRemove(&pFirstMsg->ListEntry);
     1132            shClSvcMsgFree(pClient, pFirstMsg);
     1133        }
     1134
     1135        pClient->Pending.hHandle = NULL;
     1136        pClient->Pending.paParms = NULL;
     1137        pClient->Pending.cParms  = 0;
     1138        pClient->Pending.uType   = 0;
    11981139    }
    11991140    else
    12001141        LogFunc(("[Client %RU32] Not in pending state, skipping wakeup\n", pClient->State.uClientID));
    12011142
    1202     return VINF_NO_CHANGE;
     1143    return rc;
    12031144}
    12041145
     
    12081149 * @returns VBox status code.
    12091150 * @param   pClient             Client to request to read data form.
    1210  * @param   pDataReq            Data request to send to the guest.
     1151 * @param   fFormat             The format being requested (VBOX_SHCL_FMT_XXX).
    12111152 * @param   puEvent             Event ID for waiting for new data. Optional.
    12121153 */
    1213 int ShClSvcDataReadRequest(PSHCLCLIENT pClient, PSHCLDATAREQ pDataReq, PSHCLEVENTID puEvent)
    1214 {
     1154int ShClSvcDataReadRequest(PSHCLCLIENT pClient, SHCLFORMAT fFormat, PSHCLEVENTID pidEvent)
     1155{
     1156    LogFlowFuncEnter();
     1157    if (pidEvent)
     1158        *pidEvent = 0;
    12151159    AssertPtrReturn(pClient,  VERR_INVALID_POINTER);
    1216     AssertPtrReturn(pDataReq, VERR_INVALID_POINTER);
    1217     /* puEvent is optional. */
    1218 
    1219     LogFlowFuncEnter();
    1220 
     1160
     1161    /*
     1162     * Allocate a message.
     1163     */
    12211164    int rc;
    1222 
    1223     PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_READ_DATA,
    1224                                                   VBOX_SHCL_CPARMS_READ_DATA_REQ);
    1225     if (pMsgReadData)
    1226     {
    1227         const SHCLEVENTID uEvent = ShClEventIDGenerate(&pClient->EventSrc);
    1228 
    1229         LogFlowFunc(("uFmt=0x%x\n", pDataReq->uFmt));
    1230 
    1231         HGCMSvcSetU64(&pMsgReadData->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    1232                                                                           pClient->EventSrc.uID, uEvent));
    1233         HGCMSvcSetU32(&pMsgReadData->paParms[1], 0 /* fFlags */);
    1234         HGCMSvcSetU32(&pMsgReadData->paParms[2], pDataReq->uFmt);
    1235         HGCMSvcSetU32(&pMsgReadData->paParms[3], pClient->State.cbChunkSize);
    1236 
    1237         rc = shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */);
    1238         if (RT_SUCCESS(rc))
    1239         {
    1240             rc = ShClEventRegister(&pClient->EventSrc, uEvent);
    1241             if (RT_SUCCESS(rc))
    1242             {
    1243                 rc = shClSvcClientWakeup(pClient);
    1244                 if (RT_SUCCESS(rc))
    1245                 {
    1246                     if (puEvent)
    1247                         *puEvent = uEvent;
    1248                 }
    1249                 else
    1250                     ShClEventUnregister(&pClient->EventSrc, uEvent);
    1251             }
    1252         }
     1165    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient,
     1166                                          pClient->State.fGuestFeatures0 & VBOX_SHCL_GF_0_CONTEXT_ID
     1167                                          ? VBOX_SHCL_HOST_MSG_READ_DATA_CID : VBOX_SHCL_HOST_MSG_READ_DATA,
     1168                                          2);
     1169    if (pMsg)
     1170    {
     1171        /*
     1172         * Enter the critical section and generate an event.
     1173         */
     1174        RTCritSectEnter(&pClient->CritSect);
     1175
     1176        const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc);
     1177        if (idEvent != 0)
     1178        {
     1179            LogFlowFunc(("fFormat=%#x idEvent=%#x\n", fFormat, idEvent));
     1180
     1181            /*
     1182             * Format the message
     1183             */
     1184            if (pMsg->idMsg == VBOX_SHCL_HOST_MSG_READ_DATA_CID)
     1185                HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, idEvent));
     1186            else
     1187                HGCMSvcSetU32(&pMsg->aParms[0], VBOX_SHCL_HOST_MSG_READ_DATA);
     1188            HGCMSvcSetU32(&pMsg->aParms[1], fFormat);
     1189
     1190            /*
     1191             * Queue it and wake up the client if it's waiting on a message.
     1192             */
     1193            shClSvcMsgAddAndWakeupClient(pClient, pMsg);
     1194            if (pidEvent)
     1195                *pidEvent = idEvent;
     1196            rc = VINF_SUCCESS;
     1197        }
     1198        else
     1199            rc = VERR_TRY_AGAIN;
     1200
     1201        RTCritSectLeave(&pClient->CritSect);
    12531202    }
    12541203    else
     
    13001249 * @returns VBox status code.
    13011250 * @param   pClient             Client to request to read data form.
    1302  * @param   pFormats            Formats to report.
    1303  */
    1304 int ShClSvcFormatsReport(PSHCLCLIENT pClient, PSHCLFORMATDATA pFormats)
    1305 {
     1251 * @param   fFormats            The formats to report (VBOX_SHCL_FMT_XXX), zero
     1252 *                              is okay (empty the clipboard).
     1253 */
     1254int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats)
     1255{
     1256    LogFlowFuncEnter();
    13061257    AssertPtrReturn(pClient,  VERR_INVALID_POINTER);
    1307     AssertPtrReturn(pFormats, VERR_INVALID_POINTER);
    1308 
    1309     LogFlowFuncEnter();
    1310 
    1311     uint32_t fFormats = pFormats->Formats;
    1312     uint32_t fFlags   = pFormats->fFlags;
    13131258
    13141259#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1315     /* If transfer mode is set to disabled, don't report the URI list format to the guest. */
     1260    /*
     1261     * If transfer mode is set to disabled, don't report the URI list format to the guest.
     1262     */
    13161263    if (!(g_fTransferMode & VBOX_SHCL_TRANSFER_MODE_ENABLED))
     1264    {
     1265        LogFlowFunc(("fFormats=%#x -> %#x\n", fFormats, fFormats & ~VBOX_SHCL_FMT_URI_LIST));
    13171266        fFormats &= ~VBOX_SHCL_FMT_URI_LIST;
     1267    }
    13181268#endif
    1319 
    1320     LogFlowFunc(("fFormats=0x%x -> 0x%x\n", pFormats->Formats, fFormats));
    1321 
    1322     /* Nothing to report? Bail out early. */
    1323     if (fFormats == VBOX_SHCL_FMT_NONE)
    1324         return VINF_SUCCESS;
    1325 
    1326     LogRel2(("Shared Clipboard: Reporting formats 0x%x to guest\n", fFormats));
    1327 
     1269    LogRel2(("Shared Clipboard: Reporting formats %#x to guest\n", fFormats));
     1270
     1271    /*
     1272     * Allocate a message, populate parameters and post it to the client.
     1273     */
    13281274    int rc;
    1329 
    1330     PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(VBOX_SHCL_HOST_MSG_FORMATS_REPORT, 3);
     1275    PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_FORMATS_REPORT, 2);
    13311276    if (pMsg)
    13321277    {
    1333         const SHCLEVENTID uEvent = ShClEventIDGenerate(&pClient->EventSrc);
    1334 
    1335         HGCMSvcSetU64(&pMsg->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    1336                                                                   pClient->EventSrc.uID, uEvent));
    1337         HGCMSvcSetU32(&pMsg->paParms[1], fFormats);
    1338         HGCMSvcSetU32(&pMsg->paParms[2], fFlags);
    1339 
    1340         rc = shClSvcMsgAdd(pClient, pMsg, true /* fAppend */);
    1341         if (RT_SUCCESS(rc))
    1342         {
     1278        HGCMSvcSetU32(&pMsg->aParms[0], VBOX_SHCL_HOST_MSG_FORMATS_REPORT);
     1279        HGCMSvcSetU32(&pMsg->aParms[1], fFormats);
     1280
     1281        RTCritSectEnter(&pClient->CritSect);
     1282        shClSvcMsgAddAndWakeupClient(pClient, pMsg);
     1283        RTCritSectLeave(&pClient->CritSect);
     1284
     1285        /*
     1286         * ...
     1287         */
    13431288#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1344             /* If we announce an URI list, create a transfer locally and also tell the guest to create
    1345              * a transfer on the guest side. */
    1346             if (fFormats & VBOX_SHCL_FMT_URI_LIST)
    1347             {
    1348                 rc = shClSvcTransferStart(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,
    1349                                           NULL /* pTransfer */);
    1350                 if (RT_FAILURE(rc))
    1351                     LogRel(("Shared Clipboard: Initializing host write transfer failed with %Rrc\n", rc));
    1352             }
    1353             else
    1354             {
     1289# error fixme
     1290        /* If we announce an URI list, create a transfer locally and also tell the guest to create
     1291         * a transfer on the guest side. */
     1292        if (fFormats & VBOX_SHCL_FMT_URI_LIST)
     1293        {
     1294            rc = shClSvcTransferStart(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,
     1295                                      NULL /* pTransfer */);
     1296            if (RT_FAILURE(rc))
     1297                LogRel(("Shared Clipboard: Initializing host write transfer failed with %Rrc\n", rc));
     1298        }
     1299        else
    13551300#endif
    1356                 pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_READ_ACTIVE;
    1357 
    1358                 rc = shClSvcClientWakeup(pClient);
    1359 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1360             }
    1361 #endif
    1362         }
     1301        {
     1302            pClient->State.fFlags |= SHCLCLIENTSTATE_FLAGS_READ_ACTIVE;
     1303            rc = VINF_SUCCESS;
     1304        }
     1305        /** @todo r=bird: shouldn't we also call shClSvcSetSource(pClient, SHCLSOURCE_LOCAL) here??
     1306         * Looks like the caller of this function does it, but only on windows.  Very helpful. */
    13631307    }
    13641308    else
     
    15751519        /* Read clipboard data from the extension. */
    15761520        rc = g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, &parms, sizeof(parms));
    1577         LogRelFlowFunc(("DATA/Ext: fDelayedAnnouncement=%RTbool uDelayedFormats=%#x cbData=%RU32->%RU32 rc=%Rrc\n",
    1578                         g_ExtState.fDelayedAnnouncement, g_ExtState.uDelayedFormats, dataBlock.cbData, parms.cbData, rc));
     1521        LogRelFlowFunc(("DATA/Ext: fDelayedAnnouncement=%RTbool fDelayedFormats=%#x cbData=%RU32->%RU32 rc=%Rrc\n",
     1522                        g_ExtState.fDelayedAnnouncement, g_ExtState.fDelayedFormats, dataBlock.cbData, parms.cbData, rc));
    15791523
    15801524        /* Did the extension send the clipboard formats yet?
     
    15821526        if (g_ExtState.fDelayedAnnouncement)
    15831527        {
    1584             SHCLFORMATDATA FormatData;
    1585             FormatData.fFlags  = 0;
    1586             FormatData.Formats = g_ExtState.uDelayedFormats;
    1587             Assert(FormatData.Formats != VBOX_SHCL_FMT_NONE); /* There better is *any* format here now. */
    1588 
    1589             int rc2 = ShClSvcFormatsReport(pClient, &FormatData);
     1528            int rc2 = ShClSvcHostReportFormats(pClient, g_ExtState.fDelayedFormats);
    15901529            AssertRC(rc2);
    15911530
    15921531            g_ExtState.fDelayedAnnouncement = false;
    1593             g_ExtState.uDelayedFormats = 0;
     1532            g_ExtState.fDelayedFormats = 0;
    15941533        }
    15951534
     
    22242163static SSMFIELD const s_aShClSSMClientMsgHdr[] =
    22252164{
    2226     SSMFIELD_ENTRY(SHCLCLIENTMSG, uMsg),
     2165    SSMFIELD_ENTRY(SHCLCLIENTMSG, idMsg),
    22272166    SSMFIELD_ENTRY(SHCLCLIENTMSG, cParms),
    22282167    SSMFIELD_ENTRY_TERM()
     
    22302169
    22312170/**
    2232  * SSM descriptor table for the VBOXSHCLMSGCTX structure.
     2171 * SSM descriptor table for what used to be the VBOXSHCLMSGCTX structure but is
     2172 * now part of SHCLCLIENTMSG.
    22332173 */
    22342174static SSMFIELD const s_aShClSSMClientMsgCtx[] =
    22352175{
    2236     SSMFIELD_ENTRY(SHCLMSGCTX, uContextID),
     2176    SSMFIELD_ENTRY(SHCLCLIENTMSG, idContext),
    22372177    SSMFIELD_ENTRY_TERM()
    22382178};
     
    22692209
    22702210    /* Serialize the client's internal message queue. */
    2271     rc = SSMR3PutU64(pSSM, (uint64_t)pClient->queueMsg.size());
     2211    uint32_t cMsgs = 0;
     2212    PSHCLCLIENTMSG pMsg;
     2213    RTListForEach(&pClient->MsgQueue, pMsg, SHCLCLIENTMSG, ListEntry)
     2214    {
     2215        cMsgs += 1;
     2216    }
     2217
     2218    rc = SSMR3PutU64(pSSM, cMsgs);
    22722219    AssertRCReturn(rc, rc);
    22732220
    2274     for (size_t i = 0; i < pClient->queueMsg.size(); i++)
    2275     {
    2276         PSHCLCLIENTMSG pMsg = pClient->queueMsg.at(i);
    2277         AssertPtr(pMsg);
    2278 
    2279         rc = SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL);
    2280         AssertRCReturn(rc, rc);
    2281 
    2282         rc = SSMR3PutStructEx(pSSM, &pMsg->Ctx, sizeof(SHCLMSGCTX), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL);
    2283         AssertRCReturn(rc, rc);
    2284 
    2285         for (uint32_t p = 0; p < pMsg->cParms; p++)
    2286         {
    2287             rc = HGCMSvcSSMR3Put(&pMsg->paParms[p], pSSM);
    2288             AssertRCReturn(rc, rc);
    2289         }
     2221    RTListForEach(&pClient->MsgQueue, pMsg, SHCLCLIENTMSG, ListEntry)
     2222    {
     2223        SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL);
     2224        SSMR3PutStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL);
     2225
     2226        for (uint32_t iParm = 0; iParm < pMsg->cParms; iParm++)
     2227            HGCMSvcSSMR3Put(&pMsg->aParms[iParm], pSSM);
    22902228    }
    22912229
     
    23752313        for (uint64_t i = 0; i < cMsgs; i++)
    23762314        {
    2377             PSHCLCLIENTMSG pMsg = (PSHCLCLIENTMSG)RTMemAlloc(sizeof(SHCLCLIENTMSG));
     2315            union
     2316            {
     2317                SHCLCLIENTMSG Msg;
     2318                uint8_t abPadding[RT_UOFFSETOF(SHCLCLIENTMSG, aParms) + sizeof(VBOXHGCMSVCPARM) * 2];
     2319            } u;
     2320
     2321            SSMR3GetStructEx(pSSM, &u.Msg, RT_UOFFSETOF(SHCLCLIENTMSG, aParms), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL);
     2322            rc = SSMR3GetStructEx(pSSM, &u.Msg, RT_UOFFSETOF(SHCLCLIENTMSG, aParms), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL);
     2323            AssertRCReturn(rc, rc);
     2324
     2325            AssertLogRelMsgReturn(u.Msg.cParms <= VMMDEV_MAX_HGCM_PARMS,
     2326                                  ("Too many HGCM message parameters: %u (%#x)\n", u.Msg.cParms, u.Msg.cParms),
     2327                                  VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2328
     2329            PSHCLCLIENTMSG pMsg = shClSvcMsgAlloc(pClient, u.Msg.idMsg, u.Msg.cParms);
    23782330            AssertReturn(pMsg, VERR_NO_MEMORY);
    2379 
    2380             SSMR3GetStructEx(pSSM, pMsg, sizeof(SHCLCLIENTMSG), 0 /*fFlags*/, &s_aShClSSMClientMsgHdr[0], NULL);
    2381             rc = SSMR3GetStructEx(pSSM, &pMsg->Ctx, sizeof(SHCLMSGCTX), 0 /*fFlags*/, &s_aShClSSMClientMsgCtx[0], NULL);
    2382             AssertRCReturnStmt(rc, RTMemFree(pMsg), rc);
    2383 
    2384             AssertLogRelMsgReturnStmt(pMsg->cParms <= VMMDEV_MAX_HGCM_PARMS,
    2385                                       ("Too many HGCM message parameters: %u (%#x)\n", pMsg->cParms, pMsg->cParms),
    2386                                       RTMemFree(pMsg),
    2387                                       VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    2388 
    2389             pMsg->paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * pMsg->cParms);
    2390             AssertReturnStmt(pMsg->paParms, RTMemFree(pMsg), VERR_NO_MEMORY);
     2331            pMsg->idContext = u.Msg.idContext;
    23912332
    23922333            for (uint32_t p = 0; p < pMsg->cParms; p++)
    23932334            {
    2394                 rc = HGCMSvcSSMR3Get(&pMsg->paParms[p], pSSM);
    2395                 AssertRCReturn(rc, rc); /* we'll leak stuff here, oh well... */
     2335                rc = HGCMSvcSSMR3Get(&pMsg->aParms[p], pSSM);
     2336                AssertRCReturnStmt(rc, shClSvcMsgFree(pClient, pMsg), rc);
    23962337            }
    23972338
    2398             rc = shClSvcMsgAdd(pClient, pMsg, true /* fAppend */);
    2399             AssertRCReturn(rc, rc);
     2339            shClSvcMsgAdd(pClient, pMsg, true /* fAppend */);
    24002340        }
    24012341    }
     
    24362376            {
    24372377                LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE: g_ExtState.fReadingData=%RTbool\n", g_ExtState.fReadingData));
    2438                 if (g_ExtState.fReadingData)
     2378                if (!g_ExtState.fReadingData)
     2379                    rc = ShClSvcHostReportFormats(pClient, u32Format);
     2380                else
    24392381                {
    24402382                    g_ExtState.fDelayedAnnouncement = true;
    2441                     g_ExtState.uDelayedFormats = u32Format;
     2383                    g_ExtState.fDelayedFormats = u32Format;
     2384                    rc = VINF_SUCCESS;
    24422385                }
    2443                 else if (u32Format != VBOX_SHCL_FMT_NONE)
    2444                 {
    2445                     SHCLFORMATDATA formatData;
    2446                     RT_ZERO(formatData);
    2447 
    2448                     formatData.Formats = u32Format;
    2449 
    2450                     rc = ShClSvcFormatsReport(pClient, &formatData);
    2451                 }
    2452 
    24532386                break;
    24542387            }
     
    24562389            /* The service extension wants read data from the guest. */
    24572390            case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
    2458             {
    2459                 SHCLDATAREQ dataReq;
    2460                 RT_ZERO(dataReq);
    2461 
    2462                 dataReq.uFmt   = u32Format;
    2463                 dataReq.cbSize = _64K; /** @todo Make this more dynamic. */
    2464 
    2465                 rc = ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */);
     2391                rc = ShClSvcDataReadRequest(pClient, u32Format, NULL /* puEvent */);
    24662392                break;
    2467             }
    24682393
    24692394            default:
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp

    r82526 r82527  
    128128
    129129/* Adds a host data read request message to the client's message queue. */
    130 static void testMsgAddReadData(PSHCLCLIENT pClient, uint32_t uFormat)
    131 {
    132     SHCLDATAREQ dataReq;
    133     RT_ZERO(dataReq);
    134 
    135     dataReq.uFmt = uFormat;
    136 
    137     int rc = ShClSvcDataReadRequest(pClient, &dataReq, NULL /* puEvent */);
     130static void testMsgAddReadData(PSHCLCLIENT pClient, uint32_t fFormat)
     131{
     132    int rc = ShClSvcDataReadRequest(pClient, fFormat, NULL /* puEvent */);
    138133    RTTESTI_CHECK_RC_OK(rc);
    139134}
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