VirtualBox

Changeset 92735 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 3, 2021 4:03:24 PM (3 years ago)
Author:
vboxsync
Message:

Shared Clipboard/Transfers: Resolved @todos: Revamped event [source] interface to now use the event objects directly instead of the event ID. bugref:9437

Location:
trunk/src/VBox
Files:
8 edited

Legend:

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

    r91746 r92735  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    160160        /* The IDataObject *must* be created on the same thread as our (proxy) window, so post a message to it
    161161         * to do the stuff for us. */
    162         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pTransfer->Events);
    163         if (idEvent != NIL_SHCLEVENTID)
     162        PSHCLEVENT pEvent;
     163        rc = ShClEventSourceGenerateAndRegisterEvent(&pTransfer->Events, &pEvent);
     164        if (RT_SUCCESS(rc))
    164165        {
    165166            /* Don't want to rely on SendMessage (synchronous) here, so just post and wait the event getting signalled. */
    166             ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM)idEvent);
     167            ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM)pEvent->idEvent);
    167168
    168169            PSHCLEVENTPAYLOAD pPayload;
    169             rc = ShClEventWait(&pTransfer->Events, idEvent, 30 * 1000 /* Timeout in ms */, &pPayload);
     170            rc = ShClEventWait(pEvent, 30 * 1000 /* Timeout in ms */, &pPayload);
    170171            if (RT_SUCCESS(rc))
    171172            {
     
    176177            }
    177178
    178             ShClEventUnregister(&pTransfer->Events, idEvent);
     179            ShClEventRelease(pEvent);
    179180        }
    180181        else
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp

    r91630 r92735  
    77 * Includes contributions from François Revol
    88 *
    9  * Copyright (C) 2006-2020 Oracle Corporation
     9 * Copyright (C) 2006-2021 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3838*   Prototypes                                                                                                                   *
    3939*********************************************************************************************************************************/
     40static void shClEventSourceResetInternal(PSHCLEVENTSOURCE pSource);
     41
     42static void shClEventDestroy(PSHCLEVENT pEvent);
    4043DECLINLINE(PSHCLEVENT) shclEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent);
    4144
     
    103106
    104107/**
    105  * Destroys an event, but doesn't free the memory.
    106  *
    107  * @param   pEvent              Event to destroy.
    108  */
    109 static void shClEventTerm(PSHCLEVENT pEvent)
    110 {
    111     if (!pEvent)
    112         return;
    113 
    114     AssertMsgReturnVoid(pEvent->cRefs == 0, ("Event %RU32 still has %RU32 references\n",
    115                                              pEvent->idEvent, pEvent->cRefs));
    116 
    117     LogFlowFunc(("Event %RU32\n", pEvent->idEvent));
    118 
    119     if (pEvent->hEvtMulSem != NIL_RTSEMEVENT)
    120     {
    121         RTSemEventMultiDestroy(pEvent->hEvtMulSem);
    122         pEvent->hEvtMulSem = NIL_RTSEMEVENT;
    123     }
    124 
    125     ShClPayloadFree(pEvent->pPayload);
    126 
    127     pEvent->idEvent = 0;
    128 }
    129 
    130 /**
    131108 * Creates a new event source.
    132109 *
     
    140117    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
    141118
     119    int rc = RTCritSectInit(&pSource->CritSect);
     120    AssertRCReturn(rc, rc);
     121
    142122    RTListInit(&pSource->lstEvents);
    143123
     
    152132 * Destroys an event source.
    153133 *
     134 * @returns VBox status code.
    154135 * @param   pSource             Event source to destroy.
    155136 */
    156 void ShClEventSourceDestroy(PSHCLEVENTSOURCE pSource)
     137int ShClEventSourceDestroy(PSHCLEVENTSOURCE pSource)
    157138{
    158139    if (!pSource)
    159         return;
     140        return VINF_SUCCESS;
    160141
    161142    LogFlowFunc(("ID=%RU32\n", pSource->uID));
    162143
    163     ShClEventSourceReset(pSource);
    164 
    165     pSource->uID          = UINT16_MAX;
    166     pSource->idNextEvent  = UINT32_MAX;
    167 }
    168 
    169 /**
    170  * Resets an event source.
     144    int rc = RTCritSectEnter(&pSource->CritSect);
     145    if (RT_SUCCESS(rc))
     146    {
     147        shClEventSourceResetInternal(pSource);
     148
     149        rc = RTCritSectLeave(&pSource->CritSect);
     150        AssertRC(rc);
     151
     152        RTCritSectDelete(&pSource->CritSect);
     153
     154        pSource->uID          = UINT16_MAX;
     155        pSource->idNextEvent  = UINT32_MAX;
     156    }
     157
     158    return rc;
     159}
     160
     161/**
     162 * Resets an event source, internal version.
    171163 *
    172164 * @param   pSource             Event source to reset.
    173165 */
    174 void ShClEventSourceReset(PSHCLEVENTSOURCE pSource)
     166static void shClEventSourceResetInternal(PSHCLEVENTSOURCE pSource)
    175167{
    176168    LogFlowFunc(("ID=%RU32\n", pSource->uID));
     
    182174        RTListNodeRemove(&pEvIt->Node);
    183175
    184         shClEventTerm(pEvIt);
     176        shClEventDestroy(pEvIt);
    185177
    186178        RTMemFree(pEvIt);
     
    190182
    191183/**
     184 * Resets an event source.
     185 *
     186 * @param   pSource             Event source to reset.
     187 */
     188void ShClEventSourceReset(PSHCLEVENTSOURCE pSource)
     189{
     190    int rc2 = RTCritSectEnter(&pSource->CritSect);
     191    if (RT_SUCCESS(rc2))
     192    {
     193        shClEventSourceResetInternal(pSource);
     194
     195        rc2 = RTCritSectLeave(&pSource->CritSect);
     196        AssertRC(rc2);
     197    }
     198}
     199
     200/**
    192201 * Generates a new event ID for a specific event source and registers it.
    193202 *
    194  * @returns New event ID generated, or NIL_SHCLEVENTID on error.
     203 * @returns VBox status code.
    195204 * @param   pSource             Event source to generate event for.
    196  */
    197 SHCLEVENTID ShClEventIdGenerateAndRegister(PSHCLEVENTSOURCE pSource)
    198 {
    199     AssertPtrReturn(pSource, NIL_SHCLEVENTID);
    200 
    201     /*
    202      * Allocate an event.
    203      */
     205 * @param   ppEvent             Where to return the new event generated on success.
     206 */
     207int ShClEventSourceGenerateAndRegisterEvent(PSHCLEVENTSOURCE pSource, PSHCLEVENT *ppEvent)
     208{
     209    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     210    AssertPtrReturn(ppEvent, VERR_INVALID_POINTER);
     211
    204212    PSHCLEVENT pEvent = (PSHCLEVENT)RTMemAllocZ(sizeof(SHCLEVENT));
    205     AssertReturn(pEvent, NIL_SHCLEVENTID);
     213    AssertReturn(pEvent, VERR_NO_MEMORY);
    206214    int rc = RTSemEventMultiCreate(&pEvent->hEvtMulSem);
    207     AssertRCReturnStmt(rc, RTMemFree(pEvent), NIL_SHCLEVENTID);
    208 
    209     /*
    210      * Allocate an unique event ID.
    211      */
    212     for (uint32_t cTries = 0;; cTries++)
    213     {
    214         SHCLEVENTID idEvent = ++pSource->idNextEvent;
    215         if (idEvent < VBOX_SHCL_MAX_EVENTS)
    216         { /* likely */ }
    217         else
    218             pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */
    219 
    220         if (shclEventGet(pSource, idEvent) == NULL)
    221         {
    222             pEvent->idEvent = idEvent;
    223             RTListAppend(&pSource->lstEvents, &pEvent->Node);
    224 
    225             LogFlowFunc(("uSource=%RU16: New event: %#x\n", pSource->uID, idEvent));
    226             return idEvent;
    227         }
    228 
    229         AssertBreak(cTries < 4096);
     215    if (RT_SUCCESS(rc))
     216    {
     217        rc = RTCritSectEnter(&pSource->CritSect);
     218        if (RT_SUCCESS(rc))
     219        {
     220            /*
     221             * Allocate an unique event ID.
     222             */
     223            for (uint32_t cTries = 0;; cTries++)
     224            {
     225                SHCLEVENTID idEvent = ++pSource->idNextEvent;
     226                if (idEvent < VBOX_SHCL_MAX_EVENTS)
     227                { /* likely */ }
     228                else
     229                    pSource->idNextEvent = idEvent = 1; /* zero == error, remember! */
     230
     231                if (shclEventGet(pSource, idEvent) == NULL)
     232                {
     233                    pEvent->pParent = pSource;
     234                    pEvent->idEvent = idEvent;
     235                    RTListAppend(&pSource->lstEvents, &pEvent->Node);
     236
     237                    rc = RTCritSectLeave(&pSource->CritSect);
     238                    AssertRC(rc);
     239
     240                    LogFlowFunc(("uSource=%RU16: New event: %#x\n", pSource->uID, idEvent));
     241
     242                    *ppEvent = pEvent;
     243
     244                    return VINF_SUCCESS;
     245                }
     246
     247                AssertBreak(cTries < 4096);
     248            }
     249
     250            rc = RTCritSectLeave(&pSource->CritSect);
     251            AssertRC(rc);
     252        }
    230253    }
    231254
     
    235258    pEvent->hEvtMulSem = NIL_RTSEMEVENTMULTI;
    236259    RTMemFree(pEvent);
    237     return NIL_SHCLEVENTID;
     260    return rc;
     261}
     262
     263/**
     264 * Destroys an event.
     265 *
     266 * @param   pEvent              Event to destroy.
     267 */
     268static void shClEventDestroy(PSHCLEVENT pEvent)
     269{
     270    if (!pEvent)
     271        return;
     272
     273    AssertMsgReturnVoid(pEvent->cRefs == 0, ("Event %RU32 still has %RU32 references\n",
     274                                             pEvent->idEvent, pEvent->cRefs));
     275
     276    LogFlowFunc(("Event %RU32\n", pEvent->idEvent));
     277
     278    if (pEvent->hEvtMulSem != NIL_RTSEMEVENT)
     279    {
     280        RTSemEventMultiDestroy(pEvent->hEvtMulSem);
     281        pEvent->hEvtMulSem = NIL_RTSEMEVENT;
     282    }
     283
     284    ShClPayloadFree(pEvent->pPayload);
     285
     286    pEvent->idEvent = NIL_SHCLEVENTID;
     287}
     288
     289/**
     290 * Unregisters an event.
     291 *
     292 * @returns VBox status code.
     293 * @param   pSource             Event source to unregister event for.
     294 * @param   pEvent              Event to unregister. On success the pointer will be invalid.
     295 */
     296static int shClEventSourceUnregisterEventInternal(PSHCLEVENTSOURCE pSource, PSHCLEVENT pEvent)
     297{
     298    LogFlowFunc(("idEvent=%RU32, cRefs=%RU32\n", pEvent->idEvent, pEvent->cRefs));
     299
     300    AssertReturn(pEvent->cRefs == 0, VERR_WRONG_ORDER);
     301
     302    int rc = RTCritSectEnter(&pSource->CritSect);
     303    if (RT_SUCCESS(rc))
     304    {
     305        RTListNodeRemove(&pEvent->Node);
     306
     307        shClEventDestroy(pEvent);
     308
     309        rc = RTCritSectLeave(&pSource->CritSect);
     310        if (RT_SUCCESS(rc))
     311        {
     312            RTMemFree(pEvent);
     313            pEvent = NULL;
     314        }
     315    }
     316
     317    return rc;
    238318}
    239319
     
    262342 * @returns Pointer to event if found, or NULL if not found.
    263343 * @param   pSource             Event source to get event from.
    264  * @param   uID                 Event ID to get.
    265  */
    266 PSHCLEVENT ShClEventGet(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
    267 {
    268     return shclEventGet(pSource, idEvent);
     344 * @param   idEvent             ID of event to return.
     345 */
     346PSHCLEVENT ShClEventSourceGetFromId(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
     347{
     348    AssertPtrReturn(pSource, NULL);
     349
     350    int rc = RTCritSectEnter(&pSource->CritSect);
     351    if (RT_SUCCESS(rc))
     352    {
     353         PSHCLEVENT pEvent = shclEventGet(pSource, idEvent);
     354
     355         rc = RTCritSectLeave(&pSource->CritSect);
     356         AssertRC(rc);
     357
     358         return pEvent;
     359    }
     360
     361    return NULL;
    269362}
    270363
     
    272365 * Returns the last (newest) event ID which has been registered for an event source.
    273366 *
    274  * @returns Last registered event ID, or 0 if not found.
     367 * @returns Pointer to last registered event, or NULL if not found.
    275368 * @param   pSource             Event source to get last registered event from.
    276369 */
    277 SHCLEVENTID ShClEventGetLast(PSHCLEVENTSOURCE pSource)
    278 {
    279     AssertPtrReturn(pSource, 0);
    280     PSHCLEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHCLEVENT, Node);
    281     if (pEvent)
    282         return pEvent->idEvent;
    283 
    284     return 0;
     370PSHCLEVENT ShClEventSourceGetLast(PSHCLEVENTSOURCE pSource)
     371{
     372    AssertPtrReturn(pSource, NULL);
     373
     374    int rc = RTCritSectEnter(&pSource->CritSect);
     375    if (RT_SUCCESS(rc))
     376    {
     377        PSHCLEVENT pEvent = RTListGetLast(&pSource->lstEvents, SHCLEVENT, Node);
     378
     379        rc = RTCritSectLeave(&pSource->CritSect);
     380        AssertRC(rc);
     381
     382        return pEvent;
     383    }
     384
     385    return NULL;
    285386}
    286387
     
    292393 * @param   idEvent             Event ID to return reference count for.
    293394 */
    294 uint32_t ShClEventGetRefs(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
    295 {
    296     PSHCLEVENT pEvent = shclEventGet(pSource, idEvent);
    297     if (pEvent)
    298         return pEvent->cRefs;
    299 
    300     AssertMsgFailed(("No event with %RU32\n", idEvent));
    301     return 0;
     395uint32_t ShClEventGetRefs(PSHCLEVENT pEvent)
     396{
     397    AssertPtrReturn(pEvent, 0);
     398
     399    return ASMAtomicReadU32(&pEvent->cRefs);
    302400}
    303401
     
    322420
    323421/**
    324  * Unregisters an event.
     422 * Waits for an event to get signalled.
    325423 *
    326424 * @returns VBox status code.
    327  * @param   pSource             Event source to unregister event for.
    328  * @param   uID                 Event ID to unregister.
    329  *
    330  * @todo    r=bird: The caller must enter crit sect protecting the event source
    331  *          here, must it?  See explanation in ShClEventWait.
    332  */
    333 int ShClEventUnregister(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID)
    334 {
    335     AssertPtrReturn(pSource, VERR_INVALID_POINTER);
    336 
    337     int rc;
    338 
    339     LogFlowFunc(("uSource=%RU16, uEvent=%RU32\n", pSource->uID, uID));
    340 
    341     PSHCLEVENT pEvent = shclEventGet(pSource, uID);
    342     if (pEvent)
    343     {
    344         LogFlowFunc(("Event %RU32\n", pEvent->idEvent));
    345 
    346         RTListNodeRemove(&pEvent->Node);
    347 
    348         shClEventTerm(pEvent);
    349 
    350         RTMemFree(pEvent);
    351         pEvent = NULL;
    352 
    353         rc = VINF_SUCCESS;
    354     }
    355     else
    356         rc = VERR_NOT_FOUND;
    357 
    358     LogFlowFuncLeaveRC(rc);
    359     return rc;
    360 }
    361 
    362 /**
    363  * Waits for an event to get signalled.
    364  *
    365  * @returns VBox status code.
    366  * @param   pSource             Event source that contains the event to wait for.
    367  * @param   uID                 Event ID to wait for.
     425 * @param   pEvent              Event to wait for.
    368426 * @param   uTimeoutMs          Timeout (in ms) to wait.
    369427 * @param   ppPayload           Where to store the (allocated) event payload on success. Needs to be free'd with
    370428 *                              SharedClipboardPayloadFree(). Optional.
    371  *
    372  * @todo    r=bird: Locking protocol is totally buggered here, or at least not
    373  *          explained in any way whatsoever.  We cannot really do shclEventGet
    374  *          and shclEventPayloadDetachInternal w/o holding the critical section
    375  *          protecting that list, otherwise wtf is the point of the locking.
    376  *
    377  *          More to the point, ShClEventSignal is called on the HGCM service
    378  *          thread and would be racing the host clipboard worker thread/whomever
    379  *          sent the request and is making this call closely followed by
    380  *          ShClEventRelease and ShClEventUnregister.  The waiting here might be
    381  *          safe if there can only ever be one single thread making these kind
    382  *          of requests, but the unregistering is _not_ safe w/o holding the
    383  *          lock and that isn't explained anywhere that I can see.
    384  */
    385 int ShClEventWait(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload)
    386 {
    387     AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     429 */
     430int ShClEventWait(PSHCLEVENT pEvent, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload)
     431{
     432    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    388433    AssertPtrNullReturn(ppPayload, VERR_INVALID_POINTER);
    389434    LogFlowFuncEnter();
    390435
    391     int rc;
    392 
    393     PSHCLEVENT pEvent = shclEventGet(pSource, uID);
    394     if (pEvent)
    395     {
    396         rc = RTSemEventMultiWait(pEvent->hEvtMulSem, uTimeoutMs);
    397         if (RT_SUCCESS(rc))
    398         {
    399             if (ppPayload)
    400             {
    401                 /* Make sure to detach payload here, as the caller now owns the data. */
    402                 *ppPayload = shclEventPayloadDetachInternal(pEvent);
    403             }
    404         }
    405 
    406         if (RT_FAILURE(rc))
    407             LogRel2(("Shared Clipboard: Waiting for event %RU32 failed, rc=%Rrc\n", uID, rc));
    408     }
    409     else
    410         rc = VERR_NOT_FOUND;
     436    int rc = RTSemEventMultiWait(pEvent->hEvtMulSem, uTimeoutMs);
     437    if (RT_SUCCESS(rc))
     438    {
     439        if (ppPayload)
     440        {
     441            /* Make sure to detach payload here, as the caller now owns the data. */
     442            *ppPayload = shclEventPayloadDetachInternal(pEvent);
     443        }
     444    }
     445
     446    if (RT_FAILURE(rc))
     447        LogRel2(("Shared Clipboard: Waiting for event %RU32 failed, rc=%Rrc\n", pEvent->idEvent, rc));
    411448
    412449    LogFlowFuncLeaveRC(rc);
     
    418455 *
    419456 * @returns New reference count, or UINT32_MAX if failed.
    420  * @param   pSource             Event source of event to retain.
    421  * @param   idEvent             ID of event to retain.
    422  */
    423 uint32_t ShClEventRetain(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
    424 {
    425     PSHCLEVENT pEvent = shclEventGet(pSource, idEvent);
     457 * @param   pEvent              Event to retain.
     458 */
     459uint32_t ShClEventRetain(PSHCLEVENT pEvent)
     460{
     461    AssertPtrReturn(pEvent, UINT32_MAX);
     462    AssertReturn(ASMAtomicReadU32(&pEvent->cRefs) < 64, UINT32_MAX);
     463    return ASMAtomicIncU32(&pEvent->cRefs);
     464}
     465
     466/**
     467 * Releases an event by decreasing its reference count.
     468 *
     469 * @returns New reference count, or UINT32_MAX if failed.
     470 * @param   pEvent              Event to release.
     471 *                              If the reference count reaches 0, the event will
     472 *                              be destroyed and \a pEvent will be invalid.
     473 */
     474uint32_t ShClEventRelease(PSHCLEVENT pEvent)
     475{
    426476    if (!pEvent)
    427     {
    428         AssertFailed();
    429         return UINT32_MAX;
    430     }
    431 
    432     AssertReturn(pEvent->cRefs < 64, UINT32_MAX); /* Sanity. Yeah, not atomic. */
    433 
    434     return ASMAtomicIncU32(&pEvent->cRefs);
    435 }
    436 
    437 /**
    438  * Releases an event by decreasing its reference count.
    439  *
    440  * @returns New reference count, or UINT32_MAX if failed.
    441  * @param   pSource             Event source of event to release.
    442  * @param   idEvent             ID of event to release.
    443  *
    444  * @todo    r=bird: The two places this is currently used make my head explode.
    445  *          First you release then you unregister it.  Unregister frees is
    446  *          unconditionally.
    447  *
    448  *          Any sane thinking person would assume that after we've release our
    449  *          reference to the @a idEvent, we cannot touch it any more because we
    450  *          don't have a valid reference any more.  So, when ShClEventUnregister
    451  *          is then called and unconditionally frees the event: Boooooom!
    452  *
    453  *          The locking interface here is generally not sane either, as the
    454  *          locking isn't done on the @a pSource but something the caller needs
    455  *          implements.  Since we don't have access to the lock we cannot verify
    456  *          the locking protocol nor can we implement it (like in
    457  *          ShClEventWait).
    458  *
    459  *          A better interface would return PSHCLEVENT instead of SHCLEVENTID,
    460  *          and then you could work directly on that as an object, rather via a
    461  *          slow object list.  It would eliminate shclEventGet and any though
    462  *          that someone might be updating the list while shclEventGet traverses
    463  *          it.
    464  */
    465 uint32_t ShClEventRelease(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent)
    466 {
    467     PSHCLEVENT pEvent = shclEventGet(pSource, idEvent);
    468     AssertReturn(pEvent, UINT32_MAX);
    469     AssertReturn(pEvent->cRefs, UINT32_MAX); /* Sanity. Yeah, not atomic. */
    470 
    471     return ASMAtomicDecU32(&pEvent->cRefs);
     477        return 0;
     478
     479    AssertReturn(ASMAtomicReadU32(&pEvent->cRefs) > 0, UINT32_MAX);
     480
     481    uint32_t const cRefs = ASMAtomicDecU32(&pEvent->cRefs);
     482    if (cRefs == 0)
     483    {
     484        AssertPtr(pEvent->pParent);
     485        int rc2 = shClEventSourceUnregisterEventInternal(pEvent->pParent, pEvent);
     486        AssertRC(rc2);
     487
     488        return RT_SUCCESS(rc2) ? 0 : UINT32_MAX;
     489    }
     490
     491    return cRefs;
    472492}
    473493
     
    476496 *
    477497 * @returns VBox status code.
    478  * @param   pSource             Event source of event to signal.
    479  * @param   uID                 Event ID to signal.
     498 * @param   pEvent              Event to signal.
    480499 * @param   pPayload            Event payload to associate. Takes ownership on
    481500 *                              success. Optional.
    482  *
    483  * @note    Caller must enter crit sect protecting the event source!
    484  */
    485 int ShClEventSignal(PSHCLEVENTSOURCE pSource, SHCLEVENTID uID, PSHCLEVENTPAYLOAD pPayload)
    486 {
    487     AssertPtrReturn(pSource, VERR_INVALID_POINTER);
    488 
    489     int rc;
    490 
    491     LogFlowFunc(("uSource=%RU16, uEvent=%RU32\n", pSource->uID, uID));
    492 
    493     PSHCLEVENT pEvent = shclEventGet(pSource, uID);
    494     if (pEvent)
    495     {
    496         Assert(pEvent->pPayload == NULL);
    497 
    498         pEvent->pPayload = pPayload;
    499 
    500         rc = RTSemEventMultiSignal(pEvent->hEvtMulSem);
    501         if (RT_FAILURE(rc))
    502             pEvent->pPayload = NULL; /* (no race condition if consumer also enters the critical section) */
    503     }
    504     else
    505         rc = VERR_NOT_FOUND;
     501 */
     502int ShClEventSignal(PSHCLEVENT pEvent, PSHCLEVENTPAYLOAD pPayload)
     503{
     504    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     505
     506    Assert(pEvent->pPayload == NULL);
     507
     508    pEvent->pPayload = pPayload;
     509
     510    int rc = RTSemEventMultiSignal(pEvent->hEvtMulSem);
     511    if (RT_FAILURE(rc))
     512        pEvent->pPayload = NULL; /* (no race condition if consumer also enters the critical section) */
    506513
    507514    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp

    r87658 r92735  
    55
    66/*
    7  * Copyright (C) 2019-2020 Oracle Corporation
     7 * Copyright (C) 2019-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    10791079
    10801080/**
    1081  * Duplicaates a transfer object data chunk.
     1081 * Duplicates a transfer object data chunk.
    10821082 *
    10831083 * @returns Duplicated object data chunk on success, or NULL on failure.
     
    11581158    LogFlowFuncEnter();
    11591159
    1160     PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)RTMemAlloc(sizeof(SHCLTRANSFER));
    1161     if (!pTransfer)
    1162         return VERR_NO_MEMORY;
    1163 
    1164     int rc = VINF_SUCCESS;
     1160    PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)RTMemAllocZ(sizeof(SHCLTRANSFER));
     1161    AssertPtrReturn(pTransfer, VERR_NO_MEMORY);
    11651162
    11661163    pTransfer->State.uID       = 0;
     
    11811178    pTransfer->uTimeoutMs     = RT_MS_30SEC;
    11821179#endif
    1183     pTransfer->cbMaxChunkSize = _64K; /** @todo Make this configurable. */
     1180    pTransfer->cbMaxChunkSize  = _64K; /** @todo Make this configurable. */
     1181    pTransfer->cMaxListHandles = _4K;  /** @todo Ditto. */
     1182    pTransfer->cMaxObjHandles  = _4K;  /** @todo Ditto. */
    11841183
    11851184    pTransfer->pvUser = NULL;
     
    11921191    RTListInit(&pTransfer->lstRoots);
    11931192
    1194     RTListInit(&pTransfer->Events.lstEvents);
    1195     pTransfer->Events.uID          = 0;
    1196     pTransfer->Events.idNextEvent  = 1;
    1197 
     1193    int rc = ShClEventSourceCreate(&pTransfer->Events, 0 /* uID */);
    11981194    if (RT_SUCCESS(rc))
    11991195    {
     
    12481244int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource)
    12491245{
    1250     pTransfer->State.uID       = 0;
    12511246    pTransfer->State.enmDir    = enmDir;
    12521247    pTransfer->State.enmSource = enmSource;
     
    12551250                 pTransfer->State.uID, pTransfer->State.enmDir, pTransfer->State.enmSource));
    12561251
    1257     int rc = ShClEventSourceCreate(&pTransfer->Events, pTransfer->State.uID);
    1258     if (RT_SUCCESS(rc))
    1259     {
    1260         pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */
    1261 
    1262         pTransfer->cListHandles    = 0;
    1263         pTransfer->cMaxListHandles = _4K; /** @todo Make this dynamic. */
    1264         pTransfer->uListHandleNext = 1;
    1265 
    1266         pTransfer->cObjHandles     = 0;
    1267         pTransfer->cMaxObjHandles  = _4K; /** @todo Ditto. */
    1268         pTransfer->uObjHandleNext  = 1;
    1269 
    1270         if (pTransfer->Callbacks.pfnOnInitialize)
    1271             rc = pTransfer->Callbacks.pfnOnInitialize(&pTransfer->CallbackCtx);
    1272     }
     1252    pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */
     1253
     1254    pTransfer->cListHandles    = 0;
     1255    pTransfer->uListHandleNext = 1;
     1256
     1257    pTransfer->cObjHandles     = 0;
     1258    pTransfer->uObjHandleNext  = 1;
     1259
     1260    int rc = VINF_SUCCESS;
     1261
     1262    if (pTransfer->Callbacks.pfnOnInitialize)
     1263        rc = pTransfer->Callbacks.pfnOnInitialize(&pTransfer->CallbackCtx);
    12731264
    12741265    LogFlowFuncLeaveRC(rc);
     
    30483039#ifdef RT_OS_WINDOWS
    30493040            if ((fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_ATTR) != SHCL_OBJ_CF_ACCESS_ATTR_NONE)
    3050                 fOpen |= RTFILE_O_ATTR_ONLY;
     3041                fOpen |= RTFILE_O_OPEN | RTFILE_O_ATTR_ONLY;
    30513042            else
    30523043#endif
    3053                 fOpen |= RTFILE_O_READ;
     3044                fOpen |= RTFILE_O_OPEN | RTFILE_O_READ;
    30543045            LogFlowFunc(("SHCL_OBJ_CF_ACCESS_NONE\n"));
    30553046            break;
     
    30583049        case SHCL_OBJ_CF_ACCESS_READ:
    30593050        {
    3060             fOpen |= RTFILE_O_READ;
     3051            fOpen |= RTFILE_O_OPEN | RTFILE_O_READ;
    30613052            LogFlowFunc(("SHCL_OBJ_CF_ACCESS_READ\n"));
    30623053            break;
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r91749 r92735  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    293293 * @{
    294294 */
    295 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENTID pidEvent);
     295int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent);
    296296int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData);
    297297int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp

    r87658 r92735  
    55
    66/*
    7  * Copyright (C) 2019-2020 Oracle Corporation
     7 * Copyright (C) 2019-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    100100    if (pMsgHdr)
    101101    {
    102         SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    103         if (idEvent != NIL_SHCLEVENTID)
     102        PSHCLEVENT pEvent;
     103        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     104        if (RT_SUCCESS(rc))
    104105        {
    105106            HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    106                                                                         pCtx->pTransfer->State.uID, idEvent));
     107                                                                        pCtx->pTransfer->State.uID, pEvent->idEvent));
    107108            HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */);
    108109
     
    117118            {
    118119                PSHCLEVENTPAYLOAD pPayloadHdr;
    119                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent,
    120                                    pCtx->pTransfer->uTimeoutMs, &pPayloadHdr);
     120                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadHdr);
    121121                if (RT_SUCCESS(rc))
    122122                {
     
    141141                                                                               VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
    142142
    143                                     idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    144                                     if (idEvent != NIL_SHCLEVENTID)
     143                                    PSHCLEVENT pEvRoot;
     144                                    rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvRoot);
     145                                    if (RT_SUCCESS(rc))
    145146                                    {
    146147                                        HGCMSvcSetU64(&pMsgEntry->aParms[0],
    147148                                                      VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID,
    148                                                                                pCtx->pTransfer->State.uID, idEvent));
     149                                                                               pCtx->pTransfer->State.uID, pEvRoot->idEvent));
    149150                                        HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fRoots */);
    150151                                        HGCMSvcSetU32(&pMsgEntry->aParms[2], i /* uIndex */);
     
    155156
    156157                                        PSHCLEVENTPAYLOAD pPayloadEntry;
    157                                         rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent,
    158                                                            pCtx->pTransfer->uTimeoutMs, &pPayloadEntry);
     158                                        rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadEntry);
    159159                                        if (RT_FAILURE(rc))
    160160                                            break;
     
    167167                                        ShClPayloadFree(pPayloadEntry);
    168168
    169                                         ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     169                                        ShClEventRelease(pEvRoot);
     170                                        pEvRoot = NULL;
    170171                                    }
    171172                                    else
     
    197198            }
    198199
    199             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     200            ShClEventRelease(pEvent);
    200201        }
    201202        else
     
    223224    if (pMsg)
    224225    {
    225         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    226         if (idEvent != NIL_SHCLEVENTID)
     226        PSHCLEVENT pEvent;
     227        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     228        if (RT_SUCCESS(rc))
    227229        {
    228230            pMsg->idCtx = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pCtx->pTransfer->State.uID,
    229                                                    idEvent);
     231                                                   pEvent->idEvent);
    230232
    231233            rc = shClSvcTransferSetListOpen(pMsg->cParms, pMsg->aParms, pMsg->idCtx, pOpenParms);
     
    238240                {
    239241                    PSHCLEVENTPAYLOAD pPayload;
    240                     rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     242                    rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    241243                    if (RT_SUCCESS(rc))
    242244                    {
     
    257259            }
    258260
    259             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     261            ShClEventRelease(pEvent);
    260262        }
    261263        else
     
    282284    if (pMsg)
    283285    {
    284         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    285         if (idEvent != NIL_SHCLEVENTID)
     286        PSHCLEVENT pEvent;
     287        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     288        if (RT_SUCCESS(rc))
    286289        {
    287290            pMsg->idCtx = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pCtx->pTransfer->State.uID,
    288                                                    idEvent);
     291                                                   pEvent->idEvent);
    289292
    290293            rc = shClSvcTransferSetListClose(pMsg->cParms, pMsg->aParms, pMsg->idCtx, hList);
     
    297300                {
    298301                    PSHCLEVENTPAYLOAD pPayload;
    299                     rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     302                    rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    300303                    if (RT_SUCCESS(rc))
    301304                        ShClPayloadFree(pPayload);
     
    303306            }
    304307
    305             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     308            ShClEventRelease(pEvent);
    306309        }
    307310        else
     
    329332    if (pMsg)
    330333    {
    331         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    332         if (idEvent != NIL_SHCLEVENTID)
     334        PSHCLEVENT pEvent;
     335        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     336        if (RT_SUCCESS(rc))
    333337        {
    334338            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    335                                                                      pCtx->pTransfer->State.uID, idEvent));
     339                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    336340            HGCMSvcSetU64(&pMsg->aParms[1], hList);
    337341            HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fFlags */);
     
    343347            {
    344348                PSHCLEVENTPAYLOAD pPayload;
    345                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent,
    346                                    pCtx->pTransfer->uTimeoutMs, &pPayload);
     349                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    347350                if (RT_SUCCESS(rc))
    348351                {
     
    355358            }
    356359
    357             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     360            ShClEventRelease(pEvent);
    358361        }
    359362        else
     
    391394    if (pMsg)
    392395    {
    393         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    394         if (idEvent != NIL_SHCLEVENTID)
     396        PSHCLEVENT pEvent;
     397        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     398        if (RT_SUCCESS(rc))
    395399        {
    396400            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    397                                                                      pCtx->pTransfer->State.uID, idEvent));
     401                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    398402            HGCMSvcSetU64(&pMsg->aParms[1], hList);
    399403            HGCMSvcSetU32(&pMsg->aParms[2], 0 /* fInfo */);
     
    405409            {
    406410                PSHCLEVENTPAYLOAD pPayload;
    407                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     411                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    408412                if (RT_SUCCESS(rc))
    409413                {
     
    416420            }
    417421
    418             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     422            ShClEventRelease(pEvent);
    419423        }
    420424        else
     
    452456    if (pMsg)
    453457    {
    454         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    455         if (idEvent != NIL_SHCLEVENTID)
     458        PSHCLEVENT pEvent;
     459        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     460        if (RT_SUCCESS(rc))
    456461        {
    457462            LogFlowFunc(("pszPath=%s, fCreate=0x%x\n", pCreateParms->pszPath, pCreateParms->fCreate));
     
    460465
    461466            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    462                                                                      pCtx->pTransfer->State.uID, idEvent));
     467                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    463468            HGCMSvcSetU64(&pMsg->aParms[1], 0); /* uHandle */
    464469            HGCMSvcSetU32(&pMsg->aParms[2], cbPath);
     
    472477            {
    473478                PSHCLEVENTPAYLOAD pPayload;
    474                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     479                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    475480                if (RT_SUCCESS(rc))
    476481                {
     
    490495            }
    491496
    492             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     497            ShClEventRelease(pEvent);
    493498        }
    494499        else
     
    515520    if (pMsg)
    516521    {
    517         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    518         if (idEvent != NIL_SHCLEVENTID)
     522        PSHCLEVENT pEvent;
     523        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     524        if (RT_SUCCESS(rc))
    519525        {
    520526            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    521                                                                      pCtx->pTransfer->State.uID, idEvent));
     527                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    522528            HGCMSvcSetU64(&pMsg->aParms[1], hObj);
    523529
     
    528534            {
    529535                PSHCLEVENTPAYLOAD pPayload;
    530                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     536                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    531537                if (RT_SUCCESS(rc))
    532538                {
     
    544550            }
    545551
    546             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     552            ShClEventRelease(pEvent);
    547553        }
    548554        else
     
    570576    if (pMsg)
    571577    {
    572         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    573         if (idEvent != NIL_SHCLEVENTID)
     578        PSHCLEVENT pEvent;
     579        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     580        if (RT_SUCCESS(rc))
    574581        {
    575582            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    576                                                                      pCtx->pTransfer->State.uID, idEvent));
     583                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    577584            HGCMSvcSetU64(&pMsg->aParms[1], hObj);
    578585            HGCMSvcSetU32(&pMsg->aParms[2], cbData);
     
    585592            {
    586593                PSHCLEVENTPAYLOAD pPayload;
    587                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     594                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    588595                if (RT_SUCCESS(rc))
    589596                {
     
    604611            }
    605612
    606             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     613            ShClEventRelease(pEvent);
    607614        }
    608615        else
     
    630637    if (pMsg)
    631638    {
    632         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pCtx->pTransfer->Events);
    633         if (idEvent != NIL_SHCLEVENTID)
     639        PSHCLEVENT pEvent;
     640        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     641        if (RT_SUCCESS(rc))
    634642        {
    635643            HGCMSvcSetU64(&pMsg->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    636                                                                      pCtx->pTransfer->State.uID, idEvent));
     644                                                                     pCtx->pTransfer->State.uID, pEvent->idEvent));
    637645            HGCMSvcSetU64(&pMsg->aParms[1], hObj);
    638646            HGCMSvcSetU64(&pMsg->aParms[2], cbData);
     
    645653            {
    646654                PSHCLEVENTPAYLOAD pPayload;
    647                 rc = ShClEventWait(&pCtx->pTransfer->Events, idEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
     655                rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayload);
    648656                if (RT_SUCCESS(rc))
    649657                {
     
    659667            }
    660668
    661             ShClEventUnregister(&pCtx->pTransfer->Events, idEvent);
     669            ShClEventRelease(pEvent);
    662670        }
    663671        else
     
    11911199                                      uint32_t cParms, VBOXHGCMSVCPARM aParms[])
    11921200{
    1193     RT_NOREF(pClient);
     1201    RT_NOREF(pClient, pTransfer);
    11941202
    11951203    int rc;
     
    12251233                        if (RT_SUCCESS(rc))
    12261234                        {
    1227                             const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1228 
    1229                             LogFlowFunc(("uCID=%RU64 -> idEvent=%RU32\n", uCID, idEvent));
    1230 
    1231                             rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
     1235                            const PSHCLEVENT pEvent
     1236                                = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1237                            if (pEvent)
     1238                            {
     1239                                LogFlowFunc(("uCID=%RU64 -> idEvent=%RU32\n", uCID, pEvent->idEvent));
     1240
     1241                                rc = ShClEventSignal(pEvent, pPayload);
     1242                            }
     1243                            /** @todo Silently skip? */
    12321244                        }
    12331245                        break;
     
    13821394                uint32_t cbData = sizeof(SHCLROOTLISTHDR);
    13831395
    1384                 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1385 
    1386                 PSHCLEVENTPAYLOAD pPayload;
    1387                 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload);
    1388                 if (RT_SUCCESS(rc))
    1389                 {
    1390                     rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
    1391                     if (RT_FAILURE(rc))
    1392                         ShClPayloadFree(pPayload);
    1393                 }
     1396                const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1397                if (pEvent)
     1398                {
     1399                    PSHCLEVENTPAYLOAD pPayload;
     1400                    rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload);
     1401                    if (RT_SUCCESS(rc))
     1402                    {
     1403                        rc = ShClEventSignal(pEvent, pPayload);
     1404                        if (RT_FAILURE(rc))
     1405                            ShClPayloadFree(pPayload);
     1406                    }
     1407                }
     1408                else
     1409                    rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND;
    13941410            }
    13951411            break;
     
    14271443                uint32_t cbData = sizeof(SHCLROOTLISTENTRY);
    14281444
    1429                 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1430 
    1431                 PSHCLEVENTPAYLOAD pPayload;
    1432                 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload);
    1433                 if (RT_SUCCESS(rc))
    1434                 {
    1435                     rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
    1436                     if (RT_FAILURE(rc))
    1437                         ShClPayloadFree(pPayload);
    1438                 }
     1445                const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1446                if (pEvent)
     1447                {
     1448                    PSHCLEVENTPAYLOAD pPayload;
     1449                    rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload);
     1450                    if (RT_SUCCESS(rc))
     1451                    {
     1452                        rc = ShClEventSignal(pEvent, pPayload);
     1453                        if (RT_FAILURE(rc))
     1454                            ShClPayloadFree(pPayload);
     1455                    }
     1456                }
     1457                else
     1458                    rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND;
    14391459            }
    14401460            break;
     
    15021522                    uint32_t cbData = sizeof(SHCLLISTHDR);
    15031523
    1504                     const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1505 
    1506                     PSHCLEVENTPAYLOAD pPayload;
    1507                     rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload);
    1508                     if (RT_SUCCESS(rc))
     1524                    const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1525                    if (pEvent)
    15091526                    {
    1510                         rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
    1511                         if (RT_FAILURE(rc))
    1512                             ShClPayloadFree(pPayload);
     1527                        PSHCLEVENTPAYLOAD pPayload;
     1528                        rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload);
     1529                        if (RT_SUCCESS(rc))
     1530                        {
     1531                            rc = ShClEventSignal(pEvent, pPayload);
     1532                            if (RT_FAILURE(rc))
     1533                                ShClPayloadFree(pPayload);
     1534                        }
    15131535                    }
     1536                    else
     1537                        rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND;
    15141538                }
    15151539            }
     
    15511575                    uint32_t cbData = sizeof(SHCLLISTENTRY);
    15521576
    1553                     const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1554 
    1555                     PSHCLEVENTPAYLOAD pPayload;
    1556                     rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload);
    1557                     if (RT_SUCCESS(rc))
     1577                    const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1578                    if (pEvent)
    15581579                    {
    1559                         rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
    1560                         if (RT_FAILURE(rc))
    1561                             ShClPayloadFree(pPayload);
     1580                        PSHCLEVENTPAYLOAD pPayload;
     1581                        rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload);
     1582                        if (RT_SUCCESS(rc))
     1583                        {
     1584                            rc = ShClEventSignal(pEvent, pPayload);
     1585                            if (RT_FAILURE(rc))
     1586                                ShClPayloadFree(pPayload);
     1587                        }
    15621588                    }
     1589                    else
     1590                        rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND;
    15631591                }
    15641592            }
     
    16561684                uint32_t cbData = sizeof(SHCLOBJDATACHUNK);
    16571685
    1658                 const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(uCID);
    1659 
    1660                 PSHCLEVENTPAYLOAD pPayload;
    1661                 rc = ShClPayloadAlloc(idEvent, pvData, cbData, &pPayload);
    1662                 if (RT_SUCCESS(rc))
    1663                 {
    1664                     rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);
    1665                     if (RT_FAILURE(rc))
    1666                         ShClPayloadFree(pPayload);
    1667                 }
     1686                const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, VBOX_SHCL_CONTEXTID_GET_EVENT(uCID));
     1687                if (pEvent)
     1688                {
     1689                    PSHCLEVENTPAYLOAD pPayload;
     1690                    rc = ShClPayloadAlloc(pEvent->idEvent, pvData, cbData, &pPayload);
     1691                    if (RT_SUCCESS(rc))
     1692                    {
     1693                        rc = ShClEventSignal(pEvent, pPayload);
     1694                        if (RT_FAILURE(rc))
     1695                            ShClPayloadFree(pPayload);
     1696                    }
     1697                }
     1698                else
     1699                    rc = VERR_SHCLPB_EVENT_ID_NOT_FOUND;
    16681700            }
    16691701
     
    17381770 * @param   uStatus             Status to report.
    17391771 * @param   rcTransfer          Result code to report. Optional and depending on status.
    1740  * @param   pidEvent            Where to store the created wait event. Optional.
     1772 * @param   ppEvent             Where to return the wait event on success. Optional.
     1773 *                              Must be released by the caller with ShClEventRelease().
    17411774 */
    17421775int shClSvcTransferSendStatus(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus,
    1743                               int rcTransfer, PSHCLEVENTID pidEvent)
     1776                              int rcTransfer, PSHCLEVENT *ppEvent)
    17441777{
    17451778    AssertPtrReturn(pClient,   VERR_INVALID_POINTER);
    17461779    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1747     /* pidEvent is optional. */
     1780    /* ppEvent is optional. */
    17481781
    17491782    PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,
     
    17521785        return VERR_NO_MEMORY;
    17531786
    1754     int rc;
    1755 
    1756     const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pTransfer->Events);
    1757     if (idEvent != NIL_SHCLEVENTID)
     1787    PSHCLEVENT pEvent;
     1788    int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     1789    if (RT_SUCCESS(rc))
    17581790    {
    17591791        HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    1760                                                                          pTransfer->State.uID, idEvent));
     1792                                                                         pTransfer->State.uID, pEvent->idEvent));
    17611793        HGCMSvcSetU32(&pMsgReadData->aParms[1], pTransfer->State.enmDir);
    17621794        HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus);
     
    17721804                     ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID));
    17731805
    1774             if (pidEvent)
    1775             {
    1776                 *pidEvent = idEvent;
    1777             }
    1778             else /* If event is not consumed by the caller, unregister event again. */
    1779                 ShClEventUnregister(&pTransfer->Events, idEvent);
     1806            if (ppEvent)
     1807            {
     1808                *ppEvent = pEvent; /* Takes ownership. */
     1809            }
     1810            else /* If event is not consumed by the caller, release the event again. */
     1811                ShClEventRelease(pEvent);
    17801812        }
    17811813        else
    1782             ShClEventUnregister(&pTransfer->Events, idEvent);
     1814            ShClEventRelease(pEvent);
    17831815    }
    17841816    else
     
    18691901                            if (RT_SUCCESS(rc))
    18701902                            {
    1871                                 SHCLEVENTID idEvent;
     1903                                PSHCLEVENT pEvent;
    18721904                                rc = shClSvcTransferSendStatus(pClient, pTransfer,
    1873                                                                SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS,
    1874                                                                &idEvent);
     1905                                                               SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, &pEvent);
    18751906                                if (RT_SUCCESS(rc))
    18761907                                {
     
    18821913
    18831914                                    PSHCLEVENTPAYLOAD pPayload = NULL;
    1884                                     rc = ShClEventWait(&pTransfer->Events, idEvent, pTransfer->uTimeoutMs, &pPayload);
     1915                                    rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, &pPayload);
    18851916                                    if (RT_SUCCESS(rc))
    18861917                                    {
     
    19071938
    19081939                                    ShClPayloadFree(pPayload);
     1940                                    ShClEventRelease(pEvent);
    19091941
    19101942                                    /* Re-enter the client's critical section again. */
     
    19541986int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    19551987{
    1956     SHCLEVENTID idEvent;
     1988    PSHCLEVENT pEvent;
    19571989    int rc = shClSvcTransferSendStatus(pClient, pTransfer,
    1958                                        SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS,
    1959                                        &idEvent);
     1990                                       SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent);
    19601991    if (RT_SUCCESS(rc))
    19611992    {
    19621993        LogRel2(("Shared Clipboard: Waiting for stop of transfer %RU32 on guest ...\n", pTransfer->State.uID));
    19631994
    1964         rc = ShClEventWait(&pTransfer->Events, idEvent, pTransfer->uTimeoutMs, NULL);
     1995        rc = ShClEventWait(pEvent, pTransfer->uTimeoutMs, NULL /* ppPayload */);
    19651996        if (RT_SUCCESS(rc))
    19661997            LogRel2(("Shared Clipboard: Stopped transfer %RU32 on guest\n", pTransfer->State.uID));
     1998
     1999        ShClEventRelease(pEvent);
    19672000    }
    19682001
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r91749 r92735  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    207207
    208208        ShClEventRelease(&pCtx->pClient->EventSrc, idEvent);
    209         ShClEventUnregister(&pCtx->pClient->EventSrc, idEvent);
    210209    }
    211210
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp

    r91749 r92735  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    218218                 pClient, uFormat, pvData, cbData, pcbActual));
    219219
    220     int rc = VINF_SUCCESS;
     220    int rc;
    221221
    222222    CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ));
    223223    if (pReq)
    224224    {
    225         pReq->pv        = pvData;
    226         pReq->cb        = cbData;
    227         pReq->pcbActual = pcbActual;
    228         const SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc);
    229         pReq->idEvent    = idEvent;
    230         if (idEvent != NIL_SHCLEVENTID)
    231         {
     225        PSHCLEVENT pEvent;
     226        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     227        if (RT_SUCCESS(rc))
     228        {
     229            pReq->pv        = pvData;
     230            pReq->cb        = cbData;
     231            pReq->pcbActual = pcbActual;
     232            pReq->idEvent   = pEvent->idEvent;
     233
    232234            /* Note: ShClX11ReadDataFromX11() will consume pReq on success. */
    233235            rc = ShClX11ReadDataFromX11(&pClient->State.pCtx->X11, uFormat, pReq);
     
    235237            {
    236238                PSHCLEVENTPAYLOAD pPayload;
    237                 rc = ShClEventWait(&pClient->EventSrc, idEvent, 30 * 1000, &pPayload);
     239                rc = ShClEventWait(pEvent, 30 * 1000, &pPayload);
    238240                if (RT_SUCCESS(rc))
    239241                {
     
    251253            }
    252254
    253             ShClEventUnregister(&pClient->EventSrc, idEvent);
    254         }
    255         else
    256             rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
     255            ShClEventRelease(pEvent);
     256        }
    257257
    258258        if (RT_FAILURE(rc))
     
    331331        if (RT_SUCCESS(rc2))
    332332        {
    333             rc2 = ShClEventSignal(&pCtx->pClient->EventSrc, pReq->idEvent, pPayload);
     333            const PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pCtx->pClient->EventSrc, pReq->idEvent);
     334            if (pEvent)
     335                rc2 = ShClEventSignal(pEvent, pPayload);
     336
    334337            RTCritSectLeave(&pCtx->pClient->CritSect);
     338
    335339            if (RT_SUCCESS(rc2))
    336340                pPayload = NULL;
     
    394398    {
    395399        /* Request data from the guest. */
    396         SHCLEVENTID idEvent;
    397         rc = ShClSvcGuestDataRequest(pCtx->pClient, uFmt, &idEvent);
     400        PSHCLEVENT pEvent;
     401        rc = ShClSvcGuestDataRequest(pCtx->pClient, uFmt, &pEvent);
    398402        if (RT_SUCCESS(rc))
    399403        {
     
    401405
    402406            PSHCLEVENTPAYLOAD pPayload;
    403             rc = ShClEventWait(&pCtx->pClient->EventSrc, idEvent, 30 * 1000, &pPayload);
     407            rc = ShClEventWait(pEvent, 30 * 1000, &pPayload);
    404408            if (RT_SUCCESS(rc))
    405409            {
     
    418422            RTCritSectEnter(&pClient->CritSect);
    419423
    420             ShClEventRelease(&pCtx->pClient->EventSrc, idEvent);
    421             ShClEventUnregister(&pCtx->pClient->EventSrc, idEvent);
     424            ShClEventRelease(pEvent);
    422425        }
    423426    }
     
    459462    LogFlowFuncEnter();
    460463
    461     int rc;
    462 
    463     SHCLEVENTID idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc);
    464     if (idEvent != NIL_SHCLEVENTID)
     464    PSHCLEVENT pEvent;
     465    int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     466    if (RT_SUCCESS(rc))
    465467    {
    466468        CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(CLIPREADCBREQ));
    467469        if (pReq)
    468470        {
    469             pReq->idEvent = idEvent;
     471            pReq->idEvent = pEvent->idEvent;
    470472
    471473            rc = ShClX11ReadDataFromX11(&pClient->State.pCtx->X11, VBOX_SHCL_FMT_URI_LIST, pReq);
     
    474476                /* X supplies the data asynchronously, so we need to wait for data to arrive first. */
    475477                PSHCLEVENTPAYLOAD pPayload;
    476                 rc = ShClEventWait(&pClient->EventSrc, idEvent, 30 * 1000, &pPayload);
     478                rc = ShClEventWait(pEvent, 30 * 1000, &pPayload);
    477479                if (RT_SUCCESS(rc))
    478480                {
     
    485487            rc = VERR_NO_MEMORY;
    486488
    487         ShClEventUnregister(&pClient->EventSrc, idEvent);
     489        ShClEventRelease(pEvent);
    488490    }
    489491    else
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r92240 r92735  
    55
    66/*
    7  * Copyright (C) 2006-2020 Oracle Corporation
     7 * Copyright (C) 2006-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    12011201 * @param   pClient             Client to request to read data form.
    12021202 * @param   fFormats            The formats being requested, OR'ed together (VBOX_SHCL_FMT_XXX).
    1203  * @param   pidEvent            Event ID for waiting for new data. Optional.
    1204  *                              Must be released by the caller with ShClEventRelease() before unregistering then.
    1205  */
    1206 int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENTID pidEvent)
    1207 {
    1208     LogFlowFuncEnter();
    1209     if (pidEvent)
    1210         *pidEvent = NIL_SHCLEVENTID;
    1211     AssertPtrReturn(pClient,  VERR_INVALID_POINTER);
     1203 * @param   ppEvent             Where to return the event for waiting for new data on success. Optional.
     1204 *                              Must be released by the caller with ShClEventRelease().
     1205 */
     1206int ShClSvcGuestDataRequest(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent)
     1207{
     1208    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
    12121209
    12131210    LogFlowFunc(("fFormats=%#x\n", fFormats));
    12141211
    12151212    int rc = VERR_NOT_SUPPORTED;
    1216 
    1217     SHCLEVENTID idEvent = NIL_SHCLEVENTID;
    12181213
    12191214    /* Generate a separate message for every (valid) format we support. */
     
    12551250            RTCritSectEnter(&pClient->CritSect);
    12561251
    1257             idEvent = ShClEventIdGenerateAndRegister(&pClient->EventSrc);
    1258             if (idEvent != NIL_SHCLEVENTID)
     1252            PSHCLEVENT pEvent;
     1253            rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     1254            if (RT_SUCCESS(rc))
    12591255            {
    1260                 LogFlowFunc(("fFormats=%#x -> fFormat=%#x, idEvent=%#x\n", fFormats, fFormat, idEvent));
    1261 
    1262                 const uint64_t uCID = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, idEvent);
     1256                LogFlowFunc(("fFormats=%#x -> fFormat=%#x, idEvent=%#x\n", fFormats, fFormat, pEvent->idEvent));
     1257
     1258                const uint64_t uCID = VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, pClient->EventSrc.uID, pEvent->idEvent);
    12631259
    12641260                rc = VINF_SUCCESS;
     
    12961292
    12971293                    shClSvcMsgAdd(pClient, pMsg, true /* fAppend */);
     1294
     1295                    /* Retain the last event generated (in case there were multiple clipboard formats)
     1296                     * if we need to return the event to the caller. */
     1297                    if (ppEvent)
     1298                    {
     1299                        ShClEventRetain(pEvent);
     1300                        *ppEvent = pEvent;
     1301                    }
     1302
     1303                    shClSvcClientWakeup(pClient);
    12981304                }
    12991305            }
     
    13111317        if (RT_FAILURE(rc))
    13121318            break;
    1313     }
    1314 
    1315     if (RT_SUCCESS(rc))
    1316     {
    1317         RTCritSectEnter(&pClient->CritSect);
    1318 
    1319         /* Retain the last event generated (in case there were multiple clipboard formats)
    1320          * if we need to return the event ID to the caller. */
    1321         if (pidEvent)
    1322         {
    1323             ShClEventRetain(&pClient->EventSrc, idEvent);
    1324             *pidEvent = idEvent;
    1325         }
    1326 
    1327         shClSvcClientWakeup(pClient);
    1328 
    1329         RTCritSectLeave(&pClient->CritSect);
    13301319    }
    13311320
     
    13551344
    13561345    /*
    1357      * Validate intput.
     1346     * Validate input.
    13581347     */
    13591348    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
     
    13641353    const SHCLEVENTID idEvent = VBOX_SHCL_CONTEXTID_GET_EVENT(pCmdCtx->uContextID);
    13651354    AssertMsgReturn(idEvent != NIL_SHCLEVENTID, ("NIL event in context ID %#RX64\n", pCmdCtx->uContextID), VERR_WRONG_ORDER);
    1366     AssertMsg(ShClEventGet(&pClient->EventSrc, idEvent) != NULL, ("Event %#x not found\n", idEvent));
     1355
     1356    PSHCLEVENT pEvent = ShClEventSourceGetFromId(&pClient->EventSrc, idEvent);
     1357    AssertMsg(pEvent != NULL, ("Event %#x not found\n", idEvent));
    13671358
    13681359    /*
     
    13801371     * Signal the event.
    13811372     */
    1382     RTCritSectEnter(&pClient->CritSect);
    1383     int rc2 = ShClEventSignal(&pClient->EventSrc, idEvent, pPayload);
    1384     RTCritSectLeave(&pClient->CritSect);
     1373    int rc2 = ShClEventSignal(pEvent, pPayload);
    13851374    if (RT_FAILURE(rc2))
    13861375    {
     
    13911380
    13921381    /*
    1393      * No one holding a reference to the event anymore? Unregister it.
    1394      */
    1395     /** @todo r=bird: This isn't how reference counting is supposed to be
    1396      *        implemented, is it now? */
    1397     if (ShClEventGetRefs(&pClient->EventSrc, idEvent) == 0)
    1398     {
    1399         rc2 = ShClEventUnregister(&pClient->EventSrc, idEvent);
    1400         if (RT_SUCCESS(rc))
    1401             rc = rc2;
    1402     }
     1382     * Release reference (and free it if not used anymore).
     1383     */
     1384    ShClEventRelease(pEvent);
    14031385
    14041386    LogFlowFuncLeaveRC(rc);
Note: See TracChangeset for help on using the changeset viewer.

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