VirtualBox

Changeset 85371 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Jul 17, 2020 10:02:58 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
139382
Message:

DnD: Revamped code to simplify / untangle of internal data handling:

  • C-ifying and renaming classes DnDURIList / DnDURIObject -> DnDTransferList / DnDTransferObject
  • Added testcases for DnDTransferList / DnDTransferObject + DnDPath API
  • Reduced memory footprint
  • Greatly simplified / stripped down internal data flow of Main side
  • More (optional) release logging for further diagnosis

Work in progress.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibDragAndDrop.cpp

    r85029 r85371  
    349349 * @param   pDroppedFiles       Dropped files object to use for maintaining the file creation / locking.
    350350 */
    351 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, DnDDroppedFiles *pDroppedFiles)
     351static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, PDNDDROPPEDFILES pDroppedFiles)
    352352{
    353353    AssertPtrReturn(pCtx,          VERR_INVALID_POINTER);
     
    384384     * Create and query the (unique) drop target directory in the user's temporary directory.
    385385     */
    386     int rc = pDroppedFiles->OpenTemp(0 /* fFlags */);
     386    int rc = DnDDroppedFilesOpenTemp(pDroppedFiles, 0 /* fFlags */);
    387387    if (RT_FAILURE(rc))
    388388    {
     
    391391    }
    392392
    393     const char *pszDropDir = pDroppedFiles->GetDirAbs();
     393    const char *pszDropDir = DnDDroppedFilesGetDirAbs(pDroppedFiles);
    394394    AssertPtr(pszDropDir);
    395395
     
    397397     * Enter the main loop of retieving files + directories.
    398398     */
    399     DnDURIObject objFile;
     399    DNDTRANSFEROBJECT objCur;
     400    RT_ZERO(objCur);
    400401
    401402    char szPathName[RTPATH_MAX] = { 0 };
     
    424425                                            &cbPathName,
    425426                                            &fMode);
    426                     LogFlowFunc(("HOST_DND_HG_SND_DIR pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n",
     427                    LogFlowFunc(("HOST_DND_HG_SND_DIR: "
     428                                 "pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n",
    427429                                 szPathName, cbPathName, fMode, rc));
    428430
     
    437439                        rc = RTDirCreate(pszPathAbs, fCreationMode, 0);
    438440                        if (RT_SUCCESS(rc))
    439                             rc = pDroppedFiles->AddDir(pszPathAbs);
     441                            rc = DnDDroppedFilesAddDir(pDroppedFiles, pszPathAbs);
    440442
    441443                        if (RT_SUCCESS(rc))
     
    452454                }
    453455                case HOST_DND_HG_SND_FILE_HDR:
     456                    RT_FALL_THROUGH();
    454457                case HOST_DND_HG_SND_FILE_DATA:
    455458                {
     
    489492
    490493                            /* Is there already a file open, e.g. in transfer? */
    491                             if (!objFile.IsOpen())
     494                            if (!DnDTransferObjectIsOpen(&objCur))
    492495                            {
    493                                 RTCString strPathAbs(pszPathAbs);
    494496#ifdef RT_OS_WINDOWS
    495497                                uint32_t fCreationMode = (fMode & RTFS_DOS_MASK) | RTFS_DOS_NT_NORMAL;
     
    497499                                uint32_t fCreationMode = (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR;
    498500#endif
    499                                 rc = objFile.Init(DnDURIObject::Type_File, strPathAbs);
     501                                rc = DnDTransferObjectInit(&objCur, DNDTRANSFEROBJTYPE_FILE,
     502                                                           pszDropDir /* Source (base) path */, szPathName /* Destination path */);
    500503                                if (RT_SUCCESS(rc))
    501504                                {
    502                                     rc = objFile.Open(fOpen, fCreationMode);
     505                                    rc = DnDTransferObjectOpen(&objCur, fOpen, fCreationMode, DNDTRANSFEROBJECT_FLAGS_NONE);
    503506                                    if (RT_SUCCESS(rc))
    504507                                    {
    505                                         rc = pDroppedFiles->AddFile(strPathAbs.c_str());
     508                                        rc = DnDDroppedFilesAddFile(pDroppedFiles, pszPathAbs);
    506509                                        if (RT_SUCCESS(rc))
    507510                                        {
    508511                                            cbFileWritten = 0;
    509                                             objFile.SetSize(cbFileSize);
     512                                            DnDTransferObjectSetSize(&objCur, cbFileSize);
    510513                                        }
    511514                                    }
     
    514517                            else
    515518                            {
    516                                 AssertMsgFailed(("ObjType=%RU32\n", objFile.GetType()));
     519                                AssertMsgFailed(("ObjType=%RU32\n", DnDTransferObjectGetType(&objCur)));
    517520                                rc = VERR_WRONG_ORDER;
    518521                            }
     
    529532                    {
    530533                        uint32_t cbChunkWritten;
    531                         rc = objFile.Write(pvChunk, cbChunkRead, &cbChunkWritten);
     534                        rc = DnDTransferObjectWrite(&objCur, pvChunk, cbChunkRead, &cbChunkWritten);
    532535                        if (RT_SUCCESS(rc))
    533536                        {
    534                             LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA "
     537                            LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA: "
    535538                                         "cbChunkRead=%RU32, cbChunkWritten=%RU32, cbFileWritten=%RU64 cbFileSize=%RU64\n",
    536539                                         cbChunkRead, cbChunkWritten, cbFileWritten + cbChunkWritten, cbFileSize));
     
    544547
    545548                    /* Data transfer complete? Close the file. */
    546                     bool fClose = objFile.IsComplete();
     549                    bool fClose = DnDTransferObjectIsComplete(&objCur);
    547550                    if (fClose)
    548551                    {
     
    557560                    {
    558561                        LogFlowFunc(("Closing file\n"));
    559                         objFile.Close();
     562                        DnDTransferObjectDestroy(&objCur);
    560563                    }
    561564
     
    604607    if (RT_FAILURE(rc))
    605608    {
    606         objFile.Close();
    607         pDroppedFiles->Rollback();
     609        DnDTransferObjectDestroy(&objCur);
     610        DnDDroppedFilesRollback(pDroppedFiles);
    608611    }
    609612    else
    610613    {
    611         /** @todo Compare the URI list with the dirs/files we really transferred. */
     614        /** @todo Compare the transfer list with the dirs/files we really transferred. */
    612615        /** @todo Implement checksum verification, if any. */
    613616    }
     
    618621     * by the client's drag'n drop operation lateron.
    619622     */
    620     int rc2 = pDroppedFiles->Reset(false /* fRemoveDropDir */);
     623    int rc2 = DnDDroppedFilesReset(pDroppedFiles, false /* fRemoveDropDir */);
    621624    if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */
    622625        LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2));
     
    805808/**
    806809 * Host -> Guest
    807  * Main function for receiving the actual DnD data from the host, extended version.
    808  *
    809  * @returns IPRT status code.
    810  * @param   pCtx                DnD context to use.
    811  * @param   pEnmType            Where to store the meta data type. Optional.
    812  * @param   ppvData             Returns the received meta data. Needs to be free'd by the caller.  Optional.
    813  * @param   pcbData             Where to store the size (in bytes) of the received meta data. Optional.
    814  */
    815 static int vbglR3DnDHGRecvDataMainEx(PVBGLR3GUESTDNDCMDCTX        pCtx,
    816                                      VBGLR3GUESTDNDMETADATATYPE  *pEnmType,
    817                                      void                       **ppvData,
    818                                      uint32_t                    *pcbData)
     810 * Main function for receiving the actual DnD data from the host.
     811 *
     812 * @returns IPRT status code.
     813 * @param   pCtx                DnD context to use.
     814 * @param   pMeta               Where to store the actual meta data received from the host.
     815 */
     816static int vbglR3DnDHGRecvDataMain(PVBGLR3GUESTDNDCMDCTX   pCtx,
     817                                   PVBGLR3GUESTDNDMETADATA pMeta)
    819818{
    820819    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
    821     /* The rest is optional. */
     820    AssertPtrReturn(pMeta, VERR_INVALID_POINTER);
    822821
    823822    VBOXDNDDATAHDR dataHdr;
     
    831830        return VERR_NO_MEMORY;
    832831
    833     DnDURIList lstURI;
    834     DnDDroppedFiles droppedFiles;
     832    DNDDROPPEDFILES droppedFiles;
    835833
    836834    void    *pvData = NULL;
     
    855853            Assert(cbData);
    856854
    857             rc = lstURI.SetFromURIData(pvData, cbData, 0 /* fFlags */);
     855            /* Use the dropped files directory as the root directory for the current transfer. */
     856            rc = DnDTransferListInit(&pMeta->u.URI.Transfer, DnDDroppedFilesGetDirAbs(&droppedFiles));
    858857            if (RT_SUCCESS(rc))
    859                 rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles);
    860 
    861             if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */
    862858            {
    863                 if (pvData)
    864                 {
    865                     /* Reuse data buffer to fill in the transformed URI file list. */
    866                     RTMemFree(pvData);
    867                     pvData = NULL;
    868                 }
    869 
    870                 RTCString strData = lstURI.GetRootEntries(droppedFiles.GetDirAbs());
    871                 Assert(!strData.isEmpty());
    872 
    873                 cbData = strData.length() + 1;
    874                 LogFlowFunc(("URI list has %zu bytes\n", cbData));
    875 
    876                 pvData = RTMemAlloc(cbData);
    877                 if (pvData)
    878                 {
    879                     memcpy(pvData, strData.c_str(), cbData);
    880 
    881                     if (pEnmType)
    882                         *pEnmType = VBGLR3GUESTDNDMETADATATYPE_URI_LIST;
    883                 }
    884                 else
    885                     rc =  VERR_NO_MEMORY;
     859                rc = DnDTransferListAppendPathsFromBuffer(&pMeta->u.URI.Transfer, DNDTRANSFERLISTFMT_URI, (const char *)pvData, cbData,
     860                                                          DND_PATH_SEPARATOR, 0 /* fFlags */);
     861                if (RT_SUCCESS(rc))
     862                    rc = vbglR3DnDHGRecvURIData(pCtx, &dataHdr, &droppedFiles);
    886863            }
    887864        }
    888865        else /* Raw data. */
    889866        {
    890             if (pEnmType)
    891                 *pEnmType = VBGLR3GUESTDNDMETADATATYPE_RAW;
     867            pMeta->enmType = VBGLR3GUESTDNDMETADATATYPE_RAW;
    892868        }
    893869    }
     
    898874    if (RT_SUCCESS(rc))
    899875    {
    900         if (   pvData
    901             && cbData)
    902         {
    903             if (pcbData)
    904                 *pcbData = cbData;
    905             if (ppvData)
    906                 *ppvData = pvData;
    907             else
    908                 RTMemFree(pvData);
    909         }
     876
    910877    }
    911878    else if (   RT_FAILURE(rc)
     
    921888
    922889    LogFlowFuncLeaveRC(rc);
    923     return rc;
    924 }
    925 
    926 /**
    927  * Host -> Guest
    928  * Main function for receiving the actual DnD data from the host.
    929  *
    930  * @returns IPRT status code.
    931  * @param   pCtx                DnD context to use.
    932  * @param   pMeta               Where to store the actual meta data received from the host.
    933  */
    934 static int vbglR3DnDHGRecvDataMain(PVBGLR3GUESTDNDCMDCTX   pCtx,
    935                                    PVBGLR3GUESTDNDMETADATA pMeta)
    936 {
    937     AssertPtrReturn(pMeta, VERR_INVALID_POINTER);
    938 
    939     int rc = vbglR3DnDHGRecvDataMainEx(pCtx,
    940                                        &pMeta->enmType,
    941                                        &pMeta->pvMeta,
    942                                        &pMeta->cbMeta);
    943890    return rc;
    944891}
     
    13001247        {
    13011248            PVBGLR3GUESTDNDMETADATA pMeta = &pEvent->u.HG_Received.Meta;
    1302             if (pMeta->pvMeta)
     1249            switch (pMeta->enmType)
    13031250            {
    1304                 Assert(pMeta->cbMeta);
    1305                 RTMemFree(pMeta->pvMeta);
    1306                 pMeta->cbMeta = 0;
     1251                case VBGLR3GUESTDNDMETADATATYPE_RAW:
     1252                {
     1253                    if (pMeta->u.Raw.pvMeta)
     1254                    {
     1255                        Assert(pMeta->u.Raw.cbMeta);
     1256                        RTMemFree(pMeta->u.Raw.pvMeta);
     1257                        pMeta->u.Raw.cbMeta = 0;
     1258                    }
     1259                    break;
     1260                }
     1261
     1262                case VBGLR3GUESTDNDMETADATATYPE_URI_LIST:
     1263                {
     1264                    DnDTransferListDestroy(&pMeta->u.URI.Transfer);
     1265                    break;
     1266                }
     1267
     1268                default:
     1269                    break;
    13071270            }
    13081271            break;
     
    15031466 * @returns IPRT status code.
    15041467 * @param   pCtx                DnD context to use.
    1505  * @param   pObj                URI object containing the directory to send.
    1506  */
    1507 static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj)
     1468 * @param   pObj                transfer object containing the directory to send.
     1469 */
     1470static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, DNDTRANSFEROBJECT *pObj)
    15081471{
    15091472    AssertPtrReturn(pObj,                                         VERR_INVALID_POINTER);
    15101473    AssertPtrReturn(pCtx,                                         VERR_INVALID_POINTER);
    1511     AssertReturn(pObj->GetType() == DnDURIObject::Type_Directory, VERR_INVALID_PARAMETER);
    1512 
    1513     RTCString strPath = pObj->GetPath();
    1514     LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n",
    1515                  strPath.c_str(), strPath.length(), pObj->GetMode()));
    1516 
    1517     if (strPath.length() > RTPATH_MAX)
     1474    AssertReturn(DnDTransferObjectGetType(pObj) == DNDTRANSFEROBJTYPE_DIRECTORY, VERR_INVALID_PARAMETER);
     1475
     1476    const char *pcszPath = DnDTransferObjectGetDestPath(pObj);
     1477    const size_t cchPath = RTStrNLen(pcszPath, RTPATH_MAX);
     1478    const RTFMODE fMode  = DnDTransferObjectGetMode(pObj);
     1479
     1480    LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n", pcszPath, cchPath, fMode));
     1481
     1482    if (cchPath > RTPATH_MAX) /* Can't happen, but check anyway. */
    15181483        return VERR_INVALID_PARAMETER;
    1519 
    1520     const uint32_t cbPath = (uint32_t)strPath.length() + 1; /* Include termination. */
    15211484
    15221485    HGCMMsgGHSendDir Msg;
     
    15241487    /** @todo Context ID not used yet. */
    15251488    Msg.u.v3.uContext.SetUInt32(0);
    1526     Msg.u.v3.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)cbPath);
    1527     Msg.u.v3.cbName.SetUInt32((uint32_t)cbPath);
    1528     Msg.u.v3.fMode.SetUInt32(pObj->GetMode());
     1489    Msg.u.v3.pvName.SetPtr((void *)pcszPath, (uint32_t)cchPath);
     1490    Msg.u.v3.cbName.SetUInt32((uint32_t)cchPath + 1); /* Include termination. */
     1491    Msg.u.v3.fMode.SetUInt32(fMode);
    15291492
    15301493    return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     
    15371500 * @returns IPRT status code.
    15381501 * @param   pCtx                DnD context to use.
    1539  * @param   pObj                URI object containing the file to send.
    1540  */
    1541 static int vbglR3DnDGHSendFile(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj)
     1502 * @param   pObj                Transfer object containing the file to send.
     1503 */
     1504static int vbglR3DnDGHSendFile(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFEROBJECT pObj)
    15421505{
    15431506    AssertPtrReturn(pCtx,                                    VERR_INVALID_POINTER);
    15441507    AssertPtrReturn(pObj,                                    VERR_INVALID_POINTER);
    1545     AssertReturn(pObj->GetType() == DnDURIObject::Type_File, VERR_INVALID_PARAMETER);
    1546     AssertReturn(pObj->IsOpen(),                             VERR_INVALID_STATE);
     1508    AssertReturn(DnDTransferObjectGetType(pObj) == DNDTRANSFEROBJTYPE_FILE, VERR_INVALID_PARAMETER);
     1509    AssertReturn(DnDTransferObjectIsOpen(pObj),              VERR_INVALID_STATE);
    15471510
    15481511    uint32_t cbBuf = _64K;           /** @todo Make this configurable? */
     
    15511514        return VERR_NO_MEMORY;
    15521515
    1553     RTCString strPath = pObj->GetPath();
    1554 
    1555     LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(),
    1556                  pObj->GetSize(), pObj->GetMode()));
     1516    const char *pcszPath  = DnDTransferObjectGetDestPath(pObj);
     1517    const size_t cchPath  = RTStrNLen(pcszPath, RTPATH_MAX);
     1518    const uint64_t cbSize = DnDTransferObjectGetSize(pObj);
     1519    const RTFMODE fMode   = DnDTransferObjectGetMode(pObj);
     1520
     1521    LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", pcszPath, cchPath, cbSize, fMode));
    15571522
    15581523    HGCMMsgGHSendFileHdr MsgHdr;
    15591524    VBGL_HGCM_HDR_INIT(&MsgHdr.hdr, pCtx->uClientID, GUEST_DND_GH_SND_FILE_HDR, 6);
    15601525    MsgHdr.uContext.SetUInt32(0);                                                    /* Context ID; unused at the moment. */
    1561     MsgHdr.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1));
    1562     MsgHdr.cbName.SetUInt32((uint32_t)(strPath.length() + 1));
     1526    MsgHdr.pvName.SetPtr((void *)pcszPath, (uint32_t)(cchPath + 1));                 /* Include termination. */
     1527    MsgHdr.cbName.SetUInt32((uint32_t)(cchPath + 1));                                /* Ditto. */
    15631528    MsgHdr.uFlags.SetUInt32(0);                                                      /* Flags; unused at the moment. */
    1564     MsgHdr.fMode.SetUInt32(pObj->GetMode());                                         /* File mode */
    1565     MsgHdr.cbTotal.SetUInt64(pObj->GetSize());                                       /* File size (in bytes). */
     1529    MsgHdr.fMode.SetUInt32(fMode);                                                   /* File mode */
     1530    MsgHdr.cbTotal.SetUInt64(cbSize);                                                /* File size (in bytes). */
    15661531
    15671532    int rc = VbglR3HGCMCall(&MsgHdr.hdr, sizeof(MsgHdr));
     
    15801545        Msg.u.v3.cbChecksum.SetUInt32(0);
    15811546
    1582         uint64_t cbToReadTotal  = pObj->GetSize();
     1547        uint64_t cbToReadTotal  = cbSize;
    15831548        uint64_t cbWrittenTotal = 0;
    15841549        while (cbToReadTotal)
     
    15871552            uint32_t cbRead   = 0;
    15881553            if (cbToRead)
    1589                 rc = pObj->Read(pvBuf, cbToRead, &cbRead);
     1554                rc = DnDTransferObjectRead(pObj, pvBuf, cbToRead, &cbRead);
    15901555
    15911556            LogFlowFunc(("cbToReadTotal=%RU64, cbToRead=%RU32, cbRead=%RU32, rc=%Rrc\n",
     
    16121577            cbWrittenTotal += cbRead;
    16131578
    1614             LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, pObj->GetSize(), cbWrittenTotal * 100 / pObj->GetSize()));
     1579            LogFlowFunc(("%RU64/%RU64 -- %RU8%%\n", cbWrittenTotal, cbSize, cbWrittenTotal * 100 / cbSize));
    16151580        };
    16161581    }
     
    16241589/**
    16251590 * Guest -> Host
    1626  * Utility function to send an URI object from guest to the host.
    1627  *
    1628  * @returns IPRT status code.
    1629  * @param   pCtx                DnD context to use.
    1630  * @param   pObj                URI object to send from guest to the host.
    1631  */
    1632 static int vbglR3DnDGHSendURIObject(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj)
     1591 * Utility function to send a transfer object from guest to the host.
     1592 *
     1593 * @returns IPRT status code.
     1594 * @param   pCtx                DnD context to use.
     1595 * @param   pObj                Transfer object to send from guest to the host.
     1596 */
     1597static int vbglR3DnDGHSendURIObject(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFEROBJECT pObj)
    16331598{
    16341599    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    16371602    int rc;
    16381603
    1639     switch (pObj->GetType())
    1640     {
    1641         case DnDURIObject::Type_Directory:
     1604    const DNDTRANSFEROBJTYPE enmType = DnDTransferObjectGetType(pObj);
     1605
     1606    switch (enmType)
     1607    {
     1608        case DNDTRANSFEROBJTYPE_DIRECTORY:
    16421609            rc = vbglR3DnDGHSendDir(pCtx, pObj);
    16431610            break;
    16441611
    1645         case DnDURIObject::Type_File:
     1612        case DNDTRANSFEROBJTYPE_FILE:
    16461613            rc = vbglR3DnDGHSendFile(pCtx, pObj);
    16471614            break;
    16481615
    16491616        default:
    1650             AssertMsgFailed(("Object type %ld not implemented\n", pObj->GetType()));
     1617            AssertMsgFailed(("Object type %ld not implemented\n", enmType));
    16511618            rc = VERR_NOT_IMPLEMENTED;
    16521619            break;
     
    16821649/**
    16831650 * Guest -> Host
    1684  * Utility function to send URI data from guest to the host.
    1685  *
    1686  * @returns IPRT status code.
    1687  * @param   pCtx                DnD context to use.
    1688  * @param   pvData              Block to URI data to send.
    1689  * @param   cbData              Size (in bytes) of URI data to send.
    1690  */
    1691 static int vbglR3DnDGHSendURIData(PVBGLR3GUESTDNDCMDCTX pCtx, const void *pvData, size_t cbData)
    1692 {
    1693     AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
    1694     AssertPtrReturn(pvData, VERR_INVALID_POINTER);
    1695     AssertReturn(cbData,    VERR_INVALID_PARAMETER);
    1696 
    1697     RTCList<RTCString> lstPaths =
    1698         RTCString((const char *)pvData, cbData).split("\r\n");
    1699 
    1700     /** @todo Add symlink support (DNDURILIST_FLAGS_RESOLVE_SYMLINKS) here. */
    1701     /** @todo Add lazy loading (DNDURILIST_FLAGS_LAZY) here. */
    1702     uint32_t fFlags = DNDURILIST_FLAGS_KEEP_OPEN;
    1703 
    1704     DnDURIList lstURI;
    1705     int rc = lstURI.AppendURIPathsFromList(lstPaths, fFlags);
     1651 * Utility function to send transfer data from guest to the host.
     1652 *
     1653 * @returns IPRT status code.
     1654 * @param   pCtx                DnD context to use.
     1655 * @param   pTransferList       Dnd transfer list to send.
     1656 */
     1657static int vbglR3DnDGHSendTransferData(PVBGLR3GUESTDNDCMDCTX pCtx, PDNDTRANSFERLIST pTransferList)
     1658{
     1659    AssertPtrReturn(pCtx,VERR_INVALID_POINTER);
     1660    AssertPtrReturn(pTransferList, VERR_INVALID_POINTER);
     1661
     1662    /*
     1663     * Send the (meta) data; in case of URIs it's the root entries of a
     1664     * transfer list the host needs to know upfront to set up the drag'n drop operation.
     1665     */
     1666    char *pszList = NULL;
     1667    size_t cbList;
     1668    int rc = DnDTransferListGetRoots(pTransferList, DNDTRANSFERLISTFMT_URI, &pszList, &cbList);
     1669    if (RT_FAILURE(rc))
     1670        return rc;
     1671
     1672    void    *pvURIList = (void *)pszList;
     1673    uint32_t cbURLIist = (uint32_t)cbList;
     1674
     1675    /* The total size also contains the size of the meta data. */
     1676    uint64_t cbTotal  = cbURLIist;
     1677             cbTotal += DnDTransferListObjTotalBytes(pTransferList);
     1678
     1679    /* We're going to send a transfer list in text format. */
     1680    const char     szMetaFmt[] = "text/uri-list";
     1681    const uint32_t cbMetaFmt   = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */
     1682
     1683    VBOXDNDDATAHDR dataHdr;
     1684    dataHdr.uFlags    = 0; /* Flags not used yet. */
     1685    dataHdr.cbTotal   = cbTotal;
     1686    dataHdr.cbMeta    = cbURLIist;
     1687    dataHdr.pvMetaFmt = (void *)szMetaFmt;
     1688    dataHdr.cbMetaFmt = cbMetaFmt;
     1689    dataHdr.cObjects  = DnDTransferListObjCount(pTransferList);
     1690
     1691    rc = vbglR3DnDGHSendDataInternal(pCtx, pvURIList, cbURLIist, &dataHdr);
     1692
    17061693    if (RT_SUCCESS(rc))
    17071694    {
    1708         /*
    1709          * Send the (meta) data; in case of URIs it's the (non-recursive) file/directory
    1710          * URI list the host needs to know upfront to set up the drag'n drop operation.
    1711          */
    1712         RTCString strRootDest = lstURI.GetRootEntries();
    1713         if (strRootDest.isNotEmpty())
     1695        while (DnDTransferListObjCount(pTransferList))
    17141696        {
    1715             void *pvURIList  = (void *)strRootDest.c_str(); /* URI root list. */
    1716             uint32_t cbURLIist = (uint32_t)strRootDest.length() + 1; /* Include string termination. */
    1717 
    1718             /* The total size also contains the size of the meta data. */
    1719             uint64_t cbTotal  = cbURLIist;
    1720                      cbTotal += lstURI.GetTotalBytes();
    1721 
    1722             /* We're going to send an URI list in text format. */
    1723             const char     szMetaFmt[] = "text/uri-list";
    1724             const uint32_t cbMetaFmt   = (uint32_t)strlen(szMetaFmt) + 1; /* Include termination. */
    1725 
    1726             VBOXDNDDATAHDR dataHdr;
    1727             dataHdr.uFlags    = 0; /* Flags not used yet. */
    1728             dataHdr.cbTotal   = cbTotal;
    1729             dataHdr.cbMeta    = cbURLIist;
    1730             dataHdr.pvMetaFmt = (void *)szMetaFmt;
    1731             dataHdr.cbMetaFmt = cbMetaFmt;
    1732             dataHdr.cObjects  = lstURI.GetTotalCount();
    1733 
    1734             rc = vbglR3DnDGHSendDataInternal(pCtx,
    1735                                              pvURIList, cbURLIist, &dataHdr);
    1736         }
    1737         else
    1738             rc = VERR_INVALID_PARAMETER;
    1739     }
    1740 
    1741     if (RT_SUCCESS(rc))
    1742     {
    1743         while (!lstURI.IsEmpty())
    1744         {
    1745             DnDURIObject *pNextObj = lstURI.First();
    1746 
    1747             rc = vbglR3DnDGHSendURIObject(pCtx, pNextObj);
     1697            PDNDTRANSFEROBJECT pObj = DnDTransferListObjGetFirst(pTransferList);
     1698
     1699            rc = vbglR3DnDGHSendURIObject(pCtx, pObj);
    17481700            if (RT_FAILURE(rc))
    17491701                break;
    17501702
    1751             lstURI.RemoveFirst();
     1703            DnDTransferListObjRemoveFirst(pTransferList);
    17521704        }
     1705
     1706        Assert(DnDTransferListObjCount(pTransferList) == 0);
    17531707    }
    17541708
     
    17791733    if (DnDMIMEHasFileURLs(pszFormat, strlen(pszFormat)))
    17801734    {
    1781         /* Send file data. */
    1782         rc = vbglR3DnDGHSendURIData(pCtx, pvData, cbData);
     1735        DNDTRANSFERLIST lstTransfer;
     1736        rc = DnDTransferListInit(&lstTransfer, NULL /* pcszRootPathAbs */);
     1737        if (RT_SUCCESS(rc))
     1738        {
     1739            /** @todo Add symlink support (DNDTRANSFERLIST_FLAGS_RESOLVE_SYMLINKS) here. */
     1740            /** @todo Add lazy loading (DNDTRANSFERLIST_FLAGS_LAZY) here. */
     1741            const DNDTRANSFERLISTFLAGS fFlags = DNDTRANSFERLIST_FLAGS_KEEP_OPEN;
     1742
     1743            rc = DnDTransferListAppendPathsFromBuffer(&lstTransfer, DNDTRANSFERLISTFMT_NATIVE, (const char *)pvData, cbData,
     1744                                                      DND_PATH_SEPARATOR, fFlags);
     1745            if (RT_SUCCESS(rc))
     1746                rc = vbglR3DnDGHSendTransferData(pCtx, &lstTransfer);
     1747            DnDTransferListDestroy(&lstTransfer);
     1748        }
    17831749    }
    17841750    else
Note: See TracChangeset for help on using the changeset viewer.

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