VirtualBox

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:
3 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    {
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