VirtualBox

Changeset 57500 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 21, 2015 4:54:50 PM (9 years ago)
Author:
vboxsync
Message:

DnD: Use a separate context for URI object when transferring, misc cleanups.

Location:
trunk/src/VBox
Files:
8 edited

Legend:

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

    r57372 r57500  
    414414                    if (pszPathAbs)
    415415                    {
    416                         rc = RTDirCreate(pszPathAbs, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
     416#ifdef RT_OS_WINDOWS
     417                        uint32_t fCreationMode = (fMode & RTFS_DOS_MASK) | RTFS_DOS_NT_NORMAL;
     418#else
     419                        uint32_t fCreationMode = (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU;
     420#endif
     421                        rc = RTDirCreate(pszPathAbs, fCreationMode, 0);
    417422                        if (RT_SUCCESS(rc))
    418423                            rc = DnDDirDroppedAddDir(&dirDroppedFiles, pszPathAbs);
     
    455460                    if (   RT_SUCCESS(rc)
    456461                        && (   uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR
    457                              /* Protocol v1 always sends the file name, so try opening every time. */
     462                             /* Protocol v1 always sends the file name, so opening the file every time. */
    458463                            || pCtx->uProtocol <= 1)
    459464                       )
     
    465470                                         szPathName, cbPathName, fMode, cbFileSize));
    466471
    467                             uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_ALL;
     472                            uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_WRITE;
    468473                            if (pCtx->uProtocol <= 1)
    469474                                fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
     
    475480                            {
    476481                                RTCString strPathAbs(pszPathAbs);
    477                                 rc = objFile.OpenEx(strPathAbs, DnDURIObject::File, DnDURIObject::Target, fOpen,
    478                                                     (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
     482#ifdef RT_OS_WINDOWS
     483                                uint32_t fCreationMode = (fMode & RTFS_DOS_MASK) | RTFS_DOS_NT_NORMAL;
     484#else
     485                                uint32_t fCreationMode = (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR;
     486#endif
     487                                rc = objFile.OpenEx(strPathAbs, DnDURIObject::File, DnDURIObject::Target, fOpen, fCreationMode);
    479488                                if (RT_SUCCESS(rc))
    480489                                {
     
    927936            rc = VINF_PERMISSION_DENIED;
    928937
    929         /* Set the protocol version to use. */
    930         pCtx->uProtocol = 2;
    931 
    932         Assert(Info.u32ClientID);
    933         pCtx->uClientID = Info.u32ClientID;
     938        if (RT_SUCCESS(rc))
     939        {
     940            /* Set the protocol version to use. */
     941            pCtx->uProtocol = 2;
     942
     943            Assert(Info.u32ClientID);
     944            pCtx->uClientID = Info.u32ClientID;
     945        }
    934946    }
    935947
     
    941953         *       does not implement this command.
    942954         */
    943         DragAndDropSvc::VBOXDNDCONNECTPMSG Msg;
     955        DragAndDropSvc::VBOXDNDCONNECTMSG Msg;
    944956        RT_ZERO(Msg);
    945957        Msg.hdr.result      = VERR_WRONG_ORDER;
     
    11421154{
    11431155    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     1156    AssertReturn(uStatus > DragAndDropSvc::DND_PROGRESS_UNKNOWN, VERR_INVALID_PARAMETER);
    11441157
    11451158    DragAndDropSvc::VBOXDNDHGEVTPROGRESSMSG Msg;
     
    11471160    Msg.hdr.result      = VERR_WRONG_ORDER;
    11481161    Msg.hdr.u32ClientID = pCtx->uClientID;
    1149     Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS;
     1162    Msg.hdr.u32Function = uStatus;
    11501163    Msg.hdr.cParms      = 3;
    11511164
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp

    r57372 r57500  
    364364    Close();
    365365
    366     m_Type          = Unknown;
    367     m_strSrcPath    = "";
    368     m_strTgtPath    = "";
    369     m_fMode = 0;
    370     m_cbSize        = 0;
    371     m_cbProcessed   = 0;
     366    m_Type        = Unknown;
     367    m_strSrcPath  = "";
     368    m_strTgtPath  = "";
     369    m_fMode       = 0;
     370    m_cbSize      = 0;
     371    m_cbProcessed = 0;
    372372}
    373373
  • trunk/src/VBox/Main/include/GuestDnDPrivate.h

    r57469 r57500  
    9191
    9292/**
     93 * Structure for keeping an URI object's context around.
     94 */
     95typedef struct GuestDnDURIObjCtx
     96{
     97    GuestDnDURIObjCtx(void)
     98        : pObjURI(NULL)
     99        , fAllocated(false)
     100        , fHeaderSent(false) { }
     101
     102    virtual ~GuestDnDURIObjCtx(void)
     103    {
     104        Reset();
     105    }
     106
     107public:
     108
     109    void Reset(void)
     110    {
     111        if (   pObjURI
     112            && fAllocated)
     113        {
     114            delete pObjURI;
     115        }
     116
     117        pObjURI     = NULL;
     118
     119        fAllocated  = false;
     120        fHeaderSent = false;
     121    }
     122
     123
     124    /** Pointer to current object being handled. */
     125    DnDURIObject             *pObjURI;
     126    /** Flag whether pObjURI needs deletion after use. */
     127    bool                      fAllocated;
     128    /** Flag whether the object's file header has been sent already. */
     129    bool                      fHeaderSent;
     130    /** @todo Add more statistics / information here. */
     131
     132} GuestDnDURIObjCtx;
     133
     134/**
    93135 * Structure for keeping around URI (list) data.
    94136 */
     
    126168    {
    127169        lstURI.Clear();
    128         objURI.Close();
     170        objCtx.Reset();
    129171
    130172        DnDDirDroppedFilesRollback(&mDropDir);
     
    141183
    142184    DNDDIRDROPPEDFILES              mDropDir;
    143     /** (Non-recursive) List of root URI objects to receive. */
     185    /** (Non-recursive) List of URI objects to handle. */
    144186    DnDURIList                      lstURI;
    145     /** Current object to receive. */
    146     DnDURIObject                    objURI;
     187    /** Context to current object being handled.
     188     *  As we currently do all transfers one after another we
     189     *  only have one context at a time. */
     190    GuestDnDURIObjCtx               objCtx;
    147191
    148192protected:
  • trunk/src/VBox/Main/include/GuestDnDSourceImpl.h

    r57221 r57500  
    6767    int i_onReceiveData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData, uint64_t cbTotalSize);
    6868    int i_onReceiveDir(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath, uint32_t fMode);
    69     int i_onReceiveFileHdr(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath, uint64_t cbSize, uint32_t fMode, uint32_t fFlags);
    70     int i_onReceiveFileData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData);
     69    int i_onReceiveFileHdr(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, const char *pszPath, uint32_t cbPath, uint64_t cbSize, uint32_t fMode, uint32_t fFlags);
     70    int i_onReceiveFileData(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, const void *pvData, uint32_t cbData);
    7171    /** @}  */
    7272#endif
  • trunk/src/VBox/Main/include/GuestDnDTargetImpl.h

    r57221 r57500  
    8585    int i_cancelOperation(void);
    8686    int i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
    87     int i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject);
    88     int i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject);
    89     int i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject);
     87    int i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg);
     88    int i_sendFile(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg);
     89    int i_sendFileData(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg);
    9090    int i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
    9191    int i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);
  • trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp

    r57295 r57500  
    421421
    422422            if (   pCBData->cbFormat == 0
    423                 || pCBData->cbFormat >  _64K)
     423                || pCBData->cbFormat > _64K) /** @todo Make the maximum size configurable? */
    424424            {
    425425                rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp

    r57358 r57500  
    620620}
    621621
    622 int GuestDnDSource::i_onReceiveFileHdr(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath,
     622int GuestDnDSource::i_onReceiveFileHdr(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, const char *pszPath, uint32_t cbPath,
    623623                                       uint64_t cbSize, uint32_t fMode, uint32_t fFlags)
    624624{
    625625    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     626    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
    626627    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    627628    AssertReturn(cbPath,     VERR_INVALID_PARAMETER);
     
    635636    do
    636637    {
    637         if (    pCtx->mURI.objURI.IsOpen()
    638             && !pCtx->mURI.objURI.IsComplete())
    639         {
    640             AssertMsgFailed(("Object '%s' not complete yet\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     638        DnDURIObject *pObj = pObjCtx->pObjURI;
     639
     640        if (    pObj
     641            &&  pObj->IsOpen()
     642            && !pObj->IsComplete())
     643        {
     644            AssertMsgFailed(("Object '%s' not complete yet\n", pObj->GetDestPath().c_str()));
    641645            rc = VERR_WRONG_ORDER;
    642646            break;
    643647        }
    644648
    645         if (pCtx->mURI.objURI.IsOpen()) /* File already opened? */
    646         {
    647             AssertMsgFailed(("Current opened object is '%s', close this first\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     649        if (   pObj
     650            && pObj->IsOpen()) /* File already opened? */
     651        {
     652            AssertMsgFailed(("Current opened object is '%s', close this first\n", pObj->GetDestPath().c_str()));
    648653            rc = VERR_WRONG_ORDER;
    649654            break;
     
    674679        LogFunc(("Rebased to: %s\n", pszPathAbs));
    675680
    676         /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
    677         rc = pCtx->mURI.objURI.OpenEx(pszPathAbs, DnDURIObject::File, DnDURIObject::Target,
    678                                       RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
    679                                       (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
     681        if (   pObj
     682            && pObjCtx->fAllocated)
     683        {
     684            delete pObj;
     685            pObj = NULL;
     686        }
     687
     688        try
     689        {
     690            pObj = new DnDURIObject();
     691
     692            pObjCtx->pObjURI    = pObj;
     693            pObjCtx->fAllocated = true;
     694        }
     695        catch (std::bad_alloc &)
     696        {
     697            rc = VERR_NO_MEMORY;
     698        }
     699
     700        if (RT_SUCCESS(rc))
     701        {
     702            /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */
     703            rc = pObj->OpenEx(pszPathAbs, DnDURIObject::File, DnDURIObject::Target,
     704                              RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE,
     705                              (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
     706        }
     707
    680708        if (RT_SUCCESS(rc))
    681709        {
    682710            /* Note: Protocol v1 does not send any file sizes, so always 0. */
    683711            if (mDataBase.mProtocolVersion >= 2)
    684                 rc = pCtx->mURI.objURI.SetSize(cbSize);
     712                rc = pObj->SetSize(cbSize);
    685713
    686714            /** @todo Unescpae path before printing. */
    687715            LogRel2(("DnD: Transferring guest file to host: %s (%RU64 bytes, mode 0x%x)\n",
    688                      pCtx->mURI.objURI.GetDestPath().c_str(), pCtx->mURI.objURI.GetSize(), pCtx->mURI.objURI.GetMode()));
     716                     pObj->GetDestPath().c_str(), pObj->GetSize(), pObj->GetMode()));
    689717
    690718            /** @todo Set progress object title to current file being transferred? */
    691719
    692720            if (!cbSize) /* 0-byte file? Close again. */
    693                 pCtx->mURI.objURI.Close();
    694         }
    695         else
     721                pObj->Close();
     722        }
     723
     724        if (RT_FAILURE(rc))
    696725        {
    697726            LogRel2(("DnD: Error opening/creating guest file '%s' on host, rc=%Rrc\n",
    698                      pCtx->mURI.objURI.GetDestPath().c_str(), rc));
     727                     pObj->GetDestPath().c_str(), rc));
    699728            break;
    700729        }
     
    706735}
    707736
    708 int GuestDnDSource::i_onReceiveFileData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData)
     737int GuestDnDSource::i_onReceiveFileData(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, const void *pvData, uint32_t cbData)
    709738{
    710739    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     740    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
    711741    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
    712742    AssertReturn(cbData, VERR_INVALID_PARAMETER);
     
    716746    do
    717747    {
    718         if (pCtx->mURI.objURI.IsComplete())
    719         {
    720             LogFlowFunc(("Warning: Object '%s' already completed\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     748        DnDURIObject *pObj = pObjCtx->pObjURI;
     749        if (!pObj)
     750        {
     751            rc = VERR_INVALID_PARAMETER;
     752            break;
     753        }
     754
     755        if (pObj->IsComplete())
     756        {
     757            LogFlowFunc(("Warning: Object '%s' already completed\n", pObj->GetDestPath().c_str()));
    721758            rc = VERR_WRONG_ORDER;
    722759            break;
    723760        }
    724761
    725         if (!pCtx->mURI.objURI.IsOpen()) /* File opened on host? */
    726         {
    727             LogFlowFunc(("Warning: Object '%s' not opened\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     762        if (!pObj->IsOpen()) /* File opened on host? */
     763        {
     764            LogFlowFunc(("Warning: Object '%s' not opened\n", pObj->GetDestPath().c_str()));
    728765            rc = VERR_WRONG_ORDER;
    729766            break;
     
    731768
    732769        uint32_t cbWritten;
    733         rc = pCtx->mURI.objURI.Write(pvData, cbData, &cbWritten);
     770        rc = pObj->Write(pvData, cbData, &cbWritten);
    734771        if (RT_SUCCESS(rc))
    735772        {
     
    747784        if (RT_SUCCESS(rc))
    748785        {
    749             if (pCtx->mURI.objURI.IsComplete())
     786            if (pObj->IsComplete())
    750787            {
    751788                /** @todo Sanitize path. */
    752                 LogRel2(("DnD: File transfer to host complete: %s\n", pCtx->mURI.objURI.GetDestPath().c_str()));
     789                LogRel2(("DnD: File transfer to host complete: %s\n", pObj->GetDestPath().c_str()));
    753790                rc = VINF_EOF;
    754791
    755                 /* Prepare URI object for next use. */
    756                 pCtx->mURI.objURI.Reset();
     792                /* Deletion needed? */
     793                if (pObjCtx->fAllocated)
     794                {
     795                    delete pObj;
     796                    pObj = NULL;
     797
     798                    pObjCtx->fAllocated = false;
     799                }
    757800            }
    758801        }
     
    760803        {
    761804            /** @todo What to do when the host's disk is full? */
    762             LogRel(("DnD: Error writing guest file to host to '%s': %Rrc\n", pCtx->mURI.objURI.GetDestPath().c_str(), rc));
     805            LogRel(("DnD: Error writing guest file to host to '%s': %Rrc\n", pObj->GetDestPath().c_str(), rc));
    763806        }
    764807
     
    11801223            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_HDR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    11811224
    1182             rc = pThis->i_onReceiveFileHdr(pCtx, pCBData->pszFilePath, pCBData->cbFilePath,
     1225            rc = pThis->i_onReceiveFileHdr(pCtx, &pCtx->mURI.objCtx, pCBData->pszFilePath, pCBData->cbFilePath,
    11831226                                           pCBData->cbSize, pCBData->fMode, pCBData->fFlags);
    11841227            break;
     
    12001243                 *   appended data to the desired file. So just pass 0 as cbSize.
    12011244                 */
    1202                 rc = pThis->i_onReceiveFileHdr(pCtx,
     1245                rc = pThis->i_onReceiveFileHdr(pCtx, &pCtx->mURI.objCtx,
    12031246                                               pCBData->u.v1.pszFilePath, pCBData->u.v1.cbFilePath,
    12041247                                               0 /* cbSize */, pCBData->u.v1.fMode, 0 /* fFlags */);
    12051248                if (RT_SUCCESS(rc))
    1206                     rc = pThis->i_onReceiveFileData(pCtx, pCBData->pvData, pCBData->cbData);
     1249                    rc = pThis->i_onReceiveFileData(pCtx, &pCtx->mURI.objCtx, pCBData->pvData, pCBData->cbData);
    12071250            }
    12081251            else /* Protocol v2 and up. */
    1209                 rc = pThis->i_onReceiveFileData(pCtx, pCBData->pvData, pCBData->cbData);
     1252                rc = pThis->i_onReceiveFileData(pCtx, &pCtx->mURI.objCtx, pCBData->pvData, pCBData->cbData);
    12101253            break;
    12111254        }
  • trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp

    r57469 r57500  
    771771    ASMAtomicWriteBool(&pCtx->mIsActive, false);
    772772
    773 #undef DATA_IS_VALID_BREAK
    774 
    775773    LogFlowFuncLeaveRC(rc);
    776774    return rc;
    777775}
    778776
    779 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    780 {
    781     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     777int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     778{
    782779    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
    783 
    784     RTCString strPath = pObject->GetDestPath();
     780    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
     781    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     782
     783    DnDURIObject *pObj = pObjCtx->pObjURI;
     784    AssertPtr(pObj);
     785
     786    RTCString strPath = pObj->GetDestPath();
    785787    if (strPath.isEmpty())
    786788        return VERR_INVALID_PARAMETER;
     
    793795    pMsg->setNextString(strPath.c_str());                  /* path */
    794796    pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length - note: Maximum is RTPATH_MAX on guest side. */
    795     pMsg->setNextUInt32(pObject->GetMode());             /* mode */
     797    pMsg->setNextUInt32(pObj->GetMode());                  /* mode */
    796798
    797799    return VINF_SUCCESS;
    798800}
    799801
    800 int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    801 {
    802     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     802int GuestDnDTarget::i_sendFile(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     803{
    803804    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
    804 
    805     RTCString strPathSrc = pObject->GetSourcePath();
     805    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
     806    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     807
     808    DnDURIObject *pObj = pObjCtx->pObjURI;
     809    AssertPtr(pObj);
     810
     811    RTCString strPathSrc = pObj->GetSourcePath();
    806812    if (strPathSrc.isEmpty())
    807813        return VERR_INVALID_PARAMETER;
     
    809815    int rc = VINF_SUCCESS;
    810816
    811     LogFlowFunc(("Sending \"%s\" (%RU32 bytes buffer) using protocol v%RU32 ...\n",
    812                  strPathSrc.c_str(), mData.mcbBlockSize, mDataBase.mProtocolVersion));
    813 
    814     bool fOpen = pObject->IsOpen();
    815     if (!fOpen)
    816     {
    817         LogFlowFunc(("Opening \"%s\" ...\n", strPathSrc.c_str()));
    818         rc = pObject->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,
     817    LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n",
     818                  mData.mcbBlockSize, mDataBase.mProtocolVersion));
     819    LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize()));
     820
     821    if (!pObj->IsOpen())
     822    {
     823        LogRel2(("DnD: Opening host file for transferring to guest: %s\n", strPathSrc.c_str()));
     824        rc = pObj->OpenEx(strPathSrc, DnDURIObject::File, DnDURIObject::Source,
    819825                          RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
    820826        if (RT_FAILURE(rc))
    821             LogRel(("DnD: Error opening host file \"%s\", rc=%Rrc\n", strPathSrc.c_str(), rc));
    822     }
    823 
    824     bool fSendFileData = false;
     827            LogRel(("DnD: Error opening host file '%s', rc=%Rrc\n", strPathSrc.c_str(), rc));
     828    }
     829
     830    bool fSendData = false;
    825831    if (RT_SUCCESS(rc))
    826832    {
    827833        if (mDataBase.mProtocolVersion >= 2)
    828834        {
    829             if (!fOpen)
     835            if (!pObjCtx->fHeaderSent)
    830836            {
    831837                /*
     
    835841                 */
    836842                pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
    837                 pMsg->setNextUInt32(0);                                            /* context ID */
    838                 rc = pMsg->setNextString(pObject->GetDestPath().c_str());             /* pvName */
     843                pMsg->setNextUInt32(0);                                            /* uContextID */
     844                rc = pMsg->setNextString(pObj->GetDestPath().c_str());             /* pvName */
    839845                AssertRC(rc);
    840                 pMsg->setNextUInt32((uint32_t)(pObject->GetDestPath().length() + 1)); /* cbName */
     846                pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */
    841847                pMsg->setNextUInt32(0);                                            /* uFlags */
    842                 pMsg->setNextUInt32(pObject->GetMode());                              /* fMode */
    843                 pMsg->setNextUInt64(pObject->GetSize());                              /* uSize */
     848                pMsg->setNextUInt32(pObj->GetMode());                              /* fMode */
     849                pMsg->setNextUInt64(pObj->GetSize());                              /* uSize */
    844850
    845851                LogFlowFunc(("Sending file header ...\n"));
    846852                LogRel2(("DnD: Transferring host file to guest: %s (%RU64 bytes, mode 0x%x)\n",
    847                          strPathSrc.c_str(), pObject->GetSize(), pObject->GetMode()));
     853                         strPathSrc.c_str(), pObj->GetSize(), pObj->GetMode()));
    848854
    849855                /** @todo Set progress object title to current file being transferred? */
     856
     857                pObjCtx->fHeaderSent = true;
    850858            }
    851859            else
    852860            {
    853861                /* File header was sent, so only send the actual file data. */
    854                 fSendFileData = true;
     862                fSendData = true;
    855863            }
    856864        }
     
    858866        {
    859867            /* Always send the file data, every time. */
    860             fSendFileData = true;
     868            fSendData = true;
    861869        }
    862870    }
    863871
    864872    if (   RT_SUCCESS(rc)
    865         && fSendFileData)
    866     {
    867         rc = i_sendFileData(pCtx, pMsg, pObject);
     873        && fSendData)
     874    {
     875        rc = i_sendFileData(pCtx, pObjCtx, pMsg);
    868876    }
    869877
     
    872880}
    873881
    874 int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDMsg *pMsg, DnDURIObject *pObject)
    875 {
    876     AssertPtrReturn(pObject, VERR_INVALID_POINTER);
     882int GuestDnDTarget::i_sendFileData(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg)
     883{
    877884    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     885    AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);
    878886    AssertPtrReturn(pMsg,    VERR_INVALID_POINTER);
     887
     888    DnDURIObject *pObj = pObjCtx->pObjURI;
     889    AssertPtr(pObj);
    879890
    880891    GuestDnDResponse *pResp = pCtx->mpResp;
     
    882893
    883894    /** @todo Don't allow concurrent reads per context! */
    884 
    885     /* Something to transfer? */
    886     if (   pCtx->mURI.lstURI.IsEmpty()
    887         || !pCtx->mIsActive)
    888     {
    889         return VERR_WRONG_ORDER;
    890     }
    891895
    892896    /*
     
    901905    if (mDataBase.mProtocolVersion <= 1)
    902906    {
    903         pMsg->setNextString(pObject->GetDestPath().c_str());                  /* pvName */
    904         pMsg->setNextUInt32((uint32_t)(pObject->GetDestPath().length() + 1)); /* cbName */
     907        pMsg->setNextString(pObj->GetDestPath().c_str());                  /* pvName */
     908        pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */
    905909    }
    906910    else
    907911    {
    908912        /* Protocol version 2 also sends the context ID. Currently unused. */
    909         pMsg->setNextUInt32(0);                                              /* context ID */
     913        pMsg->setNextUInt32(0);                                            /* context ID */
    910914    }
    911915
    912916    uint32_t cbRead = 0;
    913917
    914     int rc = pObject->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);
     918    int rc = pObj->Read(pCtx->mURI.GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);
    915919    if (RT_SUCCESS(rc))
    916920    {
    917921        pCtx->mData.cbProcessed += cbRead;
     922        LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32, cbProcessed=%RU64, rc=%Rrc\n",
     923                     pCtx->mURI.GetBufferSize(), cbRead, pCtx->mData.cbProcessed, rc));
    918924
    919925        if (mDataBase.mProtocolVersion <= 1)
    920926        {
    921             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */
    922             pMsg->setNextUInt32(cbRead);                                 /* cbData */
    923             pMsg->setNextUInt32(pObject->GetMode());                     /* fMode */
     927            pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
     928            pMsg->setNextUInt32(cbRead);                                   /* cbData */
     929            pMsg->setNextUInt32(pObj->GetMode());                          /* fMode */
    924930        }
    925931        else
    926932        {
    927             pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */
    928             pMsg->setNextUInt32(cbRead);                                 /* cbData */
    929         }
    930 
    931         if (pObject->IsComplete()) /* Done reading? */
    932         {
    933             LogRel2(("DnD: File transfer to guest complete: %s\n", pObject->GetSourcePath().c_str()));
    934             LogFlowFunc(("File \"%s\" complete\n", pObject->GetSourcePath().c_str()));
    935             rc = VINF_EOF;
     933            pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead);   /* pvData */
     934            pMsg->setNextUInt32(cbRead);                                   /* cbData */
     935        }
     936
     937        if (pObj->IsComplete()) /* Done reading? */
     938        {
     939            LogRel2(("DnD: File transfer to guest complete: %s\n", pObj->GetSourcePath().c_str()));
     940            LogFlowFunc(("File '%s' complete\n", pObj->GetSourcePath().c_str()));
     941
     942            /* DnDURIObject::Read() returns VINF_EOF when finished reading the entire fire,
     943             * but we don't want this here -- so just override this with VINF_SUCCESS. */
     944            rc = VINF_SUCCESS;
    936945        }
    937946    }
     
    952961    LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg));
    953962
    954     int rc = VINF_SUCCESS; /* Will be reported back to guest. */
    955 
    956     int rcCallback = VINF_SUCCESS; /* rc for the callback. */
     963    int rc      = VINF_SUCCESS; /* Will be reported back to guest. */
     964    int rcGuest;                /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */
    957965    bool fNotify = false;
    958966
     
    971979
    972980                rc = pThis->i_sendURIDataLoop(pCtx, pMsg);
    973                 if (RT_SUCCESS(rc))
     981                if (rc == VINF_EOF) /* Transfer complete? */
     982                {
     983                    LogFlowFunc(("Last URI item processed, bailing out\n"));
     984                }
     985                else if (RT_SUCCESS(rc))
    974986                {
    975987                    rc = pThis->msgQueueAdd(pMsg);
     
    982994                }
    983995
    984                 if (RT_FAILURE(rc))
     996                if (   RT_FAILURE(rc)
     997                    || rc == VINF_EOF) /* Transfer complete? */
     998                {
    985999                    delete pMsg;
     1000                    pMsg = NULL;
     1001                }
    9861002            }
    9871003            catch(std::bad_alloc & /*e*/)
     
    10011017
    10021018            if (RT_SUCCESS(pCBData->rc))
     1019            {
     1020                AssertMsgFailed(("Guest has sent an error event but did not specify an actual error code\n"));
    10031021                pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */
     1022            }
    10041023
    10051024            rc = pCtx->mpResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,
    10061025                                           GuestDnDTarget::i_guestErrorToString(pCBData->rc));
    10071026            if (RT_SUCCESS(rc))
    1008                 rcCallback = VERR_GSTDND_GUEST_ERROR;
     1027            {
     1028                rc      = VERR_GSTDND_GUEST_ERROR;
     1029                rcGuest = pCBData->rc;
     1030            }
    10091031            break;
    10101032        }
     
    10611083    }
    10621084
    1063     if (   RT_FAILURE(rc)
    1064         || RT_FAILURE(rcCallback))
    1065     {
    1066         fNotify = true;
    1067         if (RT_SUCCESS(rcCallback))
    1068             rcCallback = rc;
     1085    int rcToGuest = VINF_SUCCESS; /* Status which will be sent back to the guest. */
     1086
     1087    /*
     1088     * Resolve errors.
     1089     */
     1090    switch (rc)
     1091    {
     1092        case VINF_SUCCESS:
     1093            break;
     1094
     1095        case VINF_EOF:
     1096        {
     1097            LogRel2(("DnD: Transfer to guest complete\n"));
     1098
     1099            /* Complete operation on host side. */
     1100            fNotify = true;
     1101
     1102            /* The guest expects VERR_NO_DATA if the transfer is complete. */
     1103            rcToGuest = VERR_NO_DATA;
     1104            break;
     1105        }
     1106
     1107        case VERR_GSTDND_GUEST_ERROR:
     1108        {
     1109            LogRel(("DnD: Guest reported error %Rrc, aborting transfer to guest\n", rcGuest));
     1110            break;
     1111        }
     1112
     1113        case VERR_CANCELLED:
     1114        {
     1115            LogRel2(("DnD: Transfer to guest canceled\n"));
     1116            rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */
     1117            break;
     1118        }
     1119
     1120        default:
     1121        {
     1122            LogRel(("DnD: Host error %Rrc occurred, aborting transfer to guest\n", rc));
     1123            rcToGuest = VERR_CANCELLED; /* Also cancel on guest side. */
     1124            break;
     1125        }
    10691126    }
    10701127
    10711128    if (RT_FAILURE(rc))
    10721129    {
    1073         switch (rc)
    1074         {
    1075             case VERR_NO_DATA:
    1076                 LogRel2(("DnD: Transfer to guest complete\n"));
    1077                 break;
    1078 
    1079             case VERR_CANCELLED:
    1080                 LogRel2(("DnD: Transfer to guest canceled\n"));
    1081                 break;
    1082 
    1083             default:
    1084                 LogRel(("DnD: Error %Rrc occurred, aborting transfer to guest\n", rc));
    1085                 break;
    1086         }
    1087 
    10881130        /* Unregister this callback. */
    10891131        AssertPtr(pCtx->mpResp);
    10901132        int rc2 = pCtx->mpResp->setCallback(uMsg, NULL /* PFNGUESTDNDCALLBACK */);
    10911133        AssertRC(rc2);
    1092     }
    1093 
    1094     LogFlowFunc(("fNotify=%RTbool, rcCallback=%Rrc, rc=%Rrc\n", fNotify, rcCallback, rc));
     1134
     1135        /* Let the waiter(s) know. */
     1136        fNotify = true;
     1137    }
     1138
     1139    LogFlowFunc(("fNotify=%RTbool, rc=%Rrc, rcToGuest=%Rrc\n", fNotify, rc, rcToGuest));
    10951140
    10961141    if (fNotify)
    10971142    {
    1098         int rc2 = pCtx->mCallback.Notify(rcCallback);
     1143        int rc2 = pCtx->mCallback.Notify(rc); /** @todo Also pass guest error back? */
    10991144        AssertRC(rc2);
    11001145    }
    11011146
    11021147    LogFlowFuncLeaveRC(rc);
    1103     return rc; /* Tell the guest. */
     1148    return rcToGuest; /* Tell the guest. */
    11041149}
    11051150
     
    11641209        URI_DATA_IS_VALID_BREAK(!lstURIOrg.isEmpty());
    11651210
    1166         uint32_t fFlags = DNDURILIST_FLAGS_KEEP_OPEN;
    1167 
    1168         rc = lstURI.AppendURIPathsFromList(lstURIOrg, fFlags);
     1211        /* Note: All files to be transferred will be kept open during the entire DnD
     1212         *       operation, also to keep the accounting right. */
     1213        rc = lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN);
    11691214        if (RT_SUCCESS(rc))
    11701215            LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n",
     
    12671312
    12681313    if (fComplete)
    1269     {
    1270         LogFlowFunc(("Last URI item processed, bailing out\n"));
    1271         return VERR_NO_DATA;
    1272     }
     1314        return VINF_EOF;
    12731315
    12741316    Assert(!lstURI.IsEmpty());
    12751317    DnDURIObject *pCurObj = lstURI.First();
     1318
     1319    /* As we transfer all objects one after another at a time at the moment,
     1320     * we only need one object context at the moment. */
     1321    GuestDnDURIObjCtx *pObjCtx = &pCtx->mURI.objCtx;
     1322
     1323    /* Assign the pointer of the current object to our context. */
     1324    pObjCtx->pObjURI = pCurObj;
    12761325
    12771326    uint32_t fMode = pCurObj->GetMode();
     
    12831332    if (RTFS_IS_DIRECTORY(fMode))
    12841333    {
    1285         rc = i_sendDirectory(pCtx, pMsg, pCurObj);
     1334        rc = i_sendDirectory(pCtx, pObjCtx, pMsg);
    12861335    }
    12871336    else if (RTFS_IS_FILE(fMode))
    12881337    {
    1289         rc = i_sendFile(pCtx, pMsg, pCurObj);
     1338        rc = i_sendFile(pCtx, pObjCtx, pMsg);
    12901339    }
    12911340    else
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