VirtualBox

Ignore:
Timestamp:
Aug 27, 2019 5:47:44 PM (5 years ago)
Author:
vboxsync
Message:

Shared Clipboard/URI: Added protocol versioning support plus enhanced versions of existing commands (to also provide context IDs, among other stuff). So far only the host service(s) and the Windows guest is using the new(er) protocol.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp

    r80285 r80444  
    2222#include <iprt/alloc.h>
    2323#include <iprt/assert.h>
     24#include <iprt/semaphore.h>
    2425#include <iprt/path.h>
    2526
     
    2829#include <VBox/GuestHost/clipboard-helper.h>
    2930#include <VBox/HostServices/VBoxClipboardSvc.h>
     31
     32
     33/**
     34 * Allocates a new event payload.
     35 *
     36 * @returns VBox status code.
     37 * @param   uID                 Event ID to associate payload to.
     38 * @param   pvData              Data block to associate to this payload.
     39 * @param   cbData              Size (in bytes) of data block to associate.
     40 * @param   ppPayload           Where to store the allocated event payload on success.
     41 */
     42int SharedClipboardPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData,
     43                                PSHAREDCLIPBOARDEVENTPAYLOAD *ppPayload)
     44{
     45    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     46    AssertReturn   (cbData, VERR_INVALID_PARAMETER);
     47
     48    PSHAREDCLIPBOARDEVENTPAYLOAD pPayload =
     49        (PSHAREDCLIPBOARDEVENTPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDEVENTPAYLOAD));
     50    if (!pPayload)
     51        return VERR_NO_MEMORY;
     52
     53    pPayload->pvData = RTMemAlloc(cbData);
     54    if (pPayload->pvData)
     55    {
     56        memcpy(pPayload->pvData, pvData, cbData);
     57
     58        pPayload->cbData = cbData;
     59        pPayload->uID    = uID;
     60
     61        *ppPayload = pPayload;
     62
     63        return VINF_SUCCESS;
     64    }
     65
     66    RTMemFree(pPayload);
     67    return VERR_NO_MEMORY;
     68}
     69
     70/**
     71 * Frees an event payload.
     72 *
     73 * @returns VBox status code.
     74 * @param   pPayload            Event payload to free.
     75 */
     76void SharedClipboardPayloadFree(PSHAREDCLIPBOARDEVENTPAYLOAD pPayload)
     77{
     78    if (!pPayload)
     79        return;
     80
     81    if (pPayload->pvData)
     82    {
     83        Assert(pPayload->cbData);
     84        RTMemFree(pPayload->pvData);
     85        pPayload->pvData = NULL;
     86    }
     87
     88    pPayload->cbData = 0;
     89
     90    RTMemFree(pPayload);
     91    pPayload = NULL;
     92}
     93
     94int SharedClipboardEventCreate(PSHAREDCLIPBOARDEVENT pEvent, uint16_t uID)
     95{
     96    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     97
     98    LogFlowFunc(("Event %RU16\n", uID));
     99
     100    int rc = RTSemEventCreate(&pEvent->hEventSem);
     101    if (RT_SUCCESS(rc))
     102    {
     103        pEvent->uID      = uID;
     104        pEvent->pPayload = NULL;
     105    }
     106
     107    return rc;
     108}
     109
     110void SharedClipboardEventDestroy(PSHAREDCLIPBOARDEVENT pEvent)
     111{
     112    if (!pEvent)
     113        return;
     114
     115    LogFlowFunc(("Event %RU16\n", pEvent->uID));
     116
     117    if (pEvent->hEventSem != NIL_RTSEMEVENT)
     118    {
     119        RTSemEventDestroy(pEvent->hEventSem);
     120        pEvent->hEventSem = NIL_RTSEMEVENT;
     121    }
     122
     123    SharedClipboardPayloadFree(pEvent->pPayload);
     124
     125    pEvent->uID = 0;
     126}
     127
     128int SharedClipboardEventSourceCreate(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
     129{
     130    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     131
     132    LogFlowFunc(("pSource=%p, uID=%RU16\n", pSource, uID));
     133
     134    int rc = VINF_SUCCESS;
     135
     136    RTListInit(&pSource->lstEvents);
     137
     138    pSource->uID          = uID;
     139    pSource->uEventIDNext = 1; /* Event ID 0 always is reserved (marks "unused"). */
     140
     141    LogFlowFuncLeaveRC(rc);
     142    return rc;
     143}
     144
     145void SharedClipboardEventSourceDestroy(PSHAREDCLIPBOARDEVENTSOURCE pSource)
     146{
     147    if (!pSource)
     148        return;
     149
     150    LogFlowFunc(("ID=%RU16\n", pSource->uID));
     151
     152    PSHAREDCLIPBOARDEVENT pEvIt;
     153    PSHAREDCLIPBOARDEVENT pEvItNext;
     154    RTListForEachSafe(&pSource->lstEvents, pEvIt, pEvItNext, SHAREDCLIPBOARDEVENT, Node)
     155    {
     156        SharedClipboardEventDestroy(pEvIt);
     157        RTMemFree(pEvIt);
     158    }
     159}
     160
     161/**
     162 * Generates a new event ID for a specific event source.
     163 *
     164 * @returns New event ID generated, or 0 on error.
     165 * @param   pSource             Event source to generate event for.
     166 */
     167uint16_t SharedClipboardEventIDGenerate(PSHAREDCLIPBOARDEVENTSOURCE pSource)
     168{
     169    AssertPtrReturn(pSource, 0);
     170
     171    LogFlowFunc(("uSource=%RU16: New event: %RU16\n", pSource->uID, pSource->uEventIDNext));
     172    return pSource->uEventIDNext++; /** @todo Improve this. */
     173}
     174
     175/**
     176 * Returns a specific event of a event source.
     177 *
     178 * @returns Pointer to event if found, or NULL if not found.
     179 * @param   pSource             Event source to get event from.
     180 * @param   uID                 Event ID to get.
     181 */
     182inline PSHAREDCLIPBOARDEVENT sharedClipboardEventGet(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
     183{
     184    PSHAREDCLIPBOARDEVENT pEvIt;
     185    RTListForEach(&pSource->lstEvents, pEvIt, SHAREDCLIPBOARDEVENT, Node)
     186    {
     187        if (pEvIt->uID == uID)
     188            return pEvIt;
     189    }
     190
     191    return NULL;
     192}
     193
     194/**
     195 * Registers an event.
     196 *
     197 * @returns VBox status code.
     198 * @param   pSource             Event source to register event for.
     199 * @param   uID                 Event ID to register.
     200 */
     201int SharedClipboardEventRegister(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
     202{
     203    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     204
     205    int rc;
     206
     207    LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
     208
     209    if (sharedClipboardEventGet(pSource, uID) == NULL)
     210    {
     211        PSHAREDCLIPBOARDEVENT pEvent
     212            = (PSHAREDCLIPBOARDEVENT)RTMemAllocZ(sizeof(SHAREDCLIPBOARDEVENT));
     213        if (pEvent)
     214        {
     215            rc = SharedClipboardEventCreate(pEvent, uID);
     216            if (RT_SUCCESS(rc))
     217            {
     218                RTListAppend(&pSource->lstEvents, &pEvent->Node);
     219
     220                LogFlowFunc(("Event %RU16\n", uID));
     221            }
     222        }
     223        else
     224            rc = VERR_NO_MEMORY;
     225    }
     226    else
     227        rc = VERR_ALREADY_EXISTS;
     228
     229#ifdef DEBUG_andy
     230    AssertRC(rc);
     231#endif
     232
     233    LogFlowFuncLeaveRC(rc);
     234    return rc;
     235}
     236
     237/**
     238 * Unregisters an event.
     239 *
     240 * @returns VBox status code.
     241 * @param   pSource             Event source to unregister event for.
     242 * @param   uID                 Event ID to unregister.
     243 */
     244int SharedClipboardEventUnregister(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
     245{
     246    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     247
     248    int rc;
     249
     250    LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
     251
     252    PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
     253    if (pEvent)
     254    {
     255        LogFlowFunc(("Event %RU16\n", pEvent->uID));
     256
     257        SharedClipboardEventDestroy(pEvent);
     258        RTMemFree(pEvent);
     259
     260        RTListNodeRemove(&pEvent->Node);
     261
     262        rc = VINF_SUCCESS;
     263    }
     264    else
     265        rc = VERR_NOT_FOUND;
     266
     267    AssertRC(rc);
     268
     269    LogFlowFuncLeaveRC(rc);
     270    return rc;
     271}
     272
     273/**
     274 * Waits for an event to get signalled.
     275 *
     276 * @returns VBox status code.
     277 * @param   pSource             Event source that contains the event to wait for.
     278 * @param   uID                 Event ID to wait for.
     279 * @param   uTimeoutMs          Timeout (in ms) to wait.
     280 * @param   ppPayload           Where to store the (allocated) event payload on success. Needs to be free'd with
     281 *                              SharedClipboardPayloadFree().
     282 */
     283int SharedClipboardEventWait(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID, RTMSINTERVAL uTimeoutMs,
     284                             PSHAREDCLIPBOARDEVENTPAYLOAD* ppPayload)
     285{
     286    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     287
     288    LogFlowFuncEnter();
     289
     290    int rc;
     291
     292    PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
     293    if (pEvent)
     294    {
     295        rc = RTSemEventWait(pEvent->hEventSem, uTimeoutMs);
     296        if (RT_SUCCESS(rc))
     297        {
     298            *ppPayload = pEvent->pPayload;
     299
     300            pEvent->pPayload = NULL;
     301        }
     302    }
     303    else
     304        rc = VERR_NOT_FOUND;
     305
     306    LogFlowFuncLeaveRC(rc);
     307    return rc;
     308}
     309
     310/**
     311 * Signals an event.
     312 *
     313 * @returns VBox status code.
     314 * @param   pSource             Event source of event to signal.
     315 * @param   uID                 Event ID to signal.
     316 * @param   pPayload            Event payload to associate. Takes ownership. Optional.
     317 */
     318int SharedClipboardEventSignal(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID,
     319                               PSHAREDCLIPBOARDEVENTPAYLOAD pPayload)
     320{
     321    AssertPtrReturn(pSource, VERR_INVALID_POINTER);
     322
     323    int rc;
     324
     325    LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
     326
     327    PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
     328    if (pEvent)
     329    {
     330        Assert(pEvent->pPayload == NULL);
     331
     332        pEvent->pPayload = pPayload;
     333
     334        rc = RTSemEventSignal(pEvent->hEventSem);
     335    }
     336    else
     337        rc = VERR_NOT_FOUND;
     338
     339#ifdef DEBUG_andy
     340    AssertRC(rc);
     341#endif
     342
     343    LogFlowFuncLeaveRC(rc);
     344    return rc;
     345}
     346
     347/**
     348 * Detaches a payload from an event.
     349 *
     350 * @returns VBox status code.
     351 * @param   pSource             Event source of event to detach payload for.
     352 * @param   uID                 Event ID to detach payload for.
     353 */
     354void SharedClipboardEventPayloadDetach(PSHAREDCLIPBOARDEVENTSOURCE pSource, uint16_t uID)
     355{
     356    AssertPtrReturnVoid(pSource);
     357
     358    LogFlowFunc(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
     359
     360    PSHAREDCLIPBOARDEVENT pEvent = sharedClipboardEventGet(pSource, uID);
     361    if (pEvent)
     362    {
     363        pEvent->pPayload = NULL;
     364    }
     365#ifdef DEBUG_andy
     366    else
     367        AssertMsgFailed(("uSource=%RU16, uEvent=%RU16\n", pSource->uID, uID));
     368#endif
     369}
    30370
    31371/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
     
    421761        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
    422762        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
    423         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
     763        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS_WRITE);
    424764        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
    425765        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOT_LIST_HDR_READ);
     
    453793    switch (uMsg)
    454794    {
    455         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPORT_FORMATS);
    456         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA);
    457         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA);
     795        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD);
     796        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_FORMATS_WRITE);
     797        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_READ);
     798        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_DATA_WRITE);
     799        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CONNECT);
    458800        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT);
    459801        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT);
     
    477819        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL);
    478820        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR);
    479         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
    480821    }
    481822    return "Unknown";
    482823}
     824
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