VirtualBox

Ignore:
Timestamp:
Apr 24, 2015 1:52:33 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
99765
Message:

DnD: Protocol overhaul with versioning added which now can communicate with Main.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp

    r50561 r55422  
    11/* $Id$ */
    22/** @file
    3  * Drag and Drop manager.
     3 * Drag and Drop manager: Handling of DnD messages on the host side.
    44 */
    55
    66/*
    7  * Copyright (C) 2011-2014 Oracle Corporation
     7 * Copyright (C) 2011-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3434
    3535/******************************************************************************
    36  *   Private declarations                                                     *
    37  ******************************************************************************/
    38 
    39 typedef DECLCALLBACK(int) FNDNDPRIVATEPROGRESS(size_t cbDone, void *pvUser);
    40 typedef FNDNDPRIVATEPROGRESS *PFNDNDPRIVATEPROGRESS;
    41 
    42 /**
    43  * Internal DnD message class for informing the
    44  * guest about a new directory.
    45  *
    46  * @see DnDHGSendDataMessage
    47  */
    48 class DnDHGSendDirPrivate: public DnDMessage
    49 {
    50 public:
    51 
    52     DnDHGSendDirPrivate(DnDURIObject URIObject,
    53                         PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
    54         : m_URIObject(URIObject)
    55         , m_pfnProgressCallback(pfnProgressCallback)
    56         , m_pvProgressUser(pvProgressUser)
    57     {
    58         RTCString strPath = m_URIObject.GetDestPath();
    59         LogFlowFunc(("strPath=%s (%zu)\n", strPath.c_str(), strPath.length()));
    60 
    61         VBOXHGCMSVCPARM paTmpParms[3];
    62         paTmpParms[0].setString(strPath.c_str());
    63         paTmpParms[1].setUInt32((uint32_t)(strPath.length() + 1));
    64         paTmpParms[2].setUInt32(m_URIObject.GetMode());
    65 
    66         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms);
    67     }
    68 
    69 public:
    70 
    71     int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    72     {
    73         int rc = DnDMessage::currentMessage(uMsg, cParms, paParms);
    74         /* Advance progress info */
    75         if (   RT_SUCCESS(rc)
    76             && m_pfnProgressCallback)
    77             rc = m_pfnProgressCallback(m_URIObject.GetSize(), m_pvProgressUser);
    78 
    79         return rc;
    80     }
    81 
    82 protected:
    83 
    84     DnDURIObject           m_URIObject;
    85 
    86     /* Progress stuff. */
    87     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
    88     void                  *m_pvProgressUser;
    89 };
    90 
    91 /**
    92  * Internal DnD message class for informing the guest about a new file.
    93  *
    94  * @see DnDHGSendDataMessage
    95  */
    96 class DnDHGSendFilePrivate: public DnDMessage
    97 {
    98 public:
    99 
    100     DnDHGSendFilePrivate(DnDURIObject URIObject,
    101                          PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
    102     virtual ~DnDHGSendFilePrivate(void);
    103 
    104 public:
    105 
    106     int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    107 
    108 protected:
    109 
    110     DnDURIObject           m_URIObject;
    111     /** Skeleton parameters for the next upcoming message in case
    112      *  the file data didn't fit completely into the first one. */
    113     VBOXHGCMSVCPARM        m_aSkelParms[5];
    114 
    115     /* Progress stuff. */
    116     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
    117     void                  *m_pvProgressUser;
    118 };
    119 
    120 /**
    121  * Internal DnD message class for informing the guest about new drag & drop
    122  * data.
    123  *
    124  * @see DnDHGSendDataMessage
    125  */
    126 class DnDHGSendDataMessagePrivate: public DnDMessage
    127 {
    128 public:
    129 
    130     DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms,
    131                                 VBOXHGCMSVCPARM paParms[],
    132                                 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
    133     int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    134 
    135 protected:
    136     size_t                 m_cbSize;
    137     size_t                 m_cbDone;
    138 
    139     /* Progress stuff. */
    140     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
    141     void                  *m_pvProgressUser;
    142 };
    143 
    144 /******************************************************************************
    145  *   Implementation                                                           *
    146  ******************************************************************************/
    147 
    148 /******************************************************************************
    149  *   DnDHGSendFilePrivate                                                     *
    150  ******************************************************************************/
    151 
    152 DnDHGSendFilePrivate::DnDHGSendFilePrivate(DnDURIObject URIObject,
    153                                            PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
    154     : m_URIObject(URIObject)
    155     , m_pfnProgressCallback(pfnProgressCallback)
    156     , m_pvProgressUser(pvProgressUser)
    157 {
    158     LogFlowFunc(("strPath=%s (%zu)\n",
    159                  m_URIObject.GetDestPath().c_str(), m_URIObject.GetDestPath().length()));
    160 
    161     m_aSkelParms[0].setString(m_URIObject.GetDestPath().c_str()); /* pvName */
    162     m_aSkelParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1)); /* cbName */
    163     m_aSkelParms[2].setPointer(NULL, 0); /* pvData */
    164     m_aSkelParms[3].setUInt32(0); /* cbData */
    165     m_aSkelParms[4].setUInt32(m_URIObject.GetMode()); /* fMode */
    166 
    167     m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_aSkelParms);
    168 }
    169 
    170 DnDHGSendFilePrivate::~DnDHGSendFilePrivate(void)
    171 {
    172 }
    173 
    174 int DnDHGSendFilePrivate::currentMessage(uint32_t uMsg, uint32_t cParms,
    175                                          VBOXHGCMSVCPARM paParms[])
    176 {
    177     if (!m_pNextMsg)
    178         return VERR_NO_DATA;
    179 
    180     int rc = m_pNextMsg->getData(uMsg, cParms, paParms);
    181     clearNextMsg();
    182     if (RT_FAILURE(rc))
    183         return rc;
    184 
    185     uint32_t cbRead;
    186     if (RT_SUCCESS(rc))
    187     {
    188         /* Get buffer size + pointer to buffer from guest side. */
    189         uint32_t cbToRead = paParms[2].u.pointer.size; /* cbData */
    190         Assert(cbToRead);
    191         void *pvBuf = paParms[2].u.pointer.addr; /* pvData */
    192         AssertPtr(pvBuf);
    193 
    194         rc = m_URIObject.Read(pvBuf, cbToRead, &cbRead);
    195         LogFlowFunc(("Read %RU32 bytes (%RU32 bytes buffer) for \"%s\", rc=%Rrc\n",
    196                      cbRead, cbToRead, m_URIObject.GetDestPath().c_str(), rc));
    197 
    198         if (RT_LIKELY(RT_SUCCESS(rc)))
    199         {
    200             /* Tell the guest the actual size read. */
    201             paParms[3].setUInt32((uint32_t)cbRead); /* cbData */
    202         }
    203     }
    204 
    205     if (RT_SUCCESS(rc))
    206     {
    207         if (!m_URIObject.IsComplete())
    208         {
    209             try
    210             {
    211                 /* More data needed to send over. Prepare the next message. */
    212                 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */,
    213                                                m_aSkelParms);
    214             }
    215             catch(std::bad_alloc &)
    216             {
    217                 rc = VERR_NO_MEMORY;
    218             }
    219         }
    220 
    221         /* Advance progress info. */
    222         if (   RT_SUCCESS(rc)
    223             && m_pfnProgressCallback)
    224         {
    225             rc = m_pfnProgressCallback(cbRead, m_pvProgressUser);
    226         }
    227     }
    228 
    229     return rc;
    230 }
    231 
    232 /******************************************************************************
    233  *   DnDHGSendDataMessagePrivate                                                *
    234  ******************************************************************************/
    235 
    236 DnDHGSendDataMessagePrivate::DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms,
    237                                                          VBOXHGCMSVCPARM paParms[],
    238                                                          PFNDNDPRIVATEPROGRESS pfnProgressCallback,
    239                                                          void *pvProgressUser)
    240     : m_cbSize(paParms[4].u.uint32)
    241     , m_cbDone(0)
    242     , m_pfnProgressCallback(pfnProgressCallback)
    243     , m_pvProgressUser(pvProgressUser)
    244 {
    245     /* Create the initial data message. This might throw
    246      * a bad_alloc exception. */
    247     m_pNextMsg = new HGCM::Message(uMsg, cParms, paParms);
    248 }
    249 
    250 int DnDHGSendDataMessagePrivate::currentMessage(uint32_t uMsg, uint32_t cParms,
    251                                                 VBOXHGCMSVCPARM paParms[])
    252 {
    253     /** @todo Don't copy the data parts ... just move the data pointer in
    254      *        the original data ptr. */
    255     if (!m_pNextMsg)
    256         return VERR_NO_DATA;
    257 
    258     int rc = VINF_SUCCESS;
    259 
    260     HGCM::Message *pCurMsg = m_pNextMsg;
    261     AssertPtr(pCurMsg);
    262 
    263     m_pNextMsg = 0;
    264     rc = pCurMsg->getData(uMsg, cParms, paParms);
    265 
    266     /* Depending on the current message, the data pointer is on a
    267      * different position (HOST_DND_HG_SND_DATA=3;
    268      * HOST_DND_HG_SND_MORE_DATA=0). */
    269     int iPos = uMsg == DragAndDropSvc::HOST_DND_HG_SND_DATA ? 3 : 0;
    270     m_cbDone += paParms[iPos + 1].u.uint32;
    271 
    272     /* Info + data send already? */
    273     if (rc == VERR_BUFFER_OVERFLOW)
    274     {
    275         paParms[iPos + 1].u.uint32 = paParms[iPos].u.pointer.size;
    276         VBOXHGCMSVCPARM paTmpParms[2];
    277         void     *pvOldData;
    278         uint32_t  cOldData;
    279         pCurMsg->getParmPtrInfo(iPos, &pvOldData, &cOldData);
    280         paTmpParms[0].setPointer(static_cast<uint8_t*>(pvOldData) + paParms[iPos].u.pointer.size, cOldData - paParms[iPos].u.pointer.size);
    281         paTmpParms[1].setUInt32(cOldData - paParms[iPos].u.pointer.size);
    282 
    283         try
    284         {
    285             m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA, 2, paTmpParms);
    286         }
    287         catch(std::bad_alloc &)
    288         {
    289             rc = VERR_NO_MEMORY;
    290         }
    291     }
    292 
    293     if (pCurMsg)
    294         delete pCurMsg;
    295 
    296     /* Advance progress info. */
    297     if (   RT_SUCCESS(rc)
    298         && m_pfnProgressCallback)
    299     {
    300         rc = m_pfnProgressCallback(m_cbDone, m_pvProgressUser);
    301     }
    302 
    303     return rc;
    304 }
    305 
    306 /******************************************************************************
    307  *   DnDHGSendDataMessage                                                       *
    308  ******************************************************************************/
    309 
    310 /*
    311  * This class is a meta message class. It doesn't consist of any own message
    312  * data, but handle the meta info, the data itself as well as any files or
    313  * directories which have to be transfered to the guest.
    314  */
    315 DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms,
    316                                            VBOXHGCMSVCPARM paParms[],
    317                                            PFNDNDPROGRESS pfnProgressCallback,
    318                                            void *pvProgressUser)
    319     : m_cbTotal(0)
    320     , m_cbTransfered(0)
    321     , m_pfnProgressCallback(pfnProgressCallback)
    322     , m_pvProgressUser(pvProgressUser)
    323 {
    324     if (cParms < 5) /* Paranoia. */
    325         return;
    326 
    327     const char *pszFormat = static_cast<const char*>(paParms[1].u.pointer.addr);
    328     uint32_t cbFormat = paParms[1].u.pointer.size;
    329 
    330     int rc = VINF_SUCCESS;
    331     RTCString strNewURIs;
    332 
    333     /* Do we need to build up a file tree? */
    334     if (DnDMIMEHasFileURLs(pszFormat, cbFormat))
    335     {
    336         const char *pszList = static_cast<const char*>(paParms[3].u.pointer.addr);
    337         AssertPtr(pszList);
    338         uint32_t cbList = paParms[3].u.pointer.size;
    339         Assert(cbList);
    340 
    341         LogFlowFunc(("Old data (%RU32 bytes): '%s'\n", cbList, pszList));
    342 
    343         /* The list is separated by newline (even if only one file is listed). */
    344         RTCList<RTCString> lstURIOrg
    345             = RTCString(pszList, cbList).split("\r\n");
    346         if (!lstURIOrg.isEmpty())
    347         {
    348             rc = m_lstURI.AppendURIPathsFromList(lstURIOrg, 0 /* fFlags */);
    349             if (RT_SUCCESS(rc))
    350             {
    351                 /* Add the total size of all meta data + files transferred to
    352                  * the message's total byte count. */
    353                 m_cbTotal += m_lstURI.TotalBytes();
    354 
    355                 /* We have to change the actual DnD data. Remove any host paths and
    356                  * just decode the filename into the new data. The Guest Additions will
    357                  * add the correct path again before sending the DnD drop event to
    358                  * some window. */
    359                 strNewURIs = m_lstURI.RootToString();
    360 
    361                 /* Note: We don't delete the old pointer here, cause this is done
    362                  *       by the caller. We just use the RTString data, which has the
    363                  *       scope of this ctor. This is enough cause the data is copied in
    364                  *       the DnDHGSendDataMessagePrivate anyway. */
    365                 paParms[3].u.pointer.addr = (void *)strNewURIs.c_str();
    366                 paParms[3].u.pointer.size = (uint32_t)(strNewURIs.length() + 1);
    367                 paParms[4].u.uint32       = (uint32_t)(strNewURIs.length() + 1);
    368 
    369                 LogFlowFunc(("Set new data (%RU32 bytes): '%s'\n",
    370                             paParms[3].u.pointer.size,
    371                             (const char*)paParms[3].u.pointer.addr));
    372             }
    373         }
    374     }
    375 
    376     /* Add the size of the data to the todo list. */
    377     m_cbTotal += paParms[4].u.uint32;
    378     LogFlowFunc(("cbTotal=%zu\n", m_cbTotal));
    379 
    380     /* The first message is the meta info for the data and the data itself. */
    381     m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms,
    382                                                      &DnDHGSendDataMessage::progressCallback, this);
    383 }
    384 
    385 DnDHGSendDataMessage::~DnDHGSendDataMessage(void)
    386 {
    387     if (m_pNextPathMsg)
    388         delete m_pNextPathMsg;
    389 }
    390 
    391 HGCM::Message* DnDHGSendDataMessage::nextHGCMMessage(void)
    392 {
    393     if (!m_pNextPathMsg)
    394         return NULL;
    395 
    396     return m_pNextPathMsg->nextHGCMMessage();
    397 }
    398 
    399 int DnDHGSendDataMessage::currentMessageInfo(uint32_t *puMsg, uint32_t *pcParms)
    400 {
    401     if (!m_pNextPathMsg)
    402         return VERR_NO_DATA;
    403 
    404     return m_pNextPathMsg->currentMessageInfo(puMsg, pcParms);
    405 }
    406 
    407 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg,
    408                                          uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    409 {
    410     if (!m_pNextPathMsg)
    411         return VERR_NO_DATA;
    412 
    413     /* Fill the data out of our current queued message. */
    414     int rc = m_pNextPathMsg->currentMessage(uMsg, cParms, paParms);
    415     /* Has this message more data to deliver? */
    416     if (!m_pNextPathMsg->isMessageWaiting())
    417     {
    418         delete m_pNextPathMsg;
    419         m_pNextPathMsg = NULL;
    420     }
    421 
    422     /* File/directory data to send? */
    423     if (!m_pNextPathMsg)
    424     {
    425         if (m_lstURI.IsEmpty())
    426             return rc;
    427 
    428         /* Create new messages based on our internal path list. Currently
    429          * this could be directories or regular files. */
    430         const DnDURIObject &nextObj = m_lstURI.First();
    431         try
    432         {
    433             uint32_t fMode = nextObj.GetMode();
    434             LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",
    435                          nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str(),
    436                          fMode, nextObj.GetSize(),
    437                          RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode)));
    438 
    439             if (RTFS_IS_DIRECTORY(fMode))
    440                 m_pNextPathMsg = new DnDHGSendDirPrivate(nextObj,
    441                                                          &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */,
    442                                                          this /* pvProgressUser */);
    443             else if (RTFS_IS_FILE(fMode))
    444                 m_pNextPathMsg = new DnDHGSendFilePrivate(nextObj,
    445                                                           &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */,
    446                                                           this /* pvProgressUser */);
    447             else
    448                 AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n",
    449                                        fMode, nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str()),
    450                                        VERR_NO_DATA);
    451 
    452             m_lstURI.RemoveFirst();
    453         }
    454         catch(std::bad_alloc &)
    455         {
    456             rc = VERR_NO_MEMORY;
    457         }
    458     }
    459 
    460     return rc;
    461 }
    462 
    463 int DnDHGSendDataMessage::progressCallback(size_t cbDone, void *pvUser)
    464 {
    465     AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
    466 
    467     DnDHGSendDataMessage *pSelf = static_cast<DnDHGSendDataMessage *>(pvUser);
    468     AssertPtr(pSelf);
    469 
    470     /* How many bytes are transfered already. */
    471     pSelf->m_cbTransfered += cbDone;
    472 
    473     /* Advance progress info. */
    474     int rc = VINF_SUCCESS;
    475     if (   pSelf->m_pfnProgressCallback
    476         && pSelf->m_cbTotal)
    477     {
    478         AssertMsg(pSelf->m_cbTransfered <= pSelf->m_cbTotal,
    479                   ("More bytes transferred (%zu) than expected (%zu), cbDone=%zu\n",
    480                    pSelf->m_cbTransfered, pSelf->m_cbTotal, cbDone));
    481 
    482         unsigned uPercentage = (unsigned)((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbTotal);
    483         rc = pSelf->m_pfnProgressCallback(RT_MIN(uPercentage, 100),
    484                                           DragAndDropSvc::DND_PROGRESS_RUNNING,
    485                                           VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser);
    486     }
    487 
    488     return rc;
    489 }
    490 
    491 /******************************************************************************
    49236 *   DnDManager                                                               *
    49337 ******************************************************************************/
    49438
    495 int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     39int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend /* = true */)
    49640{
    49741    int rc = VINF_SUCCESS;
    49842
     43    LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", uMsg, cParms, fAppend));
     44
    49945    try
    50046    {
     47        DnDMessage *pMessage = NULL;
     48
    50149        switch (uMsg)
    50250        {
     
    50553                clear();
    50654                LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
    507 
    508                 /* Verify parameter count and types. */
    509                 if (   cParms != 7
    510                     || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    511                     || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    512                     || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    513                     || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    514                     || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    515                     || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    516                     || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    517                     rc = VERR_INVALID_PARAMETER;
    518                 else
    519                 {
    520                     m_fOpInProcess = true;
    521                     DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    522                     m_dndMessageQueue.append(pMessage);
    523                 }
    52455                break;
    52556            }
     
    52859            {
    52960                LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
    530 
    531                 /* Verify parameter count and types. */
    532                 if (   cParms != 7
    533                     || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    534                     || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    535                     || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    536                     || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    537                     || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    538                     || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    539                     || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    540                 {
    541                     rc = VERR_INVALID_PARAMETER;
    542                 }
    543                 else
    544                 {
    545                     m_fOpInProcess = true;
    546                     DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    547                     m_dndMessageQueue.append(pMessage);
    548                 }
    54961                break;
    55062            }
     
    55365            {
    55466                LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
    555 
    556                 /* Verify parameter count and types. */
    557                 if (cParms != 0)
    558                     rc = VERR_INVALID_PARAMETER;
    559                 else
    560                 {
    561                     DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    562                     m_dndMessageQueue.append(pMessage);
    563                 }
    564 
    565                 m_fOpInProcess = false;
    56667                break;
    56768            }
     
    57071            {
    57172                LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
    572 
    573                 /* Verify parameter count and types. */
    574                 if (   cParms != 7
    575                     || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    576                     || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
    577                     || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
    578                     || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
    579                     || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
    580                     || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    581                     || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
    582                 {
    583                     rc = VERR_INVALID_PARAMETER;
    584                 }
    585                 else
    586                 {
    587                     DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    588                     m_dndMessageQueue.append(pMessage);
    589                 }
     73                break;
     74            }
     75
     76            case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
     77            {
     78                LogFlowFunc(("HOST_DND_HG_EVT_CANCEL\n"));
     79
     80                pMessage = new DnDHGCancelMessage();
    59081                break;
    59182            }
     
    59485            {
    59586                LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
    596 
    597                 /* Verify parameter count and types. */
    598                 if (   cParms != 5
    599                     || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
    600                     || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
    601                     || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
    602                     || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
    603                     || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */)
    604                 {
    605                     rc = VERR_INVALID_PARAMETER;
    606                 }
    607                 else
    608                 {
    609                     DnDHGSendDataMessage *pMessage =
    610                         new DnDHGSendDataMessage(uMsg, cParms, paParms,
    611                                                  m_pfnProgressCallback, m_pvProgressUser);
    612                     m_dndMessageQueue.append(pMessage);
    613                 }
     87                break;
     88            }
     89
     90            case DragAndDropSvc::HOST_DND_HG_SND_DIR:
     91            {
     92                LogFlowFunc(("HOST_DND_HG_SND_DIR\n"));
     93                break;
     94            }
     95
     96            /* New since protocol version 2 (VBox 5.0). */
     97            case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
     98            {
     99                LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR\n"));
     100                break;
     101            }
     102
     103            case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
     104            {
     105                LogFlowFunc(("HOST_DND_HG_SND_FILE\n"));
     106
     107                /* No parameter verification here as, depending on the protocol version
     108                 * being used, the parameter count + types might change. */
    614109                break;
    615110            }
     
    625120                {
    626121                    rc = VERR_INVALID_PARAMETER;
    627                 }
    628                 else
    629                 {
    630                     DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    631                     m_dndMessageQueue.append(pMessage);
    632122                }
    633123                break;
     
    646136                    rc = VERR_INVALID_PARAMETER;
    647137                }
    648                 else
    649                 {
    650                     try
    651                     {
    652                         DnDGenericMessage *pMessage
    653                             = new DnDGenericMessage(uMsg, cParms, paParms);
    654                         m_dndMessageQueue.append(pMessage);
    655                     }
    656                     catch(std::bad_alloc &)
    657                     {
    658                         rc = VERR_NO_MEMORY;
    659                     }
    660                 }
    661138                break;
    662139            }
     
    667144                break;
    668145        }
     146
     147        if (!pMessage) /* Generic message needed? */
     148            pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     149
     150        if (fAppend)
     151            m_dndMessageQueue.append(pMessage);
     152        else
     153            m_dndMessageQueue.prepend(pMessage);
    669154    }
    670155    catch(std::bad_alloc &)
     
    692177    AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
    693178
    694     int rc = VINF_SUCCESS;
    695 
     179    int rc;
    696180    if (m_pCurMsg)
    697181        rc = m_pCurMsg->currentMessageInfo(puMsg, pcParms);
     
    699183    {
    700184        if (m_dndMessageQueue.isEmpty())
    701         {
    702185            rc = VERR_NO_DATA;
    703 //            if (m_pfnProgressCallback)
    704 //                m_pfnProgressCallback(100.0, DragAndDropSvc::DND_OP_CANCELLED, m_pvProgressUser);
    705         }
    706186        else
    707187            rc = m_dndMessageQueue.first()->currentMessageInfo(puMsg, pcParms);
     
    743223     * callback about our exit.
    744224     */
    745     if (   RT_FAILURE(rc)
    746         && m_pfnProgressCallback)
     225    if (RT_FAILURE(rc))
    747226    {
    748227        /* Clear any pending messages. */
     
    754233        try
    755234        {
     235            if (rc == VERR_CANCELLED)
     236                LogFlowFunc(("Operation was cancelled\n"));
     237
    756238            Assert(!m_pCurMsg);
    757239            m_pCurMsg = new DnDHGCancelMessage();
    758             m_pfnProgressCallback(100 /* Percent */,
    759                                     rc == VERR_CANCELLED
    760                                   ? DragAndDropSvc::DND_PROGRESS_CANCELLED
    761                                   : DragAndDropSvc::DND_PROGRESS_ERROR, rc, m_pvProgressUser);
     240
     241            if (m_pfnProgressCallback)
     242            {
     243                LogFlowFunc(("Notifying host about aborting operation (%Rrc) ...\n", rc));
     244                m_pfnProgressCallback(  rc == VERR_CANCELLED
     245                                      ? DragAndDropSvc::DND_PROGRESS_CANCELLED
     246                                      : DragAndDropSvc::DND_PROGRESS_ERROR,
     247                                      100 /* Percent */, rc,
     248                                      m_pvProgressUser);
     249            }
    762250        }
    763251        catch(std::bad_alloc &)
     
    776264    {
    777265        delete m_pCurMsg;
    778         m_pCurMsg = 0;
     266        m_pCurMsg = NULL;
    779267    }
    780268
     
    786274}
    787275
     276/**
     277 * Triggers a rescheduling of the manager's message queue by setting the first
     278 * message available in the queue as the current one to process.
     279 *
     280 * @return  IPRT status code. VERR_NO_DATA if not message to process is available at
     281 *          the time of calling.
     282 */
     283int DnDManager::doReschedule(void)
     284{
     285    LogFlowFunc(("Rescheduling ...\n"));
     286
     287    if (!m_dndMessageQueue.isEmpty())
     288    {
     289        m_pCurMsg = m_dndMessageQueue.first();
     290        m_dndMessageQueue.removeFirst();
     291
     292        return VINF_SUCCESS;
     293    }
     294
     295    return VERR_NO_DATA;
     296}
     297
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