VirtualBox

Changeset 79497 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 3, 2019 1:28:33 PM (6 years ago)
Author:
vboxsync
Message:

Shared Clipboard/URI: Update.

Location:
trunk/src/VBox
Files:
4 deleted
20 edited

Legend:

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

    r79366 r79497  
    3232
    3333#include <VBox/GuestHost/SharedClipboard.h>
     34#include <VBox/HostServices/VBoxClipboardSvc.h> /* Temp, remove. */
    3435#include <VBox/GuestHost/SharedClipboard-win.h>
    3536#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    36 # include <VBox/GuestHost/SharedClipboard-uri.h>
     37#   include <VBox/GuestHost/SharedClipboard-uri.h>
    3738#endif
    3839
     
    4142#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    4243/** !!! HACK ALERT !!! Dynamically resolve functions! */
    43 # ifdef _WIN32_IE
    44 undef _WIN32_IE
    45 define _WIN32_IE 0x0501
    46 # endif
    47 # include <iprt/win/shlobj.h>
    48 # include <iprt/win/shlwapi.h>
     44#   ifdef _WIN32_IE
     45     undef _WIN32_IE
     46     define _WIN32_IE 0x0501
     47#   endif
     48#   include <iprt/win/shlobj.h>
     49#   include <iprt/win/shlwapi.h>
    4950#endif
    5051
     
    5455*********************************************************************************************************************************/
    5556
    56 struct _VBOXCLIPBOARDCONTEXT
     57typedef struct _VBOXCLIPBOARDCONTEXT
    5758{
    5859    /** Pointer to the VBoxClient service environment. */
     
    6667    SHAREDCLIPBOARDURICTX    URI;
    6768#endif
    68 };
     69} VBOXCLIPBOARDCONTEXT, *PVBOXCLIPBOARDCONTEXT;
     70
     71typedef struct _VBOXCLIPBOARDWRITETHREADCTX
     72{
     73    PVBOXCLIPBOARDCONTEXT       pClipboardCtx;
     74    PSHAREDCLIPBOARDURITRANSFER pTransfer;
     75    char                       *papszURIList;
     76    uint32_t                    cbURIList;
     77} VBOXCLIPBOARDWRITETHREADCTX, *PVBOXCLIPBOARDWRITETHREADCTX;
    6978
    7079
     
    8897
    8998#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     99static DECLCALLBACK(int) vboxClipboardURIWriteThread(RTTHREAD ThreadSelf, void *pvUser)
     100{
     101    RT_NOREF(ThreadSelf);
     102
     103    LogFlowFuncEnter();
     104
     105    PVBOXCLIPBOARDWRITETHREADCTX pCtx = (PVBOXCLIPBOARDWRITETHREADCTX)pvUser;
     106    AssertPtr(pCtx);
     107
     108    RTThreadUserSignal(RTThreadSelf());
     109
     110    uint32_t uClientID;
     111    int rc = VbglR3ClipboardConnect(&uClientID);
     112    if (RT_SUCCESS(rc))
     113    {
     114        VBoxClipboardTransferReport Msg;
     115        RT_ZERO(Msg);
     116
     117        VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientID,
     118                            VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT, VBOX_SHARED_CLIPBOARD_CPARMS_TRANSFER_REPORT);
     119
     120        Msg.uContext.SetUInt32(0);
     121        Msg.uStatus.SetUInt32(0);
     122
     123        rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     124
     125        if (RT_SUCCESS(rc))
     126        {
     127            bool     fTerminate = false;
     128            unsigned cErrors    = 0;
     129
     130            for (;;)
     131            {
     132                PVBGLR3CLIPBOARDEVENT pEvent;
     133                rc = VbglR3ClipboardEventGetNext(uClientID, pCtx->pTransfer, &pEvent);
     134                if (RT_SUCCESS(rc))
     135                {
     136                   switch (pEvent->enmType)
     137                   {
     138                       case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_READ:
     139                       {
     140                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_HDR\n"));
     141                           break;
     142                       }
     143
     144                       case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_ENTRY_READ:
     145                       {
     146                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_ENTRY\n"));
     147                           break;
     148                       }
     149
     150                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN:
     151                       {
     152                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN\n"));
     153                           break;
     154                       }
     155
     156                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE:
     157                       {
     158                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE\n"));
     159                           break;
     160                       }
     161
     162                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ:
     163                       {
     164                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ\n"));
     165                           break;
     166                       }
     167
     168                       case VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL:
     169                           RT_FALL_THROUGH();
     170                       case VBGLR3CLIPBOARDEVENTTYPE_URI_ERROR:
     171                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL / ERROR\n"));
     172                           fTerminate = true;
     173                           break;
     174
     175                       default:
     176                           rc = VERR_NOT_SUPPORTED;
     177                           cErrors++;
     178                           break;
     179                   }
     180
     181                   VbglR3ClipboardEventFree(pEvent);
     182                }
     183
     184                if (fTerminate)
     185                    break;
     186
     187                if (RT_FAILURE(rc))
     188                {
     189                    if (cErrors++ >= 3)
     190                        break;
     191                    RTThreadSleep(1000);
     192                }
     193            }
     194        }
     195
     196        VbglR3ClipboardDisconnect(uClientID);
     197    }
     198
     199    if (pCtx->papszURIList)
     200        RTStrFree(pCtx->papszURIList);
     201
     202    RTMemFree(pCtx);
     203
     204    LogFlowFuncLeaveRC(rc);
     205    return rc;
     206}
     207
    90208static DECLCALLBACK(void) vboxClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
    91209{
     
    136254}
    137255
    138 static int vboxClipboardURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr)
    139 {
     256static int vboxClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
     257{
     258    RT_NOREF(pCtx);
     259
     260    LogFlowFuncLeave();
     261    return VINF_SUCCESS;
     262}
     263
     264static int vboxClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
     265{
     266    RT_NOREF(pCtx);
     267
     268    LogFlowFuncLeave();
     269    return VINF_SUCCESS;
     270}
     271
     272static int vboxClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     273                                       PVBOXCLIPBOARDLISTHDR pListHdr)
     274{
     275    RT_NOREF(hList);
     276
    140277    LogFlowFuncEnter();
    141278
     
    145282    LogFlowFunc(("c=%RU32\n", pThisCtx->u32ClientID));
    146283
    147     VBOXCLIPBOARDDATAHDR dataHdr;
    148     SharedClipboardURIDataHdrInit(&dataHdr);
    149 
    150     int rc = VbglR3ClipboardReadDataHdr(pThisCtx->u32ClientID, &dataHdr);
    151     if (RT_SUCCESS(rc))
    152     {
    153         *ppDataHdr = SharedClipboardURIDataHdrDup(&dataHdr);
    154     }
     284    RT_NOREF(pListHdr);
     285    int rc = 0; //VbglR3ClipboardListHdrRead(pThisCtx->u32ClientID, pListHdr);
    155286
    156287    LogFlowFuncLeaveRC(rc);
     
    158289}
    159290
    160 static int vboxClipboardURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr)
     291static int vboxClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     292                                        PVBOXCLIPBOARDLISTHDR pListHdr)
    161293{
    162294    LogFlowFuncEnter();
     
    165297    AssertPtr(pThisCtx);
    166298
    167     int rc = VbglR3ClipboardWriteDataHdr(pThisCtx->u32ClientID, pDataHdr);
     299    int rc = VbglR3ClipboardSendListHdrWrite(pThisCtx->u32ClientID, hList, pListHdr);
    168300
    169301    LogFlowFuncLeaveRC(rc);
     
    171303}
    172304
    173 static int vboxClipboardURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
    174                                          void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead)
    175 {
    176     RT_NOREF(fFlags);
     305static int vboxClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     306                                         PVBOXCLIPBOARDLISTENTRY pListEntry)
     307{
     308    RT_NOREF(hList);
    177309
    178310    LogFlowFuncEnter();
     
    181313    AssertPtr(pThisCtx);
    182314
    183     int rc = VINF_SUCCESS;
    184 
    185     uint32_t cbReadTotal = 0;
    186     uint32_t cbToRead = RT_MIN(pDataHdr->cbMeta, cbChunk);
    187 
    188     while (cbToRead)
    189     {
    190         uint32_t cbRead;
    191         rc = VbglR3ClipboardReadMetaData(pThisCtx->u32ClientID, pDataHdr, (uint8_t *)pvChunk + cbReadTotal, cbToRead, &cbRead);
    192         if (RT_FAILURE(rc))
    193             break;
    194 
    195         cbReadTotal += cbRead;
    196         Assert(cbToRead >= cbRead);
    197         cbToRead    -= cbRead;
    198     }
    199 
    200     if (RT_SUCCESS(rc))
    201     {
    202         if (pcbRead)
    203             *pcbRead = cbReadTotal;
    204     }
     315    RT_NOREF(pListEntry);
     316    int rc = 0; // VbglR3ClipboardListEntryRead(pThisCtx->u32ClientID, pListEntry);
    205317
    206318    LogFlowFuncLeaveRC(rc);
     
    208320}
    209321
    210 static int vboxClipboardURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
    211                                           const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten)
    212 {
    213     RT_NOREF(fFlags);
    214 
     322static int vboxClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     323                                          PVBOXCLIPBOARDLISTENTRY pListEntry)
     324{
    215325    LogFlowFuncEnter();
    216326
     
    218328    AssertPtr(pThisCtx);
    219329
    220     int rc = VINF_SUCCESS;
    221 
    222     uint32_t cbWrittenTotal = 0;
    223     uint32_t cbToWrite      = RT_MIN(pDataHdr->cbMeta, cbChunk);
    224 
    225     while (cbToWrite)
    226     {
    227         uint32_t cbWritten;
    228         rc = VbglR3ClipboardWriteMetaData(pThisCtx->u32ClientID, pDataHdr, (uint8_t *)pvChunk + cbWrittenTotal, cbToWrite,
    229                                           &cbWritten);
    230         if (RT_FAILURE(rc))
    231             break;
    232 
    233         cbWrittenTotal += cbWritten;
    234         Assert(cbToWrite >= cbWritten);
    235         cbToWrite      -= cbWritten;
    236     }
    237 
    238     if (RT_SUCCESS(rc))
    239     {
    240         if (pcbWritten)
    241             *pcbWritten = cbWrittenTotal;
    242     }
    243 
    244     LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));
     330    int rc = VbglR3ClipboardSendListEntryWrite(pThisCtx->u32ClientID, hList, pListEntry);
     331
     332    LogFlowFuncLeaveRC(rc);
    245333    return rc;
    246334}
    247335
    248 static int vboxClipboardURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData)
     336static int vboxClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
     337                                   PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj)
    249338{
    250339    LogFlowFuncEnter();
     
    253342    AssertPtr(pThisCtx);
    254343
    255     VBOXCLIPBOARDDIRDATA dirData;
    256     SharedClipboardURIDirDataInit(&dirData);
    257 
    258     int rc = VbglR3ClipboardReadDir(pThisCtx->u32ClientID, dirData.pszPath, dirData.cbPath, &dirData.cbPath, &dirData.fMode);
    259     if (RT_SUCCESS(rc))
    260     {
    261         *ppDirData = SharedClipboardURIDirDataDup(&dirData);
    262     }
     344    int rc = VbglR3ClipboardObjOpen(pThisCtx->u32ClientID, pszPath, pCreateParms, phObj);
    263345
    264346    LogFlowFuncLeaveRC(rc);
     
    266348}
    267349
    268 static int vboxClipboardURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData)
     350static int vboxClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj)
    269351{
    270352    LogFlowFuncEnter();
     
    273355    AssertPtr(pThisCtx);
    274356
    275     int rc = VbglR3ClipboardWriteDir(pThisCtx->u32ClientID, pDirData->pszPath, pDirData->cbPath, pDirData->fMode);
     357    int rc = VbglR3ClipboardObjClose(pThisCtx->u32ClientID, hObj);
    276358
    277359    LogFlowFuncLeaveRC(rc);
     
    279361}
    280362
    281 static int vboxClipboardURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr)
    282 {
     363static int vboxClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     364                                   void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
     365{
     366    RT_NOREF(fFlags);
     367
    283368    LogFlowFuncEnter();
    284369
     
    286371    AssertPtr(pThisCtx);
    287372
    288     VBOXCLIPBOARDFILEHDR fileHdr;
    289     SharedClipboardURIFileHdrInit(&fileHdr);
    290 
    291     int rc = VbglR3ClipboardReadFileHdr(pThisCtx->u32ClientID, fileHdr.pszFilePath, fileHdr.cbFilePath,
    292                                         &fileHdr.fFlags, &fileHdr.fMode, &fileHdr.cbSize);
    293     if (RT_SUCCESS(rc))
    294     {
    295         *ppFileHdr = SharedClipboardURIFileHdrDup(&fileHdr);
    296     }
     373    int rc = VbglR3ClipboardObjRead(pThisCtx->u32ClientID, hObj, pvData, cbData, pcbRead);
    297374
    298375    LogFlowFuncLeaveRC(rc);
     
    300377}
    301378
    302 static int vboxClipboardURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr)
    303 {
     379static int vboxClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     380                                    void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
     381{
     382    RT_NOREF(fFlags);
     383
    304384    LogFlowFuncEnter();
    305385
     
    307387    AssertPtr(pThisCtx);
    308388
    309     int rc = VbglR3ClipboardWriteFileHdr(pThisCtx->u32ClientID, pFileHdr->pszFilePath, pFileHdr->cbFilePath,
    310                                          pFileHdr->fFlags, pFileHdr->fMode, pFileHdr->cbSize);
    311     LogFlowFuncLeaveRC(rc);
    312     return rc;
    313 }
    314 
    315 static int vboxClipboardURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
    316                                         uint32_t *pcbRead)
    317 {
    318     RT_NOREF(fFlags);
    319 
    320     AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
    321 
    322     LogFlowFuncEnter();
    323 
    324     PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
    325     AssertPtr(pThisCtx);
    326 
    327     int rc = VbglR3ClipboardReadFileData(pThisCtx->u32ClientID, pvData, cbData, pcbRead);
    328 
    329     LogFlowFuncLeaveRC(rc);
    330     return rc;
    331 }
    332 
    333 static int vboxClipboardURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
    334                                          uint32_t *pcbWritten)
    335 {
    336     RT_NOREF(fFlags);
    337 
    338     AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
    339 
    340     LogFlowFuncEnter();
    341 
    342     PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
    343     AssertPtr(pThisCtx);
    344 
    345     int rc = VbglR3ClipboardWriteFileData(pThisCtx->u32ClientID, pvData, cbData, pcbWritten);
     389    int rc = VbglR3ClipboardObjWrite(pThisCtx->u32ClientID, hObj, pvData, cbData, pcbWritten);
    346390
    347391    LogFlowFuncLeaveRC(rc);
     
    379423           }
    380424       }
    381        break;
     425           break;
    382426
    383427       case WM_CHANGECBCHAIN:
     
    386430           lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, hwnd, msg, wParam, lParam);
    387431       }
    388        break;
     432           break;
    389433
    390434       case WM_DRAWCLIPBOARD:
     
    404448           lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, msg, wParam, lParam);
    405449       }
    406        break;
     450           break;
    407451
    408452       case WM_TIMER:
    409453       {
    410             int rc = VBoxClipboardWinHandleWMTimer(pWinCtx);
    411             AssertRC(rc);
     454           int rc = VBoxClipboardWinHandleWMTimer(pWinCtx);
     455           AssertRC(rc);
    412456       }
    413        break;
     457           break;
    414458
    415459       case WM_CLOSE:
     
    417461           /* Do nothing. Ignore the message. */
    418462       }
    419        break;
     463           break;
    420464
    421465       case WM_RENDERFORMAT:
     
    566610           }
    567611       }
    568        break;
     612           break;
    569613
    570614       case WM_RENDERALLFORMATS:
     
    575619           AssertRC(rc);
    576620       }
    577        break;
     621           break;
    578622
    579623       case VBOX_CLIPBOARD_WM_SET_FORMATS:
    580624       {
    581             LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS\n"));
    582 
    583             /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT. */
    584             VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
    585             if (fFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) /* Could arrive with some older GA versions. */
    586             {
    587                 int rc = VBoxClipboardWinOpen(hwnd);
    588                 if (RT_SUCCESS(rc))
    589                 {
    590                     VBoxClipboardWinClear();
     625           LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS\n"));
     626
     627           /* Announce available formats. Do not insert data -- will be inserted in WM_RENDERFORMAT. */
     628           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
     629           if (fFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) /* Could arrive with some older GA versions. */
     630           {
     631               int rc = VBoxClipboardWinOpen(hwnd);
     632               if (RT_SUCCESS(rc))
     633               {
     634                   VBoxClipboardWinClear();
    591635
    592636#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    593                     if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    594                     {
    595                         LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST\n"));
    596 
    597                         PSHAREDCLIPBOARDURITRANSFER pTransfer;
    598                         rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_READ,
    599                                                               SHAREDCLIPBOARDSOURCE_REMOTE,
    600                                                               &pTransfer);
    601                         if (RT_SUCCESS(rc))
    602                         {
    603                             SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
    604                             RT_ZERO(TransferCallbacks);
    605 
    606                             TransferCallbacks.pvUser              = &pCtx->URI;
    607                             TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback;
    608                             TransferCallbacks.pfnTransferError    = vboxClipboardURITransferErrorCallback;
    609 
    610                             SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks);
    611 
    612                             SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
    613                             RT_ZERO(creationCtx);
    614                             creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_REMOTE;
    615 
    616                             RT_ZERO(creationCtx.Interface);
    617                             creationCtx.Interface.pfnReadDataHdr    = vboxClipboardURIReadDataHdr;
    618                             creationCtx.Interface.pfnReadDataChunk  = vboxClipboardURIReadDataChunk;
    619                             creationCtx.Interface.pfnReadDirectory  = vboxClipboardURIReadDir;
    620                             creationCtx.Interface.pfnReadFileHdr    = vboxClipboardURIReadFileHdr;
    621                             creationCtx.Interface.pfnReadFileData   = vboxClipboardURIReadFileData;
    622 
    623                             creationCtx.pvUser = pCtx;
    624 
    625                             rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
    626                             if (RT_SUCCESS(rc))
    627                             {
    628                                 rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
    629                                 if (RT_SUCCESS(rc))
    630                                     rc = VBoxClipboardWinURITransferCreate(pWinCtx, pTransfer);
    631                             }
    632 
    633                             /* Note: VBoxClipboardWinURITransferCreate() takes care of closing the clipboard. */
    634 
    635                             LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST: rc=%Rrc\n", rc));
    636                         }
    637                     }
    638                     else
    639                     {
     637                   if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     638                   {
     639                       LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST\n"));
     640
     641                       PSHAREDCLIPBOARDURITRANSFER pTransfer;
     642                       rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_READ,
     643                                                             SHAREDCLIPBOARDSOURCE_REMOTE,
     644                                                             &pTransfer);
     645                       if (RT_SUCCESS(rc))
     646                       {
     647                           SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
     648                           RT_ZERO(TransferCallbacks);
     649
     650                           TransferCallbacks.pvUser              = &pCtx->URI;
     651                           TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback;
     652                           TransferCallbacks.pfnTransferError    = vboxClipboardURITransferErrorCallback;
     653
     654                           SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks);
     655
     656                           SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
     657                           RT_ZERO(creationCtx);
     658                           creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_REMOTE;
     659
     660                           RT_ZERO(creationCtx.Interface);
     661                           creationCtx.Interface.pfnTransferOpen  = vboxClipboardURITransferOpen;
     662                           creationCtx.Interface.pfnTransferClose = vboxClipboardURITransferClose;
     663                           creationCtx.Interface.pfnListHdrRead   = vboxClipboardURIListHdrRead;
     664                           creationCtx.Interface.pfnListEntryRead = vboxClipboardURIListEntryRead;
     665                           creationCtx.Interface.pfnObjOpen       = vboxClipboardURIObjOpen;
     666                           creationCtx.Interface.pfnObjClose      = vboxClipboardURIObjClose;
     667                           creationCtx.Interface.pfnObjRead       = vboxClipboardURIObjRead;
     668
     669                           creationCtx.pvUser = pCtx;
     670
     671                           rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     672                           if (RT_SUCCESS(rc))
     673                           {
     674                               rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
     675                               if (RT_SUCCESS(rc))
     676                                   rc = VBoxClipboardWinURITransferCreate(pWinCtx, pTransfer);
     677                           }
     678
     679                           /* Note: VBoxClipboardWinURITransferCreate() takes care of closing the clipboard. */
     680
     681                           LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST: rc=%Rrc\n", rc));
     682                       }
     683                   }
     684                   else
     685                   {
    640686#endif
    641                         rc = VBoxClipboardWinAnnounceFormats(pWinCtx, fFormats);
    642 
    643                         VBoxClipboardWinClose();
     687                       rc = VBoxClipboardWinAnnounceFormats(pWinCtx, fFormats);
     688
     689                       VBoxClipboardWinClose();
    644690#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    645                     }
     691                   }
    646692#endif
    647                 }
    648             }
    649             LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=0x%x, lastErr=%ld\n", fFormats, GetLastError()));
    650         }
    651         break;
     693               }
     694           }
     695           LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=0x%x, lastErr=%ld\n", fFormats, GetLastError()));
     696       }
     697           break;
    652698
    653699       case VBOX_CLIPBOARD_WM_READ_DATA:
     
    721767                   }
    722768               }
    723 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    724                else if (uFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    725                {
    726                    LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST cTransfers=%RU32\n",
    727                             SharedClipboardURICtxGetRunningTransfers(&pCtx->URI)));
    728 
    729                     PSHAREDCLIPBOARDURITRANSFER pTransfer;
    730                     rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_WRITE,
    731                                                           SHAREDCLIPBOARDSOURCE_LOCAL,
    732                                                           &pTransfer);
    733                     if (RT_SUCCESS(rc))
    734                     {
    735                         SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
    736                         RT_ZERO(TransferCallbacks);
    737 
    738                         TransferCallbacks.pvUser              = &pCtx->URI;
    739                         TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback;
    740                         TransferCallbacks.pfnTransferError    = vboxClipboardURITransferErrorCallback;
    741 
    742                         SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks);
    743 
    744                         SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
    745                         RT_ZERO(creationCtx);
    746                         creationCtx.enmSource          = SHAREDCLIPBOARDSOURCE_LOCAL;
    747 
    748                         RT_ZERO(creationCtx.Interface);
    749                         creationCtx.Interface.pfnWriteDataHdr   = vboxClipboardURIWriteDataHdr;
    750                         creationCtx.Interface.pfnWriteDataChunk = vboxClipboardURIWriteDataChunk;
    751                         creationCtx.Interface.pfnWriteDirectory = vboxClipboardURIWriteDir;
    752                         creationCtx.Interface.pfnWriteFileHdr   = vboxClipboardURIWriteFileHdr;
    753                         creationCtx.Interface.pfnWriteFileData  = vboxClipboardURIWriteFileData;
    754 
    755                         creationCtx.pvUser = pCtx;
    756 
    757                         rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
    758                         if (RT_SUCCESS(rc))
    759                         {
    760                             rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
    761                             if (RT_SUCCESS(rc))
    762                             {
    763                                 /* The data data in CF_HDROP format, as the files are locally present and don't need to be
    764                                 * presented as a IDataObject or IStream. */
    765                                 hClip = GetClipboardData(CF_HDROP);
    766                                 if (hClip)
    767                                 {
    768                                     HDROP hDrop = (HDROP)GlobalLock(hClip);
    769                                     if (hDrop)
    770                                     {
    771                                         rc = VBoxClipboardWinDropFilesToTransfer((DROPFILES *)hDrop, pTransfer);
    772 
    773                                         GlobalUnlock(hClip);
    774 
    775                                         if (RT_SUCCESS(rc))
    776                                         {
    777                                             rc = SharedClipboardURITransferPrepare(pTransfer);
    778                                             if (RT_SUCCESS(rc))
    779                                                 rc = SharedClipboardURITransferRun(pTransfer, true /* fAsync */);
    780                                         }
    781                                     }
    782                                     else
    783                                     {
    784                                         hClip = NULL;
    785                                     }
    786                                 }
    787                             }
    788                         }
    789                    }
    790 
    791                    if (RT_FAILURE(rc))
    792                        LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_URI_LIST failed with rc=%Rrc\n", rc));
    793                }
    794 #endif
     769
    795770               if (hClip == NULL)
    796771               {
     
    806781               VBoxClipboardWinClose();
    807782           }
     783           break;
    808784       }
    809        break;
     785
     786#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     787       /* The host wants to read URI data. */
     788       case VBOX_CLIPBOARD_WM_URI_START_READ:
     789       {
     790           LogFunc(("VBOX_CLIPBOARD_WM_URI_START_READ: cTransfersRunning=%RU32\n",
     791                    SharedClipboardURICtxGetRunningTransfers(&pCtx->URI)));
     792
     793           int rc = VBoxClipboardWinOpen(hwnd);
     794           if (RT_SUCCESS(rc))
     795           {
     796               PSHAREDCLIPBOARDURITRANSFER pTransfer;
     797               rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_WRITE,
     798                                                     SHAREDCLIPBOARDSOURCE_LOCAL,
     799                                                     &pTransfer);
     800               if (RT_SUCCESS(rc))
     801               {
     802                   SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
     803                   RT_ZERO(TransferCallbacks);
     804
     805                   TransferCallbacks.pvUser              = &pCtx->URI;
     806                   TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback;
     807                   TransferCallbacks.pfnTransferError    = vboxClipboardURITransferErrorCallback;
     808
     809                   SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks);
     810
     811                   SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
     812                   RT_ZERO(creationCtx);
     813                   creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_LOCAL;
     814
     815                   RT_ZERO(creationCtx.Interface);
     816                   creationCtx.Interface.pfnListHdrWrite   = vboxClipboardURIListHdrWrite;
     817                   creationCtx.Interface.pfnListEntryWrite = vboxClipboardURIListEntryWrite;
     818                   creationCtx.Interface.pfnObjOpen        = vboxClipboardURIObjOpen;
     819                   creationCtx.Interface.pfnObjClose       = vboxClipboardURIObjClose;
     820                   creationCtx.Interface.pfnObjWrite       = vboxClipboardURIObjWrite;
     821
     822                   creationCtx.pvUser = pCtx;
     823
     824                   rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     825                   if (RT_SUCCESS(rc))
     826                   {
     827                       rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
     828                       if (RT_SUCCESS(rc))
     829                       {
     830                           /* The data data in CF_HDROP format, as the files are locally present and don't need to be
     831                           * presented as a IDataObject or IStream. */
     832                           HANDLE hClip = hClip = GetClipboardData(CF_HDROP);
     833                           if (hClip)
     834                           {
     835                               HDROP hDrop = (HDROP)GlobalLock(hClip);
     836                               if (hDrop)
     837                               {
     838                                   char    *papszList;
     839                                   uint32_t cbList;
     840                                   rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList);
     841                                   if (RT_SUCCESS(rc))
     842                                   {
     843                                       PVBOXCLIPBOARDWRITETHREADCTX pThreadCtx
     844                                           = (PVBOXCLIPBOARDWRITETHREADCTX)RTMemAllocZ(sizeof(VBOXCLIPBOARDWRITETHREADCTX));
     845                                       if (pThreadCtx)
     846                                       {
     847                                           pThreadCtx->pClipboardCtx = pCtx;
     848                                           pThreadCtx->pTransfer     = pTransfer;
     849                                           pThreadCtx->papszURIList  = papszList;
     850                                           pThreadCtx->cbURIList     = cbList;
     851
     852                                           GlobalUnlock(hClip);
     853
     854                                           if (RT_SUCCESS(rc))
     855                                           {
     856                                               rc = SharedClipboardURITransferPrepare(pTransfer);
     857                                               if (RT_SUCCESS(rc))
     858                                               {
     859                                                   rc = SharedClipboardURITransferRun(pTransfer, vboxClipboardURIWriteThread,
     860                                                                                      pThreadCtx /* pvUser */);
     861                                                   /* pThreadCtx now is owned by vboxClipboardURIWriteThread(). */
     862                                               }
     863                                           }
     864                                       }
     865                                       else
     866                                           rc = VERR_NO_MEMORY;
     867
     868                                       if (RT_FAILURE(rc))
     869                                       {
     870                                           RTStrFree(papszList);
     871                                       }
     872                                   }
     873                               }
     874                               else
     875                               {
     876                                   hClip = NULL;
     877                               }
     878                           }
     879                       }
     880                   }
     881               }
     882
     883               VBoxClipboardWinClose();
     884           }
     885
     886           if (RT_FAILURE(rc))
     887               LogFunc(("VBOX_CLIPBOARD_WM_URI_START_READ: Failed with rc=%Rrc\n", rc));
     888           break;
     889       }
     890
     891       case VBOX_CLIPBOARD_WM_URI_START_WRITE:
     892       {
     893           LogFunc(("VBOX_CLIPBOARD_WM_URI_START_WRITE: cTransfersRunning=%RU32\n",
     894                    SharedClipboardURICtxGetRunningTransfers(&pCtx->URI)));
     895
     896           break;
     897       }
     898#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
    810899
    811900       case WM_DESTROY:
     
    821910            */
    822911       }
    823        break;
     912           break;
    824913
    825914       default:
     
    828917           lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    829918       }
    830        break;
     919           break;
    831920    }
    832921
     
    10041093        uint32_t u32Msg;
    10051094        uint32_t u32Formats;
    1006         rc = VbglR3ClipboardGetHostMsg(pCtx->u32ClientID, &u32Msg, &u32Formats);
     1095        rc = VbglR3ClipboardGetHostMsgOld(pCtx->u32ClientID, &u32Msg, &u32Formats);
    10071096        if (RT_FAILURE(rc))
    10081097        {
     
    10441133               }
    10451134
     1135#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     1136               case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START:
     1137               {
     1138                   LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START\n"));
     1139
     1140                   const UINT uMsg = u32Formats == 0 ?
     1141                                     VBOX_CLIPBOARD_WM_URI_START_READ : VBOX_CLIPBOARD_WM_URI_START_WRITE;
     1142
     1143                   ::PostMessage(pWinCtx->hWnd, uMsg, 0 /* wParm */, 0 /* lParm */);
     1144                   break;
     1145               }
     1146#endif
    10461147               case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
    10471148               {
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/Makefile.kmk

    r78897 r79497  
    152152 ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    153153 VBoxGuestR3Lib_SOURCES   += \
    154         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMetaData.cpp \
    155154        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMIME.cpp
    156155 endif
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp

    r79267 r79497  
    5050*   Prototypes                                                                                                                   *
    5151*********************************************************************************************************************************/
    52 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    53 static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr);
    54 #endif
    5552
    5653
     
    6764    if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
    6865        rc = VINF_PERMISSION_DENIED;
     66
     67    LogFlowFuncLeaveRC(rc);
    6968    return rc;
    7069}
     
    8483
    8584/**
    86  * Get a host message.
     85 * Get a host message, old version.
     86 *
     87 * Note: This is the old message which still is being used for the non-URI Shared Clipboard transfers,
     88 *       to not break compatibility with older additions / VBox versions.
    8789 *
    8890 * This will block until a message becomes available.
     
    9395 * @param   pfFormats       Where to store the format(s) the message applies to.
    9496 */
    95 VBGLR3DECL(int) VbglR3ClipboardGetHostMsg(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
    96 {
    97     VBoxClipboardGetHostMsg Msg;
    98 
    99     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG);
     97VBGLR3DECL(int) VbglR3ClipboardGetHostMsgOld(HGCMCLIENTID idClient, uint32_t *pidMsg, uint32_t *pfFormats)
     98{
     99    VBoxClipboardGetHostMsgOld Msg;
     100
     101    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     102                       VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD);
     103
    100104    VbglHGCMParmUInt32Set(&Msg.msg, 0);
    101105    VbglHGCMParmUInt32Set(&Msg.formats, 0);
     
    157161}
    158162
    159 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    160 /**
    161  * Reads a (meta) data header from the host.
    162  *
    163  * @returns IPRT status code.
    164  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    165  * @param   pDataHdr            Where to store the read meta data header.
    166  */
    167 VBGLR3DECL(int) VbglR3ClipboardReadDataHdr(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr)
    168 {
    169     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
    170 
    171     VBoxClipboardReadDataHdrMsg Msg;
    172     RT_ZERO(Msg);
    173     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    174                        VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR);
    175     Msg.uContext.SetUInt32(0);
    176     Msg.uFlags.SetUInt32(0);
    177     Msg.uScreenId.SetUInt32(0);
    178     Msg.cbTotal.SetUInt64(0);
    179     Msg.cbMeta.SetUInt32(0);
    180     Msg.cbMetaFmt.SetUInt32(0);
    181     Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
    182     Msg.cObjects.SetUInt64(0);
     163static int vbglR3ClipboardGetNextMsgType(HGCMCLIENTID idClient, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
     164{
     165    AssertPtrReturn(puMsg,   VERR_INVALID_POINTER);
     166    AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
     167
     168    VBoxClipboardGetHostMsg Msg;
     169    RT_ZERO(Msg);
     170
     171    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     172                       VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG, VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG);
     173
     174    Msg.uMsg.SetUInt32(0);
     175    Msg.cParms.SetUInt32(0);
     176    Msg.fBlock.SetUInt32(fWait ? 1 : 0);
     177
     178    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     179    if (RT_SUCCESS(rc))
     180    {
     181        rc = Msg.uMsg.GetUInt32(puMsg);
     182        if (RT_SUCCESS(rc))
     183            rc = Msg.cParms.GetUInt32(pcParms);
     184    }
     185
     186    LogFlowFuncLeaveRC(rc);
     187    return rc;
     188}
     189
     190static int vbglR3ClipboardRecvListOpen(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHDR pListHdr)
     191{
     192    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
     193
     194    VBoxClipboardListOpenMsg Msg;
     195    RT_ZERO(Msg);
     196
     197    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     198                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
     199
     200    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
     201    Msg.uHandle.SetUInt64(0);
     202    Msg.fList.SetUInt32(0);
     203    Msg.fFeatures.SetUInt32(0);
     204    Msg.cbFilter.SetUInt32(0);
     205    Msg.pvFilter.SetPtr(pListHdr->pszFilter, pListHdr->cbFilter);
     206
     207    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     208    if (RT_SUCCESS(rc))
     209    {
     210        rc = Msg.fList.GetUInt32(&pListHdr->fList);         AssertRC(rc);
     211        rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures); AssertRC(rc);
     212    }
     213
     214    LogFlowFuncLeaveRC(rc);
     215    return rc;
     216}
     217
     218static int vbglR3ClipboardRecvListClose(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList)
     219{
     220    AssertPtrReturn(phList, VERR_INVALID_POINTER);
     221
     222    VBoxClipboardListCloseMsg Msg;
     223    RT_ZERO(Msg);
     224
     225    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     226                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE);
     227
     228    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
     229    Msg.uHandle.SetUInt64(0);
     230
     231    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     232    if (RT_SUCCESS(rc))
     233    {
     234        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
     235    }
     236
     237    LogFlowFuncLeaveRC(rc);
     238    return rc;
     239}
     240
     241static int vbglR3ClipboardRecvListHdrRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
     242{
     243    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
     244    AssertPtrReturn(phList,   VERR_INVALID_POINTER);
     245
     246    VBoxClipboardListHdrReadMsg Msg;
     247    RT_ZERO(Msg);
     248
     249    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     250                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
     251
     252    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
     253    Msg.uHandle.SetUInt64(0);
     254    Msg.cTotalObjects.SetUInt64(0);
     255    Msg.cbTotalSize.SetUInt64(0);
    183256    Msg.enmCompression.SetUInt32(0);
    184257    Msg.enmChecksumType.SetUInt32(0);
    185     Msg.pvChecksum.SetPtr(pDataHdr->pvChecksum, pDataHdr->cbChecksum);
    186     Msg.cbChecksum.SetUInt32(0);
    187 
    188     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    189     if (RT_SUCCESS(rc))
    190     {
    191         /* Msg.uContext not needed here. */
    192         Msg.uFlags.GetUInt32(&pDataHdr->uFlags);
    193         Msg.uScreenId.GetUInt32(&pDataHdr->uScreenId);
    194         Msg.cbTotal.GetUInt64(&pDataHdr->cbTotal);
    195         Msg.cbMeta.GetUInt32(&pDataHdr->cbMeta);
    196         Msg.cbMetaFmt.GetUInt32(&pDataHdr->cbMetaFmt);
    197         Msg.cObjects.GetUInt64(&pDataHdr->cObjects);
    198         Msg.enmCompression.GetUInt32(&pDataHdr->enmCompression);
    199         Msg.enmChecksumType.GetUInt32((uint32_t *)&pDataHdr->enmChecksumType);
    200         Msg.cbChecksum.GetUInt32(&pDataHdr->cbChecksum);
    201 
    202         AssertReturn(SharedClipboardURIDataHdrIsValid(pDataHdr), VERR_INVALID_PARAMETER);
    203     }
    204 
    205     LogFlowFuncLeaveRC(rc);
    206     return rc;
    207 }
    208 
    209 /**
    210  * Sends a guest clipboard data header to the host.
    211  *
    212  * This is usually called in reply to a VBOX_SHARED_CLIPBOARD_HOST_READ_DATA message from the host
    213  * (if URI format is specified).
     258
     259    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     260    if (RT_SUCCESS(rc))
     261    {
     262        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
     263    }
     264
     265    LogFlowFuncLeaveRC(rc);
     266    return rc;
     267}
     268
     269static int vbglR3ClipboardRecvListEntryRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList,
     270                                            PVBOXCLIPBOARDLISTENTRY pListEntry)
     271{
     272    AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
     273    AssertPtrReturn(phList,     VERR_INVALID_POINTER);
     274
     275    VBoxClipboardListEntryReadMsg Msg;
     276    RT_ZERO(Msg);
     277
     278    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     279                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ);
     280
     281    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
     282    Msg.uHandle.SetUInt64(0);
     283    Msg.fInfo.SetUInt32(0);
     284    Msg.cbInfo.SetUInt32(0);
     285    Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
     286
     287    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     288    if (RT_SUCCESS(rc))
     289    {
     290        rc = Msg.uHandle.GetUInt64(phList);             AssertRC(rc);
     291        rc = Msg.fInfo.GetUInt32(&pListEntry->fInfo);   AssertRC(rc);
     292        rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc);
     293    }
     294
     295    LogFlowFuncLeaveRC(rc);
     296    return rc;
     297}
     298
     299VBGLR3DECL(int) VbglR3ClipboardEventGetNext(HGCMCLIENTID idClient, PSHAREDCLIPBOARDURITRANSFER pTransfer,
     300                                            PVBGLR3CLIPBOARDEVENT *ppEvent)
     301{
     302    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     303    AssertPtrReturn(ppEvent,   VERR_INVALID_POINTER);
     304
     305    PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT));
     306    if (!pEvent)
     307        return VERR_NO_MEMORY;
     308
     309    uint32_t uMsg   = 0;
     310    uint32_t cParms = 0;
     311    int rc = vbglR3ClipboardGetNextMsgType(idClient, &uMsg, &cParms, true /* fWait */);
     312    if (RT_SUCCESS(rc))
     313    {
     314        /** @todo Check for VM session change. */
     315    }
     316
     317#if 0
     318    typedef struct _
     319    {
     320        union
     321        {
     322            struct Dir
     323            {
     324                RTDIR hDir;
     325            };
     326        } u;
     327    };
     328#endif
     329
     330    if (RT_SUCCESS(rc))
     331    {
     332        LogFunc(("Handling uMsg=%RU32\n", uMsg));
     333
     334        switch (uMsg)
     335        {
     336#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     337            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN:
     338            {
     339                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN\n"));
     340
     341                VBOXCLIPBOARDLISTHDR listHdr;
     342                rc = SharedClipboardURIListHdrInit(&listHdr);
     343                if (RT_SUCCESS(rc))
     344                {
     345                    rc = vbglR3ClipboardRecvListOpen(idClient, &listHdr);
     346                    if (RT_SUCCESS(rc))
     347                    {
     348                        rc = SharedClipboardURITransferListOpen(pTransfer, &listHdr, NULL /* phList */);
     349                    }
     350
     351                    SharedClipboardURIListHdrDestroy(&listHdr);
     352                }
     353
     354                break;
     355            }
     356
     357            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE:
     358            {
     359                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE\n"));
     360
     361                VBOXCLIPBOARDLISTHANDLE hList;
     362                rc = vbglR3ClipboardRecvListClose(idClient, &hList);
     363                if (RT_SUCCESS(rc))
     364                {
     365                    rc = SharedClipboardURITransferListClose(pTransfer, hList);
     366                }
     367
     368                break;
     369            }
     370
     371            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ:
     372            {
     373                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ\n"));
     374
     375                /** @todo Handle filter + list features. */
     376
     377                VBOXCLIPBOARDLISTHDR listHdr;
     378                rc = SharedClipboardURIListHdrInit(&listHdr);
     379                if (RT_SUCCESS(rc))
     380                {
     381                    VBOXCLIPBOARDLISTHANDLE hList;
     382                    rc = vbglR3ClipboardRecvListHdrRead(idClient, &hList, &listHdr);
     383                    if (RT_SUCCESS(rc))
     384                    {
     385                        if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList))
     386                        {
     387                            rc = VbglR3ClipboardSendListHdrWrite(idClient, hList, &listHdr);
     388                        }
     389                        else
     390                            rc = VERR_INVALID_HANDLE;
     391                    }
     392
     393                    SharedClipboardURIListHdrDestroy(&listHdr);
     394                }
     395
     396                break;
     397            }
     398
     399            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE:
     400            {
     401                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE\n"));
     402                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_WRITE;
     403                break;
     404            }
     405
     406            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ:
     407            {
     408                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ\n"));
     409
     410                VBOXCLIPBOARDLISTENTRY listEntry;
     411                rc = SharedClipboardURIListEntryInit(&listEntry);
     412                if (RT_SUCCESS(rc))
     413                {
     414                    VBOXCLIPBOARDLISTHANDLE hList;
     415                    rc = vbglR3ClipboardRecvListEntryRead(idClient, &hList, &listEntry);
     416                    if (RT_SUCCESS(rc))
     417                    {
     418                        if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList))
     419                        {
     420                            rc = VbglR3ClipboardSendListEntryWrite(idClient, hList, &listEntry);
     421                        }
     422                        else
     423                            rc = VERR_INVALID_HANDLE;
     424                    }
     425
     426                    SharedClipboardURIListEntryDestroy(&listEntry);
     427                }
     428                break;
     429            }
     430
     431            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE:
     432            {
     433                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE\n"));
     434                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_ENTRY_WRITE;
     435                break;
     436            }
     437
     438            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN:
     439            {
     440                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN\n"));
     441                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN;
     442                break;
     443            }
     444
     445            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE:
     446            {
     447                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE\n"));
     448                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE;
     449                break;
     450            }
     451
     452            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ:
     453            {
     454                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ\n"));
     455                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ;
     456                break;
     457            }
     458
     459            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE:
     460            {
     461                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE\n"));
     462                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_WRITE;
     463                break;
     464            }
     465#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
     466
     467            default:
     468                rc = VERR_NOT_SUPPORTED;
     469                break;
     470        }
     471    }
     472
     473
     474    if (RT_SUCCESS(rc))
     475    {
     476        if (pEvent->enmType != VBGLR3CLIPBOARDEVENTTYPE_INVALID)
     477        {
     478            *ppEvent = pEvent;
     479        }
     480        else
     481            VbglR3ClipboardEventFree(pEvent);
     482    }
     483    else
     484    {
     485        /* Report error back to the host. */
     486        VbglR3ClipboardWriteError(idClient, rc);
     487
     488        VbglR3ClipboardEventFree(pEvent);
     489    }
     490
     491    LogFlowFuncLeaveRC(rc);
     492    return rc;
     493}
     494
     495/**
     496 * Frees (destroys) a formerly allocated Shared Clipboard event.
     497 *
     498 * @returns IPRT status code.
     499 * @param   pEvent              Event to free (destroy).
     500 */
     501VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent)
     502{
     503    if (!pEvent)
     504        return;
     505
     506    /* Some messages require additional cleanup. */
     507    switch (pEvent->enmType)
     508    {
     509        default:
     510            break;
     511    }
     512
     513    RTMemFree(pEvent);
     514    pEvent = NULL;
     515}
     516
     517#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     518/**
     519 * Sends a list header to the host.
    214520 *
    215521 * @returns VBox status code.
    216522 * @param   idClient        The client id returned by VbglR3ClipboardConnect().
    217  * @param   pDataHdr        Pointer to data header to send.
    218  */
    219 VBGLR3DECL(int) VbglR3ClipboardWriteDataHdr(HGCMCLIENTID idClient, const PVBOXCLIPBOARDDATAHDR pDataHdr)
    220 {
    221     VBoxClipboardWriteDataHdrMsg Msg;
    222     RT_ZERO(Msg);
    223 
    224     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR);
    225 
    226     AssertReturn(SharedClipboardURIDataHdrIsValid(pDataHdr), VERR_INVALID_PARAMETER);
    227 
    228     Msg.uContext.SetUInt32(0);                                          /** @todo Not used yet. */
    229     Msg.uFlags.SetUInt32(pDataHdr->uFlags);                             /** @todo Not used yet. */
    230     Msg.uScreenId.SetUInt32(pDataHdr->uScreenId);                       /** @todo Not used yet. */
    231     Msg.cbTotal.SetUInt64(pDataHdr->cbTotal);
    232     Msg.cbMeta.SetUInt32(pDataHdr->cbMeta);
    233     Msg.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt);
    234     Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
    235     Msg.cObjects.SetUInt64(pDataHdr->cObjects);
    236     Msg.enmCompression.SetUInt32(pDataHdr->enmCompression);             /** @todo Not used yet. */
    237     Msg.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID);                /** @todo Not used yet. */
    238     Msg.cbChecksum.SetUInt32(0);                                        /** @todo Not used yet. */
    239     Msg.pvChecksum.SetPtr(NULL, 0);                                     /** @todo Not used yet. */
    240 
    241     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    242 
    243     LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, pvMetaFmt=%p (%RU32), cObjects=%RU64, rc=%Rrc\n",
    244                  pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt, pDataHdr->cObjects, rc));
    245 
    246     LogFlowFuncLeaveRC(rc);
    247     return rc;
    248 }
    249 
    250 /**
    251  * Reads a (meta) data chunk from the host.
     523 * @param   hList           List handle to send header for.
     524 * @param   pListHdr        List header to send.
     525 */
     526VBGLR3DECL(int) VbglR3ClipboardSendListHdrWrite(HGCMCLIENTID idClient,
     527                                                VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
     528{
     529    VBoxClipboardListHdrWriteMsg Msg;
     530    RT_ZERO(Msg);
     531
     532    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     533                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE);
     534
     535    Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
     536    Msg.uHandle.SetUInt64(hList);
     537    Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
     538    Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
     539    Msg.enmCompression.SetUInt32(pListHdr->enmCompression);
     540    Msg.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID);
     541
     542    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     543
     544    LogFlowFuncLeaveRC(rc);
     545    return rc;
     546}
     547
     548/**
     549 * Sends a list entry to the host.
    252550 *
    253551 * @returns IPRT status code.
    254  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    255  * @param   pDataHdr            Data header to use. Need for accounting and stuff.
    256  * @param   pvData              Where to store the received data from the host.
    257  * @param   cbData              Size (in bytes) of where to store the received data.
    258  * @param   pcbDataRecv         Where to store the received amount of data (in bytes).
    259  */
    260 static int vbglR3ClipboardReadDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    261                                         void *pvData, uint32_t cbData, uint32_t *pcbDataRecv)
    262 {
    263     AssertPtrReturn(pDataHdr,        VERR_INVALID_POINTER);
    264     AssertPtrReturn(pvData,          VERR_INVALID_POINTER);
    265     AssertReturn(cbData,             VERR_INVALID_PARAMETER);
    266     AssertPtrNullReturn(pcbDataRecv, VERR_INVALID_POINTER);
    267 
    268     LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData));
    269 
    270     VBoxClipboardReadDataChunkMsg Msg;
    271     RT_ZERO(Msg);
    272 
    273     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    274                        VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK);
     552 * @param   idClient            The client id returned by VbglR3ClipboardConnect()
     553 * @param   hList               List handle to send entry for.
     554 * @param   pListEntry          List entry to send.
     555 */
     556VBGLR3DECL(int) VbglR3ClipboardSendListEntryWrite(HGCMCLIENTID idClient,
     557                                                  VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     558{
     559    AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
     560
     561    VBoxClipboardListEntryWriteMsg Msg;
     562    RT_ZERO(Msg);
     563
     564    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     565                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE);
     566
     567    Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
     568    Msg.uHandle.SetUInt64(hList);
     569    Msg.fInfo.SetUInt32(pListEntry->fInfo);
     570    Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
     571    Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
     572
     573    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     574
     575    LogFlowFuncLeaveRC(rc);
     576    return rc;
     577}
     578
     579VBGLR3DECL(int) VbglR3ClipboardObjOpen(HGCMCLIENTID idClient,
     580                                       const char *pszPath, PVBOXCLIPBOARDCREATEPARMS pCreateParms,
     581                                       PSHAREDCLIPBOARDOBJHANDLE phObj)
     582{
     583    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     584    AssertPtrReturn(pCreateParms, VERR_INVALID_POINTER);
     585    AssertPtrReturn(phObj, VERR_INVALID_POINTER);
     586
     587    VBoxClipboardObjOpenMsg Msg;
     588    RT_ZERO(Msg);
     589
     590    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     591                       VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_OPEN);
     592
     593    int rc;
     594
     595    char *pszPathTmp = RTStrDup(pszPath);
     596    if (pszPathTmp)
     597    {
     598        Msg.szPath.SetPtr((void *)pszPathTmp, (uint32_t)strlen(pszPathTmp) + 1 /* Include terminating zero */);
     599        Msg.parms.SetPtr(pCreateParms, sizeof(VBOXCLIPBOARDCREATEPARMS));
     600
     601        rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     602        if (RT_SUCCESS(rc))
     603        {
     604            *phObj = pCreateParms->uHandle;
     605        }
     606
     607        RTStrFree(pszPathTmp);
     608    }
     609    else
     610        rc = VERR_NO_MEMORY;
     611
     612    LogFlowFuncLeaveRC(rc);
     613    return rc;
     614}
     615
     616VBGLR3DECL(int) VbglR3ClipboardObjClose(HGCMCLIENTID idClient, SHAREDCLIPBOARDOBJHANDLE hObj)
     617{
     618    VBoxClipboardObjCloseMsg Msg;
     619    RT_ZERO(Msg);
     620
     621    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
     622                       VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_CLOSE);
     623
     624    Msg.uHandle.SetUInt64(hObj);
     625
     626    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     627
     628    LogFlowFuncLeaveRC(rc);
     629    return rc;
     630}
     631
     632VBGLR3DECL(int) VbglR3ClipboardObjRead(HGCMCLIENTID idClient, SHAREDCLIPBOARDOBJHANDLE hObj,
     633                                       void *pvData, uint32_t cbData, uint32_t *pcbRead)
     634{
     635    AssertPtrReturn(pvData,  VERR_INVALID_POINTER);
     636    AssertReturn(cbData,     VERR_INVALID_PARAMETER);
     637    /* pcbRead is optional. */
     638
     639    VBoxClipboardObjReadWriteMsg Msg;
     640    RT_ZERO(Msg);
     641
     642    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_READ);
     643
     644    Msg.uContext.SetUInt32(0);
     645    Msg.uHandle.SetUInt64(hObj);
    275646    Msg.pvData.SetPtr(pvData, cbData);
    276647    Msg.cbData.SetUInt32(0);
     
    281652    if (RT_SUCCESS(rc))
    282653    {
    283         uint32_t cbDataRecv;
    284         rc = Msg.cbData.GetUInt32(&cbDataRecv);
    285         AssertRC(rc);
    286         if (RT_SUCCESS(rc))
     654        /** @todo Context ID not used yet. */
     655        /** @todo Add checksum support. */
     656
     657        if (pcbRead)
    287658        {
    288             /** @todo Use checksum for validating the received data. */
    289             if (pcbDataRecv)
    290                 *pcbDataRecv = cbDataRecv;
    291             LogFlowFuncLeaveRC(rc);
    292             return rc;
     659            rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
     660            AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
    293661        }
    294662    }
    295663
    296     /* failure */
    297     LogFlowFuncLeaveRC(rc);
    298     return rc;
    299 }
    300 
    301 /**
    302  * Helper function for reading the actual clipboard (meta) data from the host. Do not call directly.
    303  *
    304  * @returns IPRT status code.
    305  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    306  * @param   pDataHdr            Pointer to data header to use.
    307  * @param   pvMeta              Where to store the received meta data.
    308  * @param   cbMeta              Size (in bytes) of meta data buffer.
    309  * @param   pcbRead             How much bytes were read on success. Optional.
    310  */
    311 static int vbglR3ClipboardReadMetaDataLoop(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    312                                            void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
    313 {
    314     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
    315     AssertPtrReturn(pvMeta,   VERR_INVALID_POINTER);
    316 
    317     LogFlowFuncEnter();
    318 
    319     int rc = VINF_SUCCESS;
    320 
    321     uint32_t cbReadTotal = 0;
    322 
    323     LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));
    324     if (pDataHdr->cbMeta)
    325     {
    326         uint32_t cbToRead = RT_MIN(cbMeta, pDataHdr->cbMeta);
    327         while (cbToRead)
    328         {
    329             uint32_t cbRead;
    330             rc = vbglR3ClipboardReadDataChunk(idClient, pDataHdr,
    331                                               (uint8_t *)pvMeta + cbReadTotal, cbToRead, &cbRead);
    332             if (RT_FAILURE(rc))
    333                 break;
    334 
    335             Assert(cbToRead >= cbRead);
    336             cbToRead -= cbRead;
    337 
    338             cbReadTotal += cbRead;
    339         }
    340     }
    341 
    342     if (RT_SUCCESS(rc))
    343     {
    344         if (pcbRead)
    345             *pcbRead = cbReadTotal;
    346     }
    347 
    348     LogFlowFuncLeaveRC(rc);
    349     return rc;
    350 }
    351 
    352 /**
    353  * Reads the actual meta data from the host, internal version.
    354  *
    355  * @returns IPRT status code.
    356  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    357  * @param   pDataHdr            Pointer to data header to use.
    358  * @param   pvMeta              Where to store the received meta data.
    359  * @param   cbMeta              Size (in bytes) of meta data buffer.
    360  * @param   pcbRead             How much bytes were read on success. Optional.
    361  */
    362 static int vbglR3ClipboardReadMetaDataInternal(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    363                                                void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
    364 {
    365    LogFlowFuncEnter();
    366 
    367     int rc = vbglR3ClipboardReadMetaDataLoop(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
    368 
    369     LogFlowFuncLeaveRC(rc);
    370     return rc;
    371 }
    372 
    373 /**
    374  * Reads the actual meta data from the host, extended version.
    375  *
    376  * @returns IPRT status code.
    377  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    378  * @param   pvMeta              Where to store the received meta data.
    379  * @param   cbMeta              Size (in bytes) of meta data buffer.
    380  * @param   pcbRead             How much bytes were read on success. Optional.
    381  */
    382 VBGLR3DECL(int) VbglR3ClipboardReadMetaDataEx(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    383                                               void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
    384 {
    385     return vbglR3ClipboardReadMetaDataInternal(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
    386 }
    387 
    388 /**
    389  * Reads the actual meta data from the host.
    390  *
    391  * @returns IPRT status code.
    392  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    393  * @param   pvMeta              Where to store the received meta data.
    394  * @param   cbMeta              Size (in bytes) of meta data buffer.
    395  * @param   pcbRead             How much bytes were read on success. Optional.
    396  */
    397 VBGLR3DECL(int) VbglR3ClipboardReadMetaData(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    398                                             void *pvMeta, uint32_t cbMeta, uint32_t *pcbRead)
    399 {
    400     return VbglR3ClipboardReadMetaDataEx(idClient, pDataHdr, pvMeta, cbMeta, pcbRead);
    401 }
    402 
    403 /**
    404  * Writes a (meta) data chunk to the host.
    405  *
    406  * @returns IPRT status code.
    407  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    408  * @param   pDataHdr            Data header to use. Need for accounting and stuff.
    409  * @param   pvData              Where to store the received data from the host.
    410  * @param   cbData              Size (in bytes) of where to store the received data.
    411  * @param   pcbDataWritten      Where to store the written amount of data (in bytes).
    412  */
    413 static int vbglR3ClipboardWriteDataChunk(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    414                                          void *pvData, uint32_t cbData, uint32_t *pcbDataWritten)
    415 {
    416     AssertPtrReturn(pDataHdr,        VERR_INVALID_POINTER);
    417     AssertPtrReturn(pvData,          VERR_INVALID_POINTER);
    418     AssertReturn(cbData,             VERR_INVALID_PARAMETER);
    419     AssertPtrNullReturn(pcbDataWritten, VERR_INVALID_POINTER);
    420 
    421     LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData));
    422 
    423     VBoxClipboardReadDataChunkMsg Msg;
    424     RT_ZERO(Msg);
    425 
    426     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    427                        VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK);
    428 
    429     Msg.uContext.SetUInt32(0);                                          /** @todo Not used yet. */
     664    LogFlowFuncLeaveRC(rc);
     665    return rc;
     666}
     667
     668VBGLR3DECL(int) VbglR3ClipboardObjWrite(HGCMCLIENTID idClient,
     669                                        SHAREDCLIPBOARDOBJHANDLE hObj,
     670                                        void *pvData, uint32_t cbData, uint32_t *pcbWritten)
     671{
     672    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     673    AssertReturn(cbData, VERR_INVALID_PARAMETER);
     674    /* pcbWritten is optional. */
     675
     676    VBoxClipboardObjReadWriteMsg Msg;
     677    RT_ZERO(Msg);
     678
     679    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_OBJ_WRITE);
     680
     681    Msg.uContext.SetUInt32(0);
     682    Msg.uHandle.SetUInt64(hObj);
     683    Msg.pvData.SetPtr(pvData, cbData);
    430684    Msg.cbData.SetUInt32(cbData);
    431     Msg.pvData.SetPtr(pvData, cbData);
    432     Msg.cbChecksum.SetUInt32(0);
    433     Msg.pvChecksum.SetPtr(NULL, 0);
    434 
    435     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    436     if (RT_SUCCESS(rc))
    437     {
    438         if (pcbDataWritten)
    439             *pcbDataWritten = cbData;
    440     }
    441 
    442     /* failure */
    443     LogFlowFuncLeaveRC(rc);
    444     return rc;
    445 }
    446 
    447 /**
    448  * Writes the actual meta data to the host, internal version.
    449  *
    450  * @returns IPRT status code.
    451  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    452  * @param   pDataHdr            Pointer to data header to use.
    453  * @param   pvMeta              Meta data buffer to write.
    454  * @param   cbMeta              Size (in bytes) of meta data buffer.
    455  * @param   pcbWritten          How much bytes were written on success. Optional.
    456  */
    457 static int vbglR3ClipboardWriteMetaDataInternal(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    458                                                 const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)
    459 {
    460     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
    461     AssertPtrReturn(pvMeta,   VERR_INVALID_POINTER);
    462 
    463     LogFlowFuncEnter();
    464 
    465     int rc = VINF_SUCCESS;
    466 
    467     uint32_t cbWrittenTotal = 0;
    468 
    469     LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));
    470     if (pDataHdr->cbMeta)
    471     {
    472         uint32_t cbToWrite = RT_MIN(cbMeta, pDataHdr->cbMeta);
    473         while (cbToWrite)
    474         {
    475             uint32_t cbWritten;
    476             rc = vbglR3ClipboardWriteDataChunk(idClient, pDataHdr,
    477                                                (uint8_t *)pvMeta + cbWrittenTotal, cbToWrite, &cbWritten);
    478             if (RT_FAILURE(rc))
    479                 break;
    480 
    481             Assert(cbToWrite >= cbWritten);
    482             cbToWrite -= cbWritten;
    483 
    484             cbWrittenTotal += cbWritten;
    485         }
    486     }
    487 
    488     if (RT_SUCCESS(rc))
    489     {
    490         if (pcbWritten)
    491             *pcbWritten = cbWrittenTotal;
    492     }
    493 
    494     LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));
    495     return rc;
    496 }
    497 
    498 /**
    499  * Writes the actual meta data to the host, extended version.
    500  *
    501  * @returns IPRT status code.
    502  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    503  * @param   pDataHdr            Pointer to data header to use.
    504  * @param   pvMeta              Pointer to meta data buffer.
    505  * @param   cbMeta              Size (in bytes) of meta data buffer.
    506  * @param   pcbWritten          How much bytes were written on success. Optional.
    507  */
    508 VBGLR3DECL(int) VbglR3ClipboardWriteMetaDataEx(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    509                                                const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)
    510 {
    511     int rc = vbglR3ClipboardWriteMetaDataInternal(idClient, pDataHdr, pvMeta, cbMeta, pcbWritten);
    512 
    513     LogFlowFuncLeaveRC(rc);
    514     return rc;
    515 }
    516 
    517 /**
    518  * Writes the actual meta data to the host.
    519  *
    520  * @returns IPRT status code.
    521  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    522  * @param   pDataHdr            Pointer to data header to use.
    523  * @param   pvMeta              Pointer to meta data buffer.
    524  * @param   cbMeta              Size (in bytes) of meta data buffer.
    525  * @param   pcbWritten          How much bytes were written on success. Optional.
    526  */
    527 VBGLR3DECL(int) VbglR3ClipboardWriteMetaData(HGCMCLIENTID idClient, PVBOXCLIPBOARDDATAHDR pDataHdr,
    528                                              const void *pvMeta, uint32_t cbMeta, uint32_t *pcbWritten)
    529 {
    530     return VbglR3ClipboardWriteMetaDataEx(idClient, pDataHdr, pvMeta, cbMeta, pcbWritten);
    531 }
    532 
    533 /**
    534  * Reads a directory entry from the host.
    535  *
    536  * @returns IPRT status code.
    537  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    538  * @param   pszDirname          Where to store the directory name of the directory being created.
    539  * @param   cbDirname           Size (in bytes) of where to store the directory name of the directory being created.
    540  * @param   pcbDirnameRecv      Size (in bytes) of the actual directory name received.
    541  * @param   pfMode              Where to store the directory creation mode.
    542  */
    543 VBGLR3DECL(int) VbglR3ClipboardReadDir(HGCMCLIENTID idClient,
    544                                        char     *pszDirname,
    545                                        uint32_t  cbDirname,
    546                                        uint32_t *pcbDirnameRecv,
    547                                        uint32_t *pfMode)
    548 {
    549     AssertPtrReturn(pszDirname,     VERR_INVALID_POINTER);
    550     AssertReturn(cbDirname,         VERR_INVALID_PARAMETER);
    551     AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);
    552     AssertPtrReturn(pfMode,         VERR_INVALID_POINTER);
    553 
    554     VBoxClipboardReadDirMsg Msg;
    555     RT_ZERO(Msg);
    556 
    557     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR);
    558     /** @todo Context ID not used yet. */
    559     Msg.uContext.SetUInt32(0);
    560     Msg.pvName.SetPtr(pszDirname, cbDirname);
    561     Msg.cbName.SetUInt32(cbDirname);
    562     Msg.fMode.SetUInt32(0);
    563 
    564     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    565     if (RT_SUCCESS(rc))
    566     {
    567         /** @todo Context ID not used yet. */
    568         rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc);
    569         rc = Msg.fMode.GetUInt32(pfMode);          AssertRC(rc);
    570 
    571         AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);
    572     }
    573 
    574     return rc;
    575 }
    576 
    577 /**
    578  * Writes a guest directory to the host.
    579  *
    580  * @returns IPRT status code.
    581  * @param   idClient        The client id returned by VbglR3ClipboardConnect().
    582  * @param   pszPath         Directory path.
    583  * @param   cbPath          Size (in bytes) of directory path.
    584  * @param   fMode           File mode for directory (IPRT-style).
    585  */
    586 VBGLR3DECL(int) VbglR3ClipboardWriteDir(HGCMCLIENTID idClient,
    587                                         const char  *pszPath,
    588                                         uint32_t     cbPath,
    589                                         uint32_t     fMode)
    590 {
    591     const size_t cchDir = strlen(pszPath);
    592 
    593     if (   !cchDir
    594         ||  cchDir >  RTPATH_MAX
    595         ||  cchDir != cbPath) /* UTF-8 */
    596         return VERR_INVALID_PARAMETER;
    597 
    598     const uint32_t cbPathSz = (uint32_t)cchDir + 1; /* Include termination. */
    599 
    600     VBoxClipboardWriteDirMsg Msg;
    601     RT_ZERO(Msg);
    602 
    603     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR);
    604     /** @todo Context ID not used yet. */
    605     Msg.pvName.SetPtr((void *)pszPath, (uint32_t)cbPathSz);
    606     Msg.cbName.SetUInt32(cbPathSz);
    607     Msg.fMode.SetUInt32(fMode);
    608 
    609     return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    610 }
    611 
    612 /**
    613  * Receives a file header from the host.
    614  *
    615  * @returns IPRT status code.
    616  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    617  * @param   pszFilename         Where to store the file name of the file being transferred.
    618  * @param   cbFilename          Size (in bytes) of where to store the file name of the file being transferred.
    619  * @param   puFlags             File transfer flags. Currently not being used.
    620  * @param   pfMode              Where to store the file creation mode.
    621  * @param   pcbTotal            Where to store the file size (in bytes).
    622  */
    623 VBGLR3DECL(int) VbglR3ClipboardReadFileHdr(HGCMCLIENTID  idClient,
    624                                            char         *pszFilename,
    625                                            uint32_t      cbFilename,
    626                                            uint32_t     *puFlags,
    627                                            uint32_t     *pfMode,
    628                                            uint64_t     *pcbTotal)
    629 {
    630     AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    631     AssertReturn(cbFilename,     VERR_INVALID_PARAMETER);
    632     AssertPtrReturn(puFlags,     VERR_INVALID_POINTER);
    633     AssertPtrReturn(pfMode,      VERR_INVALID_POINTER);
    634     AssertReturn(pcbTotal,       VERR_INVALID_POINTER);
    635 
    636     VBoxClipboardReadFileHdrMsg Msg;
    637     RT_ZERO(Msg);
    638 
    639     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    640                        VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR);
    641     Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
    642     Msg.pvName.SetPtr(pszFilename, cbFilename);
    643     Msg.cbName.SetUInt32(cbFilename);
    644     Msg.uFlags.SetUInt32(0);
    645     Msg.fMode.SetUInt32(0);
    646     Msg.cbTotal.SetUInt64(0);
    647 
    648     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    649     if (RT_SUCCESS(rc))
    650     {
    651         /** @todo Get context ID. */
    652         rc = Msg.uFlags.GetUInt32(puFlags);   AssertRC(rc);
    653         rc = Msg.fMode.GetUInt32(pfMode);     AssertRC(rc);
    654         rc = Msg.cbTotal.GetUInt64(pcbTotal); AssertRC(rc);
    655     }
    656 
    657     return rc;
    658 }
    659 
    660 /**
    661  * Writes a file header from the guest to the host.
    662  *
    663  * @returns VBox status code.
    664  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    665  * @param   pszFilename         File name this header belong to.
    666  * @param   cbFilename          Size (in bytes) of file name.
    667  * @param   fFlags              Transfer flags; not being used and will be ignored.
    668  * @param   fMode               File mode.
    669  * @param   cbTotal             File size (in bytes).
    670  */
    671 VBGLR3DECL(int) VbglR3ClipboardWriteFileHdr(HGCMCLIENTID idClient, const char *pszFilename, uint32_t cbFilename,
    672                                             uint32_t fFlags, uint32_t fMode, uint64_t cbTotal)
    673 {
    674     RT_NOREF(fFlags);
    675 
    676     const size_t cchFile = strlen(pszFilename);
    677 
    678     if (   !cchFile
    679         ||  cchFile >  RTPATH_MAX
    680         ||  cchFile != cbFilename)
    681         return VERR_INVALID_PARAMETER;
    682 
    683     const uint32_t cbFileSz = (uint32_t)cchFile + 1; /* Include termination. */
    684 
    685     VBoxClipboardWriteFileHdrMsg MsgHdr;
    686     RT_ZERO(MsgHdr);
    687 
    688     VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_HDR, VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR);
    689     MsgHdr.uContext.SetUInt32(0);                                                    /* Context ID; unused at the moment. */
    690     MsgHdr.cbName.SetUInt32(cbFileSz);
    691     MsgHdr.pvName.SetPtr((void *)pszFilename, (uint32_t)(cbFileSz));
    692     MsgHdr.uFlags.SetUInt32(0);                                                      /* Flags; unused at the moment. */
    693     MsgHdr.fMode.SetUInt32(fMode);                                                   /* File mode */
    694     MsgHdr.cbTotal.SetUInt64(cbTotal);                                               /* File size (in bytes). */
    695 
    696     return VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
    697 }
    698 
    699 /**
    700  * Reads a file data chunk from the host.
    701  *
    702  * @returns IPRT status code.
    703  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    704  * @param   pvData              Where to store the file data chunk.
    705  * @param   cbData              Size (in bytes) of where to store the data chunk.
    706  * @param   pcbRead             Size (in bytes) of the actual data chunk size read.
    707  */
    708 VBGLR3DECL(int) VbglR3ClipboardReadFileData(HGCMCLIENTID          idClient,
    709                                             void                 *pvData,
    710                                             uint32_t              cbData,
    711                                             uint32_t             *pcbRead)
    712 {
    713     AssertPtrReturn(pvData,  VERR_INVALID_POINTER);
    714     AssertReturn(cbData,     VERR_INVALID_PARAMETER);
    715     AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
    716 
    717     VBoxClipboardReadFileDataMsg Msg;
    718     RT_ZERO(Msg);
    719 
    720     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
    721                        VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
    722     Msg.uContext.SetUInt32(0);
    723     Msg.pvData.SetPtr(pvData, cbData);
    724     Msg.cbData.SetUInt32(0);
    725685    Msg.pvChecksum.SetPtr(NULL, 0);
    726686    Msg.cbChecksum.SetUInt32(0);
     
    729689    if (RT_SUCCESS(rc))
    730690    {
    731         /** @todo Context ID not used yet. */
    732         rc = Msg.cbData.GetUInt32(pcbRead); AssertRC(rc);
    733         AssertReturn(cbData >= *pcbRead, VERR_TOO_MUCH_DATA);
    734         /** @todo Add checksum support. */
    735     }
    736 
    737     return rc;
    738 }
    739 
    740 /**
    741  * Writes a file data chunk to the host.
    742  *
    743  * @returns VBox status code.
    744  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    745  * @param   pvData              Data chunk to write.
    746  * @param   cbData              Size (in bytes) of data chunk to write.
    747  * @param   pcbWritten          Returns how many bytes written.
    748  */
    749 VBGLR3DECL(int) VbglR3ClipboardWriteFileData(HGCMCLIENTID idClient, void *pvData, uint32_t cbData, uint32_t *pcbWritten)
    750 {
    751     AssertPtrReturn(pvData,     VERR_INVALID_POINTER);
    752     AssertReturn(cbData,        VERR_INVALID_PARAMETER);
    753     AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
    754 
    755     VBoxClipboardWriteFileDataMsg MsgData;
    756     RT_ZERO(MsgData);
    757 
    758     VBGL_HGCM_HDR_INIT(&MsgData.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_FILE_DATA, VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA);
    759     MsgData.uContext.SetUInt32(0);                                                    /* Context ID; unused at the moment. */
    760     MsgData.pvData.SetPtr(pvData, cbData);
    761     MsgData.cbData.SetUInt32(cbData);
    762     MsgData.pvChecksum.SetPtr(NULL, 0);
    763     MsgData.cbChecksum.SetUInt32(0);
    764 
    765     int rc = VbglR3HGCMCall(&MsgData.hdr, sizeof(MsgData));
    766     if (RT_SUCCESS(rc))
    767     {
    768         *pcbWritten = cbData;
    769     }
    770 
     691        if (pcbWritten)
     692            *pcbWritten = cbData;
     693    }
     694
     695    LogFlowFuncLeaveRC(rc);
    771696    return rc;
    772697}
     
    827752{
    828753    int rc  = vbglR3ClipboardWriteDataRaw(idClient, fFormat, pv, cb);
    829 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    830     if (RT_FAILURE(rc))
    831     {
    832         int rc2 = vbglR3ClipboardWriteErrorInternal(idClient, rc);
    833         if (RT_FAILURE(rc2))
    834             LogFlowFunc(("Unable to send error (%Rrc) to host, rc=%Rrc\n", rc, rc2));
    835     }
    836 #endif
    837754
    838755    return rc;
     
    847764 * @param   rcErr               Error (IPRT-style) to send.
    848765 */
    849 static int vbglR3ClipboardWriteErrorInternal(HGCMCLIENTID idClient, int rcErr)
     766VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
    850767{
    851768    VBoxClipboardWriteErrorMsg Msg;
    852769    RT_ZERO(Msg);
    853770
    854     VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR, 2);
     771    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR, VBOX_SHARED_CLIPBOARD_CPARMS_ERROR);
     772
    855773    /** @todo Context ID not used yet. */
    856774    Msg.uContext.SetUInt32(0);
     
    859777    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    860778
    861     /*
    862      * Never return an error if the host did not accept the error at the current
    863      * time.  This can be due to the host not having any appropriate callbacks
    864      * set which would handle that error.
    865      *
    866      * bird: Looks like VERR_NOT_SUPPORTED is what the host will return if it
    867      *       doesn't an appropriate callback.  The code used to ignore ALL errors
    868      *       the host would return, also relevant ones.
    869      */
    870779    if (RT_FAILURE(rc))
    871780        LogFlowFunc(("Sending error %Rrc failed with rc=%Rrc\n", rcErr, rc));
     
    873782        rc = VINF_SUCCESS;
    874783
    875     return rc;
    876 }
    877 
    878 /**
    879  * Writes an error back to the host.
    880  *
    881  * @returns IPRT status code.
    882  * @param   idClient            The client id returned by VbglR3ClipboardConnect().
    883  * @param   rcErr               Error (IPRT-style) to send.
    884  */
    885 VBGLR3DECL(int) vbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr)
    886 {
    887     return vbglR3ClipboardWriteErrorInternal(idClient, rcErr);
     784    if (RT_FAILURE(rc))
     785        LogRel(("Shared Clipboard: Reporting error %Rrc to the host failed with %Rrc\n", rcErr, rc));
     786
     787    LogFlowFuncLeaveRC(rc);
     788    return rc;
    888789}
    889790#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibDragAndDrop.cpp

    r78080 r79497  
    359359 * @returns IPRT status code.
    360360 * @param   pCtx                DnD context to use.
    361  * @param   pDataHdr            DnD data header to use. Needed for accounting.
     361 * @param   pListHdr            DnD data header to use. Needed for accounting.
    362362 * @param   pDroppedFiles       Dropped files object to use for maintaining the file creation / locking.
    363363 */
    364 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, DnDDroppedFiles *pDroppedFiles)
     364static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr, DnDDroppedFiles *pDroppedFiles)
    365365{
    366366    AssertPtrReturn(pCtx,          VERR_INVALID_POINTER);
    367     AssertPtrReturn(pDataHdr,      VERR_INVALID_POINTER);
     367    AssertPtrReturn(pListHdr,      VERR_INVALID_POINTER);
    368368    AssertPtrReturn(pDroppedFiles, VERR_INVALID_POINTER);
    369369
    370370    /* Only count the raw data minus the already received meta data. */
    371     Assert(pDataHdr->cbTotal >= pDataHdr->cbMeta);
    372     uint64_t cbToRecvBytes = pDataHdr->cbTotal - pDataHdr->cbMeta;
    373     uint64_t cToRecvObjs   = pDataHdr->cObjects;
     371    Assert(pListHdr->cbTotal >= pListHdr->cbMeta);
     372    uint64_t cbToRecvBytes = pListHdr->cbTotal - pListHdr->cbMeta;
     373    uint64_t cToRecvObjs   = pListHdr->cObjects;
    374374
    375375    LogFlowFunc(("cbToRecvBytes=%RU64, cToRecvObjs=%RU64, (cbTotal=%RU64, cbMeta=%RU32)\n",
    376                  cbToRecvBytes, cToRecvObjs, pDataHdr->cbTotal, pDataHdr->cbMeta));
     376                 cbToRecvBytes, cToRecvObjs, pListHdr->cbTotal, pListHdr->cbMeta));
    377377
    378378    /* Anything to do at all? */
     
    641641 * @returns IPRT status code.
    642642 * @param   pCtx                DnD context to use.
    643  * @param   pDataHdr            DnD data header to use. Need for accounting and stuff.
     643 * @param   pListHdr            DnD data header to use. Need for accounting and stuff.
    644644 * @param   pvData              Where to store the received data from the host.
    645645 * @param   cbData              Size (in bytes) of where to store the received data.
    646646 * @param   pcbDataRecv         Where to store the received amount of data (in bytes).
    647647 */
    648 static int vbglR3DnDHGRecvDataRaw(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr,
     648static int vbglR3DnDHGRecvDataRaw(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr,
    649649                                  void *pvData, uint32_t cbData, uint32_t *pcbDataRecv)
    650650{
    651651    AssertPtrReturn(pCtx,            VERR_INVALID_POINTER);
    652     AssertPtrReturn(pDataHdr,        VERR_INVALID_POINTER);
     652    AssertPtrReturn(pListHdr,        VERR_INVALID_POINTER);
    653653    AssertPtrReturn(pvData,          VERR_INVALID_POINTER);
    654654    AssertReturn(cbData,             VERR_INVALID_PARAMETER);
     
    694694 * @returns IPRT status code.
    695695 * @param   pCtx                DnD context to use.
    696  * @param   pDataHdr            Where to store the receivd DnD data header.
    697  */
    698 static int vbglR3DnDHGRecvDataHdr(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr)
     696 * @param   pListHdr            Where to store the receivd DnD data header.
     697 */
     698static int vbglR3DnDHGRecvListHdr(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr)
    699699{
    700700    AssertPtrReturn(pCtx,     VERR_INVALID_POINTER);
    701     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
     701    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
    702702
    703703    Assert(pCtx->uProtocol >= 3); /* Only for protocol v3 and up. */
    704704
    705     VBOXDNDHGSENDDATAHDRMSG Msg;
     705    VBOXDNDHGSENDListHdrMSG Msg;
    706706    RT_ZERO(Msg);
    707707    VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, HOST_DND_HG_SND_DATA_HDR, 12);
     
    711711    Msg.cbTotal.SetUInt64(0);
    712712    Msg.cbMeta.SetUInt32(0);
    713     Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
     713    Msg.pvMetaFmt.SetPtr(pListHdr->pvMetaFmt, pListHdr->cbMetaFmt);
    714714    Msg.cbMetaFmt.SetUInt32(0);
    715715    Msg.cObjects.SetUInt64(0);
    716716    Msg.enmCompression.SetUInt32(0);
    717717    Msg.enmChecksumType.SetUInt32(0);
    718     Msg.pvChecksum.SetPtr(pDataHdr->pvChecksum, pDataHdr->cbChecksum);
     718    Msg.pvChecksum.SetPtr(pListHdr->pvChecksum, pListHdr->cbChecksum);
    719719    Msg.cbChecksum.SetUInt32(0);
    720720
     
    723723    {
    724724        /* Msg.uContext not needed here. */
    725         Msg.uFlags.GetUInt32(&pDataHdr->uFlags);
    726         Msg.uScreenId.GetUInt32(&pDataHdr->uScreenId);
    727         Msg.cbTotal.GetUInt64(&pDataHdr->cbTotal);
    728         Msg.cbMeta.GetUInt32(&pDataHdr->cbMeta);
    729         Msg.cbMetaFmt.GetUInt32(&pDataHdr->cbMetaFmt);
    730         Msg.cObjects.GetUInt64(&pDataHdr->cObjects);
    731         Msg.enmCompression.GetUInt32(&pDataHdr->enmCompression);
    732         Msg.enmChecksumType.GetUInt32((uint32_t *)&pDataHdr->enmChecksumType);
    733         Msg.cbChecksum.GetUInt32(&pDataHdr->cbChecksum);
     725        Msg.uFlags.GetUInt32(&pListHdr->uFlags);
     726        Msg.uScreenId.GetUInt32(&pListHdr->uScreenId);
     727        Msg.cbTotal.GetUInt64(&pListHdr->cbTotal);
     728        Msg.cbMeta.GetUInt32(&pListHdr->cbMeta);
     729        Msg.cbMetaFmt.GetUInt32(&pListHdr->cbMetaFmt);
     730        Msg.cObjects.GetUInt64(&pListHdr->cObjects);
     731        Msg.enmCompression.GetUInt32(&pListHdr->enmCompression);
     732        Msg.enmChecksumType.GetUInt32((uint32_t *)&pListHdr->enmChecksumType);
     733        Msg.cbChecksum.GetUInt32(&pListHdr->cbChecksum);
    734734    }
    735735
     
    744744 * @returns IPRT status code.
    745745 * @param   pCtx                DnD context to use.
    746  * @param   pDataHdr            Where to store the data header data.
     746 * @param   pListHdr            Where to store the data header data.
    747747 * @param   ppvData             Returns the received meta data. Needs to be free'd by the caller.
    748748 * @param   pcbData             Where to store the size (in bytes) of the received meta data.
    749749 */
    750 static int vbglR3DnDHGRecvDataLoop(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr,
     750static int vbglR3DnDHGRecvDataLoop(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDListHdr pListHdr,
    751751                                   void **ppvData, uint64_t *pcbData)
    752752{
    753753    AssertPtrReturn(pCtx,     VERR_INVALID_POINTER);
    754     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
     754    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
    755755    AssertPtrReturn(ppvData,  VERR_INVALID_POINTER);
    756756    AssertPtrReturn(pcbData,  VERR_INVALID_POINTER);
     
    761761    LogFlowFuncEnter();
    762762
    763     rc = vbglR3DnDHGRecvDataHdr(pCtx, pDataHdr);
     763    rc = vbglR3DnDHGRecvListHdr(pCtx, pListHdr);
    764764    if (RT_FAILURE(rc))
    765765        return rc;
    766766
    767     LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects));
    768     if (pDataHdr->cbMeta)
     767    LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU32\n", pListHdr->cbTotal, pListHdr->cbMeta, pListHdr->cObjects));
     768    if (pListHdr->cbMeta)
    769769    {
    770770        uint64_t cbDataTmp = 0;
    771         void    *pvDataTmp = RTMemAlloc(pDataHdr->cbMeta);
     771        void    *pvDataTmp = RTMemAlloc(pListHdr->cbMeta);
    772772        if (!pvDataTmp)
    773773            rc = VERR_NO_MEMORY;
     
    776776        {
    777777            uint8_t *pvDataOff = (uint8_t *)pvDataTmp;
    778             while (cbDataTmp < pDataHdr->cbMeta)
     778            while (cbDataTmp < pListHdr->cbMeta)
    779779            {
    780                 rc = vbglR3DnDHGRecvDataRaw(pCtx, pDataHdr,
    781                                             pvDataOff, RT_MIN(pDataHdr->cbMeta - cbDataTmp, pCtx->cbMaxChunkSize),
     780                rc = vbglR3DnDHGRecvDataRaw(pCtx, pListHdr,
     781                                            pvDataOff, RT_MIN(pListHdr->cbMeta - cbDataTmp, pCtx->cbMaxChunkSize),
    782782                                            &cbDataRecv);
    783783                if (RT_SUCCESS(rc))
    784784                {
    785785                    LogFlowFunc(("cbDataRecv=%RU32, cbDataTmp=%RU64\n", cbDataRecv, cbDataTmp));
    786                     Assert(cbDataTmp + cbDataRecv <= pDataHdr->cbMeta);
     786                    Assert(cbDataTmp + cbDataRecv <= pListHdr->cbMeta);
    787787                    cbDataTmp += cbDataRecv;
    788788                    pvDataOff += cbDataRecv;
     
    794794            if (RT_SUCCESS(rc))
    795795            {
    796                 Assert(cbDataTmp == pDataHdr->cbMeta);
     796                Assert(cbDataTmp == pListHdr->cbMeta);
    797797
    798798                LogFlowFunc(("Received %RU64 bytes of data\n", cbDataTmp));
     
    833833    /* The rest is optional. */
    834834
    835     VBOXDNDDATAHDR dataHdr;
    836     RT_ZERO(dataHdr);
     835    VBOXDNDListHdr ListHdr;
     836    RT_ZERO(ListHdr);
    837837
    838838    AssertMsg(pCtx->cbMaxChunkSize, ("Maximum chunk size must not be 0\n"));
    839839
    840     dataHdr.cbMetaFmt = pCtx->cbMaxChunkSize;
    841     dataHdr.pvMetaFmt = RTMemAlloc(dataHdr.cbMetaFmt);
    842     if (!dataHdr.pvMetaFmt)
     840    ListHdr.cbMetaFmt = pCtx->cbMaxChunkSize;
     841    ListHdr.pvMetaFmt = RTMemAlloc(ListHdr.cbMetaFmt);
     842    if (!ListHdr.pvMetaFmt)
    843843        return VERR_NO_MEMORY;
    844844
     
    849849    uint64_t cbData = 0;
    850850
    851     int rc = vbglR3DnDHGRecvDataLoop(pCtx, &dataHdr, &pvData, &cbData);
     851    int rc = vbglR3DnDHGRecvDataLoop(pCtx, &ListHdr, &pvData, &cbData);
    852852    if (RT_SUCCESS(rc))
    853853    {
     
    860860         * VBoxTray) small by not having too much redundant code.
    861861         */
    862         Assert(dataHdr.cbMetaFmt);
    863         AssertPtr(dataHdr.pvMetaFmt);
    864         if (DnDMIMEHasFileURLs((char *)dataHdr.pvMetaFmt, dataHdr.cbMetaFmt)) /* URI data. */
     862        Assert(ListHdr.cbMetaFmt);
     863        AssertPtr(ListHdr.pvMetaFmt);
     864        if (DnDMIMEHasFileURLs((char *)ListHdr.pvMetaFmt, ListHdr.cbMetaFmt)) /* URI data. */
    865865        {
    866866            AssertPtr(pvData);
     
    869869            rc = lstURI.SetFromURIData(pvData, cbData, 0 /* fFlags */);
    870870            if (RT_SUCCESS(rc))
    871                 rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles);
     871                rc = vbglR3DnDHGRecvURIData(pCtx, &ListHdr, &droppedFiles);
    872872
    873873            if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */
     
    905905    }
    906906
    907     if (dataHdr.pvMetaFmt)
    908         RTMemFree(dataHdr.pvMetaFmt);
     907    if (ListHdr.pvMetaFmt)
     908        RTMemFree(ListHdr.pvMetaFmt);
    909909
    910910    if (RT_SUCCESS(rc))
     
    14801480 * @param   pvData              Data block to send.
    14811481 * @param   cbData              Size (in bytes) of data block to send.
    1482  * @param   pDataHdr            Data header to use -- needed for accounting.
     1482 * @param   pListHdr            Data header to use -- needed for accounting.
    14831483 */
    14841484static int vbglR3DnDGHSendDataInternal(PVBGLR3GUESTDNDCMDCTX pCtx,
    1485                                        void *pvData, uint64_t cbData, PVBOXDNDSNDDATAHDR pDataHdr)
     1485                                       void *pvData, uint64_t cbData, PVBOXDNDSNDListHdr pListHdr)
    14861486{
    14871487    AssertPtrReturn(pCtx,     VERR_INVALID_POINTER);
    14881488    AssertPtrReturn(pvData,   VERR_INVALID_POINTER);
    14891489    AssertReturn(cbData,      VERR_INVALID_PARAMETER);
    1490     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
    1491 
    1492     VBOXDNDGHSENDDATAHDRMSG MsgHdr;
     1490    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
     1491
     1492    VBOXDNDGHSENDListHdrMSG MsgHdr;
    14931493    RT_ZERO(MsgHdr);
    14941494
     
    14971497    MsgHdr.uFlags.SetUInt32(0);                             /** @todo Not used yet. */
    14981498    MsgHdr.uScreenId.SetUInt32(0);                          /** @todo Not used for guest->host (yet). */
    1499     MsgHdr.cbTotal.SetUInt64(pDataHdr->cbTotal);
    1500     MsgHdr.cbMeta.SetUInt32(pDataHdr->cbMeta);
    1501     MsgHdr.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
    1502     MsgHdr.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt);
    1503     MsgHdr.cObjects.SetUInt64(pDataHdr->cObjects);
     1499    MsgHdr.cbTotal.SetUInt64(pListHdr->cbTotal);
     1500    MsgHdr.cbMeta.SetUInt32(pListHdr->cbMeta);
     1501    MsgHdr.pvMetaFmt.SetPtr(pListHdr->pvMetaFmt, pListHdr->cbMetaFmt);
     1502    MsgHdr.cbMetaFmt.SetUInt32(pListHdr->cbMetaFmt);
     1503    MsgHdr.cObjects.SetUInt64(pListHdr->cObjects);
    15041504    MsgHdr.enmCompression.SetUInt32(0);                     /** @todo Not used yet. */
    15051505    MsgHdr.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */
     
    15101510
    15111511    LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32, cObjects=%RU64, rc=%Rrc\n",
    1512                  pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects, rc));
     1512                 pListHdr->cbTotal, pListHdr->cbMeta, pListHdr->cObjects, rc));
    15131513
    15141514    if (RT_SUCCESS(rc))
     
    17331733    /* cbData can be 0. */
    17341734
    1735     VBOXDNDDATAHDR dataHdr;
    1736     RT_ZERO(dataHdr);
     1735    VBOXDNDListHdr ListHdr;
     1736    RT_ZERO(ListHdr);
    17371737
    17381738    /* For raw data only the total size is required to be specified. */
    1739     dataHdr.cbTotal = cbData;
    1740 
    1741     return vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, &dataHdr);
     1739    ListHdr.cbTotal = cbData;
     1740
     1741    return vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, &ListHdr);
    17421742}
    17431743
     
    17861786            const uint32_t cbMetaFmt   = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */
    17871787
    1788             VBOXDNDDATAHDR dataHdr;
    1789             dataHdr.uFlags    = 0; /* Flags not used yet. */
    1790             dataHdr.cbTotal   = cbTotal;
    1791             dataHdr.cbMeta    = cbURLIist;
    1792             dataHdr.pvMetaFmt = (void *)szMetaFmt;
    1793             dataHdr.cbMetaFmt = cbMetaFmt;
    1794             dataHdr.cObjects  = lstURI.GetTotalCount();
     1788            VBOXDNDListHdr ListHdr;
     1789            ListHdr.uFlags    = 0; /* Flags not used yet. */
     1790            ListHdr.cbTotal   = cbTotal;
     1791            ListHdr.cbMeta    = cbURLIist;
     1792            ListHdr.pvMetaFmt = (void *)szMetaFmt;
     1793            ListHdr.cbMetaFmt = cbMetaFmt;
     1794            ListHdr.cObjects  = lstURI.GetTotalCount();
    17951795
    17961796            rc = vbglR3DnDGHSendDataInternal(pCtx,
    1797                                              pvURIList, cbURLIist, &dataHdr);
     1797                                             pvURIList, cbURLIist, &ListHdr);
    17981798        }
    17991799        else
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceClipboard-os2.cpp

    r78346 r79497  
    884884                uint32_t Msg;
    885885                uint32_t fFormats;
    886                 rc = VbglR3ClipboardGetHostMsg(g_u32ClientId, &Msg, &fFormats);
     886                rc = VbglR3ClipboardGetHostMsgOld(g_u32ClientId, &Msg, &fFormats);
    887887                if (RT_SUCCESS(rc))
    888888                {
  • trunk/src/VBox/Additions/haiku/VBoxTray/VBoxClipboard.cpp

    r78346 r79497  
    375375        uint32_t u32Msg;
    376376        uint32_t u32Formats;
    377         int rc = VbglR3ClipboardGetHostMsg(fClientId, &u32Msg, &u32Formats);
     377        int rc = VbglR3ClipboardGetHostMsgOld(fClientId, &u32Msg, &u32Formats);
    378378        if (RT_SUCCESS(rc))
    379379        {
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp

    r78581 r79497  
    224224        uint32_t Msg;
    225225        uint32_t fFormats;
    226         rc = VbglR3ClipboardGetHostMsg(g_ctx.client, &Msg, &fFormats);
     226        rc = VbglR3ClipboardGetHostMsgOld(g_ctx.client, &Msg, &fFormats);
    227227        if (RT_SUCCESS(rc))
    228228        {
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r79366 r79497  
    3434#include <iprt/win/shlwapi.h>
    3535
     36#include <iprt/err.h>
    3637#include <iprt/path.h>
    3738#include <iprt/semaphore.h>
     
    121122        m_enmStatus = Initialized;
    122123
    123         int rc2 = RTSemEventCreate(&m_EventMetaDataComplete);
     124        int rc2 = RTSemEventCreate(&m_EventListComplete);
    124125        AssertRC(rc2);
     126        rc2 = RTSemEventCreate(&m_EventTransferComplete);
     127        AssertRC(rc2);
    125128    }
    126129
     
    130133VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
    131134{
    132     RTSemEventDestroy(m_EventMetaDataComplete);
     135    RTSemEventDestroy(m_EventListComplete);
     136    RTSemEventDestroy(m_EventTransferComplete);
    133137
    134138    if (m_pStream)
     
    216220}
    217221
     222/* static */
     223
     224/**
     225 * Thread for reading URI data.
     226 * The data object needs the (high level, root) URI listing at the time of ::GetData(), so we need
     227 * to block and wait until we have this data (via this thread) and continue.
     228 *
     229 * @returns VBox status code.
     230 * @param   ThreadSelf          Thread handle. Unused at the moment.
     231 * @param   pvUser              Pointer to user-provided data. Of type VBoxClipboardWinDataObject.
     232 */
     233DECLCALLBACK(int) VBoxClipboardWinDataObject::readThread(RTTHREAD ThreadSelf, void *pvUser)
     234{
     235    RT_NOREF(ThreadSelf);
     236
     237    LogFlowFuncEnter();
     238
     239    VBoxClipboardWinDataObject *pThis = (VBoxClipboardWinDataObject *)pvUser;
     240
     241    PSHAREDCLIPBOARDURITRANSFER pTransfer = pThis->m_pTransfer;
     242    AssertPtr(pTransfer);
     243
     244    pTransfer->Thread.fStarted = true;
     245
     246    RTThreadUserSignal(RTThreadSelf());
     247
     248    int rc = SharedClipboardURITransferOpen(pTransfer);
     249    if (RT_SUCCESS(rc))
     250    {
     251        VBOXCLIPBOARDLISTHDR Hdr;
     252        rc = SharedClipboardURIListHdrInit(&Hdr);
     253        if (RT_SUCCESS(rc))
     254        {
     255            VBOXCLIPBOARDLISTHANDLE hList;
     256            rc = SharedClipboardURITransferListOpen(pTransfer, &Hdr, &hList);
     257            if (RT_SUCCESS(rc))
     258            {
     259                LogFlowFunc(("hList=%RU64, cTotalObjects=%RU64, cbTotalSize=%RU64\n\n",
     260                             hList, Hdr.cTotalObjects, Hdr.cbTotalSize));
     261
     262                for (uint64_t i = 0; i < Hdr.cTotalObjects; i++)
     263                {
     264                    VBOXCLIPBOARDLISTENTRY Entry;
     265                    rc = SharedClipboardURITransferListRead(pTransfer, hList, &Entry);
     266                    if (RT_SUCCESS(rc))
     267                    {
     268
     269                    }
     270                    else
     271                        break;
     272
     273                    if (pTransfer->Thread.fStop)
     274                        break;
     275                }
     276
     277                if (RT_SUCCESS(rc))
     278                {
     279                    /*
     280                     * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
     281                     * This in turn then will create IStream instances (by the OS) for each file system object to handle.
     282                     */
     283                    int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
     284                    AssertRC(rc2);
     285
     286                    LogFlowFunc(("Waiting for transfer to complete ...\n"));
     287
     288                    /* Transferring stuff can take a while, so don't use any timeout here. */
     289                    rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
     290                    AssertRC(rc2);
     291                }
     292
     293                SharedClipboardURITransferListClose(pTransfer, hList);
     294            }
     295
     296            SharedClipboardURIListHdrDestroy(&Hdr);
     297        }
     298
     299        SharedClipboardURITransferClose(pTransfer);
     300    }
     301
     302    LogFlowFuncLeaveRC(rc);
     303    return rc;
     304}
     305
    218306/**
    219307 * Creates a FILEGROUPDESCRIPTOR object from a given URI transfer and stores the result into an HGLOBAL object.
     
    232320    LogFlowFuncEnter();
    233321
    234     SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(pTransfer);
    235     if (!pURIList)
    236         return VERR_WRONG_ORDER;
    237 
    238322    const size_t cbFileGroupDescriptor = fUnicode ? sizeof(FILEGROUPDESCRIPTORW) : sizeof(FILEGROUPDESCRIPTORA);
    239323    const size_t cbFileDescriptor = fUnicode ? sizeof(FILEDESCRIPTORW) : sizeof(FILEDESCRIPTORA);
    240324
    241     const UINT   cItems = (UINT)pURIList->GetRootCount(); /** @todo UINT vs. uint64_t */
     325    const UINT   cItems = (UINT)0; /** @todo UINT vs. uint64_t */
     326    if (!cItems)
     327        return VERR_NOT_FOUND;
     328
    242329    const size_t cbFGD  = cbFileGroupDescriptor + (cbFileDescriptor * (cItems - 1));
    243330
     
    254341
    255342    char *pszFileSpec = NULL;
    256 
     343#if 0
    257344    for (UINT i = 0; i < cItems; i++)
    258345    {
     
    326413#endif
    327414    }
     415#endif
    328416
    329417    if (pszFileSpec)
     
    393481#endif
    394482        {
    395             int rc = SharedClipboardURITransferPrepare(m_pTransfer);
    396             if (RT_SUCCESS(rc))
     483            const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
     484
     485            LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
     486
     487            int rc;
     488
     489            /* The caller can call GetData() several times, so make sure we don't do the same transfer multiple times. */
     490            if (SharedClipboardURITransferGetStatus(m_pTransfer) == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE)
    397491            {
    398                 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
    399 
    400                 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
    401 
    402                 /* Start the transfer asynchronously in a separate thread. */
    403                 rc = SharedClipboardURITransferRun(m_pTransfer, true /* fAsync */);
     492                rc = SharedClipboardURITransferPrepare(m_pTransfer);
    404493                if (RT_SUCCESS(rc))
    405494                {
    406                     /* Wait for the meta data to arrive. */
    407                     LogFlowFunc(("Waiting for meta data to arrive ...\n"));
    408                     rc = RTSemEventWait(m_EventMetaDataComplete, 30 * 1000 /* 30s timeout */);
     495                    /* Start the transfer asynchronously in a separate thread. */
     496                    rc = SharedClipboardURITransferRun(m_pTransfer, &VBoxClipboardWinDataObject::readThread, this);
    409497                    if (RT_SUCCESS(rc))
    410498                    {
    411                         HGLOBAL hGlobal;
    412                         rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);
     499                        LogFunc(("Waiting for listing to arrive ...\n"));
     500                        rc = RTSemEventWait(m_EventListComplete, 5 * 60 * 1000 /* 5 min timeout */);
    413501                        if (RT_SUCCESS(rc))
    414502                        {
    415                             pMedium->tymed   = TYMED_HGLOBAL;
    416                             pMedium->hGlobal = hGlobal;
    417                             /* Note: hGlobal now is being owned by pMedium / the caller. */
    418 
    419                             hr = S_OK;
     503                            LogFunc(("Listing complete\n"));
     504
     505                            HGLOBAL hGlobal;
     506                            rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);
     507                            if (RT_SUCCESS(rc))
     508                            {
     509                                pMedium->tymed   = TYMED_HGLOBAL;
     510                                pMedium->hGlobal = hGlobal;
     511                                /* Note: hGlobal now is being owned by pMedium / the caller. */
     512
     513                                hr = S_OK;
     514                            }
    420515                        }
    421516                    }
    422517                }
    423 
    424                 if (RT_FAILURE(rc))
    425                     LogRel(("Shared Clipboard: Data object unable to receive meta data, rc=%Rrc\n", rc));
    426518            }
     519            else
     520                rc = VERR_ALREADY_EXISTS;
     521
     522            if (RT_FAILURE(rc))
     523                LogRel(("Shared Clipboard: Data object unable to get data, rc=%Rrc\n", rc));
     524
    427525            break;
    428526        }
     
    588686    LogFlowFuncLeaveRC(VINF_SUCCESS);
    589687    return VINF_SUCCESS;
    590 }
    591 
    592 DECLCALLBACK(void) VBoxClipboardWinDataObject::OnMetaDataComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    593 {
    594     LogFlowFuncEnter();
    595 
    596     AssertReturnVoid(pTransfer == m_pTransfer);
    597 
    598     int rc2 = RTSemEventSignal(m_EventMetaDataComplete);
    599     AssertRC(rc2);
    600688}
    601689
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp

    r79347 r79497  
    160160    LogFlowThisFuncEnter();
    161161
    162     const SharedClipboardURIObject *pObj = SharedClipboardURITransferGetObject(m_pURITransfer, m_uObjIdx);
    163 
    164     if (pObj->IsComplete())
     162    AssertPtr(m_pURITransfer->State.ObjCtx.pObjInfo);
     163
     164    const uint64_t cbSize      = m_pURITransfer->State.ObjCtx.pObjInfo->cbObject;
     165          uint64_t cbProcessed = m_pURITransfer->State.ObjCtx.cbProcessed;
     166
     167    if (cbProcessed == cbSize)
    165168    {
    166169        /* There can be 0-byte files. */
    167         AssertMsg(pObj->GetSize() == 0, ("Object is complete -- can't read from it anymore\n"));
     170        AssertMsg(cbSize == 0, ("Object is complete -- can't read from it anymore\n"));
    168171        if (nBytesRead)
    169172            *nBytesRead = 0; /** @todo If the file size is 0, already return at least 1 byte, else the whole operation will fail. */
     
    171174    }
    172175
    173     const uint64_t cbSize      = pObj->GetSize();
    174     const uint64_t cbProcessed = pObj->GetProcessed();
    175 
    176176    const uint32_t cbToRead = RT_MIN(cbSize - cbProcessed, nBytesToRead);
    177177          uint32_t cbRead   = 0;
     
    181181    if (cbToRead)
    182182    {
    183         rc = m_pURITransfer->ProviderIface.pfnReadFileData(&m_pURITransfer->ProviderCtx,
    184                                                            pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
     183        rc = m_pURITransfer->ProviderIface.pfnObjRead(&m_pURITransfer->ProviderCtx, m_pURITransfer->State.ObjCtx.uHandle,
     184                                                      pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
    185185        if (RT_SUCCESS(rc))
    186186        {
    187 //            pObj->AddProcessed(cbRead);
    188 
    189             if (pObj->IsComplete())
     187            cbProcessed += cbRead;
     188            Assert(cbProcessed <= cbSize);
     189
     190            if (cbProcessed == cbSize)
    190191                m_pParent->OnTransferComplete();
     192
     193            m_pURITransfer->State.ObjCtx.cbProcessed = cbProcessed;
    191194        }
    192195    }
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp

    r79366 r79497  
    294294    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    295295
    296     char *pszPathURI;
    297     int rc = SharedClipboardMetaDataConvertToFormat(pszPath, strlen(pszPath), SHAREDCLIPBOARDMETADATAFMT_URI_LIST,
    298                                                     (void **)&pszPathURI, NULL /* cbData */);
    299     if (RT_SUCCESS(rc))
    300     {
    301         rc = AppendURIPath(pszPathURI, fFlags);
    302         RTStrFree(pszPathURI);
    303     }
    304 
    305     return rc;
     296    RT_NOREF(fFlags);
     297
     298    return VERR_NOT_IMPLEMENTED;
    306299}
    307300
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp

    r79366 r79497  
    2323
    2424#include <VBox/err.h>
     25#include <VBox/HostServices/VBoxClipboardSvc.h>
    2526#include <VBox/GuestHost/SharedClipboard-uri.h>
    2627
    2728
    2829#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    29 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer);
     30static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
    3031static int sharedClipboardURITransferThreadDestroy(PSHAREDCLIPBOARDURITRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);
    31 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser);
    3232static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser);
    3333static PSHAREDCLIPBOARDURITRANSFER sharedClipboardURICtxGetTransferInternal(PSHAREDCLIPBOARDURICTX pURI, uint32_t uIdx);
    34 
    35 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer);
    3634#endif
    3735
    3836
    3937/**
    40  * Allocates a VBOXCLIPBOARDDATAHDR structure.
     38 * Allocates a VBOXCLIPBOARDListHdr structure.
    4139 *
    4240 * @returns VBox status code.
    43  * @param   ppDataChunk         Where to store the allocated VBOXCLIPBOARDDATAHDR structure on success.
    44  */
    45 int SharedClipboardURIDataHdrAlloc(PVBOXCLIPBOARDDATAHDR *ppDataHdr)
     41 * @param   ppListEntry         Where to store the allocated VBOXCLIPBOARDListHdr structure on success.
     42 */
     43int SharedClipboardURIListHdrAlloc(PVBOXCLIPBOARDLISTHDR *ppListHdr)
    4644{
    4745    int rc;
    4846
    49     PVBOXCLIPBOARDDATAHDR pDataHdr = (PVBOXCLIPBOARDDATAHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDDATAHDR));
    50     if (pDataHdr)
    51     {
    52         PSHAREDCLIPBOARDMETADATAFMTDATA pMetaDataFmt
    53             = (PSHAREDCLIPBOARDMETADATAFMTDATA)RTMemAllocZ(sizeof(SHAREDCLIPBOARDMETADATAFMTDATA));
    54         if (pMetaDataFmt)
    55         {
    56             char *pszFmt = NULL;
    57             rc = RTStrAAppend(&pszFmt, "VBoxShClURIList"); /** @todo Make this more flexible. Later. */
    58             if (RT_SUCCESS(rc))
    59             {
    60                 pMetaDataFmt->uVer  = 1;
    61                 pMetaDataFmt->pvFmt = pszFmt;
    62                 pMetaDataFmt->cbFmt = (uint32_t)strlen(pszFmt) + 1 /* Include terminating zero */;
    63 
    64                 pDataHdr->pvMetaFmt = pMetaDataFmt;
    65                 pDataHdr->cbMetaFmt = sizeof(SHAREDCLIPBOARDMETADATAFMTDATA) + pMetaDataFmt->cbFmt;
    66 
    67                 *ppDataHdr = pDataHdr;
    68             }
    69         }
    70         else
    71             rc = VERR_NO_MEMORY;
    72 
    73         if (RT_FAILURE(rc))
    74         {
    75             RTMemFree(pDataHdr);
    76             pDataHdr = NULL;
    77         }
     47    PVBOXCLIPBOARDLISTHDR pListHdr = (PVBOXCLIPBOARDLISTHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTHDR));
     48    if (pListHdr)
     49    {
     50        *ppListHdr = pListHdr;
     51        rc = VINF_SUCCESS;
    7852    }
    7953    else
     
    8559
    8660/**
    87  * Frees a VBOXCLIPBOARDDATAHDR structure.
    88  *
    89  * @param   pDataChunk          VBOXCLIPBOARDDATAHDR structure to free.
    90  */
    91 void SharedClipboardURIDataHdrFree(PVBOXCLIPBOARDDATAHDR pDataHdr)
    92 {
    93     if (!pDataHdr)
     61 * Frees a VBOXCLIPBOARDListHdr structure.
     62 *
     63 * @param   pListEntry          VBOXCLIPBOARDListHdr structure to free.
     64 */
     65void SharedClipboardURIListHdrFree(PVBOXCLIPBOARDLISTHDR pListHdr)
     66{
     67    if (!pListHdr)
    9468        return;
    9569
    9670    LogFlowFuncEnter();
    9771
    98     SharedClipboardURIDataHdrDestroy(pDataHdr);
    99 
    100     RTMemFree(pDataHdr);
    101     pDataHdr = NULL;
    102 }
    103 
    104 /**
    105  * Duplicates (allocates) a VBOXCLIPBOARDDATAHDR structure.
    106  *
    107  * @returns Duplicated VBOXCLIPBOARDDATAHDR structure on success.
    108  * @param   pDataHdr            VBOXCLIPBOARDDATAHDR to duplicate.
    109  */
    110 PVBOXCLIPBOARDDATAHDR SharedClipboardURIDataHdrDup(PVBOXCLIPBOARDDATAHDR pDataHdr)
    111 {
    112     AssertPtrReturn(pDataHdr, NULL);
    113 
    114     PVBOXCLIPBOARDDATAHDR pDataHdrDup = (PVBOXCLIPBOARDDATAHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDDATAHDR));
    115     if (pDataHdrDup)
    116     {
    117         *pDataHdrDup = *pDataHdr;
    118 
    119         if (pDataHdr->pvMetaFmt)
     72    SharedClipboardURIListHdrDestroy(pListHdr);
     73
     74    RTMemFree(pListHdr);
     75    pListHdr = NULL;
     76}
     77
     78/**
     79 * Duplicates (allocates) a VBOXCLIPBOARDListHdr structure.
     80 *
     81 * @returns Duplicated VBOXCLIPBOARDListHdr structure on success.
     82 * @param   pListHdr            VBOXCLIPBOARDListHdr to duplicate.
     83 */
     84PVBOXCLIPBOARDLISTHDR SharedClipboardURIListHdrDup(PVBOXCLIPBOARDLISTHDR pListHdr)
     85{
     86    AssertPtrReturn(pListHdr, NULL);
     87
     88    PVBOXCLIPBOARDLISTHDR pListHdrDup = (PVBOXCLIPBOARDLISTHDR)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTHDR));
     89    if (pListHdrDup)
     90    {
     91        *pListHdrDup = *pListHdr;
     92
     93        if (pListHdr->pszFilter)
    12094        {
    121             pDataHdrDup->pvMetaFmt = RTMemDup(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
    122             pDataHdrDup->cbMetaFmt = pDataHdr->cbMetaFmt;
     95            pListHdrDup->pszFilter = RTStrDup(pListHdr->pszFilter);
     96            pListHdrDup->cbFilter  = (uint32_t)strlen(pListHdrDup->pszFilter);
    12397        }
    124 
    125         if (pDataHdr->pvChecksum)
     98    }
     99
     100    return pListHdrDup;
     101}
     102
     103/**
     104 * Initializes an URI data header struct.
     105 *
     106 * @returns VBox status code.
     107 * @param   pListHdr            Data header struct to initialize.
     108 */
     109int SharedClipboardURIListHdrInit(PVBOXCLIPBOARDLISTHDR pListHdr)
     110{
     111    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
     112
     113    SharedClipboardURIListHdrReset(pListHdr);
     114
     115    return VINF_SUCCESS;
     116}
     117
     118/**
     119 * Destroys an URI data header struct.
     120 *
     121 * @param   pListHdr            Data header struct to destroy.
     122 */
     123void SharedClipboardURIListHdrDestroy(PVBOXCLIPBOARDLISTHDR pListHdr)
     124{
     125    if (!pListHdr)
     126        return;
     127
     128    LogFlowFuncEnter();
     129
     130    if (pListHdr->pszFilter)
     131    {
     132        Assert(pListHdr->cbFilter);
     133
     134        RTStrFree(pListHdr->pszFilter);
     135        pListHdr->pszFilter = NULL;
     136        pListHdr->cbFilter = 0;
     137    }
     138}
     139
     140/**
     141 * Resets a VBOXCLIPBOARDListHdr structture.
     142 *
     143 * @returns VBox status code.
     144 * @param   pListHdr            VBOXCLIPBOARDListHdr structture to reset.
     145 */
     146void SharedClipboardURIListHdrReset(PVBOXCLIPBOARDLISTHDR pListHdr)
     147{
     148    AssertPtrReturnVoid(pListHdr);
     149
     150    LogFlowFuncEnter();
     151
     152    RT_BZERO(pListHdr, sizeof(VBOXCLIPBOARDLISTHDR));
     153}
     154
     155/**
     156 * Returns whether a given clipboard data header is valid or not.
     157 *
     158 * @returns \c true if valid, \c false if not.
     159 * @param   pListHdr            Clipboard data header to validate.
     160 */
     161bool SharedClipboardURIListHdrIsValid(PVBOXCLIPBOARDLISTHDR pListHdr)
     162{
     163    RT_NOREF(pListHdr);
     164    return true; /** @todo Implement this. */
     165}
     166
     167/**
     168 * Creates (allocates) and initializes a VBOXCLIPBOARDListEntry structure.
     169 *
     170 * @param   ppDirData           Where to return the created VBOXCLIPBOARDListEntry structure on success.
     171 */
     172int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry)
     173{
     174    PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
     175    if (!pListEntry)
     176        return VERR_NO_MEMORY;
     177
     178    int rc = SharedClipboardURIListEntryInit(pListEntry);
     179    if (RT_SUCCESS(rc))
     180        *ppListEntry = pListEntry;
     181
     182    return rc;
     183}
     184
     185/**
     186 * Frees a VBOXCLIPBOARDListEntry structure.
     187 *
     188 * @param   pListEntry         VBOXCLIPBOARDListEntry structure to free.
     189 */
     190void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry)
     191{
     192    if (!pListEntry)
     193        return;
     194
     195    SharedClipboardURIListEntryDestroy(pListEntry);
     196    RTMemFree(pListEntry);
     197}
     198
     199/**
     200 * Duplicates (allocates) a VBOXCLIPBOARDListEntry structure.
     201 *
     202 * @returns Duplicated VBOXCLIPBOARDListEntry structure on success.
     203 * @param   pListEntry          VBOXCLIPBOARDListEntry to duplicate.
     204 */
     205PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry)
     206{
     207    AssertPtrReturn(pListEntry, NULL);
     208
     209    PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
     210    if (pListEntryDup)
     211    {
     212        *pListEntryDup = *pListEntry;
     213
     214        if (pListEntry->pvInfo)
    126215        {
    127             pDataHdrDup->pvChecksum = RTMemDup(pDataHdr->pvChecksum, pDataHdr->cbChecksum);
    128             pDataHdrDup->cbChecksum = pDataHdr->cbChecksum;
     216            pListEntryDup->pvInfo= RTMemDup(pListEntry->pvInfo, pListEntry->cbInfo);
     217            pListEntryDup->cbInfo = pListEntry->cbInfo;
    129218        }
    130219    }
    131220
    132     return pDataHdrDup;
    133 }
    134 
    135 /**
    136  * Returns the size (in bytes) of the announced meta data.
    137  *
    138  * @returns Announced meta data size in bytes.
    139  * @param   pDataHdr            Data header struct to get announced meta data size for.
    140  */
    141 uint32_t SharedClipboardURIDataHdrGetMetaDataSize(PVBOXCLIPBOARDDATAHDR pDataHdr)
    142 {
    143     AssertPtrReturn(pDataHdr, 0);
    144 
    145     return pDataHdr->cbMeta;
    146 }
    147 
    148 /**
    149  * Initializes an URI data header struct.
    150  *
    151  * @returns VBox status code.
    152  * @param   pDataHdr            Data header struct to initialize.
    153  */
    154 int SharedClipboardURIDataHdrInit(PVBOXCLIPBOARDDATAHDR pDataHdr)
    155 {
    156     AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER);
    157 
    158     SharedClipboardURIDataHdrReset(pDataHdr);
     221    return pListEntryDup;
     222}
     223
     224/**
     225 * Initializes a VBOXCLIPBOARDListEntry structure.
     226 *
     227 * @param   pListEntry          VBOXCLIPBOARDListEntry structure to initialize.
     228 */
     229int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry)
     230{
     231    RT_BZERO(pListEntry, sizeof(VBOXCLIPBOARDLISTENTRY));
    159232
    160233    return VINF_SUCCESS;
     
    162235
    163236/**
    164  * Destroys an URI data header struct.
    165  *
    166  * @param   pDataHdr            Data header struct to destroy.
    167  */
    168 void SharedClipboardURIDataHdrDestroy(PVBOXCLIPBOARDDATAHDR pDataHdr)
    169 {
    170     if (!pDataHdr)
    171         return;
    172 
    173     LogFlowFuncEnter();
    174 
    175     if (pDataHdr->pvMetaFmt)
    176     {
    177         Assert(pDataHdr->cbMetaFmt);
    178 
    179         RTMemFree(pDataHdr->pvMetaFmt);
    180         pDataHdr->pvMetaFmt = NULL;
    181         pDataHdr->cbMetaFmt = 0;
    182     }
    183 
    184     if (pDataHdr->pvChecksum)
    185     {
    186         Assert(pDataHdr->cbChecksum);
    187 
    188         RTMemFree(pDataHdr->pvChecksum);
    189         pDataHdr->pvChecksum = NULL;
    190         pDataHdr->cbChecksum = 0;
    191     }
    192 }
    193 
    194 /**
    195  * Resets a VBOXCLIPBOARDDATAHDR structture.
    196  *
    197  * @returns VBox status code.
    198  * @param   pDataHdr            VBOXCLIPBOARDDATAHDR structture to reset.
    199  */
    200 void SharedClipboardURIDataHdrReset(PVBOXCLIPBOARDDATAHDR pDataHdr)
    201 {
    202     AssertPtrReturnVoid(pDataHdr);
    203 
    204     LogFlowFuncEnter();
    205 
    206     RT_BZERO(pDataHdr, sizeof(VBOXCLIPBOARDDATAHDR));
    207 }
    208 
    209 /**
    210  * Returns whether a given clipboard data header is valid or not.
     237 * Initializes a VBOXCLIPBOARDListEntry structure.
     238 *
     239 * @param   pListEntry          VBOXCLIPBOARDListEntry structure to destroy.
     240 */
     241void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry)
     242{
     243    if (pListEntry->pvInfo)
     244    {
     245        RTMemFree(pListEntry->pvInfo);
     246        pListEntry->pvInfo = NULL;
     247        pListEntry->cbInfo = 0;
     248    }
     249}
     250
     251/**
     252 * Returns whether a given clipboard data chunk is valid or not.
    211253 *
    212254 * @returns \c true if valid, \c false if not.
    213  * @param   pDataHdr            Clipboard data header to validate.
    214  */
    215 bool SharedClipboardURIDataHdrIsValid(PVBOXCLIPBOARDDATAHDR pDataHdr)
    216 {
    217     RT_NOREF(pDataHdr);
     255 * @param   pListEntry          Clipboard data chunk to validate.
     256 */
     257bool SharedClipboardURIListEntryIsValid(PVBOXCLIPBOARDLISTENTRY pListEntry)
     258{
     259    RT_NOREF(pListEntry);
     260
     261    /** @todo Verify checksum. */
     262
    218263    return true; /** @todo Implement this. */
    219264}
    220265
    221 /**
    222  * Creates (allocates) and initializes a VBOXCLIPBOARDDATACHUNK structure.
    223  *
    224  * @param   ppDirData           Where to return the created VBOXCLIPBOARDDATACHUNK structure on success.
    225  */
    226 int SharedClipboardURIDataChunkAlloc(PVBOXCLIPBOARDDATACHUNK *ppDataChunk)
    227 {
    228     PVBOXCLIPBOARDDATACHUNK pDataChunk = (PVBOXCLIPBOARDDATACHUNK)RTMemAlloc(sizeof(VBOXCLIPBOARDDATACHUNK));
    229     if (!pDataChunk)
    230         return VERR_NO_MEMORY;
    231 
    232     int rc = SharedClipboardURIDataChunkInit(pDataChunk);
    233     if (RT_SUCCESS(rc))
    234         *ppDataChunk = pDataChunk;
    235 
    236     return rc;
    237 }
    238 
    239 /**
    240  * Frees a VBOXCLIPBOARDDATACHUNK structure.
    241  *
    242  * @param   pDataChunk         VBOXCLIPBOARDDATACHUNK structure to free.
    243  */
    244 void SharedClipboardURIDataChunkFree(PVBOXCLIPBOARDDATACHUNK pDataChunk)
    245 {
    246     if (!pDataChunk)
    247         return;
    248 
    249     SharedClipboardURIDataChunkDestroy(pDataChunk);
    250     RTMemFree(pDataChunk);
    251 }
    252 
    253 /**
    254  * Duplicates (allocates) a VBOXCLIPBOARDDATACHUNK structure.
    255  *
    256  * @returns Duplicated VBOXCLIPBOARDDATACHUNK structure on success.
    257  * @param   pDataChunk          VBOXCLIPBOARDDATACHUNK to duplicate.
    258  */
    259 PVBOXCLIPBOARDDATACHUNK SharedClipboardURIDataChunkDup(PVBOXCLIPBOARDDATACHUNK pDataChunk)
    260 {
    261     AssertPtrReturn(pDataChunk, NULL);
    262 
    263     PVBOXCLIPBOARDDATACHUNK pDataChunkDup = (PVBOXCLIPBOARDDATACHUNK)RTMemAlloc(sizeof(VBOXCLIPBOARDDATACHUNK));
    264     if (pDataChunkDup)
    265     {
    266         *pDataChunkDup = *pDataChunk;
    267 
    268         if (pDataChunk->pvData)
    269         {
    270             pDataChunkDup->pvData = RTMemDup(pDataChunk->pvData, pDataChunk->cbData);
    271             pDataChunkDup->cbData = pDataChunk->cbData;
    272         }
    273 
    274         if (pDataChunk->pvChecksum)
    275         {
    276             pDataChunkDup->pvChecksum = RTMemDup(pDataChunk->pvChecksum, pDataChunk->cbChecksum);
    277             pDataChunkDup->cbChecksum = pDataChunk->cbChecksum;
    278         }
    279     }
    280 
    281     return pDataChunkDup;
    282 }
    283 
    284 /**
    285  * Initializes a VBOXCLIPBOARDDATACHUNK structure.
    286  *
    287  * @param   pDataChunk          VBOXCLIPBOARDDATACHUNK structure to initialize.
    288  */
    289 int SharedClipboardURIDataChunkInit(PVBOXCLIPBOARDDATACHUNK pDataChunk)
    290 {
    291     RT_BZERO(pDataChunk, sizeof(VBOXCLIPBOARDDATACHUNK));
    292 
    293     return VINF_SUCCESS;
    294 }
    295 
    296 /**
    297  * Initializes a VBOXCLIPBOARDDATACHUNK structure.
    298  *
    299  * @param   pDataChunk          VBOXCLIPBOARDDATACHUNK structure to destroy.
    300  */
    301 void SharedClipboardURIDataChunkDestroy(PVBOXCLIPBOARDDATACHUNK pDataChunk)
    302 {
    303     if (pDataChunk->pvData)
    304     {
    305         RTMemFree(pDataChunk->pvData);
    306         pDataChunk->pvData = NULL;
    307         pDataChunk->cbData = 0;
    308     }
    309 
    310     if (pDataChunk->pvChecksum)
    311     {
    312         RTMemFree(pDataChunk->pvChecksum);
    313         pDataChunk->pvChecksum = NULL;
    314         pDataChunk->cbChecksum = 0;
    315     }
    316 }
    317 
    318 /**
    319  * Returns whether a given clipboard data chunk is valid or not.
    320  *
    321  * @returns \c true if valid, \c false if not.
    322  * @param   pDataChunk          Clipboard data chunk to validate.
    323  */
    324 bool SharedClipboardURIDataChunkIsValid(PVBOXCLIPBOARDDATACHUNK pDataChunk)
    325 {
    326     RT_NOREF(pDataChunk);
    327 
    328     /** @todo Verify checksum. */
    329 
    330     return true; /** @todo Implement this. */
    331 }
    332 
     266#if 0
    333267/**
    334268 * Creates (allocates) and initializes a VBOXCLIPBOARDDIRDATA structure.
     
    514448 * @returns \c true if valid, \c false if not.
    515449 * @param   pFileHdr            Clipboard file header to validate.
    516  * @param   pDataHdr            Data header to use for validation.
    517  */
    518 bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDDATAHDR pDataHdr)
     450 * @param   pListHdr            Data header to use for validation.
     451 */
     452bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDLISTHDR pListHdr)
    519453{
    520454    if (   !pFileHdr->cbFilePath
     
    525459        return false;
    526460
    527     if (pFileHdr->cbSize > pDataHdr->cbTotal)
     461    if (pFileHdr->cbSize > pListHdr->cbTotalSize)
    528462        return false;
    529463
     
    587521 * @returns \c true if valid, \c false if not.
    588522 * @param   pFileData           Clipboard file data to validate.
    589  * @param   pDataHdr            Data header to use for validation.
    590  */
    591 bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDDATAHDR pDataHdr)
    592 {
    593     RT_NOREF(pFileData, pDataHdr);
     523 * @param   pListHdr            Data header to use for validation.
     524 */
     525bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDLISTHDR pListHdr)
     526{
     527    RT_NOREF(pFileData, pListHdr);
    594528    return true;
    595529}
     530#endif
    596531
    597532/**
     
    607542    LogFlowFuncEnter();
    608543
    609     pObjCtx->pObj = NULL;
     544    pObjCtx->uHandle  = SHAREDCLIPBOARDOBJHANDLE_INVALID;
     545    pObjCtx->pObjInfo = NULL;
    610546
    611547    return VINF_SUCCESS;
     
    623559    LogFlowFuncEnter();
    624560
    625     if (pObjCtx->pObj)
    626     {
    627         pObjCtx->pObj->Close();
    628         /* Note: Do *not* delete pObj here -- the associated URI list will do this. */
    629     }
    630 
    631     pObjCtx->pObj = NULL;
    632 }
    633 
    634 /**
    635  * Returns the URI object context's URI object.
    636  *
    637  * @returns Pointer to the URI object context's URI object.
    638  * @param   pObjCtx             URI object context to return the URI object for.
    639  */
    640 SharedClipboardURIObject *SharedClipboardURIObjCtxGetObj(PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
    641 {
    642     AssertPtrReturn(pObjCtx, NULL);
    643     return pObjCtx->pObj;
     561    pObjCtx->pObjInfo = NULL;
    644562}
    645563
     
    653571{
    654572    return (   pObjCtx
    655             && pObjCtx->pObj
    656             && pObjCtx->pObj->IsComplete() == false
    657             && pObjCtx->pObj->IsOpen());
     573            && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID
     574            && pObjCtx->pObjInfo);
    658575}
    659576
     
    686603    LogFlowFunc(("enmDir=%RU32, enmSource=%RU32\n", pTransfer->State.enmDir, pTransfer->State.enmSource));
    687604
    688     pTransfer->State.pHeader = NULL;
    689     pTransfer->State.pMeta   = NULL;
    690     pTransfer->pArea         = NULL; /* Will be created later if needed. */
     605    pTransfer->pArea = NULL; /* Will be created later if needed. */
    691606
    692607    pTransfer->Thread.hThread    = NIL_RTTHREAD;
    693608    pTransfer->Thread.fCancelled = false;
    694609    pTransfer->Thread.fStarted   = false;
     610    pTransfer->Thread.fStop      = false;
    695611
    696612    pTransfer->pvUser = NULL;
     
    743659        return rc;
    744660
    745     SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);
    746     SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);
    747 
    748661    if (pTransfer->pURIList)
    749662    {
     
    760673    SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
    761674
    762     RTMemFree(pTransfer);
    763     pTransfer = NULL;
    764 
    765675    LogFlowFuncLeave();
    766 
    767676    return VINF_SUCCESS;
     677}
     678
     679int SharedClipboardURITransferOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer)
     680{
     681    int rc = VINF_SUCCESS;
     682
     683    if (pTransfer->ProviderIface.pfnTransferOpen)
     684        rc = pTransfer->ProviderIface.pfnTransferOpen(&pTransfer->ProviderCtx);
     685
     686    LogFlowFuncLeaveRC(rc);
     687    return rc;
     688}
     689
     690int SharedClipboardURITransferClose(PSHAREDCLIPBOARDURITRANSFER pTransfer)
     691{
     692    int rc = VINF_SUCCESS;
     693
     694    if (pTransfer->ProviderIface.pfnTransferClose)
     695        rc = pTransfer->ProviderIface.pfnTransferClose(&pTransfer->ProviderCtx);
     696
     697    LogFlowFuncLeaveRC(rc);
     698    return rc;
     699}
     700
     701int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTHDR pListHdr,
     702                                       PVBOXCLIPBOARDLISTHANDLE phList)
     703{
     704    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     705    AssertPtrReturn(pListHdr,  VERR_INVALID_POINTER);
     706    /* phList is optional. */
     707
     708    int rc = VINF_SUCCESS;
     709
     710    VBOXCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
     711
     712    if (pTransfer->ProviderIface.pfnListOpen)
     713        rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pListHdr, &hList);
     714
     715    if (RT_SUCCESS(rc))
     716    {
     717        AssertPtr(pTransfer->ProviderIface.pfnListHdrRead);
     718        rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pListHdr);
     719    }
     720
     721    if (RT_SUCCESS(rc))
     722    {
     723        if (phList)
     724            *phList = hList;
     725    }
     726    else if (pTransfer->ProviderIface.pfnListClose)
     727    {
     728        int rc2 = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
     729        AssertRC(rc2);
     730    }
     731
     732    LogFlowFuncLeaveRC(rc);
     733    return rc;
     734}
     735
     736int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
     737{
     738    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     739
     740    int rc = VINF_SUCCESS;
     741
     742    if (pTransfer->ProviderIface.pfnListClose)
     743        rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
     744
     745    LogFlowFuncLeaveRC(rc);
     746    return rc;
     747}
     748
     749int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
     750                                       PVBOXCLIPBOARDLISTENTRY pEntry)
     751{
     752    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     753
     754    int rc = VINF_SUCCESS;
     755
     756    if (pTransfer->ProviderIface.pfnListEntryRead)
     757        rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
     758
     759    LogFlowFuncLeaveRC(rc);
     760    return rc;
     761}
     762
     763int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
     764                                        PVBOXCLIPBOARDLISTENTRY pEntry)
     765{
     766    int rc = VINF_SUCCESS;
     767
     768    if (pTransfer->ProviderIface.pfnListEntryWrite)
     769        rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry);
     770
     771    LogFlowFuncLeaveRC(rc);
     772    return rc;
     773}
     774
     775bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
     776{
     777    RT_NOREF(pTransfer, hList);
     778
     779    return true; /** @todo Implement this. */
    768780}
    769781
     
    791803        SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    792804        pTransfer->Callbacks.pfnTransferPrepare(&callbackData);
    793     }
    794 
    795     if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
    796     {
    797         if (pTransfer->ProviderIface.pfnPrepare)
    798             rc = pTransfer->ProviderIface.pfnPrepare(&pTransfer->ProviderCtx);
    799     #if 0
    800         rc = pTransfer->pURIList->SetFromURIData(SharedClipboardMetaDataRaw(pMeta),
    801                                                  SharedClipboardMetaDataGetUsed(pMeta),
    802                                                  SHAREDCLIPBOARDURILIST_FLAGS_NONE);
    803         /** @todo Verify pvMetaFmt. */
    804     #endif
    805 
    806         sharedClipboardURITransferMetaDataDestroyInternal(pTransfer);
    807     }
    808     else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)
    809     {
    810         if (   pTransfer->State.pMeta
    811             && pTransfer->pURIList)
    812         {
    813             const PSHAREDCLIPBOARDMETADATA pMeta = pTransfer->State.pMeta;
    814 
    815             rc = pTransfer->pURIList->AppendURIPathsFromList((char *)SharedClipboardMetaDataRaw(pMeta),
    816                                                              SharedClipboardMetaDataGetUsed(pMeta),
    817                                                              SHAREDCLIPBOARDURILIST_FLAGS_KEEP_OPEN);
    818             if (RT_SUCCESS(rc))
    819             {
    820                 PVBOXCLIPBOARDDATAHDR pHeader;
    821                 rc = SharedClipboardURIDataHdrAlloc(&pHeader);
    822                 if (RT_SUCCESS(rc))
    823                 {
    824                     /* The total size also contains the size of the meta data. */
    825                     uint64_t cbTotal  = pMeta->cbUsed;
    826                              cbTotal += pTransfer->pURIList->GetTotalBytes();
    827 
    828                     pHeader->cbTotal  = cbTotal;
    829                     pHeader->cbMeta   = (uint32_t)SharedClipboardMetaDataGetUsed(pMeta);
    830                     pHeader->cObjects = pTransfer->pURIList->GetTotalCount();
    831 
    832                     SharedClipboardURIDataHdrDestroy(pTransfer->State.pHeader);
    833 
    834                     if (RT_SUCCESS(rc))
    835                     {
    836                         LogFlowFunc(("Writing cbTotal=%RU64, cbMeta=%RU32, cObj=%RU64\n",
    837                                      pHeader->cbTotal, pHeader->cbMeta, pHeader->cObjects));
    838 
    839                         pTransfer->State.pHeader = pHeader;
    840                     }
    841                     else
    842                         SharedClipboardURIDataHdrFree(pHeader);
    843                 }
    844             }
    845         }
    846         else
    847             rc = VERR_WRONG_ORDER;
    848     }
    849     else
    850     {
    851         rc = VERR_NOT_IMPLEMENTED;
    852         AssertFailed();
    853805    }
    854806
     
    1000952
    1001953/**
    1002  * Runs (starts) an URI transfer, either in synchronous or asynchronous (threaded) mode.
     954 * Runs (starts) an URI transfer thread.
    1003955 *
    1004956 * @returns VBox status code.
    1005957 * @param   pTransfer           URI clipboard transfer to run.
    1006  * @param   fAsync              Whether to run the transfer synchronously or asynchronously.
    1007  */
    1008 int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, bool fAsync)
     958 * @param   pfnThreadFunc       Pointer to thread function to use.
     959 * @param   pvUser              Pointer to user-provided data.
     960 */
     961int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
    1009962{
    1010963    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1011964
    1012     int rc;
    1013 
    1014     LogFlowFunc(("fAsync=%RTbool\n", fAsync));
    1015 
    1016     if (fAsync)
    1017     {
    1018         rc = sharedClipboardURITransferThreadCreate(pTransfer);
    1019     }
    1020     else
    1021     {
    1022         if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
    1023             rc = SharedClipboardURITransferRead(pTransfer);
    1024         else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)
    1025             rc = SharedClipboardURITransferWrite(pTransfer);
    1026         else
    1027             rc = VERR_NOT_IMPLEMENTED;
    1028     }
     965    AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
     966                    ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
     967
     968    int rc = sharedClipboardURITransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
    1029969
    1030970    LogFlowFuncLeaveRC(rc);
     
    1053993    SET_CALLBACK(pfnTransferPrepare);
    1054994    SET_CALLBACK(pfnTransferStarted);
    1055     SET_CALLBACK(pfnDataHeaderComplete);
    1056     SET_CALLBACK(pfnDataComplete);
     995    SET_CALLBACK(pfnListHeaderComplete);
     996    SET_CALLBACK(pfnListEntryComplete);
    1057997    SET_CALLBACK(pfnTransferCanceled);
    1058998    SET_CALLBACK(pfnTransferError);
     
    12091149 * @returns VBox status code.
    12101150 * @param   pTransfer           URI clipboard transfer to create thread for.
    1211  */
    1212 static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer)
     1151 * @param   pfnThreadFunc       Thread function to use for this transfer.
     1152 * @param   pvUser              Pointer to user-provided data.
     1153 */
     1154static int sharedClipboardURITransferThreadCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
     1155
    12131156{
    12141157    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    12151158
    1216     PFNRTTHREAD pfnRTThread = NULL;
    1217 
    1218     if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
    1219         pfnRTThread = sharedClipboardURITransferReadThread;
    1220     else if (pTransfer->State.enmDir == SHAREDCLIPBOARDURITRANSFERDIR_WRITE)
    1221         pfnRTThread = sharedClipboardURITransferWriteThread;
    1222 
    1223     AssertPtrReturn(pfnRTThread, VERR_NOT_SUPPORTED);
    1224 
    12251159    /* Spawn a worker thread, so that we don't block the window thread for too long. */
    1226     int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnRTThread,
    1227                             pTransfer /* pvUser */, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
     1160    int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc,
     1161                            pvUser, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
    12281162                            "shclp");
    12291163    if (RT_SUCCESS(rc))
     
    12321166        AssertRC(rc2);
    12331167
    1234         if (!pTransfer->Thread.fStarted) /* Did the thread fail to start? */
     1168        if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */
     1169        {
     1170            pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
     1171        }
     1172        else
    12351173            rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
    12361174    }
     
    12541192        return VINF_SUCCESS;
    12551193
     1194    LogFlowFuncEnter();
     1195
     1196    /* Set stop indicator. */
     1197    pTransfer->Thread.fStop = true;
     1198
    12561199    int rcThread = VERR_WRONG_ORDER;
    12571200    int rc = RTThreadWait(pTransfer->Thread.hThread, uTimeoutMs, &rcThread);
     
    12631206
    12641207/**
    1265  * Reads all URI objects using the connected provider.
    1266  *
    1267  * @returns VBox status code.
    1268  * @param   pTransfer           Transfer to read objects for.
    1269  */
    1270 int SharedClipboardURITransferRead(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1271 {
    1272     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1273 
    1274     LogFlowFuncEnter();
    1275 
    1276     AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
    1277                     ("Read transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
    1278 
    1279     pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
    1280 
    1281     if (pTransfer->Callbacks.pfnTransferStarted)
    1282     {
    1283         SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1284         pTransfer->Callbacks.pfnTransferStarted(&callbackData);
    1285     }
    1286 
    1287     int rc = SharedClipboardURITransferMetaDataRead(pTransfer, NULL /* pcbRead */);
    1288     if (RT_SUCCESS(rc))
    1289     {
    1290         rc = SharedClipboardURITransferReadObjects(pTransfer);
    1291         if (RT_SUCCESS(rc))
    1292         {
    1293             if (pTransfer->Callbacks.pfnTransferComplete)
    1294             {
    1295                 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1296                 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);
    1297             }
    1298         }
    1299     }
    1300 
    1301     if (RT_FAILURE(rc))
    1302     {
    1303         if (pTransfer->Callbacks.pfnTransferError)
    1304         {
    1305             SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1306             pTransfer->Callbacks.pfnTransferError(&callbackData, rc);
    1307         }
    1308     }
    1309 
    1310     pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
    1311 
    1312     LogFlowFuncLeaveRC(rc);
    1313     return rc;
    1314 }
    1315 
    1316 int SharedClipboardURITransferReadDir(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
    1317 {
    1318     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1319 
    1320     RT_NOREF(pObjCtx);
    1321 
    1322     LogFlowFuncEnter();
    1323 
    1324     PVBOXCLIPBOARDDIRDATA pDirData;
    1325     AssertPtr(pTransfer->ProviderIface.pfnReadDirectory);
    1326     int rc = pTransfer->ProviderIface.pfnReadDirectory(&pTransfer->ProviderCtx, &pDirData);
    1327     if (RT_SUCCESS(rc))
    1328     {
    1329         SharedClipboardURIDirDataFree(pDirData);
    1330     }
    1331 
    1332     LogFlowFuncLeaveRC(rc);
    1333     return rc;
    1334 }
    1335 
    1336 int SharedClipboardURITransferReadFile(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
    1337 {
    1338     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1339 
    1340     RT_NOREF(pObjCtx);
    1341 
    1342     LogFlowFuncEnter();
    1343 
    1344     PVBOXCLIPBOARDFILEHDR pFileHdr;
    1345     AssertPtr(pTransfer->ProviderIface.pfnReadFileHdr);
    1346     int rc = pTransfer->ProviderIface.pfnReadFileHdr(&pTransfer->ProviderCtx, &pFileHdr);
    1347     if (RT_SUCCESS(rc))
    1348     {
    1349         uint64_t cbToRead = pFileHdr->cbSize;
    1350         uint32_t cbRead;
    1351 
    1352         uint8_t  pvBuf[_64K]; /** @todo Improve. */
    1353         uint32_t cbBuf = _64K;
    1354 
    1355         while (cbToRead)
    1356         {
    1357             AssertPtr(pTransfer->ProviderIface.pfnReadFileData);
    1358             rc = pTransfer->ProviderIface.pfnReadFileData(&pTransfer->ProviderCtx,
    1359                                                           pvBuf, cbBuf, 0 /* fFlags */, &cbRead);
    1360             if (RT_FAILURE(rc))
    1361                 break;
    1362 
    1363             /** @todo Validate data block checksum. */
    1364 
    1365             Assert(cbToRead >= cbRead);
    1366             cbToRead -= cbRead;
    1367         }
    1368 
    1369         SharedClipboardURIFileHdrFree(pFileHdr);
    1370     }
    1371 
    1372     LogFlowFuncLeaveRC(rc);
    1373     return rc;
    1374 }
    1375 
    1376 int SharedClipboardURITransferReadObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, PSHAREDCLIPBOARDCLIENTURIOBJCTX pObjCtx)
    1377 {
    1378     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1379 
    1380     RT_NOREF(pObjCtx);
    1381 
    1382     LogFlowFuncEnter();
    1383 
    1384     PVBOXCLIPBOARDOBJHDR pObjHdr;
    1385     AssertPtr(pTransfer->ProviderIface.pfnReadObjHdr);
    1386     int rc = pTransfer->ProviderIface.pfnReadObjHdr(&pTransfer->ProviderCtx, &pObjHdr);
    1387     if (RT_SUCCESS(rc))
    1388     {
    1389         switch (pObjHdr->enmType)
    1390         {
    1391 #if 0
    1392             case Dir:
    1393             {
    1394                 SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;
    1395                 rc = SharedClipboardURITransferReadDir(pTransfer, &objCtx);
    1396                 break;
    1397             }
    1398 
    1399             case File:
    1400             {
    1401                 SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;
    1402                 rc = SharedClipboardURITransferReadFile(pTransfer, &objCtx);
    1403                 break;
    1404             }
    1405 #endif
    1406             default:
    1407                 /** @todo Skip -- how? */
    1408                 break;
    1409         }
    1410     }
    1411 
    1412     LogFlowFuncLeaveRC(rc);
    1413     return rc;
    1414 }
    1415 
    1416 /**
    1417  * Reads all URI objects using the connected provider.
    1418  *
    1419  * @returns VBox status code.
    1420  * @param   pTransfer           Transfer to read objects for.
    1421  */
    1422 int SharedClipboardURITransferReadObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1423 {
    1424     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1425 
    1426     LogFlowFuncEnter();
    1427 
    1428     const PVBOXCLIPBOARDDATAHDR pHdr = pTransfer->State.pHeader;
    1429     AssertPtrReturn(pHdr, VERR_WRONG_ORDER);
    1430 
    1431     int rc = VINF_SUCCESS;
    1432 
    1433     for (uint64_t i = 0; i < pHdr->cObjects; i++)
    1434     {
    1435         SHAREDCLIPBOARDCLIENTURIOBJCTX objCtx;
    1436         rc = SharedClipboardURITransferReadObject(pTransfer, &objCtx);
    1437         if (RT_FAILURE(rc))
    1438             break;
    1439     }
    1440 
    1441     LogFlowFuncLeaveRC(rc);
    1442     return rc;
    1443 }
    1444 
    1445 /**
    1446  * Thread for transferring (reading) URI objects from source to the target.
    1447  * For target to source transfers we utilize our own IDataObject / IStream implementations.
    1448  *
    1449  * @returns VBox status code.
    1450  * @param   hThread             Thread handle.
    1451  * @param   pvUser              User arguments; is PSHAREDCLIPBOARDURITRANSFER.
    1452  */
    1453 static int sharedClipboardURITransferReadThread(RTTHREAD hThread, void *pvUser)
    1454 {
    1455     AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
    1456 
    1457     LogFlowFuncEnter();
    1458 
    1459     /* At the moment we only support one transfer at a time. */
    1460     PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;
    1461     AssertPtr(pTransfer);
    1462 
    1463     int rc = VINF_SUCCESS;
    1464 
    1465     if (RT_SUCCESS(rc))
    1466         pTransfer->Thread.fStarted = true;
    1467 
    1468     int rc2 = RTThreadUserSignal(hThread);
    1469     const bool fSignalled = RT_SUCCESS(rc2);
    1470 
    1471     if (RT_SUCCESS(rc))
    1472         rc = SharedClipboardURITransferRead(pTransfer);
    1473 
    1474     if (!fSignalled)
    1475     {
    1476         rc2 = RTThreadUserSignal(hThread);
    1477         AssertRC(rc2);
    1478     }
    1479 
    1480     LogFlowFuncLeaveRC(rc);
    1481     return rc;
    1482 }
    1483 
    1484 /**
    1485  * Creates the internal meta data buffer of an URI clipboard transfer.
    1486  *
    1487  * @returns VBox status code.
    1488  * @param   pTransfer           URI clipboard transfer to create internal meta data for.
    1489  * @param   cbSize              Size (in bytes) of meta data buffer to create. An existing meta data buffer
    1490  *                              will be resized accordingly.
    1491  */
    1492 static int sharedClipboardURITransferMetaDataCreateInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t cbSize)
    1493 {
    1494     int rc;
    1495 
    1496     LogFlowFuncEnter();
    1497 
    1498     if (pTransfer->State.pMeta == NULL)
    1499     {
    1500         pTransfer->State.pMeta = (PSHAREDCLIPBOARDMETADATA)RTMemAlloc(sizeof(SHAREDCLIPBOARDMETADATA));
    1501         if (pTransfer->State.pMeta)
    1502         {
    1503             /** @todo Make meta data format handling more flexible. */
    1504             rc = SharedClipboardMetaDataInit(pTransfer->State.pMeta, SHAREDCLIPBOARDMETADATAFMT_URI_LIST);
    1505         }
    1506         else
    1507             rc = VERR_NO_MEMORY;
    1508     }
    1509     else
    1510         rc = SharedClipboardMetaDataResize(pTransfer->State.pMeta, cbSize);
    1511 
    1512     LogFlowFuncLeaveRC(rc);
    1513     return rc;
    1514 }
    1515 
    1516 /**
    1517  * Destroys a clipboard URI transfer's internal meta data.
    1518  *
    1519  * @param   pTransfer           URI clipboard transfer to destroy internal meta data of.
    1520  */
    1521 static void sharedClipboardURITransferMetaDataDestroyInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1522 {
    1523     if (!pTransfer->State.pMeta)
    1524         return;
    1525 
    1526     LogFlowFuncEnter();
    1527 
    1528     /* We're done processing the meta data, so just destroy it. */
    1529     SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);
    1530 
    1531     RTMemFree(pTransfer->State.pMeta);
    1532     pTransfer->State.pMeta = NULL;
    1533 }
    1534 
    1535 /**
    1536  * Adds meta data for a clipboard URI transfer, internal version.
    1537  *
    1538  * @returns VBox status code.
    1539  * @param   pTransfer           URI clipboard transfer to set meta data for.
    1540  * @param   pvMeta              Pointer to meta data buffer.
    1541  * @param   cbMeta              Size (in bytes) of meta data buffer.
    1542  */
    1543 static int sharedClipboardURITransferMetaDataAddInternal(PSHAREDCLIPBOARDURITRANSFER pTransfer,
    1544                                                          const void *pvMeta, uint32_t cbMeta)
    1545 {
    1546     LogFlowFunc(("pvMeta=%p, cbMeta=%RU32\n", pvMeta, cbMeta));
    1547 
    1548     AssertPtrReturn(pTransfer->State.pHeader, VERR_WRONG_ORDER); /* Header must be present. */
    1549     AssertReturn(SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta) + cbMeta <= pTransfer->State.pHeader->cbMeta,
    1550                  VERR_BUFFER_OVERFLOW);
    1551 
    1552     int rc = SharedClipboardMetaDataAdd(pTransfer->State.pMeta, pvMeta, cbMeta);
    1553 
    1554     LogFlowFuncLeaveRC(rc);
    1555     return rc;
    1556 }
    1557 
    1558 /**
    1559  * Adds meta data for a clipboard URI transfer.
    1560  *
    1561  * @returns VBox status code.
    1562  * @param   pTransfer           URI clipboard transfer to set meta data for.
    1563  * @param   pvMeta              Pointer to meta data buffer.
    1564  * @param   cbMeta              Size (in bytes) of meta data buffer.
    1565  */
    1566 int SharedClipboardURITransferMetaDataAdd(PSHAREDCLIPBOARDURITRANSFER pTransfer, const void *pvMeta, uint32_t cbMeta)
    1567 {
    1568     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1569 
    1570     LogFlowFuncEnter();
    1571 
    1572     int rc = sharedClipboardURITransferMetaDataCreateInternal(pTransfer, cbMeta);
    1573     if (RT_SUCCESS(rc))
    1574         rc = sharedClipboardURITransferMetaDataAddInternal(pTransfer, pvMeta, cbMeta);
    1575 
    1576     LogFlowFuncLeaveRC(rc);
    1577     return rc;
    1578 }
    1579 
    1580 /**
    1581  * Returns whether the meta data is in a complete state (e.g. completetely read / written) or not.
    1582  *
    1583  * @returns \c true if meta data is complete, \c false if not.
    1584  * @param   pTransfer           URI clipboard transfer to get completion status of meta data for.
    1585  */
    1586 bool SharedClipboardURITransferMetaDataIsComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1587 {
    1588     AssertPtrReturn(pTransfer->State.pHeader, false);
    1589     AssertPtrReturn(pTransfer->State.pMeta,   false);
    1590 
    1591     return SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta) == pTransfer->State.pHeader->cbMeta;
    1592 }
    1593 
    1594 /**
    1595  * Reads meta for a clipboard URI transfer.
    1596  *
    1597  * @returns VBox status code.
    1598  * @param   pTransfer           URI clipboard transfer to read meta data for.
    1599  * @param   pcbRead             How much meta data (in bytes) was read on success.
    1600  */
    1601 int SharedClipboardURITransferMetaDataRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbRead)
    1602 {
    1603     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1604     /* pcbRead is optional. */
    1605 
    1606     LogFlowFuncEnter();
    1607 
    1608     /* Destroy any former meta data. */
    1609     SharedClipboardMetaDataDestroy(pTransfer->State.pMeta);
    1610 
    1611     uint32_t cbReadTotal = 0;
    1612 
    1613     AssertPtr(pTransfer->ProviderIface.pfnReadDataHdr);
    1614     int rc = pTransfer->ProviderIface.pfnReadDataHdr(&pTransfer->ProviderCtx, &pTransfer->State.pHeader);
    1615     if (RT_SUCCESS(rc))
    1616     {
    1617         if (pTransfer->Callbacks.pfnDataHeaderComplete)
    1618         {
    1619             SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1620             pTransfer->Callbacks.pfnDataHeaderComplete(&callbackData);
    1621         }
    1622 
    1623         uint32_t cbMetaToRead = pTransfer->State.pHeader->cbMeta;
    1624 
    1625         uint32_t cbMeta = cbMetaToRead;
    1626         void    *pvMeta = RTMemAlloc(cbMetaToRead);
    1627 
    1628         if (pvMeta)
    1629         {
    1630             AssertPtr(pTransfer->State.pHeader);
    1631             while (cbMetaToRead)
    1632             {
    1633                 const uint32_t cbToRead = RT_MIN(cbMetaToRead, cbMeta);
    1634 
    1635                 uint32_t cbMetaRead;
    1636                 AssertPtr(pTransfer->ProviderIface.pfnReadDataChunk);
    1637                 rc = pTransfer->ProviderIface.pfnReadDataChunk(&pTransfer->ProviderCtx,
    1638                                                                pTransfer->State.pHeader, pvMeta, cbToRead,
    1639                                                                0 /* fFlags */, &cbMetaRead);
    1640                 if (RT_SUCCESS(rc))
    1641                     rc = SharedClipboardURITransferMetaDataAdd(pTransfer, pvMeta, cbMetaRead);
    1642 
    1643                 if (RT_FAILURE(rc))
    1644                     break;
    1645 
    1646                 Assert(cbMetaToRead >= cbMetaRead);
    1647                 cbMetaToRead -= cbMetaRead;
    1648 
    1649                 cbReadTotal += cbMetaRead;
    1650             }
    1651 
    1652             RTMemFree(pvMeta);
    1653 
    1654             if (RT_SUCCESS(rc))
    1655             {
    1656                 rc = pTransfer->pURIList->SetFromURIData(SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta),
    1657                                                          SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta),
    1658                                                          SHAREDCLIPBOARDURILIST_FLAGS_NONE);
    1659                 if (   RT_SUCCESS(rc)
    1660                     && pTransfer->Callbacks.pfnDataComplete)
    1661                 {
    1662                     SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1663                     pTransfer->Callbacks.pfnDataComplete(&callbackData);
    1664                 }
    1665 
    1666                 if (pcbRead)
    1667                     *pcbRead = cbReadTotal;
    1668             }
    1669         }
    1670         else
    1671             rc = VERR_NO_MEMORY;
    1672     }
    1673 
    1674     LogFlowFuncLeaveRC(rc);
    1675     return rc;
    1676 }
    1677 
    1678 /**
    1679  * Writes the actual meta data.
    1680  *
    1681  * @returns IPRT status code.
    1682  * @param   pTransfer           Transfer to write meta data for.
    1683  * @param   pcbWritten          How much bytes were written on success. Optional.
    1684  */
    1685 int SharedClipboardURITransferMetaDataWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint32_t *pcbWritten)
    1686 {
    1687     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1688     /* pcbWritten is optional. */
    1689 
    1690     LogFlowFuncEnter();
    1691 
    1692     AssertPtrReturn(pTransfer->State.pHeader, VERR_WRONG_ORDER);
    1693     AssertPtrReturn(pTransfer->State.pMeta,   VERR_WRONG_ORDER);
    1694 
    1695     uint32_t cbWrittenTotal = 0;
    1696 
    1697     AssertPtr(pTransfer->ProviderIface.pfnWriteDataHdr);
    1698     int rc = pTransfer->ProviderIface.pfnWriteDataHdr(&pTransfer->ProviderCtx, pTransfer->State.pHeader);
    1699     if (RT_SUCCESS(rc))
    1700     {
    1701         /* Sanity. */
    1702         Assert(pTransfer->State.pHeader->cbMeta == pTransfer->State.pMeta->cbUsed);
    1703 
    1704         uint32_t cbMetaToWrite = pTransfer->State.pHeader->cbMeta;
    1705         while (cbMetaToWrite)
    1706         {
    1707             uint32_t cbMetaWritten;
    1708             AssertPtr(pTransfer->ProviderIface.pfnWriteDataChunk);
    1709             rc = pTransfer->ProviderIface.pfnWriteDataChunk(&pTransfer->ProviderCtx, pTransfer->State.pHeader,
    1710                                                             (uint8_t *)pTransfer->State.pMeta->pvMeta + cbWrittenTotal,
    1711                                                             cbMetaToWrite, 0 /* fFlags */, &cbMetaWritten);
    1712             if (RT_FAILURE(rc))
    1713                 break;
    1714 
    1715             Assert(cbMetaToWrite >= cbMetaWritten);
    1716             cbMetaToWrite -= cbMetaWritten;
    1717 
    1718             cbWrittenTotal += cbMetaWritten;
    1719             Assert(cbWrittenTotal <= pTransfer->State.pHeader->cbMeta);
    1720         }
    1721 
    1722         if (RT_SUCCESS(rc))
    1723         {
    1724             if (pcbWritten)
    1725                 *pcbWritten = cbWrittenTotal;
    1726 
    1727             if (pTransfer->Callbacks.pfnDataComplete)
    1728             {
    1729                 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1730                 pTransfer->Callbacks.pfnDataComplete(&callbackData);
    1731             }
    1732         }
    1733     }
    1734 
    1735     LogFlowFuncLeaveRC(rc);
    1736     return rc;
    1737 }
    1738 
    1739 /**
    1740  * Writes all URI objects using the connected provider.
    1741  *
    1742  * @returns VBox status code.
    1743  * @param   pTransfer           Transfer to write objects for.
    1744  */
    1745 int SharedClipboardURITransferWriteObjects(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1746 {
    1747     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1748 
    1749     LogFlowFuncEnter();
    1750 
    1751     int rc = VINF_SUCCESS;
    1752 
    1753     AssertPtrReturn(pTransfer->pURIList, VERR_WRONG_ORDER);
    1754 
    1755     while (!pTransfer->pURIList->IsEmpty())
    1756     {
    1757         SharedClipboardURIObject *pObj = pTransfer->pURIList->First();
    1758         AssertPtrBreakStmt(pObj, rc = VERR_INVALID_POINTER);
    1759 
    1760         switch (pObj->GetType())
    1761         {
    1762             case SharedClipboardURIObject::Type_Directory:
    1763             {
    1764                 RTCString strPath = pObj->GetDestPathAbs();
    1765                 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",
    1766                              strPath.c_str(), strPath.length(), pObj->GetMode()));
    1767 
    1768                 VBOXCLIPBOARDDIRDATA dirData;
    1769                 SharedClipboardURIDirDataInit(&dirData);
    1770 
    1771                 dirData.pszPath = RTStrDup(strPath.c_str());
    1772                 dirData.cbPath  = (uint32_t)strlen(dirData.pszPath);
    1773 
    1774                 AssertPtr(pTransfer->ProviderIface.pfnWriteDirectory);
    1775                 rc = pTransfer->ProviderIface.pfnWriteDirectory(&pTransfer->ProviderCtx, &dirData);
    1776 
    1777                 SharedClipboardURIDirDataDestroy(&dirData);
    1778                 break;
    1779             }
    1780 
    1781             case SharedClipboardURIObject::Type_File:
    1782             {
    1783                 AssertBreakStmt(pObj->IsOpen(), rc = VERR_INVALID_STATE);
    1784 
    1785                 RTCString strPath = pObj->GetDestPathAbs();
    1786 
    1787                 LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),
    1788                              pObj->GetSize(), pObj->GetMode()));
    1789 
    1790                 VBOXCLIPBOARDFILEHDR fileHdr;
    1791                 SharedClipboardURIFileHdrInit(&fileHdr);
    1792 
    1793                 fileHdr.pszFilePath = RTStrDup(strPath.c_str());
    1794                 fileHdr.cbFilePath  = (uint32_t)strlen(fileHdr.pszFilePath);
    1795                 fileHdr.cbSize      = pObj->GetSize();
    1796                 fileHdr.fFlags      = 0;
    1797                 fileHdr.fMode       = pObj->GetMode();
    1798 
    1799                 AssertPtr(pTransfer->ProviderIface.pfnWriteFileHdr);
    1800                 rc = pTransfer->ProviderIface.pfnWriteFileHdr(&pTransfer->ProviderCtx, &fileHdr);
    1801                 SharedClipboardURIFileHdrDestroy(&fileHdr);
    1802 
    1803                 if (RT_FAILURE(rc))
    1804                     break;
    1805 
    1806                 uint32_t cbData = _64K; /** @todo Improve. */
    1807                 void    *pvData = RTMemAlloc(cbData);
    1808 
    1809                 AssertPtrBreakStmt(pvData, rc = VERR_NO_MEMORY);
    1810 
    1811                 while (!pObj->IsComplete())
    1812                 {
    1813                     uint32_t cbRead;
    1814                     rc = pObj->Read(pvData, cbData, &cbRead);
    1815                     if (RT_SUCCESS(rc))
    1816                     {
    1817                         uint32_t cbToRead = cbRead;
    1818                         AssertPtr(pTransfer->ProviderIface.pfnWriteFileData);
    1819                         rc = pTransfer->ProviderIface.pfnWriteFileData(&pTransfer->ProviderCtx,
    1820                                                                        pvData, cbToRead, 0 /* fFlags */, &cbRead);
    1821                     }
    1822 
    1823                     if (RT_FAILURE(rc))
    1824                         break;
    1825                 }
    1826 
    1827                 RTMemFree(pvData);
    1828                 pvData = NULL;
    1829                 break;
    1830             }
    1831 
    1832             default:
    1833                 AssertFailed();
    1834                 break;
    1835         }
    1836 
    1837         if (RT_FAILURE(rc))
    1838             break;
    1839 
    1840         /* Only remove current object on success. */
    1841         pTransfer->pURIList->RemoveFirst();
    1842     }
    1843 
    1844     LogFlowFuncLeaveRC(rc);
    1845     return rc;
    1846 }
    1847 
    1848 /**
    1849  * Thread for transferring (writing) URI objects from source to the target.
    1850  * For target to source transfers we utilize our own IDataObject / IStream implementations.
    1851  *
    1852  * @returns VBox status code.
    1853  * @param   hThread             Thread handle.
    1854  * @param   pvUser              User arguments; is PSHAREDCLIPBOARDURITRANSFER.
    1855  */
    1856 static int sharedClipboardURITransferWriteThread(RTTHREAD hThread, void *pvUser)
    1857 {
    1858     AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
    1859 
    1860     LogFlowFuncEnter();
    1861 
    1862     /* At the moment we only support one transfer at a time. */
    1863     PSHAREDCLIPBOARDURITRANSFER pTransfer = (PSHAREDCLIPBOARDURITRANSFER)pvUser;
    1864 
    1865     int rc = VINF_SUCCESS;
    1866 
    1867     if (RT_SUCCESS(rc))
    1868         pTransfer->Thread.fStarted = true;
    1869 
    1870     int rc2 = RTThreadUserSignal(hThread);
    1871     const bool fSignalled = RT_SUCCESS(rc2);
    1872 
    1873     if (RT_SUCCESS(rc))
    1874         rc = SharedClipboardURITransferWrite(pTransfer);
    1875 
    1876     if (!fSignalled)
    1877     {
    1878         rc2 = RTThreadUserSignal(hThread);
    1879         AssertRC(rc2);
    1880     }
    1881 
    1882     LogFlowFuncLeaveRC(rc);
    1883     return rc;
    1884 }
    1885 
    1886 /**
    1887  * Main function to write a clipboard URI transfer.
    1888  *
    1889  * @returns VBox status code.
    1890  * @param   pURI                URI clipboard context to write.
    1891  */
    1892 int SharedClipboardURITransferWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    1893 {
    1894     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    1895 
    1896     LogFlowFuncEnter();
    1897 
    1898     AssertMsgReturn(pTransfer->State.enmStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
    1899                     ("Write transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
    1900 
    1901     pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING;
    1902 
    1903     if (pTransfer->Callbacks.pfnTransferStarted)
    1904     {
    1905         SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1906         pTransfer->Callbacks.pfnTransferStarted(&callbackData);
    1907     }
    1908 
    1909     int rc = SharedClipboardURITransferMetaDataWrite(pTransfer, NULL /* pcbWritten */);
    1910     if (RT_SUCCESS(rc))
    1911     {
    1912         rc = SharedClipboardURITransferWriteObjects(pTransfer);
    1913         if (RT_SUCCESS(rc))
    1914         {
    1915             if (pTransfer->Callbacks.pfnTransferComplete)
    1916             {
    1917                 SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1918                 pTransfer->Callbacks.pfnTransferComplete(&callbackData, rc);
    1919             }
    1920         }
    1921     }
    1922 
    1923     if (RT_FAILURE(rc))
    1924     {
    1925         if (pTransfer->Callbacks.pfnTransferError)
    1926         {
    1927             SHAREDCLIPBOARDURITRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
    1928             pTransfer->Callbacks.pfnTransferError(&callbackData, rc);
    1929         }
    1930     }
    1931 
    1932     pTransfer->State.enmStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
    1933 
    1934     LogFlowFuncLeaveRC(rc);
    1935     return rc;
    1936 }
    1937 
    1938 /**
    19391208 * Initializes a clipboard URI transfer.
    19401209 *
     
    19461215    AssertPtrReturn(pURI, VERR_INVALID_POINTER);
    19471216
    1948     LogFlowFuncEnter();
     1217    LogFlowFunc(("%p\n", pURI));
    19491218
    19501219    int rc = RTCritSectInit(&pURI->CritSect);
     
    19741243    AssertPtrReturnVoid(pURI);
    19751244
    1976     LogFlowFuncEnter();
     1245    LogFlowFunc(("%p\n", pURI));
    19771246
    19781247    RTCritSectDelete(&pURI->CritSect);
     
    19821251    {
    19831252        SharedClipboardURITransferDestroy(pTransfer);
     1253
    19841254        RTListNodeRemove(&pTransfer->Node);
     1255
     1256        RTMemFree(pTransfer);
     1257        pTransfer = NULL;
    19851258    }
    19861259
     
    20491322    {
    20501323        RTListNodeRemove(&pTransfer->Node);
     1324
     1325        RTMemFree(pTransfer);
     1326        pTransfer = NULL;
    20511327    }
    20521328
     
    21251401            RTListNodeRemove(&pTransfer->Node);
    21261402
     1403            RTMemFree(pTransfer);
     1404            pTransfer = NULL;
     1405
    21271406            Assert(pURI->cTransfers);
    21281407            pURI->cTransfers--;
     
    21431422    AssertPtrReturn(pURI, true);
    21441423
    2145     LogFlowFunc(("cRunning=%RU32\n", pURI->cRunning));
     1424    LogFlowFunc(("cRunning=%RU32, cMaxRunning=%RU32\n", pURI->cRunning, pURI->cMaxRunning));
    21461425
    21471426    Assert(pURI->cRunning <= pURI->cMaxRunning);
     
    21491428}
    21501429
     1430/**
     1431 * Copies file system objinfo from IPRT to Shared Clipboard format.
     1432 *
     1433 * @param   pDst                The Shared Clipboard structure to convert data to.
     1434 * @param   pSrc                The IPRT structure to convert data from.
     1435 */
     1436void SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO pDst, PCRTFSOBJINFO pSrc)
     1437{
     1438    pDst->cbObject          = pSrc->cbObject;
     1439    pDst->cbAllocated       = pSrc->cbAllocated;
     1440    pDst->AccessTime        = pSrc->AccessTime;
     1441    pDst->ModificationTime  = pSrc->ModificationTime;
     1442    pDst->ChangeTime        = pSrc->ChangeTime;
     1443    pDst->BirthTime         = pSrc->BirthTime;
     1444    pDst->Attr.fMode        = pSrc->Attr.fMode;
     1445    /* Clear bits which we don't pass through for security reasons. */
     1446    pDst->Attr.fMode       &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT);
     1447    RT_ZERO(pDst->Attr.u);
     1448    switch (pSrc->Attr.enmAdditional)
     1449    {
     1450        default:
     1451        case RTFSOBJATTRADD_NOTHING:
     1452            pDst->Attr.enmAdditional        = SHAREDCLIPBOARDFSOBJATTRADD_NOTHING;
     1453            break;
     1454
     1455        case RTFSOBJATTRADD_UNIX:
     1456            pDst->Attr.enmAdditional        = SHAREDCLIPBOARDFSOBJATTRADD_UNIX;
     1457            pDst->Attr.u.Unix.uid           = pSrc->Attr.u.Unix.uid;
     1458            pDst->Attr.u.Unix.gid           = pSrc->Attr.u.Unix.gid;
     1459            pDst->Attr.u.Unix.cHardlinks    = pSrc->Attr.u.Unix.cHardlinks;
     1460            pDst->Attr.u.Unix.INodeIdDevice = pSrc->Attr.u.Unix.INodeIdDevice;
     1461            pDst->Attr.u.Unix.INodeId       = pSrc->Attr.u.Unix.INodeId;
     1462            pDst->Attr.u.Unix.fFlags        = pSrc->Attr.u.Unix.fFlags;
     1463            pDst->Attr.u.Unix.GenerationId  = pSrc->Attr.u.Unix.GenerationId;
     1464            pDst->Attr.u.Unix.Device        = pSrc->Attr.u.Unix.Device;
     1465            break;
     1466
     1467        case RTFSOBJATTRADD_EASIZE:
     1468            pDst->Attr.enmAdditional        = SHAREDCLIPBOARDFSOBJATTRADD_EASIZE;
     1469            pDst->Attr.u.EASize.cb          = pSrc->Attr.u.EASize.cb;
     1470            break;
     1471    }
     1472}
     1473
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r79366 r79497  
    944944 * @returns VBox status code.
    945945 * @param   pDropFiles          Pointer to DROPFILES structure to convert.
    946  * @param   pTransfer           Transfer where to add the string list to.
    947  */
    948 int VBoxClipboardWinDropFilesToTransfer(DROPFILES *pDropFiles, PSHAREDCLIPBOARDURITRANSFER pTransfer)
     946 * @param   papszList           Where to store the allocated string list.
     947 * @param   pcbList             Where to store the size (in bytes) of the allocated string list.
     948 */
     949int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList)
    949950{
    950951    AssertPtrReturn(pDropFiles, VERR_INVALID_POINTER);
    951     AssertPtrReturn(pTransfer,  VERR_INVALID_POINTER);
     952    AssertPtrReturn(papszList,  VERR_INVALID_POINTER);
     953    AssertPtrReturn(pcbList,    VERR_INVALID_POINTER);
    952954
    953955    /* Do we need to do Unicode stuff? */
     
    10281030            LogRel(("Shared Clipboard: Adding guest file '%s'\n", pszFileUtf8));
    10291031
     1032        #if 0
    10301033            char    *pszFileURI;
    10311034            uint32_t cchFileURI;
     
    10421045                RTStrFree(pszFileURI);
    10431046            }
     1047        #endif
    10441048        }
    10451049
     
    10681072                     cFiles, cchFiles, cbFiles, pszFiles));
    10691073
    1070         rc = SharedClipboardURITransferMetaDataAdd(pTransfer, pszFiles, cbFiles);
    1071     }
    1072 
    1073     LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
    1074                  rc, pszFiles, cFiles, cchFiles));
    1075 
    1076     if (pszFiles)
    1077         RTStrFree(pszFiles);
    1078 
     1074        *papszList = pszFiles;
     1075        *pcbList   = cbFiles;
     1076    }
     1077    else
     1078    {
     1079        if (pszFiles)
     1080            RTStrFree(pszFiles);
     1081    }
     1082
     1083    LogFlowFuncLeaveRC(rc);
    10791084    return rc;
    10801085}
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r79347 r79497  
    3535VBoxSharedClipboard_SOURCES = \
    3636        VBoxSharedClipboardSvc.cpp \
     37        $(PATH_ROOT)/src/VBox/HostServices/common/message.cpp \
    3738        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp
    3839VBoxSharedClipboard_SOURCES.win = \
     
    4950        VBoxSharedClipboardSvc-utils.cpp \
    5051        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardArea.cpp \
    51         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardMetaData.cpp \
    5252        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
    5353        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r79366 r79497  
    2222#endif
    2323
     24#include <algorithm>
     25#include <list>
     26#include <map>
     27
    2428#include <iprt/list.h>
    2529
     
    2731#include <VBox/log.h>
    2832
     33#include <VBox/HostServices/Service.h>
    2934#include <VBox/GuestHost/SharedClipboard.h>
    3035#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     
    3237# include <VBox/GuestHost/SharedClipboard-uri.h>
    3338#endif
     39
     40using namespace HGCM;
    3441
    3542#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     
    4653#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
    4754
     55typedef struct _VBOXCLIPBOARDCLIENTMSG
     56{
     57    /** Stored message type. */
     58    uint32_t         m_uMsg;
     59    /** Number of stored HGCM parameters. */
     60    uint32_t         m_cParms;
     61    /** Stored HGCM parameters. */
     62    PVBOXHGCMSVCPARM m_paParms;
     63} VBOXCLIPBOARDCLIENTMSG, *PVBOXCLIPBOARDCLIENTMSG;
     64
     65#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     66typedef struct VBOXCLIPBOARDCLIENTURISTATE
     67{
     68    /** Whether to start a new transfer. */
     69    bool                          fTransferStart;
     70    /** Directory of the transfer to start. */
     71    SHAREDCLIPBOARDURITRANSFERDIR enmTransferDir;
     72} VBOXCLIPBOARDCLIENTURISTATE, *PVBOXCLIPBOARDCLIENTURISTATE;
     73#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
     74
    4875/**
    4976 * Structure for keeping generic client state data within the Shared Clipboard host service.
    5077 * This structure needs to be serializable by SSM.
    5178 */
    52 struct VBOXCLIPBOARDCLIENTSTATE
     79typedef struct VBOXCLIPBOARDCLIENTSTATE
    5380{
    5481    struct VBOXCLIPBOARDCLIENTSTATE *pNext;
     
    7299    bool fHostMsgFormats;
    73100
     101#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     102    /** The client's URI state. */
     103    VBOXCLIPBOARDCLIENTURISTATE URI;
     104#endif
     105
    74106    struct {
    75107        VBOXHGCMCALLHANDLE callHandle;
     
    92124    uint32_t u32AvailableFormats;
    93125    uint32_t u32RequestedFormat;
    94 };
    95 typedef struct VBOXCLIPBOARDCLIENTSTATE *PVBOXCLIPBOARDCLIENTSTATE;
     126
     127    /** The client's message queue (FIFO). */
     128    RTCList<VBOXCLIPBOARDCLIENTMSG *> queueMsg;
     129} VBOXCLIPBOARDCLIENTSTATE, *PVBOXCLIPBOARDCLIENTSTATE;
    96130
    97131/**
     
    103137    VBOXCLIPBOARDCLIENTSTATE       State;
    104138#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     139    /** URI context data. */
    105140    SHAREDCLIPBOARDURICTX          URI;
    106141#endif
    107142} VBOXCLIPBOARDCLIENTDATA, *PVBOXCLIPBOARDCLIENTDATA;
     143
     144typedef struct _VBOXCLIPBOARDCLIENT
     145{
     146    /** The client's HGCM client ID. */
     147    uint32_t                 uClientID;
     148    /** Pointer to the client'data, owned by HGCM. */
     149    PVBOXCLIPBOARDCLIENTDATA pData;
     150    /** Optional protocol version the client uses. Set to 0 by default. */
     151    uint32_t                 uProtocolVer;
     152    /** Flag indicating whether this client currently is deferred mode,
     153     *  meaning that it did not return to the caller yet. */
     154    bool                     fDeferred;
     155    /** Structure for keeping the client's deferred state.
     156     *  A client is in a deferred state when it asks for the next HGCM message,
     157     *  but the service can't provide it yet. That way a client will block (on the guest side, does not return)
     158     *  until the service can complete the call. */
     159    struct
     160    {
     161        /** The client's HGCM call handle. Needed for completing a deferred call. */
     162        VBOXHGCMCALLHANDLE hHandle;
     163        /** Message type (function number) to use when completing the deferred call. */
     164        uint32_t           uType;
     165        /** Parameter count to use when completing the deferred call. */
     166        uint32_t           cParms;
     167        /** Parameters to use when completing the deferred call. */
     168        PVBOXHGCMSVCPARM   paParms;
     169    } Deferred;
     170} VBOXCLIPBOARDCLIENT, *PVBOXCLIPBOARDCLIENT;
     171
     172/** Map holding pointers to drag and drop clients. Key is the (unique) HGCM client ID. */
     173typedef std::map<uint32_t, VBOXCLIPBOARDCLIENT *> ClipboardClientMap;
     174
     175/** Simple queue (list) which holds deferred (waiting) clients. */
     176typedef std::list<uint32_t> ClipboardClientQueue;
    108177
    109178/*
     
    114183int vboxSvcClipboardReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uFormats);
    115184int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENTDATA pClientData, SHAREDCLIPBOARDSOURCE enmSource);
     185
     186int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
     187                                VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     188int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc);
     189int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rc);
     190int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms);
     191
     192void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTSTATE pState);
     193PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms);
     194void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg);
     195int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTSTATE pState, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend);
     196int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTSTATE pState, uint32_t *puType, uint32_t *pcParms);
     197int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTSTATE pState,
     198                               uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    116199
    117200# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     
    139222
    140223#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    141 int VBoxSvcClipboardProviderImplURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr);
    142 int VBoxSvcClipboardProviderImplURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr);
    143 int VBoxSvcClipboardProviderImplURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead);
    144 int VBoxSvcClipboardProviderImplURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr, const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten);
    145 int VBoxSvcClipboardProviderImplURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData);
    146 int VBoxSvcClipboardProviderImplURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData);
    147 int VBoxSvcClipboardProviderImplURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr);
    148 int VBoxSvcClipboardProviderImplURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr);
    149 int VBoxSvcClipboardProviderImplURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead);
    150 int VBoxSvcClipboardProviderImplURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten);
     224int vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx);
     225int vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx);
     226
     227int vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     228                                PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList);
     229int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList);
     230int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     231                                   PVBOXCLIPBOARDLISTHDR pListHdr);
     232int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     233                                    PVBOXCLIPBOARDLISTHDR pListHdr);
     234int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     235                                     PVBOXCLIPBOARDLISTENTRY pListEntry);
     236int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
     237                                      PVBOXCLIPBOARDLISTENTRY pListEntry);
     238
     239int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
     240                               PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj);
     241int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj);
     242int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     243                               void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead);
     244int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     245                                void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten);
    151246
    152247DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData);
     
    159254int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer);
    160255int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer);
    161 
    162 void VBoxClipboardSvcImplURIOnDataHeaderComplete(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData);
    163256#endif
    164257
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp

    r79367 r79497  
    4242extern void *g_pvExtension;
    4343
     44extern ClipboardClientQueue g_listClientsDeferred;
     45
    4446
    4547/*********************************************************************************************************************************
     
    4749*********************************************************************************************************************************/
    4850
    49 int VBoxSvcClipboardProviderImplURIReadDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDATAHDR *ppDataHdr)
    50 {
     51DECLCALLBACK(int) vboxSvcClipboardURITransferOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
     52{
     53    RT_NOREF(pCtx);
     54
     55    LogFlowFuncLeave();
     56    return VINF_SUCCESS;
     57}
     58
     59DECLCALLBACK(int) vboxSvcClipboardURITransferClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx)
     60{
     61    RT_NOREF(pCtx);
     62
     63    LogFlowFuncLeave();
     64    return VINF_SUCCESS;
     65}
     66
     67DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     68                                              PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList)
     69{
     70    RT_NOREF(pCtx, pListHdr, phList);
     71
     72    LogFlowFuncEnter();
     73
     74    int rc = VINF_SUCCESS;
     75
     76    LogFlowFuncLeaveRC(rc);
     77    return rc;
     78}
     79
     80DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList)
     81{
     82    RT_NOREF(pCtx, hList);
     83
     84    LogFlowFuncEnter();
     85
     86    int rc = VINF_SUCCESS;
     87
     88    LogFlowFuncLeaveRC(rc);
     89    return rc;
     90}
     91
     92DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     93                                                 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
     94{
     95    RT_NOREF(pCtx, hList, pListHdr);
     96
     97    LogFlowFuncEnter();
     98
     99    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
     100    AssertPtr(pClient);
     101
     102    int rc;
     103
     104    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
     105                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
     106    if (pMsg)
     107    {
     108        rc = vboxSvcClipboardMsgAdd(&pClient->pData->State, pMsg, true /* fAppend */);
     109        if (RT_SUCCESS(rc))
     110            rc = vboxSvcClipboardClientDeferredComplete(pClient, VINF_SUCCESS);
     111    }
     112    else
     113        rc = VERR_NO_MEMORY;
     114
     115    if (RT_SUCCESS(rc))
     116    {
     117        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
     118        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
     119                                                 30 * 1000 /* Timeout in ms */, &pPayload);
     120        if (RT_SUCCESS(rc))
     121        {
     122            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR));
     123            //*ppListHdr = (PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
     124
     125            RTMemFree(pPayload);
     126        }
     127    }
     128
     129    LogFlowFuncLeaveRC(rc);
     130    return rc;
     131}
     132
     133DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     134                                                  VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
     135{
     136    RT_NOREF(pCtx, hList, pListHdr);
     137
     138    LogFlowFuncEnter();
     139
     140    return VERR_NOT_IMPLEMENTED;
     141}
     142
     143DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     144                                                   VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     145{
     146    RT_NOREF(pCtx, hList, pListEntry);
     147
    51148    LogFlowFuncEnter();
    52149
     
    55152
    56153    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    57     int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
     154    int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
    58155                                                 30 * 1000 /* Timeout in ms */, &pPayload);
    59156    if (RT_SUCCESS(rc))
    60157    {
    61         Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATAHDR));
    62         *ppDataHdr = (PVBOXCLIPBOARDDATAHDR)pPayload->pvData;
    63 
    64         RTMemFree(pPayload);
    65     }
    66 
    67     LogFlowFuncLeaveRC(rc);
    68     return rc;
    69 }
    70 
    71 int VBoxSvcClipboardProviderImplURIWriteDataHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr)
    72 {
    73     RT_NOREF(pCtx, pDataHdr);
     158        Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
     159
     160        PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData;
     161        AssertPtr(pListEntry);
     162
     163   /*     const uint32_t cbToRead = RT_MIN(cbChunk, pListEntry->cbData);
     164
     165        memcpy(pvChunk, pListEntry->pvData, cbToRead);*/
     166
     167        SharedClipboardURITransferPayloadFree(pPayload);
     168
     169/*        if (pcbRead)
     170            *pcbRead = cbToRead;*/
     171    }
     172
     173    LogFlowFuncLeaveRC(rc);
     174    return rc;
     175}
     176
     177DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
     178                                                    VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
     179{
     180    RT_NOREF(pCtx, hList, pListEntry);
    74181
    75182    LogFlowFuncEnter();
     
    78185}
    79186
    80 int VBoxSvcClipboardProviderImplURIReadDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
    81                                                  void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbRead)
    82 {
    83     RT_NOREF(pDataHdr, fFlags);
    84 
    85     LogFlowFuncEnter();
    86 
    87     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
    88     AssertPtr(pClientData);
    89 
    90     PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    91     int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
    92                                                  30 * 1000 /* Timeout in ms */, &pPayload);
    93     if (RT_SUCCESS(rc))
    94     {
    95         Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDDATACHUNK));
    96 
    97         const uint32_t cbToRead = RT_MIN(cbChunk, pPayload->cbData);
    98 
    99         memcpy(pvChunk, pPayload->pvData, cbToRead);
    100 
    101         SharedClipboardURITransferPayloadFree(pPayload);
    102 
    103         if (pcbRead)
    104             *pcbRead = cbToRead;
    105     }
    106 
    107     LogFlowFuncLeaveRC(rc);
    108     return rc;
    109 }
    110 
    111 int VBoxSvcClipboardProviderImplURIWriteDataChunk(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDATAHDR pDataHdr,
    112                                                   const void *pvChunk, uint32_t cbChunk, uint32_t fFlags, uint32_t *pcbWritten)
    113 {
    114     RT_NOREF(pCtx, pDataHdr, pvChunk, cbChunk, fFlags, pcbWritten);
     187int vboxSvcClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
     188                               PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj)
     189{
     190    RT_NOREF(pCtx, pszPath, pCreateParms, phObj);
    115191
    116192    LogFlowFuncEnter();
     
    119195}
    120196
    121 int VBoxSvcClipboardProviderImplURIReadDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDDIRDATA *ppDirData)
    122 {
    123     RT_NOREF(pCtx, ppDirData);
     197int vboxSvcClipboardURIObjClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj)
     198{
     199    RT_NOREF(pCtx, hObj);
     200
     201    LogFlowFuncEnter();
     202
     203    int rc = VINF_SUCCESS;
     204
     205    PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
     206    AssertPtr(pThisCtx);
     207
     208    LogFlowFuncLeaveRC(rc);
     209    return rc;
     210}
     211
     212int vboxSvcClipboardURIObjRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     213                               void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
     214{
     215    RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbRead);
    124216
    125217    LogFlowFuncEnter();
     
    128220}
    129221
    130 int VBoxSvcClipboardProviderImplURIWriteDir(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDDIRDATA pDirData)
    131 {
    132     RT_NOREF(pCtx, pDirData);
    133 
    134     LogFlowFuncEnter();
    135 
    136     return VERR_NOT_IMPLEMENTED;
    137 }
    138 
    139 int VBoxSvcClipboardProviderImplURIReadFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDFILEHDR *ppFileHdr)
    140 {
    141     RT_NOREF(pCtx, ppFileHdr);
    142 
    143     LogFlowFuncEnter();
    144 
    145     return VERR_NOT_IMPLEMENTED;
    146 }
    147 
    148 int VBoxSvcClipboardProviderImplURIWriteFileHdr(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const PVBOXCLIPBOARDFILEHDR pFileHdr)
    149 {
    150     RT_NOREF(pCtx, pFileHdr);
    151 
    152     LogFlowFuncEnter();
    153 
    154     return VERR_NOT_IMPLEMENTED;
    155 }
    156 
    157 int VBoxSvcClipboardProviderImplURIReadFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
    158                                                 uint32_t *pcbRead)
    159 {
    160     RT_NOREF(pCtx, pvData, cbData, fFlags, pcbRead);
    161 
    162     LogFlowFuncEnter();
    163 
    164     return VERR_NOT_IMPLEMENTED;
    165 }
    166 
    167 int VBoxSvcClipboardProviderImplURIWriteFileData(PSHAREDCLIPBOARDPROVIDERCTX pCtx, void *pvData, uint32_t cbData, uint32_t fFlags,
    168                                                  uint32_t *pcbWritten)
    169 {
    170     RT_NOREF(pCtx, pvData, cbData, fFlags, pcbWritten);
     222int vboxSvcClipboardURIObjWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDOBJHANDLE hObj,
     223                                void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
     224{
     225    RT_NOREF(pCtx, pCtx, hObj, pvData, cbData, fFlags, pcbWritten);
    171226
    172227    LogFlowFuncEnter();
     
    184239    LogFlowFuncEnter();
    185240
    186     LogFlowFuncEnter();
    187 
    188241    AssertPtrReturnVoid(pData);
    189242
     
    191244    AssertPtrReturnVoid(pClientData);
    192245
     246    PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer;
     247    AssertPtrReturnVoid(pTransfer);
     248
     249    /* Register needed events. */
     250    int rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ);
     251    AssertRC(rc2);
     252    rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ);
     253    AssertRC(rc2);
     254
     255#if 0
    193256    /* Tell the guest that it can start sending URI data. */
    194     int rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
    195                                         VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
     257    rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START,
     258                                    0 /* u32Formats == 0 means reading data */);
    196259    AssertRC(rc2);
    197 
    198     rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR);
    199     AssertRC(rc2);
    200     rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK);
    201     AssertRC(rc2);
    202 }
    203 
    204 DECLCALLBACK(void) VBoxSvcClipboardURIDataHeaderCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
     260#endif
     261}
     262
     263DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
     264{
     265    LogFlowFuncEnter();
     266
     267    RT_NOREF(pData, rc);
     268
     269    LogRel2(("Shared Clipboard: Transfer complete\n"));
     270}
     271
     272DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
    205273{
    206274    LogFlowFuncEnter();
    207275
    208276    RT_NOREF(pData);
    209 }
    210 
    211 DECLCALLBACK(void) VBoxSvcClipboardURIDataCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
    212 {
    213     LogFlowFuncEnter();
    214 
    215     VBoxClipboardSvcImplURIOnDataHeaderComplete(pData);
    216 }
    217 
    218 DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
     277
     278    LogRel2(("Shared Clipboard: Transfer canceled\n"));
     279}
     280
     281DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
    219282{
    220283    LogFlowFuncEnter();
     
    222285    RT_NOREF(pData, rc);
    223286
    224     LogRel2(("Shared Clipboard: Transfer complete\n"));
    225 }
    226 
    227 DECLCALLBACK(void) VBoxSvcClipboardURITransferCanceledCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
    228 {
    229     LogFlowFuncEnter();
    230 
    231     RT_NOREF(pData);
    232 
    233     LogRel2(("Shared Clipboard: Transfer canceled\n"));
    234 }
    235 
    236 DECLCALLBACK(void) VBoxSvcClipboardURITransferErrorCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
    237 {
    238     LogFlowFuncEnter();
    239 
    240     RT_NOREF(pData, rc);
    241 
    242287    LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
    243288}
    244289
    245290/**
    246  * Gets an URI data header from HGCM service parameters.
     291 * Gets an URI list header from HGCM service parameters.
    247292 *
    248293 * @returns VBox status code.
    249294 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    250295 * @param   paParms             Array of HGCM parameters.
    251  * @param   pDataHdr            Where to store the result.
     296 * @param   phList              Where to store the list handle.
     297 * @param   pListHdr            Where to store the list header.
    252298 */
    253 int VBoxSvcClipboardURIGetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
     299int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     300                                  PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
    254301{
    255302    int rc;
    256303
    257     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_HDR)
     304    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE)
    258305    {
    259306        /* Note: Context ID (paParms[0]) not used yet. */
    260         rc = HGCMSvcGetU32(&paParms[1], &pDataHdr->uFlags);
    261         if (RT_SUCCESS(rc))
    262             rc = HGCMSvcGetU32(&paParms[2], &pDataHdr->uScreenId);
    263         if (RT_SUCCESS(rc))
    264             rc = HGCMSvcGetU64(&paParms[3], &pDataHdr->cbTotal);
    265         if (RT_SUCCESS(rc))
    266             rc = HGCMSvcGetU32(&paParms[4], &pDataHdr->cbMeta);
    267         if (RT_SUCCESS(rc))
    268             rc = HGCMSvcGetU32(&paParms[5], &pDataHdr->cbMetaFmt);
    269         if (RT_SUCCESS(rc))
    270             rc = HGCMSvcGetPv(&paParms[6], &pDataHdr->pvMetaFmt, &pDataHdr->cbMetaFmt);
    271         if (RT_SUCCESS(rc))
    272             rc = HGCMSvcGetU64(&paParms[7], &pDataHdr->cObjects);
    273         if (RT_SUCCESS(rc))
    274             rc = HGCMSvcGetU32(&paParms[8], &pDataHdr->enmCompression);
    275         if (RT_SUCCESS(rc))
    276             rc = HGCMSvcGetU32(&paParms[9], (uint32_t *)&pDataHdr->enmChecksumType);
    277         if (RT_SUCCESS(rc))
    278             rc = HGCMSvcGetU32(&paParms[10], &pDataHdr->cbChecksum);
    279         if (RT_SUCCESS(rc))
    280             rc = HGCMSvcGetPv(&paParms[11], &pDataHdr->pvChecksum, &pDataHdr->cbChecksum);
    281 
    282         LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
    283                      pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
     307        rc = HGCMSvcGetU64(&paParms[1], phList);
     308        if (RT_SUCCESS(rc))
     309            rc = HGCMSvcGetU64(&paParms[2], &pListHdr->cTotalObjects);
     310        if (RT_SUCCESS(rc))
     311            rc = HGCMSvcGetU64(&paParms[3], &pListHdr->cbTotalSize);
     312        if (RT_SUCCESS(rc))
     313            rc = HGCMSvcGetU32(&paParms[4], &pListHdr->enmCompression);
     314        if (RT_SUCCESS(rc))
     315            rc = HGCMSvcGetU32(&paParms[5], (uint32_t *)&pListHdr->enmChecksumType);
    284316
    285317        if (RT_SUCCESS(rc))
     
    297329
    298330/**
    299  * Sets an URI data header to HGCM service parameters.
     331 * Sets an URI list header to HGCM service parameters.
    300332 *
    301333 * @returns VBox status code.
    302334 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    303335 * @param   paParms             Array of HGCM parameters.
    304  * @param   pDataHdr            Pointer to data to set to the HGCM parameters.
     336 * @param   pListHdr            Pointer to data to set to the HGCM parameters.
    305337 */
    306 int VBoxSvcClipboardURISetDataHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATAHDR pDataHdr)
     338int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr)
    307339{
    308340    int rc;
    309341
    310     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_HDR)
     342    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ)
    311343    {
    312344        /** @todo Set pvMetaFmt + cbMetaFmt. */
     
    314346
    315347        /* Note: Context ID (paParms[0]) not used yet. */
    316         HGCMSvcSetU32(&paParms[1],  pDataHdr->uFlags);
    317         HGCMSvcSetU32(&paParms[2],  pDataHdr->uScreenId);
    318         HGCMSvcSetU64(&paParms[3],  pDataHdr->cbTotal);
    319         HGCMSvcSetU32(&paParms[4],  pDataHdr->cbMeta);
    320         HGCMSvcSetU32(&paParms[5],  pDataHdr->cbMetaFmt);
    321         HGCMSvcSetPv (&paParms[6],  pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt);
    322         HGCMSvcSetU64(&paParms[7],  pDataHdr->cObjects);
    323         HGCMSvcSetU32(&paParms[8],  pDataHdr->enmCompression);
    324         HGCMSvcSetU32(&paParms[9],  (uint32_t)pDataHdr->enmChecksumType);
    325         HGCMSvcSetU32(&paParms[10], pDataHdr->cbChecksum);
    326         HGCMSvcSetPv (&paParms[11], pDataHdr->pvChecksum, pDataHdr->cbChecksum);
    327 
    328         LogFlowFunc(("fFlags=0x%x, cbMeta=%RU32, cbTotalSize=%RU64, cObj=%RU64\n",
    329                      pDataHdr->uFlags, pDataHdr->cbMeta, pDataHdr->cbTotal, pDataHdr->cObjects));
     348        HGCMSvcSetU32(&paParms[1], pListHdr->fList);
     349        HGCMSvcSetU32(&paParms[2], pListHdr->fFeatures);
     350        HGCMSvcSetU32(&paParms[3], pListHdr->cbFilter);
     351        HGCMSvcSetPv (&paParms[4], pListHdr->pszFilter, pListHdr->cbFilter);
     352        HGCMSvcSetU64(&paParms[5], pListHdr->cTotalObjects);
     353        HGCMSvcSetU64(&paParms[6], pListHdr->cbTotalSize);
     354        HGCMSvcSetU32(&paParms[7], pListHdr->enmCompression);
     355        HGCMSvcSetU32(&paParms[8], (uint32_t)pListHdr->enmChecksumType);
    330356
    331357        rc = VINF_SUCCESS;
     
    339365
    340366/**
    341  * Gets an URI data chunk from HGCM service parameters.
     367 * Gets an URI list entry from HGCM service parameters.
    342368 *
    343369 * @returns VBox status code.
    344370 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    345371 * @param   paParms             Array of HGCM parameters.
    346  * @param   pDataChunk          Where to store the result.
     372 * @param   phList              Where to store the list handle.
     373 * @param   pListEntry          Where to store the list entry.
    347374 */
    348 int VBoxSvcClipboardURIGetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
     375int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
     376                                    PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
    349377{
    350378    int rc;
    351379
    352     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DATA_CHUNK)
     380    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE)
    353381    {
    354382        /* Note: Context ID (paParms[0]) not used yet. */
    355         rc = HGCMSvcGetU32(&paParms[1], &pDataChunk->cbData);
    356         if (RT_SUCCESS(rc))
    357             rc = HGCMSvcGetPv(&paParms[2], &pDataChunk->pvData, &pDataChunk->cbData);
    358         if (RT_SUCCESS(rc))
    359             rc = HGCMSvcGetU32(&paParms[3], &pDataChunk->cbChecksum);
    360         if (RT_SUCCESS(rc))
    361             rc = HGCMSvcGetPv(&paParms[4], &pDataChunk->pvChecksum, &pDataChunk->cbChecksum);
    362 
    363         if (RT_SUCCESS(rc))
    364         {
    365             if (!SharedClipboardURIDataChunkIsValid(pDataChunk))
     383        rc = HGCMSvcGetU64(&paParms[1], phList);
     384        if (RT_SUCCESS(rc))
     385            rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo);
     386        if (RT_SUCCESS(rc))
     387            rc = HGCMSvcGetU32(&paParms[3], &pListEntry->cbInfo);
     388        if (RT_SUCCESS(rc))
     389            rc = HGCMSvcGetPv(&paParms[4], &pListEntry->pvInfo, &pListEntry->cbInfo);
     390
     391        if (RT_SUCCESS(rc))
     392        {
     393            if (!SharedClipboardURIListEntryIsValid(pListEntry))
    366394                rc = VERR_INVALID_PARAMETER;
    367395        }
     
    380408 * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    381409 * @param   paParms             Array of HGCM parameters.
    382  * @param   pDataChunk          Pointer to data to set to the HGCM parameters.
     410 * @param   pListEntry          Pointer to data to set to the HGCM parameters.
    383411 */
    384 int VBoxSvcClipboardURISetDataChunk(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDATACHUNK pDataChunk)
     412int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry)
    385413{
    386414    int rc;
    387415
    388     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DATA_CHUNK)
     416    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ)
    389417    {
    390418        /** @todo Calculate chunk checksum. */
    391419
    392420        /* Note: Context ID (paParms[0]) not used yet. */
    393         HGCMSvcSetU32(&paParms[1], pDataChunk->cbData);
    394         HGCMSvcSetPv (&paParms[2], pDataChunk->pvData, pDataChunk->cbData);
    395         HGCMSvcSetU32(&paParms[3], pDataChunk->cbChecksum);
    396         HGCMSvcSetPv (&paParms[4], pDataChunk->pvChecksum, pDataChunk->cbChecksum);
     421        HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
     422        HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
     423        HGCMSvcSetPv (&paParms[3], pListEntry->pvInfo, pListEntry->cbInfo);
    397424
    398425        rc = VINF_SUCCESS;
     
    405432}
    406433
    407 /**
    408  * Gets an URI directory entry from HGCM service parameters.
    409  *
    410  * @returns VBox status code.
    411  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    412  * @param   paParms             Array of HGCM parameters.
    413  * @param   pDirData            Where to store the result.
    414  */
    415 int VBoxSvcClipboardURIGetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
    416 {
     434int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
     435{
     436    AssertPtrReturn(paParms, VERR_INVALID_PARAMETER);
     437    AssertPtrReturn(pRc,     VERR_INVALID_PARAMETER);
     438
    417439    int rc;
    418440
    419     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_DIR)
     441    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ERROR)
    420442    {
    421443        /* Note: Context ID (paParms[0]) not used yet. */
    422         rc = HGCMSvcGetU32(&paParms[1], &pDirData->cbPath);
    423         if (RT_SUCCESS(rc))
    424             rc = HGCMSvcGetPv(&paParms[2], (void **)&pDirData->pszPath, &pDirData->cbPath);
    425         if (RT_SUCCESS(rc))
    426             rc = HGCMSvcGetU32(&paParms[3], &pDirData->fMode);
    427 
    428         LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pDirData->pszPath, pDirData->cbPath, pDirData->fMode));
    429 
    430         if (RT_SUCCESS(rc))
    431         {
    432             if (!SharedClipboardURIDirDataIsValid(pDirData))
    433                 rc = VERR_INVALID_PARAMETER;
    434         }
    435     }
    436     else
    437         rc = VERR_INVALID_PARAMETER;
    438 
    439     LogFlowFuncLeaveRC(rc);
    440     return rc;
    441 }
    442 
    443 /**
    444  * Sets an URI directory entry to HGCM service parameters.
    445  *
    446  * @returns VBox status code.
    447  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    448  * @param   paParms             Array of HGCM parameters.
    449  * @param   pDirData            Pointer to data to set to the HGCM parameters.
    450  */
    451 int VBoxSvcClipboardURISetDir(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDDIRDATA pDirData)
    452 {
    453     int rc;
    454 
    455     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_DIR)
    456     {
    457         /* Note: Context ID (paParms[0]) not used yet. */
    458         HGCMSvcSetU32(&paParms[1], pDirData->cbPath);
    459         HGCMSvcSetPv (&paParms[2], pDirData->pszPath, pDirData->cbPath);
    460         HGCMSvcSetU32(&paParms[3], pDirData->fMode);
    461 
    462         rc = VINF_SUCCESS;
    463     }
    464     else
    465         rc = VERR_INVALID_PARAMETER;
    466 
    467     LogFlowFuncLeaveRC(rc);
    468     return rc;
    469 }
    470 
    471 /**
    472  * Reads an URI file header from HGCM service parameters.
    473  *
    474  * @returns VBox status code.
    475  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    476  * @param   paParms             Array of HGCM parameters.
    477  * @param   pFileHdr            Where to store the result.
    478  */
    479 int VBoxSvcClipboardURIGetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
    480 {
    481     int rc;
    482 
    483     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_HDR)
    484     {
    485         /* Note: Context ID (paParms[0]) not used yet. */
    486         rc = HGCMSvcGetU32(&paParms[1], &pFileHdr->cbFilePath);
    487         if (RT_SUCCESS(rc))
    488             rc = HGCMSvcGetPv(&paParms[2], (void **)&pFileHdr->pszFilePath, &pFileHdr->cbFilePath);
    489         if (RT_SUCCESS(rc))
    490             rc = HGCMSvcGetU32(&paParms[3], &pFileHdr->fFlags);
    491         if (RT_SUCCESS(rc))
    492             rc = HGCMSvcGetU32(&paParms[4], &pFileHdr->fMode);
    493         if (RT_SUCCESS(rc))
    494             rc = HGCMSvcGetU64(&paParms[5], &pFileHdr->cbSize);
    495 
    496         LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x, cbSize=%RU64\n",
    497                      pFileHdr->pszFilePath, pFileHdr->cbFilePath, pFileHdr->fMode, pFileHdr->cbSize));
    498     }
    499     else
    500         rc = VERR_INVALID_PARAMETER;
    501 
    502     LogFlowFuncLeaveRC(rc);
    503     return rc;
    504 }
    505 
    506 /**
    507  * Sets an URI file header to HGCM service parameters.
    508  *
    509  * @returns VBox status code.
    510  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    511  * @param   paParms             Array of HGCM parameters.
    512  * @param   pFileHdr            Pointer to data to set to the HGCM parameters.
    513  */
    514 int VBoxSvcClipboardURISetFileHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEHDR pFileHdr)
    515 {
    516     int rc;
    517 
    518     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_HDR)
    519     {
    520         /* Note: Context ID (paParms[0]) not used yet. */
    521         HGCMSvcSetU32(&paParms[1], pFileHdr->cbFilePath);
    522         HGCMSvcSetPv (&paParms[2], pFileHdr->pszFilePath, pFileHdr->cbFilePath);
    523         HGCMSvcSetU32(&paParms[3], pFileHdr->fFlags);
    524         HGCMSvcSetU32(&paParms[4], pFileHdr->fMode);
    525         HGCMSvcSetU64(&paParms[5], pFileHdr->cbSize);
    526 
    527         rc = VINF_SUCCESS;
    528     }
    529     else
    530         rc = VERR_INVALID_PARAMETER;
    531 
    532     LogFlowFuncLeaveRC(rc);
    533     return rc;
    534 }
    535 
    536 /**
    537  * Gets an URI file data chunk from HGCM service parameters.
    538  *
    539  * @returns VBox status code.
    540  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    541  * @param   paParms             Array of HGCM parameters.
    542  * @param   pFileData           Where to store the result.
    543  */
    544 int VBoxSvcClipboardURIGetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
    545 {
    546     int rc;
    547 
    548     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_WRITE_FILE_DATA)
    549     {
    550         /* Note: Context ID (paParms[0]) not used yet. */
    551         rc = HGCMSvcGetU32(&paParms[1], &pFileData->cbData);
    552         if (RT_SUCCESS(rc))
    553             rc = HGCMSvcGetPv(&paParms[2], &pFileData->pvData, &pFileData->cbData);
    554         if (RT_SUCCESS(rc))
    555             rc = HGCMSvcGetU32(&paParms[3], &pFileData->cbChecksum);
    556         if (RT_SUCCESS(rc))
    557             rc = HGCMSvcGetPv(&paParms[4], &pFileData->pvChecksum, &pFileData->cbChecksum);
    558 
    559         LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", pFileData->pvData, pFileData->cbData));
    560     }
    561     else
    562         rc = VERR_INVALID_PARAMETER;
    563 
    564     LogFlowFuncLeaveRC(rc);
    565     return rc;
    566 }
    567 
    568 /**
    569  * Sets an URI file data chunk to HGCM service parameters.
    570  *
    571  * @returns VBox status code.
    572  * @param   cParms              Number of HGCM parameters supplied in \a paParms.
    573  * @param   paParms             Array of HGCM parameters.
    574  * @param   pFileData           Pointer to data to set to the HGCM parameters.
    575  */
    576 int VBoxSvcClipboardURISetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData)
    577 {
    578     int rc;
    579 
    580     if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_READ_FILE_DATA)
    581     {
    582         /* Note: Context ID (paParms[0]) not used yet. */
    583         HGCMSvcSetU32(&paParms[1], pFileData->cbData);
    584         HGCMSvcSetPv (&paParms[2], pFileData->pvData, pFileData->cbData);
    585         HGCMSvcSetU32(&paParms[3], pFileData->cbChecksum);
    586         HGCMSvcSetPv (&paParms[4], pFileData->pvChecksum, pFileData->cbChecksum);
    587 
    588         rc = VINF_SUCCESS;
     444        rc = HGCMSvcGetU32(&paParms[1], (uint32_t *)pRc); /** @todo int vs. uint32_t !!! */
    589445    }
    590446    else
     
    599455 *
    600456 * @returns VBox status code.
    601  * @param   u32ClientID         Client ID of the client which called this handler.
    602  * @param   pvClient            Pointer to client-specific data block.
     457 * @param   pClient             Pointer to associated client.
     458 * @param   callHandle          The client's call handle of this call.
    603459 * @param   u32Function         Function number being called.
    604460 * @param   cParms              Number of function parameters supplied.
    605461 * @param   paParms             Array function parameters  supplied.
    606462 * @param   tsArrival           Timestamp of arrival.
    607  * @param   pfAsync             Returns \c true if the response needs to be being asynchronous or \c false if not,
    608463 */
    609 int vboxSvcClipboardURIHandler(uint32_t u32ClientID,
    610                                void *pvClient,
     464int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient,
     465                               VBOXHGCMCALLHANDLE callHandle,
    611466                               uint32_t u32Function,
    612467                               uint32_t cParms,
    613468                               VBOXHGCMSVCPARM paParms[],
    614                                uint64_t tsArrival,
    615                                bool *pfAsync)
    616 {
    617     RT_NOREF(u32ClientID, paParms, tsArrival, pfAsync);
    618 
    619     LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
    620                  u32ClientID, u32Function, cParms, g_pfnExtension));
    621 
    622     const PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
     469                               uint64_t tsArrival)
     470{
     471    RT_NOREF(paParms, tsArrival);
     472
     473    LogFlowFunc(("uClient=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
     474                 pClient->uClientID, u32Function, cParms, g_pfnExtension));
     475
     476    const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
    623477    AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
    624478
    625479    /* Check if we've the right mode set. */
    626480    if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), u32Function))
     481    {
     482        LogFunc(("Wrong clipboard mode, denying access\n"));
    627483        return VERR_ACCESS_DENIED;
     484    }
    628485
    629486    /* A (valid) service extension is needed because VBoxSVC needs to keep track of the
     
    638495    }
    639496
    640     if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
    641     {
    642         LogFunc(("No transfers found\n"));
    643         return VERR_WRONG_ORDER;
    644     }
    645 
    646     const uint32_t uTransferID = 0; /* Only one transfer is supported at the moment. */
    647 
    648     const PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
    649     if (!pTransfer)
    650     {
    651         LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
    652         return VERR_WRONG_ORDER;
    653     }
    654 
    655     bool fWriteToProvider = false; /* Whether to (also) dispatch the HGCM data to the transfer provider. */
    656 
    657     int rc = VERR_INVALID_PARAMETER; /* Play safe. */
    658 
     497    int rc = VINF_SUCCESS;
     498
     499    /*
     500     * Pre-check: For certain messages we need to make sure that a (right) transfer is present.
     501     */
     502    PSHAREDCLIPBOARDURITRANSFER pTransfer = NULL;
    659503    switch (u32Function)
    660504    {
    661         case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR:
    662         {
    663             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n"));
    664 
    665             VBOXCLIPBOARDDATAHDR dataHdr;
    666             rc = VBoxSvcClipboardURISetDataHdr(cParms, paParms, &dataHdr);
    667             break;
    668         }
    669 
    670         case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR:
    671         {
    672             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_HDR\n"));
    673 
    674             VBOXCLIPBOARDDATAHDR dataHdr;
    675             rc = SharedClipboardURIDataHdrInit(&dataHdr);
    676             if (RT_SUCCESS(rc))
    677             {
    678                 rc = VBoxSvcClipboardURIGetDataHdr(cParms, paParms, &dataHdr);
     505        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     506            RT_FALL_THROUGH();
     507        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
     508            break;
     509        default:
     510        {
     511            if (!SharedClipboardURICtxGetTotalTransfers(&pClientData->URI))
     512            {
     513                LogFunc(("No transfers found\n"));
     514                rc = VERR_WRONG_ORDER;
     515                break;
     516            }
     517
     518            const uint32_t uTransferID = 0; /* Only one transfer per client is supported at the moment. */
     519
     520            pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, uTransferID);
     521            if (!pTransfer)
     522            {
     523                LogFunc(("Transfer with ID %RU32 not found\n", uTransferID));
     524                rc = VERR_WRONG_ORDER;
     525            }
     526            break;
     527        }
     528    }
     529
     530    if (RT_FAILURE(rc))
     531        return rc;
     532
     533    rc = VERR_INVALID_PARAMETER; /* Play safe. */
     534
     535    switch (u32Function)
     536    {
     537        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
     538        {
     539            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT\n"));
     540
     541            if (!SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
     542            {
     543                SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
     544
     545                SHAREDCLIPBOARDURITRANSFERDIR enmDir = SHAREDCLIPBOARDURITRANSFERDIR_READ;
     546
     547                PSHAREDCLIPBOARDURITRANSFER pTransfer;
     548                rc = SharedClipboardURITransferCreate(enmDir,
     549                                                      SHAREDCLIPBOARDSOURCE_REMOTE, &pTransfer);
    679550                if (RT_SUCCESS(rc))
    680551                {
    681                     void    *pvData = SharedClipboardURIDataHdrDup(&dataHdr);
    682                     uint32_t cbData = sizeof(VBOXCLIPBOARDDATAHDR);
     552                    rc = vboxSvcClipboardURIAreaRegister(&pClientData->State, pTransfer);
     553                    if (RT_SUCCESS(rc))
     554                    {
     555                        SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
     556                        RT_ZERO(creationCtx);
     557
     558                        creationCtx.enmSource = pClientData->State.enmSource;
     559
     560                        RT_ZERO(creationCtx.Interface);
     561                        creationCtx.Interface.pfnTransferOpen  = vboxSvcClipboardURITransferOpen;
     562                        creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose;
     563                        creationCtx.Interface.pfnListOpen      = vboxSvcClipboardURIListOpen;
     564                        creationCtx.Interface.pfnListClose     = vboxSvcClipboardURIListClose;
     565                        creationCtx.Interface.pfnObjOpen       = vboxSvcClipboardURIObjOpen;
     566                        creationCtx.Interface.pfnObjClose      = vboxSvcClipboardURIObjClose;
     567
     568                        if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
     569                        {
     570                            creationCtx.Interface.pfnListHdrRead   = vboxSvcClipboardURIListHdrRead;
     571                            creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
     572                            creationCtx.Interface.pfnObjRead       = vboxSvcClipboardURIObjRead;
     573                        }
     574                        else
     575                        {
     576                            AssertFailed();
     577                        }
     578
     579                        creationCtx.pvUser = pClient;
     580
     581                        /* Register needed callbacks so that we can wait for the meta data to arrive here. */
     582                        SHAREDCLIPBOARDURITRANSFERCALLBACKS Callbacks;
     583                        RT_ZERO(Callbacks);
     584
     585                        Callbacks.pvUser                = pClientData;
     586
     587                        Callbacks.pfnTransferPrepare    = VBoxSvcClipboardURITransferPrepareCallback;
     588                        Callbacks.pfnTransferComplete   = VBoxSvcClipboardURITransferCompleteCallback;
     589                        Callbacks.pfnTransferCanceled   = VBoxSvcClipboardURITransferCanceledCallback;
     590                        Callbacks.pfnTransferError      = VBoxSvcClipboardURITransferErrorCallback;
     591
     592                        SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
     593
     594                        rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
     595                        if (RT_SUCCESS(rc))
     596                            rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
     597                    }
     598
     599                    if (RT_SUCCESS(rc))
     600                    {
     601                        rc = VBoxClipboardSvcImplURITransferCreate(pClientData, pTransfer);
     602                        if (RT_SUCCESS(rc))
     603                            rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST);
     604                    }
     605
     606                    if (RT_FAILURE(rc))
     607                    {
     608                        VBoxClipboardSvcImplURITransferDestroy(pClientData, pTransfer);
     609                        SharedClipboardURITransferDestroy(pTransfer);
     610                    }
     611                }
     612            }
     613            else
     614                rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
     615
     616            LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: %Rrc\n", rc));
     617
     618            if (RT_FAILURE(rc))
     619                LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc));
     620
     621            break;
     622        }
     623
     624        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     625        {
     626            if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG)
     627            {
     628                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n"));
     629                rc = vboxSvcClipboardMsgGetNextInfo(&pClientData->State,
     630                                                    &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
     631
     632                /* No (new) messages available or some error occurred? */
     633                if (   rc == VERR_NO_DATA
     634                    || RT_FAILURE(rc))
     635                {
     636                    uint32_t fFlags = 0;
     637                    int rc2 = HGCMSvcGetU32(&paParms[2], &fFlags);
     638                    if (   RT_SUCCESS(rc2)
     639                        && fFlags) /* Blocking flag set? */
     640                    {
     641                        /* Defer client returning. */
     642                        rc = VINF_HGCM_ASYNC_EXECUTE;
     643                    }
     644                    else
     645                        rc = VERR_INVALID_PARAMETER;
     646
     647                    LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc));
     648                }
     649            }
     650            break;
     651        }
     652
     653        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
     654        {
     655            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN\n"));
     656            rc = VINF_SUCCESS;
     657            break;
     658        }
     659
     660        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
     661        {
     662            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE\n"));
     663            rc = VINF_SUCCESS;
     664            break;
     665        }
     666
     667        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
     668        {
     669            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_HDR\n"));
     670
     671            VBOXCLIPBOARDLISTHANDLE hList;
     672            VBOXCLIPBOARDLISTHDR    hdrList;
     673            rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
     674            if (RT_SUCCESS(rc))
     675            {
     676                if (RT_SUCCESS(rc))
     677                    rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
     678            }
     679            break;
     680        }
     681
     682        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
     683        {
     684            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_HDR\n"));
     685
     686            VBOXCLIPBOARDLISTHDR hdrList;
     687            rc = SharedClipboardURIListHdrInit(&hdrList);
     688            if (RT_SUCCESS(rc))
     689            {
     690                VBOXCLIPBOARDLISTHANDLE hList;
     691                rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
     692                if (RT_SUCCESS(rc))
     693                {
     694                    void    *pvData = SharedClipboardURIListHdrDup(&hdrList);
     695                    uint32_t cbData = sizeof(VBOXCLIPBOARDLISTHDR);
    683696
    684697                    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    685                     rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
     698                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
    686699                                                                pvData, cbData, &pPayload);
    687700                    if (RT_SUCCESS(rc))
    688701                    {
    689                         rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_HDR,
     702                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
    690703                                                                   pPayload);
    691704                    }
     
    695708        }
    696709
    697         case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK:
    698         {
    699             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_CHUNK\n"));
    700             break;
    701         }
    702 
    703         case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK:
    704         {
    705             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA_CHUNK\n"));
    706 
    707             VBOXCLIPBOARDDATACHUNK dataChunk;
    708             rc = SharedClipboardURIDataChunkInit(&dataChunk);
     710        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
     711        {
     712            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_ENTRY\n"));
     713            break;
     714        }
     715
     716        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
     717        {
     718            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_ENTRY\n"));
     719
     720            VBOXCLIPBOARDLISTENTRY entryList;
     721            rc = SharedClipboardURIListEntryInit(&entryList);
    709722            if (RT_SUCCESS(rc))
    710723            {
    711                 rc = VBoxSvcClipboardURIGetDataChunk(cParms, paParms, &dataChunk);
     724                VBOXCLIPBOARDLISTHANDLE hList;
     725                rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
    712726                if (RT_SUCCESS(rc))
    713727                {
    714                     void    *pvData = SharedClipboardURIDataChunkDup(&dataChunk);
    715                     uint32_t cbData = sizeof(VBOXCLIPBOARDDATACHUNK);
     728                    void    *pvData = SharedClipboardURIListEntryDup(&entryList);
     729                    uint32_t cbData = sizeof(VBOXCLIPBOARDLISTENTRY);
    716730
    717731                    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
    718                     rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
     732                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
    719733                                                                pvData, cbData, &pPayload);
    720734                    if (RT_SUCCESS(rc))
    721735                    {
    722                         rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_METADATA_CHUNK,
     736                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
    723737                                                                   pPayload);
    724738                    }
     
    728742            break;
    729743        }
    730 
    731         case VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR:
    732         {
    733             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DIR\n"));
    734 
    735             VBOXCLIPBOARDDIRDATA data;
    736             rc = VBoxSvcClipboardURISetDir(cParms, paParms, &data);
    737             break;
    738         }
    739 
     744#if 0
    740745        case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
    741746        {
     
    906911            break;
    907912        }
    908 
    909         case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_CANCEL:
    910             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_CANCEL\n"));
    911             AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    912             break;
    913 
    914         case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_ERROR:
    915             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_WRITE_ERROR\n"));
    916             AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    917             break;
     913#endif
     914        case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
     915            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_CANCEL\n"));
     916
     917            LogRel2(("Shared Clipboard: Transfer canceled\n"));
     918            break;
     919
     920        case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
     921        {
     922            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_ERROR\n"));
     923
     924            int rcGuest;
     925            rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
     926            if (RT_SUCCESS(rc))
     927                LogRel(("Shared Clipboard: Transfer error: %Rrc\n", rcGuest));
     928            break;
     929        }
    918930
    919931        default:
     
    922934    }
    923935
    924     if (fWriteToProvider)
    925         rc = VINF_SUCCESS;
    926 
    927     if (RT_SUCCESS(rc))
    928     {
    929         if (fWriteToProvider)
    930         {
    931             SHAREDCLIPBOARDPROVIDERWRITEPARMS writeParms;
    932             RT_ZERO(writeParms);
    933 
    934             writeParms.u.HostService.uMsg    = u32Function;
    935             writeParms.u.HostService.cParms  = cParms;
    936             writeParms.u.HostService.paParms = paParms;
    937 
    938             //rc = pTransfer->pProvider->OnWrite(&writeParms);
    939         }
    940     }
    941 
    942     LogFlowFuncLeaveRC(rc);
     936    if (rc == VINF_HGCM_ASYNC_EXECUTE)
     937    {
     938        try
     939        {
     940            vboxSvcClipboardClientDefer(pClient, callHandle, u32Function, cParms, paParms);
     941            g_listClientsDeferred.push_back(pClient->uClientID);
     942        }
     943        catch (std::bad_alloc &)
     944        {
     945            rc = VERR_NO_MEMORY;
     946            /* Don't report to guest. */
     947        }
     948    }
     949    else if (pClient)
     950    {
     951        int rc2 = vboxSvcClipboardClientComplete(pClient, callHandle, rc);
     952        AssertRC(rc2);
     953    }
     954
     955    LogFlowFunc(("Returning uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
    943956    return rc;
    944957}
     
    958971    RT_NOREF(cParms, paParms);
    959972
    960     int rc = VERR_INVALID_PARAMETER; /* Play safe. */
     973    int rc = VERR_NOT_IMPLEMENTED; /* Play safe. */
    961974
    962975    switch (u32Function)
    963976    {
    964977        case VBOX_SHARED_CLIPBOARD_HOST_FN_CANCEL:
    965             AssertFailed(); /** @todo Implement this. */
     978            /** @todo */
    966979            break;
    967980
    968981        case VBOX_SHARED_CLIPBOARD_HOST_FN_ERROR:
    969             AssertFailed(); /** @todo Implement this. */
     982            /** @todo */
    970983            break;
    971984
    972985        default:
    973             AssertMsgFailed(("Not implemented\n"));
    974986            break;
    975987
     
    10061018
    10071019        parms.uID = NIL_SHAREDCLIPBOARDAREAID;
    1008 
    1009         if (pTransfer->State.pMeta)
    1010         {
    1011             parms.u.fn_register.pvData = SharedClipboardMetaDataMutableRaw(pTransfer->State.pMeta);
    1012             parms.u.fn_register.cbData = (uint32_t)SharedClipboardMetaDataGetUsed(pTransfer->State.pMeta);
    1013         }
    10141020
    10151021        /* As the meta data is now complete, register a new clipboard on the host side. */
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.h

    r79347 r79497  
    2222#endif
    2323
    24 //int vboxSvcClipboardURIAnnounce(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    25 
    26 int vboxSvcClipboardURIHandler(uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival, bool *pfAsync);
     24int vboxSvcClipboardURIHandler(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE callHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival);
    2725int vboxSvcClipboardURIHostHandler(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    2826
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp

    r79347 r79497  
    5252    switch (uMsg)
    5353    {
    54         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR:
    55             RT_FALL_THROUGH();
    56         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK:
    57             RT_FALL_THROUGH();
    58         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR:
    59             RT_FALL_THROUGH();
    60         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR:
    61             RT_FALL_THROUGH();
    62         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA:
     54        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
     55            RT_FALL_THROUGH();
     56        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
     57            RT_FALL_THROUGH();
     58        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
     59            RT_FALL_THROUGH();
     60        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
     61            RT_FALL_THROUGH();
     62        case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN:
     63            RT_FALL_THROUGH();
     64        case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE:
     65            RT_FALL_THROUGH();
     66        case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ:
     67            fAllowed = fHostToGuest;
     68            break;
     69
     70        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
     71            RT_FALL_THROUGH();
     72        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
     73            RT_FALL_THROUGH();
     74        case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE:
    6375            fAllowed = fGuestToHost;
    6476            break;
    6577
    66         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR:
    67             RT_FALL_THROUGH();
    68         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK:
    69             RT_FALL_THROUGH();
    70         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR:
    71             RT_FALL_THROUGH();
    72         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR:
    73             RT_FALL_THROUGH();
    74         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA:
    75             fAllowed = fHostToGuest;
    76             break;
    77 
    78         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL:
    79             RT_FALL_THROUGH();
    80         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR:
     78        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
     79            RT_FALL_THROUGH();
     80        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     81            RT_FALL_THROUGH();
     82        case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
     83            RT_FALL_THROUGH();
     84        case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
    8185            fAllowed = fHostToGuest || fGuestToHost;
    8286            break;
     
    9094}
    9195
    92 int vboxSvcClipboardURIReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uFormats)
     96int vboxSvcClipboardURIReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uParm)
    9397{
    9498    AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
    9599
    96     RT_NOREF(uFormats);
    97 
    98     if (!vboxSvcClipboardURIMsgIsAllowed(vboxSvcClipboardGetMode(), uMsg))
    99         return VERR_ACCESS_DENIED;
    100 
    101100    int rc = VINF_SUCCESS;
    102101
    103102    switch (uMsg)
    104103    {
    105         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR:
    106             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_HDR\n"));
    107             break;
    108         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR:
    109             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_HDR\n"));
    110             break;
    111         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK:
    112             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DATA_CHUNK\n"));
    113             break;
    114         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK:
    115             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DATA_CHUNK\n"));
    116             break;
    117         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR:
    118             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_DIR\n"));
    119             break;
    120         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR:
    121             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_DIR\n"));
    122             break;
    123         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR:
    124             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_HDR\n"));
    125             break;
    126         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR:
    127             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_HDR\n"));
    128             break;
    129         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA:
    130             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_READ_FILE_DATA\n"));
    131             break;
    132         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA:
    133             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_WRITE_FILE_DATA\n"));
    134             break;
    135         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL:
    136             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL\n"));
    137             break;
    138         case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR:
    139             LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR\n"));
    140             break;
     104        case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START:
     105        {
     106            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START\n"));
     107
     108            if (   vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
     109                && vboxSvcClipboardGetMode() != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
     110            {
     111                LogFlowFunc(("Wrong clipboard mode, skipping\n"));
     112                break;
     113            }
     114
     115            pClientData->State.URI.fTransferStart = true;
     116            pClientData->State.URI.enmTransferDir = (SHAREDCLIPBOARDURITRANSFERDIR)uParm;
     117            break;
     118
     119        }
    141120
    142121        default:
     
    150129}
    151130
    152 static bool s_fReqHdr = false;
    153 
    154131bool vboxSvcClipboardURIReturnMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    155132{
     
    158135    bool fHandled = false;
    159136
    160     /* For now we only support one transfer at a time. */
    161     PSHAREDCLIPBOARDURITRANSFER pTransfer = SharedClipboardURICtxGetTransfer(&pClientData->URI, 0 /* Index */);
    162     if (!pTransfer)
    163         return fHandled;
     137    if (   pClientData->State.URI.fTransferStart
     138        && cParms >= 2)
     139    {
     140        HGCMSvcSetU32(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
     141        HGCMSvcSetU32(&paParms[1], pClientData->State.URI.enmTransferDir);
     142        pClientData->State.URI.fTransferStart = false;
     143
     144        fHandled = true;
     145    }
    164146
    165147#if 1
     
    175157    {
    176158        LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA_HDR\n"));
    177         rc = VBoxSvcClipboardURIWriteDataHdr(cParms, paParms, pTransfer->State.pHeader);
     159        rc = VBoxSvcClipboardURIWriteListHdr(cParms, paParms, pTransfer->State.pHeader);
    178160        if (RT_SUCCESS(rc))
    179161        {
    180162            /* We're done witht the data header, destroy it. */
    181             SharedClipboardURIDataHdrFree(pTransfer->State.pHeader);
     163            SharedClipboardURIListHdrFree(pTransfer->State.pHeader);
    182164            pTransfer->State.pHeader = NULL;
    183165
     
    198180            Assert(cbRead <= cbBuf);
    199181
    200             VBOXCLIPBOARDDATACHUNK dataChunk;
    201             RT_ZERO(dataChunk);
    202             dataChunk.pvData = pvBuf;
    203             dataChunk.cbData = cbRead;
    204 
    205             rc = VBoxSvcClipboardURIWriteDataChunk(cParms, paParms, &dataChunk);
     182            VBOXCLIPBOARDListEntry ListEntry;
     183            RT_ZERO(ListEntry);
     184            ListEntry.pvData = pvBuf;
     185            ListEntry.cbData = cbRead;
     186
     187            rc = VBoxSvcClipboardURIWriteListEntry(cParms, paParms, &ListEntry);
    206188        }
    207189
     
    234216                case SharedClipboardURIObject::Type_Directory:
    235217                {
    236                     rc = VBoxSvcClipboardURIWriteDir(cParms, paParms, &dataChunk);
     218                    rc = VBoxSvcClipboardURIWriteDir(cParms, paParms, &ListEntry);
    237219                    break;
    238220                }
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r79366 r79497  
    4949#endif
    5050
    51 /** Static window class name. */
    52 static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME;
    53 
    5451
    5552/*********************************************************************************************************************************
     
    6966    VBOXCLIPBOARDWINCTX      Win;
    7067};
    71 
    72 /* Only one client is supported. There seems to be no need for more clients. */
    73 static VBOXCLIPBOARDCONTEXT g_ctx;
    7468
    7569
     
    151145}
    152146
    153 static LRESULT CALLBACK vboxClipboardSvcWinWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    154 {
     147static LRESULT CALLBACK vboxClipboardSvcWinWndProcMain(PVBOXCLIPBOARDCONTEXT pCtx,
     148                                                       HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     149{
     150    AssertPtr(pCtx);
     151
    155152    LRESULT lresultRc = 0;
    156153
    157     const PVBOXCLIPBOARDCONTEXT pCtx    = &g_ctx;
    158     const PVBOXCLIPBOARDWINCTX  pWinCtx = &pCtx->Win;
    159 
    160     switch (msg)
     154    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
     155
     156    switch (uMsg)
    161157    {
    162158        case WM_CLIPBOARDUPDATE:
     
    165161            if (pWinCtx->hWndClipboardOwnerUs != hWndClipboardOwner)
    166162            {
    167                 LogFunc(("WM_CLIPBOARDUPDATE: hWndOldClipboardOwner=%p, hWndNewClipboardOwner=%p\n",
     163                LogFunc(("WM_CLIPBOARDUPDATE: hWndClipboardOwnerUs=%p, hWndNewClipboardOwner=%p\n",
    168164                         pWinCtx->hWndClipboardOwnerUs, hWndClipboardOwner));
    169165
     
    179175        {
    180176            LogFunc(("WM_CHANGECBCHAIN\n"));
    181             lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, hwnd, msg, wParam, lParam);
     177            lresultRc = VBoxClipboardWinHandleWMChangeCBChain(pWinCtx, hWnd, uMsg, wParam, lParam);
    182178        } break;
    183179
     
    186182            LogFunc(("WM_DRAWCLIPBOARD\n"));
    187183
    188             if (GetClipboardOwner() != hwnd)
     184            if (GetClipboardOwner() != hWnd)
    189185            {
    190186                /* Clipboard was updated by another application, retrieve formats and report back. */
     
    194190            }
    195191
    196             lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, msg, wParam, lParam);
     192            lresultRc = VBoxClipboardWinChainPassToNext(pWinCtx, uMsg, wParam, lParam);
    197193
    198194        } break;
     
    226222                int rc = vboxClipboardSvcWinRequestData(pCtx, fFormat, 30 * 1000 /* 30s timeout */);
    227223
    228                 LogFunc(("vboxClipboardReadDataFromClient rc = %Rrc, pv %p, cb %d, u32Format %d\n",
    229                          rc, pCtx->pClientData->State.data.pv, pCtx->pClientData->State.data.cb,
    230                          pCtx->pClientData->State.data.u32Format));
     224                LogFlowFunc(("rc=%Rrc, pv=%p, cb=%RU32, u32Format=%RU32\n",
     225                             rc, pCtx->pClientData->State.data.pv, pCtx->pClientData->State.data.cb,
     226                             pCtx->pClientData->State.data.u32Format));
    231227
    232228                if (   RT_SUCCESS (rc)
     
    237233                    HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, pCtx->pClientData->State.data.cb);
    238234
    239                     LogFunc(("hMem %p\n", hMem));
     235                    LogFlowFunc(("hMem=%p\n", hMem));
    240236
    241237                    if (hMem)
     
    243239                        void *pMem = GlobalLock(hMem);
    244240
    245                         LogFunc(("pMem %p, GlobalSize %d\n", pMem, GlobalSize(hMem)));
     241                        LogFlowFunc(("pMem=%p, GlobalSize=%zu\n", pMem, GlobalSize(hMem)));
    246242
    247243                        if (pMem)
    248244                        {
    249                             LogFunc(("WM_RENDERFORMAT setting data\n"));
     245                            LogFlowFunc(("WM_RENDERFORMAT: Setting data\n"));
    250246
    251247                            if (pCtx->pClientData->State.data.pv)
     
    268264                            HANDLE hClip = SetClipboardData(cfFormat, hMem);
    269265
    270                             LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip));
     266                            LogFlowFunc(("hClip=%p\n", hClip));
    271267
    272268                            if (hClip)
     
    295291            LogFunc(("WM_RENDERALLFORMATS\n"));
    296292
    297             int rc = VBoxClipboardWinHandleWMRenderAllFormats(pWinCtx, hwnd);
     293            int rc = VBoxClipboardWinHandleWMRenderAllFormats(pWinCtx, hWnd);
    298294            AssertRC(rc);
    299295        } break;
     
    309305                 * because host clipboard has more priority.
    310306                 */
    311                 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored\n"));
     307                LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored; pClientData=%p\n", pCtx->pClientData));
    312308                break;
    313309            }
     
    317313            if (fFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE) /* Could arrive with some older GA versions. */
    318314            {
    319                 int rc = VBoxClipboardWinOpen(hwnd);
     315                int rc = VBoxClipboardWinOpen(hWnd);
    320316                if (RT_SUCCESS(rc))
    321317                {
     
    369365
    370366        default:
    371         {
    372             LogFunc(("WM_ %p\n", msg));
    373             lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    374         }
    375     }
    376 
    377     LogFunc(("WM_ rc %d\n", lresultRc));
    378     return lresultRc;
     367            break;
     368    }
     369
     370    LogFlowFunc(("hWnd=%p, WM_ %u\n", hWnd, uMsg));
     371    return DefWindowProc(hWnd, uMsg, wParam, lParam);
     372}
     373
     374/**
     375 * Static helper function for having a per-client proxy window instances.
     376 */
     377static LRESULT CALLBACK vboxClipboardSvcWinWndProcInstance(HWND hWnd, UINT uMsg,
     378                                                           WPARAM wParam, LPARAM lParam)
     379{
     380    LONG_PTR pUserData = GetWindowLongPtr(hWnd, GWLP_USERDATA);
     381    AssertPtrReturn(pUserData, 0);
     382
     383    PVBOXCLIPBOARDCONTEXT pCtx = reinterpret_cast<PVBOXCLIPBOARDCONTEXT>(pUserData);
     384    if (pCtx)
     385        return vboxClipboardSvcWinWndProcMain(pCtx, hWnd, uMsg, wParam, lParam);
     386
     387    return 0;
     388}
     389
     390/**
     391 * Static helper function for routing Windows messages to a specific
     392 * proxy window instance.
     393 */
     394static LRESULT CALLBACK vboxClipboardSvcWinWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     395{
     396    /* Note: WM_NCCREATE is not the first ever message which arrives, but
     397     *       early enough for us. */
     398    if (uMsg == WM_NCCREATE)
     399    {
     400        LogFlowFunc(("WM_NCCREATE\n"));
     401
     402        LPCREATESTRUCT pCS = (LPCREATESTRUCT)lParam;
     403        AssertPtr(pCS);
     404        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCS->lpCreateParams);
     405        SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)vboxClipboardSvcWinWndProcInstance);
     406
     407        return vboxClipboardSvcWinWndProcInstance(hWnd, uMsg, wParam, lParam);
     408    }
     409
     410    /* No window associated yet. */
     411    return DefWindowProc(hWnd, uMsg, wParam, lParam);
    379412}
    380413
    381414DECLCALLBACK(int) vboxClipboardSvcWinThread(RTTHREAD hThreadSelf, void *pvUser)
    382415{
    383     RT_NOREF(hThreadSelf, pvUser);
    384 
    385     /* Create a window and make it a clipboard viewer. */
    386     int rc = VINF_SUCCESS;
    387 
    388416    LogFlowFuncEnter();
    389417
    390     const PVBOXCLIPBOARDCONTEXT pCtx    = &g_ctx;
     418    bool fThreadSignalled = false;
     419
     420    const PVBOXCLIPBOARDCONTEXT pCtx    = (PVBOXCLIPBOARDCONTEXT)pvUser;
     421    AssertPtr(pCtx);
    391422    const PVBOXCLIPBOARDWINCTX  pWinCtx = &pCtx->Win;
    392423
     
    401432    wc.hInstance     = hInstance;
    402433    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
    403     wc.lpszClassName = s_szClipWndClassName;
     434
     435    /* Register an unique wnd class name. */
     436    char szWndClassName[32];
     437    RTStrPrintf2(szWndClassName, sizeof(szWndClassName),
     438                 "%s-%RU64", VBOX_CLIPBOARD_WNDCLASS_NAME, RTThreadGetNative(hThreadSelf));
     439    wc.lpszClassName = szWndClassName;
     440
     441    int rc;
    404442
    405443    ATOM atomWindowClass = RegisterClass(&wc);
    406 
    407444    if (atomWindowClass == 0)
    408445    {
     
    412449    else
    413450    {
    414         /* Create the window. */
     451        /* Create a window and make it a clipboard viewer. */
    415452        pWinCtx->hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
    416                                        s_szClipWndClassName, s_szClipWndClassName,
     453                                       szWndClassName, szWndClassName,
    417454                                       WS_POPUPWINDOW,
    418                                        -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
     455                                       -200, -200, 100, 100, NULL, NULL, hInstance, pCtx /* lpParam */);
    419456        if (pWinCtx->hWnd == NULL)
    420457        {
     
    447484            }
    448485#endif
     486
     487            int rc2 = RTThreadUserSignal(hThreadSelf);
     488            AssertRC(rc2);
     489
     490            fThreadSignalled = true;
     491
    449492            MSG msg;
    450493            BOOL msgret = 0;
     
    454497                DispatchMessage(&msg);
    455498            }
     499
    456500            /*
    457             * Window procedure can return error,
    458             * but this is exceptional situation
    459             * that should be identified in testing
    460             */
     501             * Window procedure can return error, * but this is exceptional situation that should be
     502             * identified in testing.
     503             */
    461504            Assert(msgret >= 0);
    462505            LogFunc(("Message loop finished. GetMessage returned %d, message id: %d \n", msgret, msg.message));
     
    473516    if (atomWindowClass != 0)
    474517    {
    475         UnregisterClass(s_szClipWndClassName, hInstance);
     518        UnregisterClass(szWndClassName, hInstance);
    476519        atomWindowClass = 0;
     520    }
     521
     522    if (!fThreadSignalled)
     523    {
     524        int rc2 = RTThreadUserSignal(hThreadSelf);
     525        AssertRC(rc2);
    477526    }
    478527
     
    498547    if (pCtx->pClientData)
    499548    {
    500         uint32_t uFormats;
     549        VBOXCLIPBOARDFORMATS uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;
    501550        rc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
    502         if (RT_SUCCESS(rc))
     551        if (   RT_SUCCESS(rc)
     552            && uFormats != VBOX_SHARED_CLIPBOARD_FMT_NONE
     553#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     554            /* For URI handling we don't need to sync the format. */
     555            && !(uFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     556#endif
     557           )
     558        {
    503559            vboxSvcClipboardReportMsg(pCtx->pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, uFormats);
     560        }
    504561    }
    505562    else /* If we don't have any client data (yet), bail out. */
     
    516573int VBoxClipboardSvcImplInit(void)
    517574{
    518     RT_ZERO(g_ctx); /* Be careful not messing up non-POD types! */
    519 
    520     /* Check that new Clipboard API is available. */
    521     VBoxClipboardWinCheckAndInitNewAPI(&g_ctx.Win.newAPI);
    522 
    523     int rc = RTSemEventCreate(&g_ctx.hRenderEvent);
    524     if (RT_SUCCESS(rc))
    525     {
    526         rc = RTThreadCreate(&g_ctx.hThread, vboxClipboardSvcWinThread, NULL, _64K /* Stack size */,
    527                             RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
    528     }
    529 
    530     if (RT_FAILURE(rc))
    531         RTSemEventDestroy(g_ctx.hRenderEvent);
     575    /* Initialization is done in VBoxClipboardSvcImplConnect(). */
     576    return VINF_SUCCESS;
     577}
     578
     579void VBoxClipboardSvcImplDestroy(void)
     580{
     581    /* Destruction is done in VBoxClipboardSvcImplDisconnect(). */
     582}
     583
     584int VBoxClipboardSvcImplConnect(PVBOXCLIPBOARDCLIENTDATA pClientData, bool fHeadless)
     585{
     586    RT_NOREF(fHeadless);
     587
     588    AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
     589
     590    LogFlowFuncEnter();
     591
     592    int rc;
     593
     594    PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT));
     595    if (pCtx)
     596    {
     597        /* Check that new Clipboard API is available. */
     598        rc = VBoxClipboardWinCheckAndInitNewAPI(&pCtx->Win.newAPI);
     599        if (RT_SUCCESS(rc))
     600        {
     601            rc = RTSemEventCreate(&pCtx->hRenderEvent);
     602            if (RT_SUCCESS(rc))
     603            {
     604                rc = RTThreadCreate(&pCtx->hThread, vboxClipboardSvcWinThread, pCtx /* pvUser */, _64K /* Stack size */,
     605                                    RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
     606                if (RT_SUCCESS(rc))
     607                {
     608                    int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */);
     609                    AssertRC(rc2);
     610                }
     611            }
     612
     613            if (RT_FAILURE(rc))
     614                RTSemEventDestroy(pCtx->hRenderEvent);
     615        }
     616
     617        pClientData->State.pCtx = pCtx;
     618        pClientData->State.pCtx->pClientData = pClientData;
     619
     620        /* Sync the host clipboard content with the client. */
     621        rc = VBoxClipboardSvcImplSync(pClientData);
     622    }
     623    else
     624        rc = VERR_NO_MEMORY;
    532625
    533626    LogFlowFuncLeaveRC(rc);
     
    535628}
    536629
    537 void VBoxClipboardSvcImplDestroy(void)
    538 {
    539     LogFlowFuncEnter();
    540 
    541     if (g_ctx.Win.hWnd)
    542     {
    543         PostMessage(g_ctx.Win.hWnd, WM_CLOSE, 0, 0);
    544     }
    545 
    546     int rc = RTSemEventDestroy(g_ctx.hRenderEvent);
    547     AssertRC(rc);
    548 
    549     /* Wait for the window thread to terminate. */
    550     rc = RTThreadWait(g_ctx.hThread, 30 * 1000 /* Timeout in ms */, NULL);
    551     if (RT_FAILURE(rc))
    552         LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc));
    553 
    554     g_ctx.hThread = NIL_RTTHREAD;
    555 }
    556 
    557 int VBoxClipboardSvcImplConnect(PVBOXCLIPBOARDCLIENTDATA pClientData, bool fHeadless)
    558 {
    559     RT_NOREF(fHeadless);
    560 
    561     LogFlowFuncEnter();
    562 
    563     if (g_ctx.pClientData != NULL)
    564     {
    565         /* One client only. */
    566         return VERR_NOT_SUPPORTED;
    567     }
    568 
    569     pClientData->State.pCtx = &g_ctx;
    570 
    571     pClientData->State.pCtx->pClientData = pClientData;
    572 
    573     /* Sync the host clipboard content with the client. */
    574     VBoxClipboardSvcImplSync(pClientData);
    575 
    576     return VINF_SUCCESS;
    577 }
    578 
    579630int VBoxClipboardSvcImplSync(PVBOXCLIPBOARDCLIENTDATA pClientData)
    580631{
     
    585636int VBoxClipboardSvcImplDisconnect(PVBOXCLIPBOARDCLIENTDATA pClientData)
    586637{
    587     RT_NOREF(pClientData);
     638    AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
    588639
    589640    LogFlowFuncEnter();
    590641
    591     g_ctx.pClientData = NULL;
    592 
    593     return VINF_SUCCESS;
     642    int rc = VINF_SUCCESS;
     643
     644    PVBOXCLIPBOARDCONTEXT pCtx = pClientData->State.pCtx;
     645    if (pCtx)
     646    {
     647        if (pCtx->Win.hWnd)
     648            PostMessage(pCtx->Win.hWnd, WM_CLOSE, 0 /* wParam */, 0 /* lParam */);
     649
     650        rc = RTSemEventDestroy(pCtx->hRenderEvent);
     651        if (RT_SUCCESS(rc))
     652        {
     653            if (pCtx->hThread != NIL_RTTHREAD)
     654            {
     655                LogFunc(("Waiting for thread to terminate ...\n"));
     656
     657                /* Wait for the window thread to terminate. */
     658                rc = RTThreadWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */, NULL);
     659                if (RT_FAILURE(rc))
     660                    LogRel(("Shared Clipboard: Waiting for window thread termination failed with rc=%Rrc\n", rc));
     661
     662                pCtx->hThread = NIL_RTTHREAD;
     663            }
     664        }
     665
     666        if (RT_SUCCESS(rc))
     667        {
     668            RTMemFree(pCtx);
     669            pCtx = NULL;
     670
     671            pClientData->State.pCtx = NULL;
     672        }
     673    }
     674
     675    LogFlowFuncLeaveRC(rc);
     676    return rc;
    594677}
    595678
     
    597680{
    598681    AssertPtrReturn(pClientData, VERR_INVALID_POINTER);
    599     AssertPtrReturn(pClientData->State.pCtx, VERR_INVALID_POINTER);
     682
     683    PVBOXCLIPBOARDCONTEXT pCtx = pClientData->State.pCtx;
     684    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     685
     686    LogFlowFunc(("u32Formats=0x%x, hWnd=%p\n", u32Formats, pCtx->Win.hWnd));
    600687
    601688    /*
    602      * The guest announces formats. Forward to the window thread.
     689     * The guest announced formats. Forward to the window thread.
    603690     */
    604     PostMessage(pClientData->State.pCtx->Win.hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 0, u32Formats);
     691    PostMessage(pCtx->Win.hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS,
     692                0 /* wParam */, u32Formats /* lParam */);
    605693
    606694    return VINF_SUCCESS;
     
    770858
    771859#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    772 void VBoxClipboardSvcImplURIOnDataHeaderComplete(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
    773 {
     860int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer)
     861{
     862    RT_NOREF(pClientData, pTransfer);
     863
    774864    LogFlowFuncEnter();
    775865
    776     AssertPtrReturnVoid(pData);
    777 
    778     PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer;
    779     AssertPtrReturnVoid(pTransfer);
    780 
    781     SharedClipboardWinURITransferCtx *pTransferCtx = (SharedClipboardWinURITransferCtx *)pTransfer->pvUser;
    782     AssertPtrReturnVoid(pTransferCtx);
    783 
    784     /* Notify the Windows implementation's data object that the meta data has been read successfully. */
    785     if (pTransferCtx->pDataObj)
    786         pTransferCtx->pDataObj->OnMetaDataComplete(pTransfer);
    787 }
    788 
    789 int VBoxClipboardSvcImplURITransferCreate(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer)
    790 {
    791     RT_NOREF(pClientData, pTransfer);
    792 
     866    return VINF_SUCCESS;
     867}
     868
     869int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer)
     870{
    793871    LogFlowFuncEnter();
    794872
     873    VBoxClipboardWinURITransferDestroy(&pClientData->State.pCtx->Win, pTransfer);
     874
    795875    return VINF_SUCCESS;
    796876}
    797 
    798 int VBoxClipboardSvcImplURITransferDestroy(PVBOXCLIPBOARDCLIENTDATA pClientData, PSHAREDCLIPBOARDURITRANSFER pTransfer)
    799 {
    800     LogFlowFuncEnter();
    801 
    802     VBoxClipboardWinURITransferDestroy(&pClientData->State.pCtx->Win, pTransfer);
    803 
    804     return VINF_SUCCESS;
    805 }
    806877#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
    807878
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r79366 r79497  
    136136#include <VBox/log.h>
    137137
     138#include <VBox/HostServices/Service.h>
    138139#include <VBox/HostServices/VBoxClipboardSvc.h>
    139140#include <VBox/HostServices/VBoxClipboardExt.h>
     
    151152# include "VBoxSharedClipboardSvc-uri.h"
    152153#endif
     154
     155using namespace HGCM;
    153156
    154157
     
    172175void *g_pvExtension;
    173176
    174 static PVBOXCLIPBOARDCLIENTDATA g_pClientData;
    175 
    176177/* Serialization of data reading and format announcements from the RDP client. */
    177178static bool g_fReadingData = false;
     
    181182/** Is the clipboard running in headless mode? */
    182183static bool g_fHeadless = false;
     184
     185/** Map of all connected clients. */
     186ClipboardClientMap g_mapClients;
     187
     188/** List of all clients which are queued up (deferred return) and ready
     189 *  to process new commands. The key is the (unique) client ID. */
     190ClipboardClientQueue g_listClientsDeferred;
    183191
    184192
     
    252260    int rc2 = RTCritSectLeave(&g_CritSect);
    253261    AssertRC(rc2);
     262}
     263
     264/**
     265 * Resets a client's state message queue.
     266 *
     267 * @param   pState              Pointer to the client's state structure to reset message queue for.
     268 */
     269void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTSTATE pState)
     270{
     271    LogFlowFuncEnter();
     272
     273    while (!pState->queueMsg.isEmpty())
     274    {
     275        RTMemFree(pState->queueMsg.last());
     276        pState->queueMsg.removeLast();
     277    }
     278}
     279
     280/**
     281 * Allocates a new clipboard message.
     282 *
     283 * @returns Allocated clipboard message, or NULL on failure.
     284 * @param   uMsg                Message type of message to allocate.
     285 * @param   cParms              Number of HGCM parameters to allocate.
     286 */
     287PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms)
     288{
     289    PVBOXCLIPBOARDCLIENTMSG pMsg = (PVBOXCLIPBOARDCLIENTMSG)RTMemAlloc(sizeof(VBOXCLIPBOARDCLIENTMSG));
     290    if (pMsg)
     291    {
     292        pMsg->m_paParms = (PVBOXHGCMSVCPARM)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * cParms);
     293        if (pMsg->m_paParms)
     294        {
     295            pMsg->m_cParms = cParms;
     296            pMsg->m_uMsg   = uMsg;
     297
     298            return pMsg;
     299        }
     300    }
     301
     302    RTMemFree(pMsg);
     303    return NULL;
     304}
     305
     306/**
     307 * Frees a formerly allocated clipboard message.
     308 *
     309 * @param   pMsg                Clipboard message to free.
     310 *                              The pointer will be invalid after calling this function.
     311 */
     312void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg)
     313{
     314    if (!pMsg)
     315        return;
     316
     317    if (pMsg->m_paParms)
     318        RTMemFree(pMsg->m_paParms);
     319
     320    RTMemFree(pMsg);
     321    pMsg = NULL;
     322}
     323
     324/**
     325 * Adds a new message to a client'S message queue.
     326 *
     327 * @returns IPRT status code.
     328 * @param   pState              Pointer to the client's state structure to add new message to.
     329 * @param   pMsg                Pointer to message to add. The queue then owns the pointer.
     330 * @param   fAppend             Whether to append or prepend the message to the queue.
     331 */
     332int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTSTATE pState, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend)
     333{
     334    AssertPtrReturn(pMsg, VERR_INVALID_POINTER);
     335
     336    LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", pMsg->m_uMsg, pMsg->m_cParms, fAppend));
     337
     338    if (fAppend)
     339        pState->queueMsg.append(pMsg);
     340    else
     341        pState->queueMsg.prepend(pMsg);
     342
     343    /** @todo Catch / handle OOM? */
     344
     345    return VINF_SUCCESS;
     346}
     347
     348/**
     349 * Retrieves information about the next message in the queue.
     350 *
     351 * @returns IPRT status code. VERR_NO_DATA if no next message is available.
     352 * @param   pState              Pointer to the client's state structure to get message info for.
     353 * @param   puType              Where to store the message type.
     354 * @param   pcParms             Where to store the message parameter count.
     355 */
     356int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTSTATE pState, uint32_t *puType, uint32_t *pcParms)
     357{
     358    AssertPtrReturn(puType, VERR_INVALID_POINTER);
     359    AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
     360
     361    int rc;
     362
     363    if (pState->queueMsg.isEmpty())
     364    {
     365        rc = VERR_NO_DATA;
     366    }
     367    else
     368    {
     369        PVBOXCLIPBOARDCLIENTMSG pMsg = pState->queueMsg.first();
     370        AssertPtr(pMsg);
     371
     372        *puType  = pMsg->m_uMsg;
     373        *pcParms = pMsg->m_cParms;
     374
     375        rc = VINF_SUCCESS;
     376    }
     377
     378    LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puType, *pcParms, rc));
     379    return rc;
     380}
     381
     382/**
     383 * Retrieves the next queued up message and removes it from the queue on success.
     384 * Will return VERR_NO_DATA if no next message is available.
     385 *
     386 * @returns IPRT status code.
     387 * @param   pState              Pointer to the client's state structure to get message for.
     388 * @param   uMsg                Message type to retrieve.
     389 * @param   cParms              Number of parameters the \@a paParms array can store.
     390 * @param   paParms             Where to store the message parameters.
     391 */
     392int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTSTATE pState,
     393                               uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     394{
     395    LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
     396
     397    /* Check for pending messages in our queue. */
     398    if (pState->queueMsg.isEmpty())
     399        return VERR_NO_DATA;
     400
     401    /* Get the current message. */
     402    PVBOXCLIPBOARDCLIENTMSG pMsg = pState->queueMsg.first();
     403    AssertPtr(pMsg);
     404
     405    int rc = VINF_SUCCESS;
     406
     407    /* Fetch the current message info. */
     408    if (pMsg->m_uMsg != uMsg)
     409    {
     410        LogFunc(("Stored message type (%RU32) does not match request (%RU32)\n", pMsg->m_uMsg, uMsg));
     411        rc = VERR_INVALID_PARAMETER;
     412    }
     413    else if (pMsg->m_cParms > cParms)
     414    {
     415        LogFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", pMsg->m_cParms, cParms));
     416        rc = VERR_INVALID_PARAMETER;
     417    }
     418
     419    if (RT_SUCCESS(rc))
     420    {
     421        rc = Message::CopyParms(paParms, cParms, pMsg->m_paParms, pMsg->m_cParms, true /* fDeepCopy */);
     422
     423        /** @todo Only remove on success? */
     424        pState->queueMsg.removeFirst(); /* Remove the current message from the queue. */
     425    }
     426    else
     427    {
     428        vboxSvcClipboardMsgQueueReset(pState);
     429        /** @todo Cleanup, send notification to guest. */
     430    }
     431
     432    LogFlowFunc(("Message processed with rc=%Rrc\n", rc));
     433    return rc;
    254434}
    255435
     
    469649static DECLCALLBACK(int) svcUnload(void *)
    470650{
     651    LogFlowFuncEnter();
     652
    471653    VBoxClipboardSvcImplDestroy();
     654
     655    ClipboardClientMap::iterator itClient = g_mapClients.begin();
     656    while (itClient != g_mapClients.end())
     657    {
     658        RTMemFree(itClient->second);
     659        g_mapClients.erase(itClient);
     660
     661        itClient = g_mapClients.begin();
     662    }
     663
    472664    RTCritSectDelete(&g_CritSect);
     665
    473666    return VINF_SUCCESS;
    474667}
     
    482675    RT_NOREF(u32ClientID);
    483676
    484     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
    485 
    486677    LogFunc(("u32ClientID=%RU32\n", u32ClientID));
     678
     679    ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID);
     680    if (itClient == g_mapClients.end())
     681    {
     682        AssertFailed(); /* Should never happen. */
     683        return VERR_NOT_FOUND;
     684    }
     685
     686    PVBOXCLIPBOARDCLIENT     pClient     = itClient->second;
     687    AssertPtr(pClient);
     688    PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
     689    AssertPtr(pClientData);
     690
     691    /* Sanity. */
     692    Assert(pClientData == (PVBOXCLIPBOARDCLIENTDATA)pvClient);
    487693
    488694    vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0); /** @todo r=andy Why is this necessary? The client already disconnected ... */
     
    503709    vboxSvcClipboardClientStateDestroy(&pClientData->State);
    504710
    505     g_pClientData = NULL;
     711    RTMemFree(itClient->second);
     712    g_mapClients.erase(itClient);
    506713
    507714    return VINF_SUCCESS;
     
    512719    RT_NOREF(fRequestor, fRestoring);
    513720
    514     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
    515 
    516721    LogFlowFunc(("u32ClientID=%RU32\n", u32ClientID));
    517722
    518     /* If there is already a client connected then we want to release it first. */
    519     if (g_pClientData != NULL)
    520     {
    521         uint32_t uOldClientID = g_pClientData->State.u32ClientID;
    522         if (uOldClientID)
    523         {
    524             svcDisconnect(NULL, uOldClientID, g_pClientData);
    525 
    526             /* And free the resources in the HGCM subsystem. */
    527             g_pHelpers->pfnDisconnectClient(g_pHelpers->pvInstance, uOldClientID);
     723    int rc = VINF_SUCCESS;
     724
     725    if (g_mapClients.find(u32ClientID) != g_mapClients.end())
     726    {
     727        rc = VERR_ALREADY_EXISTS;
     728        AssertFailed(); /* Should never happen. */
     729    }
     730
     731    if (RT_SUCCESS(rc))
     732    {
     733        PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCLIENT));
     734        if (RT_SUCCESS(rc))
     735        {
     736            pClient->uClientID = u32ClientID;
     737            pClient->pData     = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
     738
     739            /* Reset the client state. */
     740            vboxSvcClipboardClientStateReset(&pClient->pData->State);
     741
     742            /* (Re-)initialize the client state. */
     743            vboxSvcClipboardClientStateInit(&pClient->pData->State, u32ClientID);
     744
     745            rc = VBoxClipboardSvcImplConnect(pClient->pData, VBoxSvcClipboardGetHeadless());
     746#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     747            if (RT_SUCCESS(rc))
     748                rc = SharedClipboardURICtxInit(&pClient->pData->URI);
     749#endif
     750            g_mapClients[u32ClientID] = pClient; /** @todo Can this throw? */
    528751        }
    529     }
    530 
    531     /* Reset the client state. */
    532     vboxSvcClipboardClientStateReset(&pClientData->State);
    533 
    534     /* (Re-)initialize the client state. */
    535     vboxSvcClipboardClientStateInit(&pClientData->State, u32ClientID);
    536 
    537     int rc = VBoxClipboardSvcImplConnect(pClientData, VBoxSvcClipboardGetHeadless());
    538 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    539     if (RT_SUCCESS(rc))
    540         rc = SharedClipboardURICtxInit(&pClientData->URI);
    541 #endif
    542 
    543     if (RT_SUCCESS(rc))
    544     {
    545         g_pClientData = pClientData;
    546752    }
    547753
     
    559765                                  uint64_t tsArrival)
    560766{
    561     RT_NOREF(u32ClientID, tsArrival);
     767    RT_NOREF(u32ClientID, pvClient, tsArrival);
    562768
    563769    int rc = VINF_SUCCESS;
     
    566772             u32ClientID, u32Function, cParms, paParms));
    567773
    568     PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pvClient;
     774    ClipboardClientMap::iterator itClient = g_mapClients.find(u32ClientID);
     775    if (itClient == g_mapClients.end())
     776    {
     777        AssertFailed(); /* Should never happen. */
     778        return;
     779    }
     780
     781    PVBOXCLIPBOARDCLIENT     pClient     = itClient->second;
     782    AssertPtr(pClient);
     783    PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
     784    AssertPtr(pClientData);
    569785
    570786#ifdef DEBUG
     
    578794#endif
    579795
    580     bool fAsynchronousProcessing = false;
     796    bool fDefer = false;
    581797
    582798    switch (u32Function)
    583799    {
    584         case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
     800        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD:
    585801        {
    586802            /* The quest requests a host message. */
    587             LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n"));
    588 
    589             if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG)
     803            LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD\n"));
     804
     805            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG_OLD)
    590806            {
    591807                rc = VERR_INVALID_PARAMETER;
     
    610826                    {
    611827                        /* No event available at the time. Process asynchronously. */
    612                         fAsynchronousProcessing = true;
     828                        fDefer = true;
    613829
    614830                        pClientData->State.fAsync           = true;
     
    655871                        rc = vboxSvcClipboardSetSource(pClientData, SHAREDCLIPBOARDSOURCE_REMOTE);
    656872
    657 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     873#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_DISABLED
    658874                        if (   RT_SUCCESS(rc)
    659875                            && (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST))
     
    677893
    678894                                        RT_ZERO(creationCtx.Interface);
    679                                         creationCtx.Interface.pfnReadDataHdr    = VBoxSvcClipboardProviderImplURIReadDataHdr;
    680                                         creationCtx.Interface.pfnReadDataChunk  = VBoxSvcClipboardProviderImplURIReadDataChunk;
    681                                         creationCtx.Interface.pfnReadDirectory  = VBoxSvcClipboardProviderImplURIReadDir;
    682                                         creationCtx.Interface.pfnReadFileHdr    = VBoxSvcClipboardProviderImplURIReadFileHdr;
    683                                         creationCtx.Interface.pfnReadFileData   = VBoxSvcClipboardProviderImplURIReadFileData;
    684 
    685                                         creationCtx.pvUser = pClientData;
     895                                        RT_ZERO(creationCtx.Interface);
     896                                        creationCtx.Interface.pfnTransferOpen  = vboxSvcClipboardURITransferOpen;
     897                                        creationCtx.Interface.pfnTransferClose = vboxSvcClipboardURITransferClose;
     898                                        creationCtx.Interface.pfnListOpen      = vboxSvcClipboardURIListOpen;
     899                                        creationCtx.Interface.pfnListClose     = vboxSvcClipboardURIListClose;
     900                                        creationCtx.Interface.pfnListHdrRead   = vboxSvcClipboardURIListHdrRead;
     901                                        creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
     902                                        creationCtx.Interface.pfnObjOpen       = vboxSvcClipboardURIObjOpen;
     903                                        creationCtx.Interface.pfnObjClose      = vboxSvcClipboardURIObjClose;
     904                                        creationCtx.Interface.pfnObjRead       = vboxSvcClipboardURIObjRead;
     905
     906                                        creationCtx.pvUser = pClient;
    686907
    687908                                        /* Register needed callbacks so that we can wait for the meta data to arrive here. */
     
    692913
    693914                                        Callbacks.pfnTransferPrepare    = VBoxSvcClipboardURITransferPrepareCallback;
    694                                         Callbacks.pfnDataHeaderComplete = VBoxSvcClipboardURIDataHeaderCompleteCallback;
    695                                         Callbacks.pfnDataComplete       = VBoxSvcClipboardURIDataCompleteCallback;
    696915                                        Callbacks.pfnTransferComplete   = VBoxSvcClipboardURITransferCompleteCallback;
    697916                                        Callbacks.pfnTransferCanceled   = VBoxSvcClipboardURITransferCanceledCallback;
     
    728947                        if (RT_SUCCESS(rc))
    729948                        {
    730                             if (g_pfnExtension)
     949                            if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    731950                            {
    732                                 VBOXCLIPBOARDEXTPARMS parms;
    733                                 RT_ZERO(parms);
    734                                 parms.u32Format = u32Formats;
    735 
    736                                 g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms));
     951                                /* Tell the guest that we want to start a (reading) transfer. */
     952                                rc = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START,
     953                                                               0 /* u32Formats == 0 means reading data */);
     954
     955                                /* Note: Announcing the actual format will be done in the
     956                                         host service URI handler (vboxSvcClipboardURIHandler). */
    737957                            }
    738 
    739                             rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, u32Formats);
     958                            else /* Announce simple formats to the OS-specific service implemenation. */
     959                            {
     960                                if (g_pfnExtension)
     961                                {
     962                                    VBOXCLIPBOARDEXTPARMS parms;
     963                                    RT_ZERO(parms);
     964                                    parms.u32Format = u32Formats;
     965
     966                                    g_pfnExtension(g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms));
     967                                }
     968
     969                                rc = VBoxClipboardSvcImplFormatAnnounce(pClientData, u32Formats);
     970                            }
    740971                        }
    741972                    }
     
    7971028                                    RT_ZERO(creationCtx.Interface);
    7981029
    799                                     creationCtx.Interface.pfnWriteDataHdr    = VBoxSvcClipboardProviderImplURIWriteDataHdr;
    800                                     creationCtx.Interface.pfnWriteDataChunk  = VBoxSvcClipboardProviderImplURIWriteDataChunk;
    801                                     creationCtx.Interface.pfnWriteDirectory  = VBoxSvcClipboardProviderImplURIWriteDir;
    802                                     creationCtx.Interface.pfnWriteFileHdr    = VBoxSvcClipboardProviderImplURIWriteFileHdr;
    803                                     creationCtx.Interface.pfnWriteFileData   = VBoxSvcClipboardProviderImplURIWriteFileData;
     1030                                    creationCtx.Interface.pfnListHdrWrite    = vboxSvcClipboardURIListHdrWrite;
     1031                                    creationCtx.Interface.pfnListEntryWrite  = vboxSvcClipboardURIListEntryWrite;
     1032                                    creationCtx.Interface.pfnObjWrite        = vboxSvcClipboardURIObjWrite;
    8041033
    8051034                                    creationCtx.pvUser = pClientData;
     
    8531082                                if (g_fDelayedAnnouncement)
    8541083                                {
    855                                     vboxSvcClipboardReportMsg(g_pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, g_u32DelayedFormats);
     1084                                    vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, g_u32DelayedFormats);
    8561085                                    g_fDelayedAnnouncement = false;
    8571086                                    g_u32DelayedFormats = 0;
     
    8831112                                    pClientData->State.asyncRead.paParms    = paParms;
    8841113                                    pClientData->State.fReadPending         = true;
    885                                     fAsynchronousProcessing = true;
     1114                                    fDefer = true;
    8861115                                    VBoxSvcClipboardUnlock();
    8871116                                }
     
    9561185        {
    9571186#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    958             rc = vboxSvcClipboardURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival,
    959                                             &fAsynchronousProcessing);
     1187            rc = vboxSvcClipboardURIHandler(pClient, callHandle, u32Function, cParms, paParms, tsArrival);
     1188            if (RT_SUCCESS(rc))
     1189            {
     1190                /* The URI handler does deferring on its own. */
     1191                fDefer = true;
     1192            }
    9601193#else
    9611194            rc = VERR_NOT_IMPLEMENTED;
     
    9641197    }
    9651198
    966     LogFlowFunc(("fAsynchronousProcessing=%RTbool\n", fAsynchronousProcessing));
    967 
    968     if (!fAsynchronousProcessing)
     1199    LogFlowFunc(("u32ClientID=%RU32, fDefer=%RTbool\n", pClient->uClientID, fDefer));
     1200
     1201    if (!fDefer)
    9691202        g_pHelpers->pfnCallComplete(callHandle, rc);
    9701203
     
    9981231
    9991232/**
     1233 * Defers a client from returning back to the caller (guest side).
     1234 *
     1235 * @returns VBox status code.
     1236 * @param   pClient             Client to defer.
     1237 * @param   hHandle             The call handle to defer.
     1238 * @param   u32Function         Function ID to save.
     1239 * @param   cParms              Number of parameters to save.
     1240 * @param   paParms             Parameter arrray to save.
     1241 */
     1242int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
     1243                                VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1244{
     1245    LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
     1246
     1247    AssertMsgReturn(pClient->fDeferred == false, ("Client already in deferred mode\n"),
     1248                    VERR_WRONG_ORDER);
     1249
     1250    pClient->fDeferred = true;
     1251
     1252    pClient->Deferred.hHandle = hHandle;
     1253    pClient->Deferred.uType   = u32Function;
     1254    pClient->Deferred.cParms  = cParms;
     1255    pClient->Deferred.paParms = paParms;
     1256
     1257    return false;
     1258}
     1259
     1260/**
     1261 * Completes a call of a client, which in turn will return the result to the caller on
     1262 * the guest side.
     1263 *
     1264 * @returns VBox status code.
     1265 * @param   pClient             Client to complete.
     1266 * @param   hHandle             Call handle to complete.
     1267 * @param   rc                  Return code to set for the client.
     1268 */
     1269int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc)
     1270{
     1271    RT_NOREF(pClient);
     1272
     1273    LogFlowFunc(("uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
     1274
     1275    g_pHelpers->pfnCallComplete(hHandle, rc);
     1276
     1277    return VINF_SUCCESS;
     1278}
     1279
     1280/**
     1281 * Completes a deferred client.
     1282 *
     1283 * @returns VBox status code.
     1284 * @param   pClient             Client to complete.
     1285 * @param   rcComplete          Return code to set for the client.
     1286 */
     1287int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rcComplete)
     1288{
     1289    LogFlowFunc(("uClient=%RU32, fDeferred=%RTbool\n", pClient->uClientID, pClient->fDeferred));
     1290
     1291    int rc = VINF_SUCCESS;
     1292
     1293    if (pClient->fDeferred) /* Not deferred? Bail out early. */
     1294    {
     1295        LogFlowFunc(("Completing call\n"));
     1296
     1297        rc = vboxSvcClipboardClientComplete(pClient, pClient->Deferred.hHandle, rcComplete);
     1298
     1299        pClient->fDeferred = false;
     1300        RT_ZERO(pClient->Deferred);
     1301    }
     1302
     1303    return rc;
     1304}
     1305
     1306/**
     1307 * Sets a deferred client's next message info -- when returning to the client, it then
     1308 * can retrieve the actual message sent by the host.
     1309 *
     1310 * @returns VBox status code.
     1311 * @param   pClient             Client to set the next message information for.
     1312 * @param   uMsg                Message ID to set.
     1313 * @param   cParms              Number of parameters of message required.
     1314 */
     1315int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms)
     1316{
     1317    int rc;
     1318
     1319    LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
     1320
     1321    if (pClient->fDeferred)
     1322    {
     1323        if (pClient->Deferred.cParms >= 2)
     1324        {
     1325            AssertPtrReturn(pClient->Deferred.paParms, VERR_BUFFER_OVERFLOW);
     1326
     1327            HGCMSvcSetU32(&pClient->Deferred.paParms[0], uMsg);
     1328            HGCMSvcSetU32(&pClient->Deferred.paParms[1], cParms);
     1329
     1330            rc = VINF_SUCCESS;
     1331        }
     1332        else
     1333            rc = VERR_INVALID_PARAMETER;
     1334    }
     1335    else
     1336        rc = VERR_INVALID_STATE;
     1337
     1338    LogFlowFuncLeaveRC(rc);
     1339    return rc;
     1340}
     1341
     1342/**
    10001343 * Initializes a Shared Clipboard service's client state.
    10011344 *
     
    10251368    LogFlowFuncEnter();
    10261369
    1027     RT_NOREF(pState);
     1370    vboxSvcClipboardMsgQueueReset(pState);
    10281371
    10291372    return VINF_SUCCESS;
     
    10401383
    10411384    /** @todo Clear async / asynRead / ... data? */
    1042 
    1043     pState->u32ClientID = 0;
    1044     pState->fAsync = false;
    1045     pState->fHostMsgFormats = false;
    1046     pState->fHostMsgQuit = false;
    1047     pState->fHostMsgReadData = false;
    1048     pState->fReadPending = false;
     1385    vboxSvcClipboardMsgQueueReset(pState);
     1386
     1387    pState->u32ClientID                  = 0;
     1388    pState->fAsync                       = false;
     1389    pState->fReadPending                 = false;
     1390
     1391    pState->fHostMsgQuit                 = false;
     1392    pState->fHostMsgReadData             = false;
     1393    pState->fHostMsgFormats              = false;
     1394#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     1395    pState->URI.fTransferStart = false;
     1396    pState->URI.enmTransferDir = SHAREDCLIPBOARDURITRANSFERDIR_UNKNOWN;
     1397#endif
     1398
    10491399    pState->u32AvailableFormats = 0;
    10501400    pState->u32RequestedFormat = 0;
     
    10611411    int rc = VINF_SUCCESS;
    10621412
    1063     LogFunc(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n",
    1064              u32Function, cParms, paParms));
     1413    LogFlowFunc(("u32Function=%RU32, cParms=%RU32, paParms=%p\n", u32Function, cParms, paParms));
    10651414
    10661415    switch (u32Function)
     
    11111460#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    11121461            rc = vboxSvcClipboardURIHostHandler(u32Function, cParms, paParms);
     1462#else
     1463            rc = VERR_NOT_IMPLEMENTED;
    11131464#endif
    11141465        } break;
    11151466    }
    11161467
    1117     LogFlowFunc(("svcHostCall: rc = %Rrc\n", rc));
     1468    LogFlowFuncLeaveRC(rc);
    11181469    return rc;
    11191470}
     
    12181569    int rc = VINF_SUCCESS;
    12191570
    1220     if (g_pClientData != NULL)
     1571    PVBOXCLIPBOARDCLIENTDATA pClientData = NULL; /** @todo FIX !!! */
     1572
     1573    if (pClientData != NULL)
    12211574    {
    12221575        switch (u32Function)
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp

    r79120 r79497  
    118118    HGCMSvcSetU32(&parms[1], 0);
    119119    call.rc = VERR_TRY_AGAIN;
    120     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     120    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    121121                  2, parms, 0);
    122122    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This should get updated only when the guest call completes. */
     
    127127    RTTESTI_CHECK_RC_OK(call.rc);
    128128    call.rc = VERR_TRY_AGAIN;
    129     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     129    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    130130                  2, parms, 0);
    131131    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     
    138138    HGCMSvcSetU32(&parms[1], 0);
    139139    call.rc = VERR_TRY_AGAIN;
    140     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     140    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    141141                  2, parms, 0);
    142142    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     
    144144    RTTESTI_CHECK_RC_OK(call.rc);
    145145    call.rc = VERR_TRY_AGAIN;
    146     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     146    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    147147                  2, parms, 0);
    148148    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     
    153153    HGCMSvcSetU32(&parms[1], 0);
    154154    call.rc = VERR_TRY_AGAIN;
    155     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     155    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    156156                  2, parms, 0);
    157157    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This should get updated only when the guest call completes. */
     
    162162    RTTESTI_CHECK_RC_OK(call.rc);
    163163    call.rc = VERR_TRY_AGAIN;
    164     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     164    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    165165                  2, parms, 0);
    166166    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     
    168168    RTTESTI_CHECK_RC_OK(call.rc);
    169169    call.rc = VERR_TRY_AGAIN;
    170     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     170    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    171171                  2, parms, 0);
    172172    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
     
    179179    HGCMSvcSetU32(&parms[1], 0);
    180180    call.rc = VERR_TRY_AGAIN;
    181     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     181    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    182182                  2, parms, 0);
    183183    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     
    185185    RTTESTI_CHECK_RC_OK(call.rc);
    186186    call.rc = VERR_TRY_AGAIN;
    187     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     187    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    188188                  2, parms, 0);
    189189    RTTESTI_CHECK(parms[0].u.uint32 == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
     
    191191    RTTESTI_CHECK_RC_OK(call.rc);
    192192    call.rc = VERR_TRY_AGAIN;
    193     table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG,
     193    table.pfnCall(NULL, &call, 1 /* clientId */, &g_Client, VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD,
    194194                  2, parms, 0);
    195195    RTTESTI_CHECK_RC(call.rc, VERR_TRY_AGAIN);  /* This call should not complete yet. */
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