VirtualBox

Changeset 49891 in vbox for trunk/src/VBox/HostServices


Ignore:
Timestamp:
Dec 12, 2013 8:09:20 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
91269
Message:

Merged private draganddrop branch into trunk.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/VBox

  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp

    r44102 r49891  
    55
    66/*
    7  * Copyright (C) 2011-2012 Oracle Corporation
     7 * Copyright (C) 2011-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020 ******************************************************************************/
    2121
    22 #define LOG_GROUP LOG_GROUP_HGCM
     22#ifdef LOG_GROUP
     23 #undef LOG_GROUP
     24#endif
     25#define LOG_GROUP LOG_GROUP_GUEST_DND
    2326
    2427#include "dndmanager.h"
     
    2932#include <iprt/path.h>
    3033#include <iprt/uri.h>
    31 
    32 #define VERBOSE 1
    33 
    34 #if defined(VERBOSE) && defined(DEBUG_poetzsch)
    35 # include <iprt/stream.h>
    36 # define DO(s) RTPrintf s
    37 #else
    38 # define DO(s) do {} while(0)
    39 //# define DO(s) Log s
    40 #endif
    4134
    4235/******************************************************************************
     
    6558        paTmpParms[1].setUInt32(m_strPath.length() + 1);
    6659        paTmpParms[2].setUInt32(fMode);
     60
    6761        m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms);
    6862    }
     
    9791public:
    9892    DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
    99     ~DnDHGSendFilePrivate();
     93    virtual ~DnDHGSendFilePrivate();
    10094
    10195    int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     
    10498    RTCString              m_strHostPath;
    10599    RTCString              m_strGuestPath;
    106     uint64_t               m_cbSize;
    107     uint64_t               m_cbDone;
     100    uint64_t               m_cbFileSize;
     101    uint64_t               m_cbFileProcessed;
    108102    RTFILE                 m_hCurFile;
    109103    VBOXHGCMSVCPARM        m_paSkelParms[5];
     
    146140  : m_strHostPath(strHostPath)
    147141  , m_strGuestPath(strGuestPath)
    148   , m_cbSize(cbSize)
    149   , m_cbDone(0)
     142  , m_cbFileSize(cbSize)
     143  , m_cbFileProcessed(0)
    150144  , m_hCurFile(0)
    151145  , m_pfnProgressCallback(pfnProgressCallback)
     
    157151    m_paSkelParms[3].setUInt32(0);
    158152    m_paSkelParms[4].setUInt32(fMode);
     153
    159154    m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms);
    160155}
     
    178173    if (!m_hCurFile)
    179174    {
    180         rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_ALL);
    181         if (RT_FAILURE(rc))
    182             return rc;
    183     }
    184 
    185     /* How big is the pointer provided by the guest? */
    186     uint32_t cbToRead = paParms[2].u.pointer.size;
     175        /* Open files on the host with RTFILE_O_DENY_WRITE to prevent races where the host
     176         * writes to the file while the guest transfers it over. */
     177        rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(),
     178                        RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
     179    }
     180
    187181    size_t cbRead;
    188     rc = RTFileRead(m_hCurFile, paParms[2].u.pointer.addr, cbToRead, &cbRead);
    189     if (RT_FAILURE(rc))
    190     {
    191         /* On error, immediately close the file. */
    192         RTFileClose(m_hCurFile);
    193         m_hCurFile = 0;
    194         return rc;
    195     }
    196     m_cbDone += cbRead;
    197     /* Tell the guest the actual size. */
    198     paParms[3].setUInt32(cbRead);
    199     /* Check if we are done. */
    200     if (m_cbSize == m_cbDone)
    201     {
    202         RTFileClose(m_hCurFile);
    203         m_hCurFile = 0;
    204     }
    205     else
    206     {
    207         /* More data! Prepare the next message. */
    208         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms);
    209     }
    210 
    211     /* Advance progress info */
    212     if (   RT_SUCCESS(rc)
    213         && m_pfnProgressCallback)
    214         rc = m_pfnProgressCallback(cbRead, m_pvProgressUser);
     182    if (RT_SUCCESS(rc))
     183    {
     184        /* Get buffer size + pointer to buffer from guest side. */
     185        uint32_t cbToRead = paParms[2].u.pointer.size;
     186        Assert(cbToRead);
     187        void *pvBuf = paParms[2].u.pointer.addr;
     188        AssertPtr(pvBuf);
     189        rc = RTFileRead(m_hCurFile, pvBuf, cbToRead, &cbRead);
     190        if (RT_LIKELY(RT_SUCCESS(rc)))
     191        {
     192            /* Advance. */
     193            m_cbFileProcessed += cbRead;
     194            Assert(m_cbFileProcessed <= m_cbFileSize);
     195
     196            /* Tell the guest the actual size. */
     197            paParms[3].setUInt32(cbRead);
     198        }
     199    }
     200
     201    if (RT_SUCCESS(rc))
     202    {
     203        /* Check if we are done. */
     204        bool fDone = m_cbFileSize == m_cbFileProcessed;
     205        if (!fDone)
     206        {
     207            try
     208            {
     209                /* More data! Prepare the next message. */
     210                m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */,
     211                                               m_paSkelParms);
     212            }
     213            catch(std::bad_alloc &)
     214            {
     215                rc = VERR_NO_MEMORY;
     216            }
     217        }
     218
     219        /* Advance progress info. */
     220        if (   RT_SUCCESS(rc)
     221            && m_pfnProgressCallback)
     222            rc = m_pfnProgressCallback(cbRead, m_pvProgressUser);
     223
     224        if (   fDone
     225            || RT_FAILURE(rc))
     226        {
     227            RTFileClose(m_hCurFile);
     228            m_hCurFile = 0;
     229        }
     230    }
    215231
    216232    return rc;
     
    241257
    242258    HGCM::Message *pCurMsg = m_pNextMsg;
     259    AssertPtr(pCurMsg);
     260
    243261    m_pNextMsg = 0;
    244262    rc = pCurMsg->getData(uMsg, cParms, paParms);
     
    258276        paTmpParms[0].setPointer(static_cast<uint8_t*>(pvOldData) + paParms[iPos].u.pointer.size, cOldData - paParms[iPos].u.pointer.size);
    259277        paTmpParms[1].setUInt32(cOldData - paParms[iPos].u.pointer.size);
    260         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA, 2, paTmpParms);
    261     }
     278
     279        try
     280        {
     281            m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA, 2, paTmpParms);
     282        }
     283        catch(std::bad_alloc &)
     284        {
     285            rc = VERR_NO_MEMORY;
     286        }
     287    }
     288
    262289    delete pCurMsg;
    263290
     
    280307 */
    281308DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser)
    282   : m_cbAll(0)
    283   , m_cbTransfered(0)
    284   , m_pfnProgressCallback(pfnProgressCallback)
    285   , m_pvProgressUser(pvProgressUser)
     309    : m_cbAll(0)
     310    , m_cbTransfered(0)
     311    , m_pfnProgressCallback(pfnProgressCallback)
     312    , m_pvProgressUser(pvProgressUser)
    286313{
    287314    RTCString strNewUris;
     
    289316    if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), paParms[1].u.pointer.size))
    290317    {
    291         DO(("old data '%s'\n", (char*)paParms[3].u.pointer.addr));
     318        LogFlowFunc(("Old data: '%s'\n", (char*)paParms[3].u.pointer.addr));
    292319        /* The list is separated by newline (Even if only one file is
    293320         * listed). */
    294         RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr), paParms[3].u.pointer.size).split("\r\n");
     321        RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr),
     322                                                  paParms[3].u.pointer.size).split("\r\n");
    295323        if (!oldUriList.isEmpty())
    296324        {
     
    337365    m_cbAll += paParms[4].u.uint32;
    338366    /* The first message is the meta info for the data and the data itself. */
    339     m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, &DnDHGSendDataMessage::progressCallback, this);
    340 
    341     DO(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));
    342     DO(("cbAll: %u\n", m_cbAll));
    343     DO(("cbData: %u\n", paParms[4].u.uint32));
     367    m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms,
     368                                                     &DnDHGSendDataMessage::progressCallback, this);
     369
     370    LogFlowFunc(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));
     371    LogFlowFunc(("cbAll: %zu\n", m_cbAll));
     372    LogFlowFunc(("cbData: %RU32\n", paParms[4].u.uint32));
    344373
    345374    for (size_t i = 0; i < m_uriList.size(); ++i)
    346         DO(("file: %s : %s - %o - %ld\n", m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(), m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));
     375        LogFlowFunc(("file: %s : %s - %o - %ld\n",
     376                     m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(),
     377                     m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));
    347378}
    348379
     
    391422         * this could be directories or regular files. */
    392423        PathEntry nextPath = m_uriList.first();
    393         if (RTFS_IS_DIRECTORY(nextPath.m_fMode))
    394             m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this);
    395         else if (RTFS_IS_FILE(nextPath.m_fMode))
    396             m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this);
    397         else
    398             AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA);
    399         m_uriList.removeFirst();
    400     }
     424        try
     425        {
     426            if (RTFS_IS_DIRECTORY(nextPath.m_fMode))
     427                m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath,
     428                                                         nextPath.m_fMode, nextPath.m_cbSize,
     429                                                         &DnDHGSendDataMessage::progressCallback, this);
     430            else if (RTFS_IS_FILE(nextPath.m_fMode))
     431                m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath,
     432                                                          nextPath.m_fMode, nextPath.m_cbSize,
     433                                                          &DnDHGSendDataMessage::progressCallback, this);
     434            else
     435                AssertMsgFailedReturn(("type '%d' is not supported for path '%s'",
     436                                       nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA);
     437
     438            m_uriList.removeFirst();
     439        }
     440        catch(std::bad_alloc &)
     441        {
     442            rc = VERR_NO_MEMORY;
     443        }
     444    }
     445
    401446    return rc;
    402447}
     
    404449bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const
    405450{
    406     DO(("format %s\n", pcszFormat));
    407     /* text/uri also an official variant? */
     451    LogFlowFunc(("format %s\n", pcszFormat));
     452    /** @todo text/uri also an official variant? */
    408453    return    RTStrNICmp(pcszFormat, "text/uri-list", cbMax)             == 0
    409454           || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0;
     
    435480    m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize));
    436481    m_cbAll += cbSize;
    437     DO(("cbFile: %u\n", cbSize));
     482    LogFlowFunc(("cbFile: %RU64\n", cbSize));
    438483
    439484    PRTDIR hDir;
     
    518563        && pSelf->m_cbAll)
    519564        rc = pSelf->m_pfnProgressCallback((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbAll,
    520                                           DragAndDropSvc::DND_PROGRESS_RUNNING, pSelf->m_pvProgressUser);
     565                                          DragAndDropSvc::DND_PROGRESS_RUNNING, VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser);
    521566
    522567    return rc;
     
    530575{
    531576    int rc = VINF_SUCCESS;
    532     switch (uMsg)
    533     {
    534         case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:
    535         {
    536             clear();
    537             LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
    538             DO(("HOST_DND_HG_EVT_ENTER\n"));
    539             /* Verify parameter count and types. */
    540             if (   cParms != 7
    541                 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    542                 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    543                 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    544                 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    545                 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    546                 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    547                 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    548                 rc = VERR_INVALID_PARAMETER;
    549             else
    550             {
    551                 m_fOpInProcess = true;
    552                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    553                 m_dndMessageQueue.append(pMessage);
    554             }
    555             break;
    556         }
    557         case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
    558         {
    559             LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
    560             DO(("HOST_DND_HG_EVT_MOVE\n"));
    561             /* Verify parameter count and types. */
    562             if (   cParms != 7
    563                 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    564                 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    565                 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    566                 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    567                 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    568                 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    569                 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    570                 rc = VERR_INVALID_PARAMETER;
    571             else
    572             {
    573                 m_fOpInProcess = true;
    574                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    575                 m_dndMessageQueue.append(pMessage);
    576             }
    577             break;
    578         }
    579         case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:
    580         {
    581             LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
    582             DO(("HOST_DND_HG_EVT_LEAVE\n"));
    583 
    584             /* Verify parameter count and types. */
    585             if (cParms != 0)
    586                 rc = VERR_INVALID_PARAMETER;
    587             else
    588             {
    589                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    590                 m_dndMessageQueue.append(pMessage);
    591             }
    592             m_fOpInProcess = false;
    593             break;
    594         }
    595         case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:
    596         {
    597             LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
    598             DO(("HOST_DND_HG_EVT_DROPPED\n"));
    599             /* Verify parameter count and types. */
    600             if (   cParms != 7
    601                 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    602                 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    603                 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    604                 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    605                 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    606                 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    607                 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    608                 rc = VERR_INVALID_PARAMETER;
    609             else
    610             {
    611                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    612                 m_dndMessageQueue.append(pMessage);
    613             }
    614             break;
    615         }
    616         case DragAndDropSvc::HOST_DND_HG_SND_DATA:
    617         {
    618             LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
    619             DO(("HOST_DND_HG_SND_DATA\n"));
    620 
    621             /* Verify parameter count and types. */
    622             if (   cParms != 5
    623                 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    624                 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
    625                 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
    626                 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    627                 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */)
    628                 rc = VERR_INVALID_PARAMETER;
    629             else
    630             {
    631                 DnDHGSendDataMessage *pMessage = new DnDHGSendDataMessage(uMsg, cParms, paParms, m_pfnProgressCallback, m_pvProgressUser);
    632                 m_dndMessageQueue.append(pMessage);
    633             }
    634             break;
    635         }
    636 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    637         case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
    638         {
    639             LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n"));
    640             DO(("HOST_DND_GH_REQ_PENDING\n"));
    641 
    642             /* Verify parameter count and types. */
    643             if (   cParms != 1
    644                 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */)
    645                 rc = VERR_INVALID_PARAMETER;
    646             else
    647             {
    648                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    649                 m_dndMessageQueue.append(pMessage);
    650             }
    651             break;
    652         }
    653         case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
    654         {
    655             LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n"));
    656             DO(("HOST_DND_GH_EVT_DROPPED\n"));
    657 
    658             /* Verify parameter count and types. */
    659             if (   cParms != 3
    660                 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
    661                 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
    662                 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
    663                 rc = VERR_INVALID_PARAMETER;
    664             else
    665             {
    666                 DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    667                 m_dndMessageQueue.append(pMessage);
    668             }
    669             break;
    670         }
    671 #endif
    672         default: rc = VERR_NOT_IMPLEMENTED; break;
     577
     578    try
     579    {
     580        switch (uMsg)
     581        {
     582            case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:
     583            {
     584                clear();
     585                LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
     586
     587                /* Verify parameter count and types. */
     588                if (   cParms != 7
     589                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
     590                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
     591                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
     592                    || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
     593                    || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
     594                    || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
     595                    || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
     596                    rc = VERR_INVALID_PARAMETER;
     597                else
     598                {
     599                    m_fOpInProcess = true;
     600                    DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     601                    m_dndMessageQueue.append(pMessage);
     602                }
     603                break;
     604            }
     605            case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
     606            {
     607                LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
     608
     609                /* Verify parameter count and types. */
     610                if (   cParms != 7
     611                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
     612                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
     613                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
     614                    || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
     615                    || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
     616                    || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
     617                    || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
     618                    rc = VERR_INVALID_PARAMETER;
     619                else
     620                {
     621                    m_fOpInProcess = true;
     622                    DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     623                    m_dndMessageQueue.append(pMessage);
     624                }
     625                break;
     626            }
     627            case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:
     628            {
     629                LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
     630
     631                /* Verify parameter count and types. */
     632                if (cParms != 0)
     633                    rc = VERR_INVALID_PARAMETER;
     634                else
     635                {
     636                    DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     637                    m_dndMessageQueue.append(pMessage);
     638                }
     639                m_fOpInProcess = false;
     640                break;
     641            }
     642            case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:
     643            {
     644                LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
     645
     646                /* Verify parameter count and types. */
     647                if (   cParms != 7
     648                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
     649                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
     650                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
     651                    || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
     652                    || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
     653                    || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
     654                    || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
     655                    rc = VERR_INVALID_PARAMETER;
     656                else
     657                {
     658                    DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     659                    m_dndMessageQueue.append(pMessage);
     660                }
     661                break;
     662            }
     663            case DragAndDropSvc::HOST_DND_HG_SND_DATA:
     664            {
     665                LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
     666
     667                /* Verify parameter count and types. */
     668                if (   cParms != 5
     669                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
     670                    || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
     671                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
     672                    || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
     673                    || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */)
     674                    rc = VERR_INVALID_PARAMETER;
     675                else
     676                {
     677                    DnDHGSendDataMessage *pMessage = new DnDHGSendDataMessage(uMsg, cParms, paParms, m_pfnProgressCallback, m_pvProgressUser);
     678                    m_dndMessageQueue.append(pMessage);
     679                }
     680                break;
     681            }
     682    #ifdef VBOX_WITH_DRAG_AND_DROP_GH
     683            case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
     684            {
     685                LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n"));
     686
     687                /* Verify parameter count and types. */
     688                if (   cParms != 1
     689                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */)
     690                    rc = VERR_INVALID_PARAMETER;
     691                else
     692                {
     693                    DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     694                    m_dndMessageQueue.append(pMessage);
     695                }
     696                break;
     697            }
     698            case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
     699            {
     700                LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n"));
     701
     702                /* Verify parameter count and types. */
     703                if (   cParms != 3
     704                    || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
     705                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
     706                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
     707                    rc = VERR_INVALID_PARAMETER;
     708                else
     709                {
     710                    try
     711                    {
     712                        DnDGenericMessage *pMessage
     713                            = new DnDGenericMessage(uMsg, cParms, paParms);
     714                        m_dndMessageQueue.append(pMessage);
     715                    }
     716                    catch(std::bad_alloc &)
     717                    {
     718                        rc = VERR_NO_MEMORY;
     719                    }
     720                }
     721                break;
     722            }
     723    #endif
     724            default:
     725                rc = VERR_NOT_IMPLEMENTED;
     726                break;
     727        }
     728    }
     729    catch(std::bad_alloc &)
     730    {
     731        rc = VERR_NO_MEMORY;
    673732    }
    674733
     
    710769    }
    711770
    712     DO(("next msg info: %d %d %Rrc\n", *puMsg, *pcParms, rc));
     771    LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puMsg, *pcParms, rc));
    713772    return rc;
    714773}
     
    716775int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    717776{
     777    LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
     778
    718779    if (!m_pCurMsg)
    719780    {
    720781        /* Check for pending messages in our queue. */
    721782        if (m_dndMessageQueue.isEmpty())
     783        {
     784            LogFlowFunc(("Message queue is empty, returning\n"));
    722785            return VERR_NO_DATA;
     786        }
     787
    723788        m_pCurMsg = m_dndMessageQueue.first();
    724789        m_dndMessageQueue.removeFirst();
     
    727792    /* Fetch the current message info */
    728793    int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms);
    729     /* If this message not provide any additional sub messages, clear it. */
     794    /* If this message doesn't provide any additional sub messages, clear it. */
    730795    if (!m_pCurMsg->isMessageWaiting())
     796    {
     797        delete m_pCurMsg;
     798        m_pCurMsg = NULL;
     799    }
     800
     801    /*
     802     * If there was an error handling the current message or the user has canceled
     803     * the operation, we need to cleanup all pending events and inform the progress
     804     * callback about our exit.
     805     */
     806    if (   RT_FAILURE(rc)
     807        && m_pfnProgressCallback)
     808    {
     809        /* Clear any pending messages. */
     810        clear();
     811
     812        /* Create a new cancel message to inform the guest + call
     813         * the host whether the current transfer was canceled or aborted
     814         * due to an error. */
     815        try
     816        {
     817            Assert(!m_pCurMsg);
     818            m_pCurMsg = new DnDHGCancelMessage();
     819            m_pfnProgressCallback(100 /* Percent */,
     820                                    rc == VERR_CANCELLED
     821                                  ? DragAndDropSvc::DND_PROGRESS_CANCELLED
     822                                  : DragAndDropSvc::DND_PROGRESS_ERROR, rc, m_pvProgressUser);
     823        }
     824        catch(std::bad_alloc &)
     825        {
     826            rc = VERR_NO_MEMORY;
     827        }
     828    }
     829
     830    LogFlowFunc(("Message processed with rc=%Rrc\n", rc));
     831    return rc;
     832}
     833
     834void DnDManager::clear()
     835{
     836    if (m_pCurMsg)
    731837    {
    732838        delete m_pCurMsg;
    733839        m_pCurMsg = 0;
    734840    }
    735 
    736     /* If the user has canceled the operation, we need to cleanup all pending
    737      * events and inform the progress callback about our successful cleanup. */
    738     if (   rc == VERR_CANCELLED
    739         && m_pfnProgressCallback)
    740     {
    741         /* Clear any pending messages */
    742         clear();
    743         /* Create a new cancel message to inform the guest. */
    744         m_pCurMsg = new DnDHGCancelMessage();
    745         m_pfnProgressCallback(100, DragAndDropSvc::DND_PROGRESS_CANCELLED, m_pvProgressUser);
    746     }
    747 
    748     DO(("next msg: %d %d %Rrc\n", uMsg, cParms, rc));
    749     return rc;
    750 }
    751 
    752 void DnDManager::clear()
    753 {
    754     if (m_pCurMsg)
    755     {
    756         delete m_pCurMsg;
    757         m_pCurMsg = 0;
    758     }
    759841    while (!m_dndMessageQueue.isEmpty())
    760842    {
  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h

    r42342 r49891  
    2424#include <iprt/cpp/list.h>
    2525
    26 typedef DECLCALLBACK(int) FNDNDPROGRESS(unsigned uPercentage, uint32_t uState, void *pvUser);
     26typedef DECLCALLBACK(int) FNDNDPROGRESS(unsigned uPercentage, uint32_t uState, int rc, void *pvUser);
    2727typedef FNDNDPROGRESS *PFNDNDPROGRESS;
    2828
     
    168168      , m_pvProgressUser(pvProgressUser)
    169169    {}
    170     ~DnDManager()
     170    virtual ~DnDManager()
    171171    {
    172172        clear();
  • trunk/src/VBox/HostServices/DragAndDrop/service.cpp

    r43996 r49891  
    55
    66/*
    7  * Copyright (C) 2011-2012 Oracle Corporation
     7 * Copyright (C) 2011-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5555 *   Header Files                                                             *
    5656 ******************************************************************************/
    57 #define LOG_GROUP LOG_GROUP_HGCM
     57#ifdef LOG_GROUP
     58 #undef LOG_GROUP
     59#endif
     60#define LOG_GROUP LOG_GROUP_GUEST_DND
    5861
    5962#include "dndmanager.h"
    60 
    61 //# define DO(s) RTPrintf s
    62 #define DO(s) do {} while(0)
    63 //#define DO(s) Log s
    6463
    6564/******************************************************************************
     
    8887    int  hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    8988
    90     static DECLCALLBACK(int) progressCallback(unsigned uPercentage, uint32_t uState, void *pvUser);
     89    static DECLCALLBACK(int) progressCallback(uint32_t uPercentage, uint32_t uState, int rc, void *pvUser);
    9190    int      hostMessage(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    9291    void     modeSet(uint32_t u32Mode);
     
    128127{
    129128    LogFlowFunc(("New client (%ld) connected\n", u32ClientID));
    130     DO(("New client (%ld) connected\n", u32ClientID));
    131129    if (m_cClients < UINT32_MAX)
    132130        m_cClients++;
     
    173171void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    174172{
     173    LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32\n",
     174                 u32ClientID, u32Function, cParms));
     175
    175176    int rc = VINF_SUCCESS;
    176     LogFlowFunc(("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
    177                  u32ClientID, u32Function, cParms, paParms));
    178 //    RTPrintf("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
    179 //                 u32ClientID, u32Function, cParms, paParms);
    180 
    181177    switch (u32Function)
    182178    {
    183179        case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:
    184180        {
    185             DO(("GUEST_DND_GET_NEXT_HOST_MSG\n"));
     181            LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n"));
    186182            if (   cParms != 3
    187183                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */
     
    203199        case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
    204200        {
    205             DO(("GUEST_DND_HG_ACK_OP\n"));
     201            LogFlowFunc(("GUEST_DND_HG_ACK_OP\n"));
    206202            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
    207203                && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)
    208204            {
    209                 DO(("=> ignoring!\n"));
     205                LogFlowFunc(("=> ignoring!\n"));
    210206                break;
    211207            }
     
    227223        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
    228224        {
    229             DO(("GUEST_DND_HG_REQ_DATA\n"));
     225            LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n"));
    230226            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
    231227                && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)
    232228            {
    233                 DO(("=> ignoring!\n"));
     229                LogFlowFunc(("=> ignoring!\n"));
    234230                break;
    235231            }
     
    257253        case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
    258254        {
    259             DO(("GUEST_DND_GH_ACK_PENDING\n"));
     255            LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n"));
    260256            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
    261257                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
    262258            {
    263                 DO(("=> ignoring!\n"));
     259                LogFlowFunc(("=> ignoring!\n"));
    264260                break;
    265261            }
     
    285281        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
    286282        {
    287             DO(("GUEST_DND_GH_SND_DATA\n"));
     283            LogFlowFunc(("GUEST_DND_GH_SND_DATA\n"));
    288284            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
    289285                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
    290286            {
    291                 DO(("=> ignoring\n"));
     287                LogFlowFunc(("=> ignoring\n"));
    292288                break;
    293289            }
     
    310306        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
    311307        {
    312             DO(("GUEST_DND_GH_EVT_ERROR\n"));
     308            LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n"));
    313309            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
    314310                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
    315311            {
    316                 DO(("=> ignoring!\n"));
     312                LogFlowFunc(("=> ignoring!\n"));
    317313                break;
    318314            }
     
    338334            /* All other messages are handled by the DnD manager. */
    339335            rc = m_pManager->nextMessage(u32Function, cParms, paParms);
    340             /* Check for error. Buffer overflow is allowed. It signals the
    341              * guest to ask for more data in the next event. */
    342             if (   RT_FAILURE(rc)
    343                 && rc != VERR_CANCELLED
    344                 && rc != VERR_BUFFER_OVERFLOW) /* Buffer overflow is allowed. */
    345             {
    346                 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms));
    347                 rc = VINF_HGCM_ASYNC_EXECUTE;
    348             }
    349336            break;
    350337        }
     
    355342    if (rc != VINF_HGCM_ASYNC_EXECUTE)
    356343        m_pHelpers->pfnCallComplete(callHandle, rc);
    357     DO(("guest call: %Rrc\n", rc));
     344    LogFlowFunc(("Returning rc=%Rrc\n", rc));
    358345}
    359346
     
    415402int DragAndDropService::hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    416403{
     404    LogFlowFunc(("u32Function=%RU32, cParms=%RU32\n", u32Function, cParms));
     405
    417406    int rc = VINF_SUCCESS;
    418407    if (u32Function == DragAndDropSvc::HOST_DND_SET_MODE)
     
    428417    {
    429418        rc = m_pManager->addMessage(u32Function, cParms, paParms);
    430         if (    RT_SUCCESS(rc)
     419        if (   RT_SUCCESS(rc)
    431420            && !m_clientQueue.isEmpty())
    432421        {
    433422            HGCM::Client *pClient = m_clientQueue.first();
     423            AssertPtr(pClient);
    434424            /* Check if this was a request for getting the next host
    435425             * message. If so, return the message id and the parameter
     
    437427            if (pClient->message() == DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG)
    438428            {
    439                 DO(("client is waiting for next host msg\n"));
    440 //              rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32);
     429                LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId()));
     430
    441431                uint32_t uMsg1;
    442432                uint32_t cParms1;
     
    463453}
    464454
    465 DECLCALLBACK(int) DragAndDropService::progressCallback(unsigned uPercentage, uint32_t uState, void *pvUser)
     455DECLCALLBACK(int) DragAndDropService::progressCallback(uint32_t uPercentage, uint32_t uState, int rc, void *pvUser)
    466456{
    467457    AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
     
    471461    if (pSelf->m_pfnHostCallback)
    472462    {
    473         DO(("GUEST_DND_HG_EVT_PROGRESS %u\n", uPercentage));
     463        LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS: uPercentage=%RU32, uState=%RU32, rc=%Rrc\n",
     464                     uPercentage, uState, rc));
    474465        DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data;
    475466        data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS;
    476467        data.uPercentage  = uPercentage;
    477468        data.uState       = uState;
     469        data.rc           = rc;
    478470
    479471        return pSelf->m_pfnHostCallback(pSelf->m_pvHostData, DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS, &data, sizeof(data));
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