Index: /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
===================================================================
--- /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 74210)
+++ /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 74211)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2011-2017 Oracle Corporation
+ * Copyright (C) 2011-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -39,5 +39,35 @@
 *********************************************************************************************************************************/
 
-int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend /* = true */)
+/**
+ * Adds a DnD message to the manager's queue.
+ *
+ * @returns IPRT status code.
+ * @param   pMsg                Pointer to DnD message to add. The queue then owns the pointer.
+ * @param   fAppend             Whether to append or prepend the message to the queue.
+ */
+int DnDManager::AddMsg(DnDMessage *pMsg, bool fAppend /* = true */)
+{
+    AssertPtrReturn(pMsg, VERR_INVALID_POINTER);
+
+    LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", pMsg->GetType(), pMsg->GetParamCount(), fAppend));
+
+    if (fAppend)
+        m_queueMsg.append(pMsg);
+    else
+        m_queueMsg.prepend(pMsg);
+
+    /** @todo Catch / handle OOM? */
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Adds a DnD message to the manager's queue.
+ *
+ * @returns IPRT status code.
+ * @param   pMsg                Pointer to DnD message to add. The queue then owns the pointer.
+ * @param   fAppend             Whether to append or prepend the message to the queue.
+ */
+int DnDManager::AddMsg(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend /* = true */)
 {
     int rc;
@@ -45,13 +75,6 @@
     try
     {
-        LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", uMsg, cParms, fAppend));
-
-        DnDMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
-        if (fAppend)
-            m_dndMessageQueue.append(pMessage);
-        else
-            m_dndMessageQueue.prepend(pMessage);
-
-        rc = VINF_SUCCESS;
+        DnDMessage *pMsg = new DnDGenericMessage(uMsg, cParms, paParms);
+        rc = AddMsg(pMsg, fAppend);
     }
     catch(std::bad_alloc &)
@@ -64,58 +87,62 @@
 }
 
-HGCM::Message* DnDManager::nextHGCMMessage(void)
-{
-    if (m_pCurMsg)
-        return m_pCurMsg->nextHGCMMessage();
-
-    if (m_dndMessageQueue.isEmpty())
-        return NULL;
-
-    return m_dndMessageQueue.first()->nextHGCMMessage();
-}
-
-int DnDManager::nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms)
-{
-    AssertPtrReturn(puMsg, VERR_INVALID_POINTER);
+/**
+ * Retrieves information about the next message in the queue.
+ *
+ * @returns IPRT status code. VERR_NO_DATA if no next message is available.
+ * @param   puType              Where to store the message type.
+ * @param   pcParms             Where to store the message parameter count.
+ */
+int DnDManager::GetNextMsgInfo(uint32_t *puType, uint32_t *pcParms)
+{
+    AssertPtrReturn(puType, VERR_INVALID_POINTER);
     AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
 
     int rc;
-    if (m_pCurMsg)
-        rc = m_pCurMsg->currentMessageInfo(puMsg, pcParms);
+
+    if (m_queueMsg.isEmpty())
+    {
+        rc = VERR_NO_DATA;
+    }
     else
     {
-        if (m_dndMessageQueue.isEmpty())
-            rc = VERR_NO_DATA;
-        else
-            rc = m_dndMessageQueue.first()->currentMessageInfo(puMsg, pcParms);
-    }
-
-    LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puMsg, *pcParms, rc));
+        DnDMessage *pMsg = m_queueMsg.first();
+        AssertPtr(pMsg);
+
+        *puType  = pMsg->GetType();
+        *pcParms = pMsg->GetParamCount();
+
+        rc = VINF_SUCCESS;
+    }
+
+    LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puType, *pcParms, rc));
     return rc;
 }
 
-int DnDManager::nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+/**
+ * Retrieves the next queued up message and removes it from the queue on success.
+ * Will return VERR_NO_DATA if no next message is available.
+ *
+ * @returns IPRT status code.
+ * @param   uMsg                Message type to retrieve.
+ * @param   cParms              Number of parameters the \@a paParms array can store.
+ * @param   paParms             Where to store the message parameters.
+ */
+int DnDManager::GetNextMsg(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
 {
     LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
 
-    if (!m_pCurMsg)
-    {
-        /* Check for pending messages in our queue. */
-        if (m_dndMessageQueue.isEmpty())
-            return VERR_NO_DATA;
-
-        m_pCurMsg = m_dndMessageQueue.first();
-        AssertPtr(m_pCurMsg);
-        m_dndMessageQueue.removeFirst();
-    }
-
-    /* Fetch the current message info */
-    int rc = m_pCurMsg->currentMessage(uMsg, cParms, paParms);
-    /* If this message doesn't provide any additional sub messages, clear it. */
-    if (!m_pCurMsg->isMessageWaiting())
-    {
-        delete m_pCurMsg;
-        m_pCurMsg = NULL;
-    }
+    /* Check for pending messages in our queue. */
+    if (m_queueMsg.isEmpty())
+        return VERR_NO_DATA;
+
+    /* Get the current message. */
+    DnDMessage *pMsg = m_queueMsg.first();
+    AssertPtr(pMsg);
+
+    m_queueMsg.removeFirst(); /* Remove the current message from the queue. */
+
+    /* Fetch the current message info. */
+    int rc = pMsg->GetData(uMsg, cParms, paParms);
 
     /*
@@ -127,5 +154,5 @@
     {
         /* Clear any pending messages. */
-        clear();
+        Reset();
 
         /* Create a new cancel message to inform the guest + call
@@ -137,6 +164,8 @@
                 LogFlowFunc(("Operation was cancelled\n"));
 
-            Assert(!m_pCurMsg);
-            m_pCurMsg = new DnDHGCancelMessage();
+            DnDHGCancelMessage *pMsgCancel = new DnDHGCancelMessage();
+
+            int rc2 = AddMsg(pMsgCancel, false /* Prepend */);
+            AssertRC(rc2);
 
             if (m_pfnProgressCallback)
@@ -160,41 +189,16 @@
 }
 
-void DnDManager::clear(void)
+/**
+ * Resets the manager by clearing the message queue and internal state.
+ */
+void DnDManager::Reset(void)
 {
     LogFlowFuncEnter();
 
-    if (m_pCurMsg)
-    {
-        delete m_pCurMsg;
-        m_pCurMsg = NULL;
-    }
-
-    while (!m_dndMessageQueue.isEmpty())
-    {
-        delete m_dndMessageQueue.last();
-        m_dndMessageQueue.removeLast();
-    }
-}
-
-/**
- * Triggers a rescheduling of the manager's message queue by setting the first
- * message available in the queue as the current one to process.
- *
- * @return  IPRT status code. VERR_NO_DATA if not message to process is available at
- *          the time of calling.
- */
-int DnDManager::doReschedule(void)
-{
-    LogFlowFunc(("Rescheduling ...\n"));
-
-    if (!m_dndMessageQueue.isEmpty())
-    {
-        m_pCurMsg = m_dndMessageQueue.first();
-        m_dndMessageQueue.removeFirst();
-
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NO_DATA;
-}
-
+    while (!m_queueMsg.isEmpty())
+    {
+        delete m_queueMsg.last();
+        m_queueMsg.removeLast();
+    }
+}
+
Index: /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h
===================================================================
--- /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h	(revision 74210)
+++ /trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h	(revision 74211)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2011-2017 Oracle Corporation
+ * Copyright (C) 2011-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -32,63 +32,16 @@
  * message classes.
  */
-class DnDMessage
+class DnDMessage : public HGCM::Message
 {
 public:
 
     DnDMessage(void)
-        : m_pNextMsg(NULL)
     {
     }
 
-    virtual ~DnDMessage(void)
-    {
-        clearNextMsg();
-    }
+    DnDMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
+        : Message(uMsg, cParms, aParms) { }
 
-    virtual HGCM::Message* nextHGCMMessage(void)
-    {
-        return m_pNextMsg;
-    }
-
-    virtual int currentMessageInfo(uint32_t *puMsg, uint32_t *pcParms)
-    {
-        AssertPtrReturn(puMsg, VERR_INVALID_POINTER);
-        AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
-
-        if (!m_pNextMsg)
-            return VERR_NO_DATA;
-
-        *puMsg = m_pNextMsg->GetType();
-        *pcParms = m_pNextMsg->GetParamCount();
-
-        return VINF_SUCCESS;
-    }
-
-    virtual int currentMessage(uint32_t uMsg, uint32_t cParms,
-                               VBOXHGCMSVCPARM paParms[])
-    {
-        if (!m_pNextMsg)
-            return VERR_NO_DATA;
-        int rc = m_pNextMsg->GetData(uMsg, cParms, paParms);
-
-        clearNextMsg();
-
-        return rc;
-    }
-
-    virtual void clearNextMsg(void)
-    {
-        if (m_pNextMsg)
-        {
-            delete m_pNextMsg;
-            m_pNextMsg = NULL;
-        }
-    }
-
-    virtual bool isMessageWaiting(void) const { return m_pNextMsg != NULL; }
-
-protected:
-
-    HGCM::Message *m_pNextMsg;
+    virtual ~DnDMessage(void) { }
 };
 
@@ -101,7 +54,5 @@
 public:
     DnDGenericMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
-    {
-        m_pNextMsg = new HGCM::Message(uMsg, cParms, paParms);
-    }
+        : DnDMessage(uMsg, cParms, paParms) { }
 };
 
@@ -115,7 +66,7 @@
     DnDHGCancelMessage(void)
     {
-        m_pNextMsg
-            = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL,
-                                0 /* cParms */, 0 /* aParms */);
+        int rc2 = initData(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL,
+                           0 /* cParms */, 0 /* aParms */);
+        AssertRC(rc2);
     }
 };
@@ -130,6 +81,5 @@
 
     DnDManager(PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser)
-        : m_pCurMsg(NULL)
-        , m_pfnProgressCallback(pfnProgressCallback)
+        : m_pfnProgressCallback(pfnProgressCallback)
         , m_pvProgressUser(pvProgressUser)
     {}
@@ -137,22 +87,22 @@
     virtual ~DnDManager(void)
     {
-        clear();
+        Reset();
     }
 
-    int addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend = true);
+    int AddMsg(DnDMessage *pMessage, bool fAppend = true);
+    int AddMsg(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend = true);
 
-    HGCM::Message *nextHGCMMessage(void);
-    int nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms);
-    int nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+    int GetNextMsgInfo(uint32_t *puType, uint32_t *pcParms);
+    int GetNextMsg(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
 
-    void clear(void);
-    int doReschedule(void);
+    void Reset(void);
 
-private:
-    DnDMessage           *m_pCurMsg;
-    RTCList<DnDMessage*>  m_dndMessageQueue;
+protected:
 
-    /* Progress stuff */
+    /** DnD message queue (FIFO). */
+    RTCList<DnDMessage *> m_queueMsg;
+    /** Pointer to host progress callback. Optional, can be NULL. */
     PFNDNDPROGRESS        m_pfnProgressCallback;
+    /** Pointer to progress callback user context. Can be NULL if not used. */
     void                 *m_pvProgressUser;
 };
Index: /trunk/src/VBox/HostServices/DragAndDrop/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 74210)
+++ /trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 74211)
@@ -236,9 +236,9 @@
         {
             /*
-             * Clear the message queue as soon as a new clients connect
+             * Reset the message queue as soon as a new clients connect
              * to ensure that every client has the same state.
              */
             if (m_pManager)
-                m_pManager->clear();
+                m_pManager->Reset();
         }
     }
@@ -429,5 +429,5 @@
                 if (cParms == 3)
                 {
-                    rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
+                    rc = m_pManager->GetNextMsgInfo(&paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
                     if (RT_FAILURE(rc)) /* No queued messages available? */
                     {
@@ -449,5 +449,5 @@
 
                         if (RT_FAILURE(rc))
-                            rc = m_pManager->nextMessage(u32Function, cParms, paParms);
+                            rc = m_pManager->GetNextMsg(u32Function, cParms, paParms);
 
                         /* Some error occurred or no (new) messages available? */
@@ -975,5 +975,5 @@
             {
                 /* All other messages are handled by the DnD manager. */
-                rc = m_pManager->nextMessage(u32Function, cParms, paParms);
+                rc = m_pManager->GetNextMsg(u32Function, cParms, paParms);
                 if (rc == VERR_NO_DATA) /* Manager has no new messsages? Try asking the host. */
                 {
@@ -1072,6 +1072,6 @@
             case HOST_DND_HG_EVT_ENTER:
             {
-                /* Clear the message queue as a new DnD operation just began. */
-                m_pManager->clear();
+                /* Reset the message queue as a new DnD operation just began. */
+                m_pManager->Reset();
 
                 fSendToGuest = true;
@@ -1084,6 +1084,6 @@
                 LogFlowFunc(("Cancelling all waiting clients ...\n"));
 
-                /* Clear the message queue as the host cancelled the whole operation. */
-                m_pManager->clear();
+                /* Reset the message queue as the host cancelled the whole operation. */
+                m_pManager->Reset();
 
                 /*
@@ -1144,5 +1144,5 @@
             }
 
-            rc = m_pManager->addMessage(u32Function, cParms, paParms, true /* fAppend */);
+            rc = m_pManager->AddMsg(u32Function, cParms, paParms, true /* fAppend */);
             if (RT_FAILURE(rc))
             {
@@ -1174,5 +1174,5 @@
             uint32_t uMsgNext   = 0;
             uint32_t cParmsNext = 0;
-            int rcNext = m_pManager->nextMessageInfo(&uMsgNext, &cParmsNext);
+            int rcNext = m_pManager->GetNextMsgInfo(&uMsgNext, &cParmsNext);
 
             LogFlowFunc(("uMsgClient=%RU32, uMsgNext=%RU32, cParmsNext=%RU32, rcNext=%Rrc\n",
@@ -1194,5 +1194,5 @@
                 else if (uMsgClient == uMsgNext)
                 {
-                    rc = m_pManager->nextMessage(u32Function, cParms, paParms);
+                    rc = m_pManager->GetNextMsg(u32Function, cParms, paParms);
 
                     /* Note: Report the current rc back to the guest. */
