VirtualBox

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


Ignore:
Timestamp:
Jul 17, 2020 10:02:58 AM (4 years ago)
Author:
vboxsync
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.

Location:
trunk/src/VBox/Additions
Files:
7 edited

Legend:

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

    r85121 r85371  
    10681068int VBoxDnDWnd::OnHgDataReceive(PVBGLR3GUESTDNDMETADATA pMeta)
    10691069{
    1070     LogFlowThisFunc(("mState=%ld, enmMetaType=%RU32, cbMeta=%RU32\n", mState, pMeta->enmType, pMeta->cbMeta));
    1071 
    1072     mState = Dropped;
    1073 
    1074     int rc = VINF_SUCCESS;
    1075     if (pMeta->pvMeta)
    1076     {
    1077         Assert(pMeta->cbMeta);
    1078         rc = RTCritSectEnter(&mCritSect);
     1070    LogFlowThisFunc(("mState=%ld, enmMetaType=%RU32\n", mState, pMeta->enmType));
     1071
     1072    int rc = RTCritSectEnter(&mCritSect);
     1073    if (RT_SUCCESS(rc))
     1074    {
     1075        mState = Dropped;
     1076
     1077        if (startupInfo.pDataObject)
     1078        {
     1079            switch (pMeta->enmType)
     1080            {
     1081                case VBGLR3GUESTDNDMETADATATYPE_RAW:
     1082                {
     1083                    AssertBreakStmt(pMeta->u.Raw.pvMeta != NULL, rc = VERR_INVALID_POINTER);
     1084                    AssertBreakStmt(pMeta->u.Raw.cbMeta, rc = VERR_INVALID_PARAMETER);
     1085
     1086                    rc = startupInfo.pDataObject->Signal(mFormatRequested, pMeta->u.Raw.pvMeta, pMeta->u.Raw.cbMeta);
     1087                    break;
     1088                }
     1089
     1090                case VBGLR3GUESTDNDMETADATATYPE_URI_LIST:
     1091                {
     1092                    LogRel2(("DnD: URI transfer root directory is '%s'\n", DnDTransferListGetRootPathAbs(&pMeta->u.URI.Transfer)));
     1093
     1094                    char  *pszBuf;
     1095                    size_t cbBuf;
     1096                    /* Note: The transfer list already has its root set to a temporary directory, so no need to set/add a new
     1097                     *       path base here. */
     1098                    rc = DnDTransferListGetRootsEx(&pMeta->u.URI.Transfer, DNDTRANSFERLISTFMT_NATIVE, NULL /* pszPathBase */,
     1099                                                   DND_PATH_SEPARATOR, &pszBuf, &cbBuf);
     1100                    if (RT_SUCCESS(rc))
     1101                    {
     1102                        rc = startupInfo.pDataObject->Signal(mFormatRequested, pszBuf, cbBuf);
     1103                        RTStrFree(pszBuf);
     1104                    }
     1105                    break;
     1106                }
     1107
     1108                default:
     1109                    AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
     1110                    break;
     1111            }
     1112        }
     1113        else
     1114            rc = VERR_NOT_FOUND;
     1115
     1116        int rc2 = mouseRelease();
    10791117        if (RT_SUCCESS(rc))
    1080         {
    1081             if (startupInfo.pDataObject)
    1082                 rc = startupInfo.pDataObject->Signal(mFormatRequested, pMeta->pvMeta, pMeta->cbMeta);
    1083             else
    1084                 rc = VERR_NOT_FOUND;
    1085 
    1086             RTCritSectLeave(&mCritSect);
    1087         }
    1088     }
    1089 
    1090     int rc2 = mouseRelease();
    1091     if (RT_SUCCESS(rc))
    1092         rc = rc2;
     1118            rc = rc2;
     1119
     1120        RTCritSectLeave(&mCritSect);
     1121    }
    10931122
    10941123    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h

    r85121 r85371  
    7171    int Abort(void);
    7272    void SetStatus(Status status);
    73     int Signal(const RTCString &strFormat, const void *pvData, uint32_t cbData);
     73    int Signal(const RTCString &strFormat, const void *pvData, size_t cbData);
    7474
    7575protected:
     
    8888    RTCString   mstrFormat;
    8989    void       *mpvData;
    90     uint32_t    mcbData;
     90    size_t      mcbData;
    9191};
    9292
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp

    r82968 r85371  
    229229         * URI list handling.
    230230         */
    231         if (mstrFormat.equalsIgnoreCase("text/uri-list"))
     231        if (DnDMIMEHasFileURLs(mstrFormat.c_str(), RTSTR_MAX))
    232232        {
    233             int rc = VINF_SUCCESS;
    234 
    235             RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
    236             RTCList<RTCString> lstFiles;
    237             for (size_t i = 0; i < lstFilesURI.size(); i++)
    238             {
    239                 char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());
    240                 if (pszFilePath)
    241                 {
    242                     lstFiles.append(pszFilePath);
    243                     RTStrFree(pszFilePath);
    244                 }
    245                 else /* Unable to parse -- refuse entire request. */
    246                 {
    247                     lstFiles.clear();
    248                     rc = VERR_INVALID_PARAMETER;
    249                     break;
    250                 }
    251             }
    252 
    253             size_t cFiles = lstFiles.size();
     233            char **papszFiles;
     234            size_t cFiles;
     235            int rc = RTStrSplit((const char *)mpvData, mcbData, DND_PATH_SEPARATOR, &papszFiles, &cFiles);
    254236            if (   RT_SUCCESS(rc)
    255237                && cFiles)
    256238            {
    257 #ifdef DEBUG
    258                 LogFlowFunc(("Files (%zu)\n", cFiles));
     239                LogRel2(("DnD: Files (%zu)\n", cFiles));
    259240                for (size_t i = 0; i < cFiles; i++)
    260                     LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
    261 #endif
     241                    LogRel2(("\tDnD: File '%s'\n", papszFiles[i]));
    262242
    263243#if 0
     
    310290                    for (size_t i = 0; i < cFiles; i++)
    311291                    {
    312                         cchFiles += strlen(lstFiles.at(i).c_str());
     292                        cchFiles += strlen(papszFiles[i]);
    313293                        cchFiles += 1; /* Terminating '\0'. */
    314294                    }
     
    328308                            size_t cchCurFile;
    329309                            PRTUTF16 pwszFile;
    330                             rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
     310                            rc = RTStrToUtf16(papszFiles[i], &pwszFile);
    331311                            if (RT_SUCCESS(rc))
    332312                            {
     
    373353                        rc = VERR_NO_MEMORY;
    374354                }
     355
     356                for (size_t i = 0; i < cFiles; ++i)
     357                    RTStrFree(papszFiles[i]);
     358                RTMemFree(papszFiles);
    375359            }
    376360
     
    671655
    672656int VBoxDnDDataObject::Signal(const RTCString &strFormat,
    673                               const void *pvData, uint32_t cbData)
     657                              const void *pvData, size_t cbData)
    674658{
    675659    int rc;
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp

    r82968 r85371  
    2828#include "VBox/HostServices/DragAndDropSvc.h"
    2929
     30#include <iprt/path.h>
    3031#include <iprt/utf16.h>
    3132#include <VBox/log.h>
     
    451452                                LogRel(("DnD: Adding guest file '%s'\n", pszFileUtf8));
    452453
    453                                 rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
    454454                                if (RT_SUCCESS(rc))
    455                                     cchFiles += cchFileUtf8;
     455                                {
     456                                    rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
     457                                    if (RT_SUCCESS(rc))
     458                                        cchFiles += cchFileUtf8;
     459                                }
    456460                            }
    457                             else
     461
     462                            if (RT_FAILURE(rc))
    458463                                LogRel(("DnD: Error handling file entry #%u, rc=%Rrc\n", i, rc));
    459464
    460                             if (pszFileUtf8)
    461                                 RTStrFree(pszFileUtf8);
     465                            RTStrFree(pszFileUtf8);
    462466
    463467                            if (RT_FAILURE(rc))
     
    479483                                         cFiles, cchFiles, cbFiles, pszFiles));
    480484
    481                             /* Translate the list into URI elements. */
    482                             DnDURIList lstURI;
    483                             rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
    484                                                                   DNDURILIST_FLAGS_ABSOLUTE_PATHS);
    485                             if (RT_SUCCESS(rc))
    486                             {
    487                                 RTCString strRoot = lstURI.GetRootEntries();
    488                                 size_t cbRoot = strRoot.length() + 1; /* Include termination */
    489 
    490                                 mpvData = RTMemAlloc(cbRoot);
    491                                 if (mpvData)
    492                                 {
    493                                     memcpy(mpvData, strRoot.c_str(), cbRoot);
    494                                     mcbData = cbRoot;
    495                                 }
    496                                 else
    497                                     rc = VERR_NO_MEMORY;
    498                             }
     485                            mpvData = pszFiles;
     486                            mcbData = cbFiles;
    499487                        }
    500 
    501                         LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
    502                                      rc, pszFiles, cFiles, cchFiles));
    503 
    504                         if (pszFiles)
     488                        else
     489                        {
    505490                            RTStrFree(pszFiles);
     491                            pszFiles = NULL;
     492                        }
     493
     494                        LogFlowFunc(("Building CF_HDROP list rc=%Rrc, cFiles=%RU16, cchFiles=%RU32\n",
     495                                     rc, cFiles, cchFiles));
    506496                        break;
    507497                    }
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp

    r85121 r85371  
    154154static VBOXSERVICEINFO g_aServices[] =
    155155{
    156     { &g_SvcDescClipboard,      NIL_RTTHREAD, NULL, false, false, false, false, true }
     156    {&g_SvcDescDnD,      NIL_RTTHREAD, NULL, false, false, false, false, true }
    157157};
    158158#else
  • 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
  • trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp

    r82968 r85371  
    549549    int hgMove(uint32_t uPosX, uint32_t uPosY, VBOXDNDACTION dndActionDefault);
    550550    int hgDrop(uint32_t uPosX, uint32_t uPosY, VBOXDNDACTION dndActionDefault);
    551     int hgDataReceive(PVBGLR3GUESTDNDMETADATA pMetaData);
     551    int hgDataReceive(PVBGLR3GUESTDNDMETADATA pMeta);
    552552
    553553    /* X11 helpers. */
     
    19001900 *
    19011901 * @returns IPRT status code.
    1902  * @param   pMetaData               Pointer to meta data from host.
    1903  */
    1904 int DragInstance::hgDataReceive(PVBGLR3GUESTDNDMETADATA pMetaData)
     1902 * @param   pMeta               Pointer to meta data from host.
     1903 */
     1904int DragInstance::hgDataReceive(PVBGLR3GUESTDNDMETADATA pMeta)
    19051905{
    19061906    LogFlowThisFunc(("enmMode=%RU32, enmState=%RU32\n", m_enmMode, m_enmState));
    1907     LogFlowThisFunc(("enmMetaDataType=%RU32\n", pMetaData->enmType));
     1907    LogFlowThisFunc(("enmMetaType=%RU32\n", pMeta->enmType));
    19081908
    19091909    if (   m_enmMode  != HG
     
    19131913    }
    19141914
    1915     if (   pMetaData->pvMeta == NULL
    1916         || pMetaData->cbMeta == 0)
    1917     {
    1918         return VERR_INVALID_PARAMETER;
    1919     }
    1920 
    1921     int rc = VINF_SUCCESS;
    1922 
    1923     const void    *pvData = pMetaData->pvMeta;
    1924     const uint32_t cbData = pMetaData->cbMeta;
     1915    void  *pvData = NULL;
     1916    size_t cbData = 0;
     1917
     1918    int rc;
     1919
     1920    switch (pMeta->enmType)
     1921    {
     1922        case VBGLR3GUESTDNDMETADATATYPE_RAW:
     1923        {
     1924            AssertBreakStmt(pMeta->u.Raw.pvMeta != NULL, rc = VERR_INVALID_POINTER);
     1925            pvData = pMeta->u.Raw.pvMeta;
     1926            AssertBreakStmt(pMeta->u.Raw.cbMeta, rc = VERR_INVALID_PARAMETER);
     1927            cbData = pMeta->u.Raw.cbMeta;
     1928
     1929            rc = VINF_SUCCESS;
     1930            break;
     1931        }
     1932
     1933        case VBGLR3GUESTDNDMETADATATYPE_URI_LIST:
     1934        {
     1935            VBClLogInfo(("URI transfer root directory is '%s'\n", DnDTransferListGetRootPathAbs(&pMeta->u.URI.Transfer)));
     1936
     1937            /* Note: The transfer list already has its root set to a temporary directory, so no need to set/add a new
     1938             *       path base here. */
     1939            rc = DnDTransferListGetRootsEx(&pMeta->u.URI.Transfer, DNDTRANSFERLISTFMT_NATIVE, NULL /* pszPathBase */,
     1940                                           DND_PATH_SEPARATOR, (char **)&pvData, &cbData);
     1941            break;
     1942        }
     1943
     1944        default:
     1945            AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
     1946            break;
     1947    }
     1948
     1949    if (RT_FAILURE(rc))
     1950        return rc;
    19251951
    19261952    /*
     
    19281954     * be on the guest, so proceed working on communicating with the target window.
    19291955     */
    1930     VBClLogInfo("Received %RU32 bytes of URI list meta data from host\n", cbData);
     1956    VBClLogInfo("Received %RU32 bytes of meta data from host\n", cbData);
    19311957
    19321958    /* Destroy any old data. */
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